SUNRPC: send notification events on pipefs sb creation and destruction
Stanislav Kinsbursky [Mon, 26 Dec 2011 12:39:13 +0000 (15:39 +0300)]
They will be used to notify subscribers about pipefs superblock creation and
destruction.
Subcribers will have to create their dentries on passed superblock on mount
event and destroy otherwise.

Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

include/linux/sunrpc/rpc_pipe_fs.h
net/sunrpc/rpc_pipe.c

index edadc3a..d39782c 100644 (file)
@@ -43,6 +43,14 @@ RPC_I(struct inode *inode)
        return container_of(inode, struct rpc_inode, vfs_inode);
 }
 
+extern int rpc_pipefs_notifier_register(struct notifier_block *);
+extern void rpc_pipefs_notifier_unregister(struct notifier_block *);
+
+enum {
+       RPC_PIPEFS_MOUNT,
+       RPC_PIPEFS_UMOUNT,
+};
+
 extern ssize_t rpc_pipe_generic_upcall(struct file *, struct rpc_pipe_msg *,
                                       char __user *, size_t);
 extern int rpc_queue_upcall(struct inode *, struct rpc_pipe_msg *);
index f628b0f..58a5062 100644 (file)
 #include <linux/sunrpc/rpc_pipe_fs.h>
 #include <linux/sunrpc/cache.h>
 #include <linux/nsproxy.h>
+#include <linux/notifier.h>
 
 #include "netns.h"
+#include "sunrpc.h"
 
 static struct vfsmount *rpc_mnt __read_mostly;
 static int rpc_mount_count;
@@ -41,6 +43,20 @@ static struct kmem_cache *rpc_inode_cachep __read_mostly;
 
 #define RPC_UPCALL_TIMEOUT (30*HZ)
 
+static BLOCKING_NOTIFIER_HEAD(rpc_pipefs_notifier_list);
+
+int rpc_pipefs_notifier_register(struct notifier_block *nb)
+{
+       return blocking_notifier_chain_cond_register(&rpc_pipefs_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(rpc_pipefs_notifier_register);
+
+void rpc_pipefs_notifier_unregister(struct notifier_block *nb)
+{
+       blocking_notifier_chain_unregister(&rpc_pipefs_notifier_list, nb);
+}
+EXPORT_SYMBOL_GPL(rpc_pipefs_notifier_unregister);
+
 static void rpc_purge_list(struct rpc_inode *rpci, struct list_head *head,
                void (*destroy_msg)(struct rpc_pipe_msg *), int err)
 {
@@ -997,6 +1013,7 @@ rpc_fill_super(struct super_block *sb, void *data, int silent)
        struct inode *inode;
        struct dentry *root;
        struct net *net = data;
+       int err;
 
        sb->s_blocksize = PAGE_CACHE_SIZE;
        sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
@@ -1014,8 +1031,20 @@ rpc_fill_super(struct super_block *sb, void *data, int silent)
        }
        if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL))
                return -ENOMEM;
+       err = blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
+                                          RPC_PIPEFS_MOUNT,
+                                          sb);
+       if (err)
+               goto err_depopulate;
        sb->s_fs_info = get_net(net);
        return 0;
+
+err_depopulate:
+       blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
+                                          RPC_PIPEFS_UMOUNT,
+                                          sb);
+       __rpc_depopulate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF);
+       return err;
 }
 
 static struct dentry *
@@ -1030,6 +1059,9 @@ void rpc_kill_sb(struct super_block *sb)
        struct net *net = sb->s_fs_info;
 
        put_net(net);
+       blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
+                                          RPC_PIPEFS_UMOUNT,
+                                          sb);
        kill_litter_super(sb);
 }