Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Stanislav Kinsbursky and committed by
Trond Myklebust
80df9d20 70abc49b

+92 -10
+2
include/linux/sunrpc/auth.h
··· 99 99 100 100 struct rpc_cred * (*lookup_cred)(struct rpc_auth *, struct auth_cred *, int); 101 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 106 struct rpc_credops {
+7 -3
net/sunrpc/auth_gss/auth_gss.c
··· 762 762 struct gss_auth *gss_auth; 763 763 764 764 gss_auth = container_of(auth, struct gss_auth, rpc_auth); 765 - rpc_unlink(gss_auth->pipe[0]->dentry); 766 - rpc_unlink(gss_auth->pipe[1]->dentry); 765 + if (gss_auth->pipe[0]->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 771 static int gss_pipes_dentries_create(struct rpc_auth *auth) ··· 1616 1614 .create = gss_create, 1617 1615 .destroy = gss_destroy, 1618 1616 .lookup_cred = gss_lookup_cred, 1619 - .crcreate = gss_create_cred 1617 + .crcreate = gss_create_cred, 1618 + .pipes_create = gss_pipes_dentries_create, 1619 + .pipes_destroy = gss_pipes_dentries_destroy, 1620 1620 }; 1621 1621 1622 1622 static const struct rpc_credops gss_credops = {
+68 -1
net/sunrpc/clnt.c
··· 98 98 99 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 104 rpc_remove_client_dir(clnt->cl_path.dentry); 105 + } 103 106 clnt->cl_path.dentry = NULL; 104 107 } 105 108 ··· 182 179 } 183 180 clnt->cl_path = path; 184 181 return 0; 182 + } 183 + 184 + static int __rpc_pipefs_event(struct rpc_clnt *clnt, unsigned long event, 185 + struct super_block *sb) 186 + { 187 + struct dentry *dentry; 188 + int err = 0; 189 + 190 + switch (event) { 191 + case RPC_PIPEFS_MOUNT: 192 + if (clnt->cl_program->pipe_dir_name == NULL) 193 + break; 194 + dentry = rpc_setup_pipedir_sb(sb, clnt, 195 + clnt->cl_program->pipe_dir_name); 196 + BUG_ON(dentry == NULL); 197 + if (IS_ERR(dentry)) 198 + return PTR_ERR(dentry); 199 + clnt->cl_path.dentry = dentry; 200 + if (clnt->cl_auth->au_ops->pipes_create) { 201 + err = clnt->cl_auth->au_ops->pipes_create(clnt->cl_auth); 202 + if (err) 203 + __rpc_clnt_remove_pipedir(clnt); 204 + } 205 + break; 206 + case RPC_PIPEFS_UMOUNT: 207 + __rpc_clnt_remove_pipedir(clnt); 208 + break; 209 + default: 210 + printk(KERN_ERR "%s: unknown event: %ld\n", __func__, event); 211 + return -ENOTSUPP; 212 + } 213 + return err; 214 + } 215 + 216 + static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event, 217 + void *ptr) 218 + { 219 + struct super_block *sb = ptr; 220 + struct rpc_clnt *clnt; 221 + int error = 0; 222 + struct sunrpc_net *sn = net_generic(sb->s_fs_info, sunrpc_net_id); 223 + 224 + spin_lock(&sn->rpc_client_lock); 225 + list_for_each_entry(clnt, &sn->all_clients, cl_clients) { 226 + error = __rpc_pipefs_event(clnt, event, sb); 227 + if (error) 228 + break; 229 + } 230 + spin_unlock(&sn->rpc_client_lock); 231 + return error; 232 + } 233 + 234 + static struct notifier_block rpc_clients_block = { 235 + .notifier_call = rpc_pipefs_event, 236 + }; 237 + 238 + int rpc_clients_notifier_register(void) 239 + { 240 + return rpc_pipefs_notifier_register(&rpc_clients_block); 241 + } 242 + 243 + void rpc_clients_notifier_unregister(void) 244 + { 245 + return rpc_pipefs_notifier_unregister(&rpc_clients_block); 185 246 } 186 247 187 248 static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt)
+13 -6
net/sunrpc/rpc_pipe.c
··· 937 937 938 938 /** 939 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 942 int rpc_remove_client_dir(struct dentry *dentry) 943 943 { ··· 1188 1188 init_once); 1189 1189 if (!rpc_inode_cachep) 1190 1190 return -ENOMEM; 1191 + err = rpc_clients_notifier_register(); 1192 + if (err) 1193 + goto err_notifier; 1191 1194 err = register_filesystem(&rpc_pipe_fs_type); 1192 - if (err) { 1193 - kmem_cache_destroy(rpc_inode_cachep); 1194 - return err; 1195 - } 1196 - 1195 + if (err) 1196 + goto err_register; 1197 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 1206 void unregister_rpc_pipefs(void) 1201 1207 { 1208 + rpc_clients_notifier_unregister(); 1202 1209 kmem_cache_destroy(rpc_inode_cachep); 1203 1210 unregister_filesystem(&rpc_pipe_fs_type); 1204 1211 }
+2
net/sunrpc/sunrpc.h
··· 47 47 struct page *headpage, unsigned long headoffset, 48 48 struct page *tailpage, unsigned long tailoffset); 49 49 50 + int rpc_clients_notifier_register(void); 51 + void rpc_clients_notifier_unregister(void); 50 52 #endif /* _NET_SUNRPC_SUNRPC_H */ 51 53