aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorStanislav Kinsbursky <skinsbursky@parallels.com>2012-01-11 10:18:01 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-01-31 18:20:25 -0500
commit0157d021d23a087eecfa830502f81cfe843f0d16 (patch)
treee1e1e7e75146c7d234f552a0ffc6b0124827fe6f /net
parentc239d83b9921b8a8005a3bcd23000cfe18acf5c2 (diff)
SUNRPC: handle RPC client pipefs dentries by network namespace aware routines
v2: 1) "Over-put" of PipeFS mount point fixed. Fix is ugly, but allows to bisect the patch set. And it will be removed later in the series. This patch makes RPC clients PipeFs dentries allocations in it's owner network namespace context. RPC client pipefs dentries creation logic has been changed: 1) Pipefs dentries creation by sb was moved to separated function, which will be used for handling PipeFS mount notification. 2) Initial value of RPC client PipeFS dir dentry is set no NULL now. RPC client pipefs dentries cleanup logic has been changed: 1) Cleanup is done now in separated rpc_remove_pipedir() function, which takes care about pipefs superblock locking. Also this patch removes slashes from cb_program.pipe_dir_name and from NFS_PIPE_DIRNAME to make rpc_d_lookup_sb() work. This doesn't affect vfs_path_lookup() results in nfs4blocklayout_init() since this slash is cutted off anyway in link_path_walk(). 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/clnt.c97
1 files changed, 64 insertions, 33 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index f0268ea7e711..5ef192c1a57c 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -93,52 +93,89 @@ static void rpc_unregister_client(struct rpc_clnt *clnt)
93 spin_unlock(&rpc_client_lock); 93 spin_unlock(&rpc_client_lock);
94} 94}
95 95
96static int 96static void __rpc_clnt_remove_pipedir(struct rpc_clnt *clnt)
97rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name) 97{
98 if (clnt->cl_path.dentry)
99 rpc_remove_client_dir(clnt->cl_path.dentry);
100 clnt->cl_path.dentry = NULL;
101}
102
103static void rpc_clnt_remove_pipedir(struct rpc_clnt *clnt)
104{
105 struct super_block *pipefs_sb;
106 int put_mnt = 0;
107
108 pipefs_sb = rpc_get_sb_net(clnt->cl_xprt->xprt_net);
109 if (pipefs_sb) {
110 if (clnt->cl_path.dentry)
111 put_mnt = 1;
112 __rpc_clnt_remove_pipedir(clnt);
113 rpc_put_sb_net(clnt->cl_xprt->xprt_net);
114 }
115 if (put_mnt)
116 rpc_put_mount();
117}
118
119static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb,
120 struct rpc_clnt *clnt, char *dir_name)
98{ 121{
99 static uint32_t clntid; 122 static uint32_t clntid;
100 struct path path, dir;
101 char name[15]; 123 char name[15];
102 struct qstr q = { 124 struct qstr q = {
103 .name = name, 125 .name = name,
104 }; 126 };
127 struct dentry *dir, *dentry;
105 int error; 128 int error;
106 129
107 clnt->cl_path.mnt = ERR_PTR(-ENOENT); 130 dir = rpc_d_lookup_sb(sb, dir_name);
108 clnt->cl_path.dentry = ERR_PTR(-ENOENT); 131 if (dir == NULL)
109 if (dir_name == NULL) 132 return dir;
110 return 0;
111
112 path.mnt = rpc_get_mount();
113 if (IS_ERR(path.mnt))
114 return PTR_ERR(path.mnt);
115 error = vfs_path_lookup(path.mnt->mnt_root, path.mnt, dir_name, 0, &dir);
116 if (error)
117 goto err;
118
119 for (;;) { 133 for (;;) {
120 q.len = snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++); 134 q.len = snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++);
121 name[sizeof(name) - 1] = '\0'; 135 name[sizeof(name) - 1] = '\0';
122 q.hash = full_name_hash(q.name, q.len); 136 q.hash = full_name_hash(q.name, q.len);
123 path.dentry = rpc_create_client_dir(dir.dentry, &q, clnt); 137 dentry = rpc_create_client_dir(dir, &q, clnt);
124 if (!IS_ERR(path.dentry)) 138 if (!IS_ERR(dentry))
125 break; 139 break;
126 error = PTR_ERR(path.dentry); 140 error = PTR_ERR(dentry);
127 if (error != -EEXIST) { 141 if (error != -EEXIST) {
128 printk(KERN_INFO "RPC: Couldn't create pipefs entry" 142 printk(KERN_INFO "RPC: Couldn't create pipefs entry"
129 " %s/%s, error %d\n", 143 " %s/%s, error %d\n",
130 dir_name, name, error); 144 dir_name, name, error);
131 goto err_path_put; 145 break;
132 } 146 }
133 } 147 }
134 path_put(&dir); 148 dput(dir);
149 return dentry;
150}
151
152static int
153rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
154{
155 struct super_block *pipefs_sb;
156 struct path path;
157
158 clnt->cl_path.mnt = ERR_PTR(-ENOENT);
159 clnt->cl_path.dentry = NULL;
160 if (dir_name == NULL)
161 return 0;
162
163 path.mnt = rpc_get_mount();
164 if (IS_ERR(path.mnt))
165 return PTR_ERR(path.mnt);
166 pipefs_sb = rpc_get_sb_net(clnt->cl_xprt->xprt_net);
167 if (!pipefs_sb) {
168 rpc_put_mount();
169 return -ENOENT;
170 }
171 path.dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt, dir_name);
172 rpc_put_sb_net(clnt->cl_xprt->xprt_net);
173 if (IS_ERR(path.dentry)) {
174 rpc_put_mount();
175 return PTR_ERR(path.dentry);
176 }
135 clnt->cl_path = path; 177 clnt->cl_path = path;
136 return 0; 178 return 0;
137err_path_put:
138 path_put(&dir);
139err:
140 rpc_put_mount();
141 return error;
142} 179}
143 180
144static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt) 181static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt)
@@ -246,10 +283,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
246 return clnt; 283 return clnt;
247 284
248out_no_auth: 285out_no_auth:
249 if (!IS_ERR(clnt->cl_path.dentry)) { 286 rpc_clnt_remove_pipedir(clnt);
250 rpc_remove_client_dir(clnt->cl_path.dentry);
251 rpc_put_mount();
252 }
253out_no_path: 287out_no_path:
254 kfree(clnt->cl_principal); 288 kfree(clnt->cl_principal);
255out_no_principal: 289out_no_principal:
@@ -474,10 +508,7 @@ rpc_free_client(struct rpc_clnt *clnt)
474{ 508{
475 dprintk("RPC: destroying %s client for %s\n", 509 dprintk("RPC: destroying %s client for %s\n",
476 clnt->cl_protname, clnt->cl_server); 510 clnt->cl_protname, clnt->cl_server);
477 if (!IS_ERR(clnt->cl_path.dentry)) { 511 rpc_clnt_remove_pipedir(clnt);
478 rpc_remove_client_dir(clnt->cl_path.dentry);
479 rpc_put_mount();
480 }
481 if (clnt->cl_parent != clnt) { 512 if (clnt->cl_parent != clnt) {
482 rpc_release_client(clnt->cl_parent); 513 rpc_release_client(clnt->cl_parent);
483 goto out_free; 514 goto out_free;