diff options
| -rw-r--r-- | include/linux/sunrpc/auth.h | 2 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 10 | ||||
| -rw-r--r-- | net/sunrpc/clnt.c | 69 | ||||
| -rw-r--r-- | net/sunrpc/rpc_pipe.c | 19 | ||||
| -rw-r--r-- | net/sunrpc/sunrpc.h | 2 |
5 files changed, 92 insertions, 10 deletions
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h index 7874a8a5663..492a36d7282 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 | ||
| 104 | struct rpc_credops { | 106 | struct rpc_credops { |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 1a6fa917351..9da2d837b51 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 | ||
| 769 | static int gss_pipes_dentries_create(struct rpc_auth *auth) | 771 | static 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 | ||
| 1620 | static const struct rpc_credops gss_credops = { | 1624 | static const struct rpc_credops gss_credops = { |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 90e82c5daeb..41707450059 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 | ||
| 99 | static void __rpc_clnt_remove_pipedir(struct rpc_clnt *clnt) | 99 | static 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 | ||
| 187 | static 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 | |||
| 219 | static 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 | |||
| 237 | static struct notifier_block rpc_clients_block = { | ||
| 238 | .notifier_call = rpc_pipefs_event, | ||
| 239 | }; | ||
| 240 | |||
| 241 | int rpc_clients_notifier_register(void) | ||
| 242 | { | ||
| 243 | return rpc_pipefs_notifier_register(&rpc_clients_block); | ||
| 244 | } | ||
| 245 | |||
| 246 | void rpc_clients_notifier_unregister(void) | ||
| 247 | { | ||
| 248 | return rpc_pipefs_notifier_unregister(&rpc_clients_block); | ||
| 249 | } | ||
| 250 | |||
| 184 | static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt) | 251 | static 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 6dd8b96e8df..910de4169a8 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 | */ |
| 942 | int rpc_remove_client_dir(struct dentry *dentry) | 942 | int 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 | |||
| 1199 | err_register: | ||
| 1200 | rpc_clients_notifier_unregister(); | ||
| 1201 | err_notifier: | ||
| 1202 | kmem_cache_destroy(rpc_inode_cachep); | ||
| 1203 | return err; | ||
| 1198 | } | 1204 | } |
| 1199 | 1205 | ||
| 1200 | void unregister_rpc_pipefs(void) | 1206 | void 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 90c292e2738..14c9f6d1c5f 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 | ||
| 50 | int rpc_clients_notifier_register(void); | ||
| 51 | void rpc_clients_notifier_unregister(void); | ||
| 50 | #endif /* _NET_SUNRPC_SUNRPC_H */ | 52 | #endif /* _NET_SUNRPC_SUNRPC_H */ |
| 51 | 53 | ||
