aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorStanislav Kinsbursky <skinsbursky@parallels.com>2012-01-11 10:18:17 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-01-31 18:20:25 -0500
commit80df9d202255071c8ec610a6a3fdca5cac69f7bd (patch)
tree140bf4a80e2ffe5d5e5601330b9a3e27e1aecf14 /net
parent70abc49b4f4a4ef04a6bd9852edbd047b480bed7 (diff)
SUNRPC: subscribe RPC clients to pipefs notifications
This patch subscribes RPC clients to RPC pipefs notifications. RPC clients notifier block is registering with pipefs initialization during SUNRPC module init. This notifier callback is responsible for RPC client PipeFS directory and GSS pipes creation. For pipes creation and destruction two additional callbacks were added to struct rpc_authops. Note that no locking required in notifier callback because PipeFS superblock pointer is passed as an argument from it's creation or destruction routine and thus we can be sure about it's validity. Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c10
-rw-r--r--net/sunrpc/clnt.c69
-rw-r--r--net/sunrpc/rpc_pipe.c19
-rw-r--r--net/sunrpc/sunrpc.h2
4 files changed, 90 insertions, 10 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 1a6fa9173519..9da2d837b512 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -762,8 +762,10 @@ static void gss_pipes_dentries_destroy(struct rpc_auth *auth)
762 struct gss_auth *gss_auth; 762 struct gss_auth *gss_auth;
763 763
764 gss_auth = container_of(auth, struct gss_auth, rpc_auth); 764 gss_auth = container_of(auth, struct gss_auth, rpc_auth);
765 rpc_unlink(gss_auth->pipe[0]->dentry); 765 if (gss_auth->pipe[0]->dentry)
766 rpc_unlink(gss_auth->pipe[1]->dentry); 766 rpc_unlink(gss_auth->pipe[0]->dentry);
767 if (gss_auth->pipe[1]->dentry)
768 rpc_unlink(gss_auth->pipe[1]->dentry);
767} 769}
768 770
769static int gss_pipes_dentries_create(struct rpc_auth *auth) 771static int gss_pipes_dentries_create(struct rpc_auth *auth)
@@ -1614,7 +1616,9 @@ static const struct rpc_authops authgss_ops = {
1614 .create = gss_create, 1616 .create = gss_create,
1615 .destroy = gss_destroy, 1617 .destroy = gss_destroy,
1616 .lookup_cred = gss_lookup_cred, 1618 .lookup_cred = gss_lookup_cred,
1617 .crcreate = gss_create_cred 1619 .crcreate = gss_create_cred,
1620 .pipes_create = gss_pipes_dentries_create,
1621 .pipes_destroy = gss_pipes_dentries_destroy,
1618}; 1622};
1619 1623
1620static const struct rpc_credops gss_credops = { 1624static const struct rpc_credops gss_credops = {
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 90e82c5daeb6..417074500592 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -98,8 +98,11 @@ static void rpc_unregister_client(struct rpc_clnt *clnt)
98 98
99static void __rpc_clnt_remove_pipedir(struct rpc_clnt *clnt) 99static void __rpc_clnt_remove_pipedir(struct rpc_clnt *clnt)
100{ 100{
101 if (clnt->cl_path.dentry) 101 if (clnt->cl_path.dentry) {
102 if (clnt->cl_auth && clnt->cl_auth->au_ops->pipes_destroy)
103 clnt->cl_auth->au_ops->pipes_destroy(clnt->cl_auth);
102 rpc_remove_client_dir(clnt->cl_path.dentry); 104 rpc_remove_client_dir(clnt->cl_path.dentry);
105 }
103 clnt->cl_path.dentry = NULL; 106 clnt->cl_path.dentry = NULL;
104} 107}
105 108
@@ -181,6 +184,70 @@ rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
181 return 0; 184 return 0;
182} 185}
183 186
187static int __rpc_pipefs_event(struct rpc_clnt *clnt, unsigned long event,
188 struct super_block *sb)
189{
190 struct dentry *dentry;
191 int err = 0;
192
193 switch (event) {
194 case RPC_PIPEFS_MOUNT:
195 if (clnt->cl_program->pipe_dir_name == NULL)
196 break;
197 dentry = rpc_setup_pipedir_sb(sb, clnt,
198 clnt->cl_program->pipe_dir_name);
199 BUG_ON(dentry == NULL);
200 if (IS_ERR(dentry))
201 return PTR_ERR(dentry);
202 clnt->cl_path.dentry = dentry;
203 if (clnt->cl_auth->au_ops->pipes_create) {
204 err = clnt->cl_auth->au_ops->pipes_create(clnt->cl_auth);
205 if (err)
206 __rpc_clnt_remove_pipedir(clnt);
207 }
208 break;
209 case RPC_PIPEFS_UMOUNT:
210 __rpc_clnt_remove_pipedir(clnt);
211 break;
212 default:
213 printk(KERN_ERR "%s: unknown event: %ld\n", __func__, event);
214 return -ENOTSUPP;
215 }
216 return err;
217}
218
219static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event,
220 void *ptr)
221{
222 struct super_block *sb = ptr;
223 struct rpc_clnt *clnt;
224 int error = 0;
225 struct sunrpc_net *sn = net_generic(sb->s_fs_info, sunrpc_net_id);
226
227 spin_lock(&sn->rpc_client_lock);
228 list_for_each_entry(clnt, &sn->all_clients, cl_clients) {
229 error = __rpc_pipefs_event(clnt, event, sb);
230 if (error)
231 break;
232 }
233 spin_unlock(&sn->rpc_client_lock);
234 return error;
235}
236
237static struct notifier_block rpc_clients_block = {
238 .notifier_call = rpc_pipefs_event,
239};
240
241int rpc_clients_notifier_register(void)
242{
243 return rpc_pipefs_notifier_register(&rpc_clients_block);
244}
245
246void rpc_clients_notifier_unregister(void)
247{
248 return rpc_pipefs_notifier_unregister(&rpc_clients_block);
249}
250
184static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt) 251static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt)
185{ 252{
186 struct rpc_program *program = args->program; 253 struct rpc_program *program = args->program;
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 6dd8b96e8df7..910de4169a8d 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -937,7 +937,7 @@ struct dentry *rpc_create_client_dir(struct dentry *dentry,
937 937
938/** 938/**
939 * rpc_remove_client_dir - Remove a directory created with rpc_create_client_dir() 939 * rpc_remove_client_dir - Remove a directory created with rpc_create_client_dir()
940 * @dentry: directory to remove 940 * @clnt: rpc client
941 */ 941 */
942int rpc_remove_client_dir(struct dentry *dentry) 942int rpc_remove_client_dir(struct dentry *dentry)
943{ 943{
@@ -1188,17 +1188,24 @@ int register_rpc_pipefs(void)
1188 init_once); 1188 init_once);
1189 if (!rpc_inode_cachep) 1189 if (!rpc_inode_cachep)
1190 return -ENOMEM; 1190 return -ENOMEM;
1191 err = rpc_clients_notifier_register();
1192 if (err)
1193 goto err_notifier;
1191 err = register_filesystem(&rpc_pipe_fs_type); 1194 err = register_filesystem(&rpc_pipe_fs_type);
1192 if (err) { 1195 if (err)
1193 kmem_cache_destroy(rpc_inode_cachep); 1196 goto err_register;
1194 return err;
1195 }
1196
1197 return 0; 1197 return 0;
1198
1199err_register:
1200 rpc_clients_notifier_unregister();
1201err_notifier:
1202 kmem_cache_destroy(rpc_inode_cachep);
1203 return err;
1198} 1204}
1199 1205
1200void unregister_rpc_pipefs(void) 1206void unregister_rpc_pipefs(void)
1201{ 1207{
1208 rpc_clients_notifier_unregister();
1202 kmem_cache_destroy(rpc_inode_cachep); 1209 kmem_cache_destroy(rpc_inode_cachep);
1203 unregister_filesystem(&rpc_pipe_fs_type); 1210 unregister_filesystem(&rpc_pipe_fs_type);
1204} 1211}
diff --git a/net/sunrpc/sunrpc.h b/net/sunrpc/sunrpc.h
index 90c292e2738b..14c9f6d1c5ff 100644
--- a/net/sunrpc/sunrpc.h
+++ b/net/sunrpc/sunrpc.h
@@ -47,5 +47,7 @@ int svc_send_common(struct socket *sock, struct xdr_buf *xdr,
47 struct page *headpage, unsigned long headoffset, 47 struct page *headpage, unsigned long headoffset,
48 struct page *tailpage, unsigned long tailoffset); 48 struct page *tailpage, unsigned long tailoffset);
49 49
50int rpc_clients_notifier_register(void);
51void rpc_clients_notifier_unregister(void);
50#endif /* _NET_SUNRPC_SUNRPC_H */ 52#endif /* _NET_SUNRPC_SUNRPC_H */
51 53