mirror of https://gitee.com/openkylin/linux.git
SUNRPC: Fix a 'Busy inodes' error in rpc_pipefs
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
parent
a9a801787a
commit
5428154827
|
@ -60,6 +60,7 @@ struct rpc_clnt {
|
||||||
int cl_nodelen; /* nodename length */
|
int cl_nodelen; /* nodename length */
|
||||||
char cl_nodename[UNX_MAXNODENAME];
|
char cl_nodename[UNX_MAXNODENAME];
|
||||||
char cl_pathname[30];/* Path in rpc_pipe_fs */
|
char cl_pathname[30];/* Path in rpc_pipe_fs */
|
||||||
|
struct vfsmount * cl_vfsmnt;
|
||||||
struct dentry * cl_dentry; /* inode */
|
struct dentry * cl_dentry; /* inode */
|
||||||
struct rpc_clnt * cl_parent; /* Points to parent of clones */
|
struct rpc_clnt * cl_parent; /* Points to parent of clones */
|
||||||
struct rpc_rtt cl_rtt_default;
|
struct rpc_rtt cl_rtt_default;
|
||||||
|
|
|
@ -45,6 +45,8 @@ extern struct dentry *rpc_mkdir(char *, struct rpc_clnt *);
|
||||||
extern int rpc_rmdir(char *);
|
extern int rpc_rmdir(char *);
|
||||||
extern struct dentry *rpc_mkpipe(char *, void *, struct rpc_pipe_ops *, int flags);
|
extern struct dentry *rpc_mkpipe(char *, void *, struct rpc_pipe_ops *, int flags);
|
||||||
extern int rpc_unlink(char *);
|
extern int rpc_unlink(char *);
|
||||||
|
extern struct vfsmount *rpc_get_mount(void);
|
||||||
|
extern void rpc_put_mount(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -70,8 +70,15 @@ rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
|
||||||
static uint32_t clntid;
|
static uint32_t clntid;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
clnt->cl_vfsmnt = ERR_PTR(-ENOENT);
|
||||||
|
clnt->cl_dentry = ERR_PTR(-ENOENT);
|
||||||
if (dir_name == NULL)
|
if (dir_name == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
clnt->cl_vfsmnt = rpc_get_mount();
|
||||||
|
if (IS_ERR(clnt->cl_vfsmnt))
|
||||||
|
return PTR_ERR(clnt->cl_vfsmnt);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
snprintf(clnt->cl_pathname, sizeof(clnt->cl_pathname),
|
snprintf(clnt->cl_pathname, sizeof(clnt->cl_pathname),
|
||||||
"%s/clnt%x", dir_name,
|
"%s/clnt%x", dir_name,
|
||||||
|
@ -84,6 +91,7 @@ rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
|
||||||
if (error != -EEXIST) {
|
if (error != -EEXIST) {
|
||||||
printk(KERN_INFO "RPC: Couldn't create pipefs entry %s, error %d\n",
|
printk(KERN_INFO "RPC: Couldn't create pipefs entry %s, error %d\n",
|
||||||
clnt->cl_pathname, error);
|
clnt->cl_pathname, error);
|
||||||
|
rpc_put_mount();
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -175,7 +183,11 @@ rpc_new_client(struct rpc_xprt *xprt, char *servname,
|
||||||
return clnt;
|
return clnt;
|
||||||
|
|
||||||
out_no_auth:
|
out_no_auth:
|
||||||
rpc_rmdir(clnt->cl_pathname);
|
if (!IS_ERR(clnt->cl_dentry)) {
|
||||||
|
rpc_rmdir(clnt->cl_pathname);
|
||||||
|
dput(clnt->cl_dentry);
|
||||||
|
rpc_put_mount();
|
||||||
|
}
|
||||||
out_no_path:
|
out_no_path:
|
||||||
if (clnt->cl_server != clnt->cl_inline_name)
|
if (clnt->cl_server != clnt->cl_inline_name)
|
||||||
kfree(clnt->cl_server);
|
kfree(clnt->cl_server);
|
||||||
|
@ -240,13 +252,15 @@ rpc_clone_client(struct rpc_clnt *clnt)
|
||||||
new->cl_autobind = 0;
|
new->cl_autobind = 0;
|
||||||
new->cl_oneshot = 0;
|
new->cl_oneshot = 0;
|
||||||
new->cl_dead = 0;
|
new->cl_dead = 0;
|
||||||
dget(new->cl_dentry);
|
if (!IS_ERR(new->cl_dentry)) {
|
||||||
|
dget(new->cl_dentry);
|
||||||
|
rpc_get_mount();
|
||||||
|
}
|
||||||
rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
|
rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
|
||||||
if (new->cl_auth)
|
if (new->cl_auth)
|
||||||
atomic_inc(&new->cl_auth->au_count);
|
atomic_inc(&new->cl_auth->au_count);
|
||||||
new->cl_pmap = &new->cl_pmap_default;
|
new->cl_pmap = &new->cl_pmap_default;
|
||||||
new->cl_metrics = rpc_alloc_iostats(clnt);
|
new->cl_metrics = rpc_alloc_iostats(clnt);
|
||||||
rpc_init_wait_queue(&new->cl_pmap_default.pm_bindwait, "bindwait");
|
|
||||||
return new;
|
return new;
|
||||||
out_no_clnt:
|
out_no_clnt:
|
||||||
printk(KERN_INFO "RPC: out of memory in %s\n", __FUNCTION__);
|
printk(KERN_INFO "RPC: out of memory in %s\n", __FUNCTION__);
|
||||||
|
@ -318,8 +332,10 @@ rpc_destroy_client(struct rpc_clnt *clnt)
|
||||||
out_free:
|
out_free:
|
||||||
rpc_free_iostats(clnt->cl_metrics);
|
rpc_free_iostats(clnt->cl_metrics);
|
||||||
clnt->cl_metrics = NULL;
|
clnt->cl_metrics = NULL;
|
||||||
if (clnt->cl_dentry)
|
if (!IS_ERR(clnt->cl_dentry)) {
|
||||||
dput(clnt->cl_dentry);
|
dput(clnt->cl_dentry);
|
||||||
|
rpc_put_mount();
|
||||||
|
}
|
||||||
kfree(clnt);
|
kfree(clnt);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -435,14 +435,17 @@ static struct rpc_filelist authfiles[] = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
struct vfsmount *rpc_get_mount(void)
|
||||||
rpc_get_mount(void)
|
|
||||||
{
|
{
|
||||||
return simple_pin_fs("rpc_pipefs", &rpc_mount, &rpc_mount_count);
|
int err;
|
||||||
|
|
||||||
|
err = simple_pin_fs("rpc_pipefs", &rpc_mount, &rpc_mount_count);
|
||||||
|
if (err != 0)
|
||||||
|
return ERR_PTR(err);
|
||||||
|
return rpc_mount;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void rpc_put_mount(void)
|
||||||
rpc_put_mount(void)
|
|
||||||
{
|
{
|
||||||
simple_release_fs(&rpc_mount, &rpc_mount_count);
|
simple_release_fs(&rpc_mount, &rpc_mount_count);
|
||||||
}
|
}
|
||||||
|
@ -452,12 +455,13 @@ rpc_lookup_parent(char *path, struct nameidata *nd)
|
||||||
{
|
{
|
||||||
if (path[0] == '\0')
|
if (path[0] == '\0')
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
if (rpc_get_mount()) {
|
nd->mnt = rpc_get_mount();
|
||||||
|
if (IS_ERR(nd->mnt)) {
|
||||||
printk(KERN_WARNING "%s: %s failed to mount "
|
printk(KERN_WARNING "%s: %s failed to mount "
|
||||||
"pseudofilesystem \n", __FILE__, __FUNCTION__);
|
"pseudofilesystem \n", __FILE__, __FUNCTION__);
|
||||||
return -ENODEV;
|
return PTR_ERR(nd->mnt);
|
||||||
}
|
}
|
||||||
nd->mnt = mntget(rpc_mount);
|
mntget(nd->mnt);
|
||||||
nd->dentry = dget(rpc_mount->mnt_root);
|
nd->dentry = dget(rpc_mount->mnt_root);
|
||||||
nd->last_type = LAST_ROOT;
|
nd->last_type = LAST_ROOT;
|
||||||
nd->flags = LOOKUP_PARENT;
|
nd->flags = LOOKUP_PARENT;
|
||||||
|
@ -594,7 +598,6 @@ __rpc_mkdir(struct inode *dir, struct dentry *dentry)
|
||||||
d_instantiate(dentry, inode);
|
d_instantiate(dentry, inode);
|
||||||
dir->i_nlink++;
|
dir->i_nlink++;
|
||||||
inode_dir_notify(dir, DN_CREATE);
|
inode_dir_notify(dir, DN_CREATE);
|
||||||
rpc_get_mount();
|
|
||||||
return 0;
|
return 0;
|
||||||
out_err:
|
out_err:
|
||||||
printk(KERN_WARNING "%s: %s failed to allocate inode for dentry %s\n",
|
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)
|
||||||
if (!error) {
|
if (!error) {
|
||||||
inode_dir_notify(dir, DN_DELETE);
|
inode_dir_notify(dir, DN_DELETE);
|
||||||
d_drop(dentry);
|
d_drop(dentry);
|
||||||
rpc_put_mount();
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue