diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-20 13:44:49 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-20 13:44:49 -0500 |
commit | 5428154827c2bf7cfdc9dab60db1e0eaa57c027a (patch) | |
tree | ec2e6c9119ad76cad353a50da2be3ac71adbf54d | |
parent | a9a801787a761616589a6526d7a29c13f4deb3d8 (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.h | 1 | ||||
-rw-r--r-- | include/linux/sunrpc/rpc_pipe_fs.h | 2 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 24 | ||||
-rw-r--r-- | net/sunrpc/rpc_pipe.c | 22 |
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 *); | |||
45 | extern int rpc_rmdir(char *); | 45 | extern int rpc_rmdir(char *); |
46 | extern struct dentry *rpc_mkpipe(char *, void *, struct rpc_pipe_ops *, int flags); | 46 | extern struct dentry *rpc_mkpipe(char *, void *, struct rpc_pipe_ops *, int flags); |
47 | extern int rpc_unlink(char *); | 47 | extern int rpc_unlink(char *); |
48 | extern struct vfsmount *rpc_get_mount(void); | ||
49 | extern 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 | ||
177 | out_no_auth: | 185 | out_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 | } | ||
179 | out_no_path: | 191 | out_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; |
251 | out_no_clnt: | 265 | out_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) | |||
318 | out_free: | 332 | out_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 | ||
438 | static int | 438 | struct vfsmount *rpc_get_mount(void) |
439 | rpc_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 | ||
444 | static void | 448 | void rpc_put_mount(void) |
445 | rpc_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; |
599 | out_err: | 602 | out_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 | } |