SUNRPC: Add an rpc_pipefs front end for the sunrpc cache code
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Sun, 9 Aug 2009 19:14:30 +0000 (15:14 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Sun, 9 Aug 2009 19:14:30 +0000 (15:14 -0400)
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
include/linux/sunrpc/cache.h
include/linux/sunrpc/rpc_pipe_fs.h
net/sunrpc/cache.c
net/sunrpc/rpc_pipe.c

index 8e5bf30..6f52b4d 100644 (file)
@@ -64,6 +64,10 @@ struct cache_detail_procfs {
        struct proc_dir_entry   *flush_ent, *channel_ent, *content_ent;
 };
 
+struct cache_detail_pipefs {
+       struct dentry *dir;
+};
+
 struct cache_detail {
        struct module *         owner;
        int                     hash_size;
@@ -110,6 +114,7 @@ struct cache_detail {
 
        union {
                struct cache_detail_procfs procfs;
+               struct cache_detail_pipefs pipefs;
        } u;
 };
 
@@ -135,6 +140,10 @@ struct cache_deferred_req {
 };
 
 
+extern const struct file_operations cache_file_operations_pipefs;
+extern const struct file_operations content_file_operations_pipefs;
+extern const struct file_operations cache_flush_operations_pipefs;
+
 extern struct cache_head *
 sunrpc_cache_lookup(struct cache_detail *detail,
                    struct cache_head *key, int hash);
@@ -186,6 +195,10 @@ extern void cache_purge(struct cache_detail *detail);
 extern int cache_register(struct cache_detail *cd);
 extern void cache_unregister(struct cache_detail *cd);
 
+extern int sunrpc_cache_register_pipefs(struct dentry *parent, const char *,
+                                       mode_t, struct cache_detail *);
+extern void sunrpc_cache_unregister_pipefs(struct cache_detail *);
+
 extern void qword_add(char **bpp, int *lp, char *str);
 extern void qword_addhex(char **bpp, int *lp, char *buf, int blen);
 extern int qword_get(char **bpp, char *dest, int bufsize);
index 88332ef..a92571a 100644 (file)
@@ -47,6 +47,14 @@ extern int rpc_queue_upcall(struct inode *, struct rpc_pipe_msg *);
 struct rpc_clnt;
 extern struct dentry *rpc_create_client_dir(struct dentry *, struct qstr *, struct rpc_clnt *);
 extern int rpc_remove_client_dir(struct dentry *);
+
+struct cache_detail;
+extern struct dentry *rpc_create_cache_dir(struct dentry *,
+                                          struct qstr *,
+                                          mode_t umode,
+                                          struct cache_detail *);
+extern void rpc_remove_cache_dir(struct dentry *);
+
 extern struct dentry *rpc_mkpipe(struct dentry *, const char *, void *,
                                 const struct rpc_pipe_ops *, int flags);
 extern int rpc_unlink(struct dentry *);
index 1cd82ed..db7720e 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/sunrpc/types.h>
 #include <linux/sunrpc/cache.h>
 #include <linux/sunrpc/stats.h>
+#include <linux/sunrpc/rpc_pipe_fs.h>
 
 #define         RPCDBG_FACILITY RPCDBG_CACHE
 
@@ -1438,3 +1439,128 @@ void cache_unregister(struct cache_detail *cd)
        sunrpc_destroy_cache_detail(cd);
 }
 EXPORT_SYMBOL_GPL(cache_unregister);
+
+static ssize_t cache_read_pipefs(struct file *filp, char __user *buf,
+                                size_t count, loff_t *ppos)
+{
+       struct cache_detail *cd = RPC_I(filp->f_path.dentry->d_inode)->private;
+
+       return cache_read(filp, buf, count, ppos, cd);
+}
+
+static ssize_t cache_write_pipefs(struct file *filp, const char __user *buf,
+                                 size_t count, loff_t *ppos)
+{
+       struct cache_detail *cd = RPC_I(filp->f_path.dentry->d_inode)->private;
+
+       return cache_write(filp, buf, count, ppos, cd);
+}
+
+static unsigned int cache_poll_pipefs(struct file *filp, poll_table *wait)
+{
+       struct cache_detail *cd = RPC_I(filp->f_path.dentry->d_inode)->private;
+
+       return cache_poll(filp, wait, cd);
+}
+
+static int cache_ioctl_pipefs(struct inode *inode, struct file *filp,
+                             unsigned int cmd, unsigned long arg)
+{
+       struct cache_detail *cd = RPC_I(inode)->private;
+
+       return cache_ioctl(inode, filp, cmd, arg, cd);
+}
+
+static int cache_open_pipefs(struct inode *inode, struct file *filp)
+{
+       struct cache_detail *cd = RPC_I(inode)->private;
+
+       return cache_open(inode, filp, cd);
+}
+
+static int cache_release_pipefs(struct inode *inode, struct file *filp)
+{
+       struct cache_detail *cd = RPC_I(inode)->private;
+
+       return cache_release(inode, filp, cd);
+}
+
+const struct file_operations cache_file_operations_pipefs = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .read           = cache_read_pipefs,
+       .write          = cache_write_pipefs,
+       .poll           = cache_poll_pipefs,
+       .ioctl          = cache_ioctl_pipefs, /* for FIONREAD */
+       .open           = cache_open_pipefs,
+       .release        = cache_release_pipefs,
+};
+
+static int content_open_pipefs(struct inode *inode, struct file *filp)
+{
+       struct cache_detail *cd = RPC_I(inode)->private;
+
+       return content_open(inode, filp, cd);
+}
+
+const struct file_operations content_file_operations_pipefs = {
+       .open           = content_open_pipefs,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release_private,
+};
+
+static ssize_t read_flush_pipefs(struct file *filp, char __user *buf,
+                           size_t count, loff_t *ppos)
+{
+       struct cache_detail *cd = RPC_I(filp->f_path.dentry->d_inode)->private;
+
+       return read_flush(filp, buf, count, ppos, cd);
+}
+
+static ssize_t write_flush_pipefs(struct file *filp,
+                                 const char __user *buf,
+                                 size_t count, loff_t *ppos)
+{
+       struct cache_detail *cd = RPC_I(filp->f_path.dentry->d_inode)->private;
+
+       return write_flush(filp, buf, count, ppos, cd);
+}
+
+const struct file_operations cache_flush_operations_pipefs = {
+       .open           = nonseekable_open,
+       .read           = read_flush_pipefs,
+       .write          = write_flush_pipefs,
+};
+
+int sunrpc_cache_register_pipefs(struct dentry *parent,
+                                const char *name, mode_t umode,
+                                struct cache_detail *cd)
+{
+       struct qstr q;
+       struct dentry *dir;
+       int ret = 0;
+
+       sunrpc_init_cache_detail(cd);
+       q.name = name;
+       q.len = strlen(name);
+       q.hash = full_name_hash(q.name, q.len);
+       dir = rpc_create_cache_dir(parent, &q, umode, cd);
+       if (!IS_ERR(dir))
+               cd->u.pipefs.dir = dir;
+       else {
+               sunrpc_destroy_cache_detail(cd);
+               ret = PTR_ERR(dir);
+       }
+       return ret;
+}
+EXPORT_SYMBOL_GPL(sunrpc_cache_register_pipefs);
+
+void sunrpc_cache_unregister_pipefs(struct cache_detail *cd)
+{
+       rpc_remove_cache_dir(cd->u.pipefs.dir);
+       cd->u.pipefs.dir = NULL;
+       sunrpc_destroy_cache_detail(cd);
+}
+EXPORT_SYMBOL_GPL(sunrpc_cache_unregister_pipefs);
+
index 57e9cd3..8dd8153 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/sunrpc/clnt.h>
 #include <linux/workqueue.h>
 #include <linux/sunrpc/rpc_pipe_fs.h>
