aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-03-20 13:44:49 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-03-20 13:44:49 -0500
commit5428154827c2bf7cfdc9dab60db1e0eaa57c027a (patch)
treeec2e6c9119ad76cad353a50da2be3ac71adbf54d
parenta9a801787a761616589a6526d7a29c13f4deb3d8 (diff)
SUNRPC: Fix a 'Busy inodes' error in rpc_pipefs
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--include/linux/sunrpc/clnt.h1
-rw-r--r--include/linux/sunrpc/rpc_pipe_fs.h2
-rw-r--r--net/sunrpc/clnt.c24
-rw-r--r--net/sunrpc/rpc_pipe.c22
4 files changed, 35 insertions, 14 deletions
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index e37c06128e51..8fe9f35eba31 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -60,6 +60,7 @@ struct rpc_clnt {
60 int cl_nodelen; /* nodename length */ 60 int cl_nodelen; /* nodename length */
61 char cl_nodename[UNX_MAXNODENAME]; 61 char cl_nodename[UNX_MAXNODENAME];
62 char cl_pathname[30];/* Path in rpc_pipe_fs */ 62 char cl_pathname[30];/* Path in rpc_pipe_fs */
63 struct vfsmount * cl_vfsmnt;
63 struct dentry * cl_dentry; /* inode */ 64 struct dentry * cl_dentry; /* inode */
64 struct rpc_clnt * cl_parent; /* Points to parent of clones */ 65 struct rpc_clnt * cl_parent; /* Points to parent of clones */
65 struct rpc_rtt cl_rtt_default; 66 struct rpc_rtt cl_rtt_default;
diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h
index 63929349571f..2c2189cb30aa 100644
--- a/include/linux/sunrpc/rpc_pipe_fs.h
+++ b/include/linux/sunrpc/rpc_pipe_fs.h
@@ -45,6 +45,8 @@ extern struct dentry *rpc_mkdir(char *, struct rpc_clnt *);
45extern int rpc_rmdir(char *); 45extern int rpc_rmdir(char *);
46extern struct dentry *rpc_mkpipe(char *, void *, struct rpc_pipe_ops *, int flags); 46extern struct dentry *rpc_mkpipe(char *, void *, struct rpc_pipe_ops *, int flags);
47extern int rpc_unlink(char *); 47extern int rpc_unlink(char *);
48extern struct vfsmount *rpc_get_mount(void);
49extern void rpc_put_mount(void);
48 50
49#endif 51#endif
50#endif 52#endif
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 0bb23e8e9d0c..9f775302d1df 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -70,8 +70,15 @@ rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
70 static uint32_t clntid; 70 static uint32_t clntid;
71 int error; 71 int error;
72 72
73 clnt->cl_vfsmnt = ERR_PTR(-ENOENT);
74 clnt->cl_dentry = ERR_PTR(-ENOENT);
73 if (dir_name == NULL) 75 if (dir_name == NULL)
74 return 0; 76 return 0;
77
78 clnt->cl_vfsmnt = rpc_get_mount();
79 if (IS_ERR(clnt->cl_vfsmnt))
80 return PTR_ERR(clnt->cl_vfsmnt);
81
75 for (;;) { 82 for (;;) {
76 snprintf(clnt->cl_pathname, sizeof(clnt->cl_pathname), 83 snprintf(clnt->cl_pathname, sizeof(clnt->cl_pathname),
77 "%s/clnt%x", dir_name, 84 "%s/clnt%x", dir_name,
@@ -84,6 +91,7 @@ rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
84 if (error != -EEXIST) { 91 if (error != -EEXIST) {
85 printk(KERN_INFO "RPC: Couldn't create pipefs entry %s, error %d\n", 92 printk(KERN_INFO "RPC: Couldn't create pipefs entry %s, error %d\n",
86 clnt->cl_pathname, error); 93 clnt->cl_pathname, error);
94 rpc_put_mount();
87 return error; 95 return error;
88 } 96 }
89 } 97 }
@@ -175,7 +183,11 @@ rpc_new_client(struct rpc_xprt *xprt, char *servname,
175 return clnt; 183 return clnt;
176 184
177out_no_auth: 185out_no_auth:
178 rpc_rmdir(clnt->cl_pathname); 186 if (!IS_ERR(clnt->cl_dentry)) {
187 rpc_rmdir(clnt->cl_pathname);
188 dput(clnt->cl_dentry);
189 rpc_put_mount();
190 }
179out_no_path: 191out_no_path:
180 if (clnt->cl_server != clnt->cl_inline_name) 192 if (clnt->cl_server != clnt->cl_inline_name)
181 kfree(clnt->cl_server); 193 kfree(clnt->cl_server);
@@ -240,13 +252,15 @@ rpc_clone_client(struct rpc_clnt *clnt)
240 new->cl_autobind = 0; 252 new->cl_autobind = 0;
241 new->cl_oneshot = 0; 253 new->cl_oneshot = 0;
242 new->cl_dead = 0; 254 new->cl_dead = 0;
243 dget(new->cl_dentry); 255 if (!IS_ERR(new->cl_dentry)) {
256 dget(new->cl_dentry);
257 rpc_get_mount();
258 }
244 rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); 259 rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
245 if (new->cl_auth) 260 if (new->cl_auth)
246 atomic_inc(&new->cl_auth->au_count); 261 atomic_inc(&new->cl_auth->au_count);
247 new->cl_pmap = &new->cl_pmap_default; 262 new->cl_pmap = &new->cl_pmap_default;
248 new->cl_metrics = rpc_alloc_iostats(clnt); 263 new->cl_metrics = rpc_alloc_iostats(clnt);
249 rpc_init_wait_queue(&new->cl_pmap_default.pm_bindwait, "bindwait");
250 return new; 264 return new;
251out_no_clnt: 265out_no_clnt:
252 printk(KERN_INFO "RPC: out of memory in %s\n", __FUNCTION__); 266 printk(KERN_INFO "RPC: out of memory in %s\n", __FUNCTION__);
@@ -318,8 +332,10 @@ rpc_destroy_client(struct rpc_clnt *clnt)
318out_free: 332out_free:
319 rpc_free_iostats(clnt->cl_metrics); 333 rpc_free_iostats(clnt->cl_metrics);
320 clnt->cl_metrics = NULL; 334 clnt->cl_metrics = NULL;
321 if (clnt->cl_dentry) 335 if (!IS_ERR(clnt->cl_dentry)) {
322 dput(clnt->cl_dentry); 336 dput(clnt->cl_dentry);
337 rpc_put_mount();
338 }
323 kfree(clnt); 339 kfree(clnt);
324 return 0; 340 return 0;
325} 341}
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 72b22172f0af..391d2bfc71aa 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -435,14 +435,17 @@ static struct rpc_filelist authfiles[] = {
435 }, 435 },
436}; 436};
437 437
438static int 438struct vfsmount *rpc_get_mount(void)
439rpc_get_mount(void)
440{ 439{
441 return simple_pin_fs("rpc_pipefs", &rpc_mount, &rpc_mount_count); 440 int err;
441
442 err = simple_pin_fs("rpc_pipefs", &rpc_mount, &rpc_mount_count);
443 if (err != 0)
444 return ERR_PTR(err);
445 return rpc_mount;
442} 446}
443 447
444static void 448void rpc_put_mount(void)
445rpc_put_mount(void)
446{ 449{
447 simple_release_fs(&rpc_mount, &rpc_mount_count); 450 simple_release_fs(&rpc_mount, &rpc_mount_count);
448} 451}
@@ -452,12 +455,13 @@ rpc_lookup_parent(char *path, struct nameidata *nd)
452{ 455{
453 if (path[0] == '\0') 456 if (path[0] == '\0')
454 return -ENOENT; 457 return -ENOENT;
455 if (rpc_get_mount()) { 458 nd->mnt = rpc_get_mount();
459 if (IS_ERR(nd->mnt)) {
456 printk(KERN_WARNING "%s: %s failed to mount " 460 printk(KERN_WARNING "%s: %s failed to mount "
457 "pseudofilesystem \n", __FILE__, __FUNCTION__); 461 "pseudofilesystem \n", __FILE__, __FUNCTION__);
458 return -ENODEV; 462 return PTR_ERR(nd->mnt);
459 } 463 }
460 nd->mnt = mntget(rpc_mount); 464 mntget(nd->mnt);
461 nd->dentry = dget(rpc_mount->mnt_root); 465 nd->dentry = dget(rpc_mount->mnt_root);
462 nd->last_type = LAST_ROOT; 466 nd->last_type = LAST_ROOT;
463 nd->flags = LOOKUP_PARENT; 467 nd->flags = LOOKUP_PARENT;
@@ -594,7 +598,6 @@ __rpc_mkdir(struct inode *dir, struct dentry *dentry)
594 d_instantiate(dentry, inode); 598 d_instantiate(dentry, inode);
595 dir->i_nlink++; 599 dir->i_nlink++;
596 inode_dir_notify(dir, DN_CREATE); 600 inode_dir_notify(dir, DN_CREATE);
597 rpc_get_mount();
598 return 0; 601 return 0;
599out_err: 602out_err:
600 printk(KERN_WARNING "%s: %s failed to allocate inode for dentry %s\n", 603 printk(KERN_WARNING "%s: %s failed to allocate inode for dentry %s\n",
@@ -615,7 +618,6 @@ __rpc_rmdir(struct inode *dir, struct dentry *dentry)
615 if (!error) { 618 if (!error) {
616 inode_dir_notify(dir, DN_DELETE); 619 inode_dir_notify(dir, DN_DELETE);
617 d_drop(dentry); 620 d_drop(dentry);
618 rpc_put_mount();
619 } 621 }
620 return 0; 622 return 0;
621} 623}