aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/sunrpc/auth.h2
-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
5 files changed, 92 insertions, 10 deletions
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index 7874a8a56638..492a36d72829 100644
--- a/include/linux/sunrpc/auth.h
+++ b/include/linux/sunrpc/auth.h
@@ -99,6 +99,8 @@ struct rpc_authops {
99 99
100 struct rpc_cred * (*lookup_cred)(struct rpc_auth *, struct auth_cred *, int); 100 struct rpc_cred * (*lookup_cred)(struct rpc_auth *, struct auth_cred *, int);
101 struct rpc_cred * (*crcreate)(struct rpc_auth*, struct auth_cred *, int); 101 struct rpc_cred * (*crcreate)(struct rpc_auth*, struct auth_cred *, int);
102 int (*pipes_create)(struct rpc_auth *);
103 void (*pipes_destroy)(struct rpc_auth *);
102}; 104};
103 105
104struct rpc_credops { 106struct rpc_credops {
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