+#include <linux/sunrpc/cache.h>
 
 static struct vfsmount *rpc_mount __read_mostly;
 static int rpc_mount_count;
@@ -882,6 +883,48 @@ int rpc_remove_client_dir(struct dentry *dentry)
        return rpc_rmdir_depopulate(dentry, rpc_clntdir_depopulate);
 }
 
+static const struct rpc_filelist cache_pipefs_files[3] = {
+       [0] = {
+               .name = "channel",
+               .i_fop = &cache_file_operations_pipefs,
+               .mode = S_IFIFO|S_IRUSR|S_IWUSR,
+       },
+       [1] = {
+               .name = "content",
+               .i_fop = &content_file_operations_pipefs,
+               .mode = S_IFREG|S_IRUSR,
+       },
+       [2] = {
+               .name = "flush",
+               .i_fop = &cache_flush_operations_pipefs,
+               .mode = S_IFREG|S_IRUSR|S_IWUSR,
+       },
+};
+
+static int rpc_cachedir_populate(struct dentry *dentry, void *private)
+{
+       return rpc_populate(dentry,
+                           cache_pipefs_files, 0, 3,
+                           private);
+}
+
+static void rpc_cachedir_depopulate(struct dentry *dentry)
+{
+       rpc_depopulate(dentry, cache_pipefs_files, 0, 3);
+}
+
+struct dentry *rpc_create_cache_dir(struct dentry *parent, struct qstr *name,
+                                   mode_t umode, struct cache_detail *cd)
+{
+       return rpc_mkdir_populate(parent, name, umode, NULL,
+                       rpc_cachedir_populate, cd);
+}
+
+void rpc_remove_cache_dir(struct dentry *dentry)
+{
+       rpc_rmdir_depopulate(dentry, rpc_cachedir_depopulate);
+}
+
 /*
  * populate the filesystem
  */