mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
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>
This commit is contained in:
parent
c239d83b99
commit
0157d021d2
@ -622,7 +622,7 @@ static struct rpc_program cb_program = {
|
|||||||
.nrvers = ARRAY_SIZE(nfs_cb_version),
|
.nrvers = ARRAY_SIZE(nfs_cb_version),
|
||||||
.version = nfs_cb_version,
|
.version = nfs_cb_version,
|
||||||
.stats = &cb_stats,
|
.stats = &cb_stats,
|
||||||
.pipe_dir_name = "/nfsd4_cb",
|
.pipe_dir_name = "nfsd4_cb",
|
||||||
};
|
};
|
||||||
|
|
||||||
static int max_cb_time(void)
|
static int max_cb_time(void)
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#define NFS_MNT_VERSION 1
|
#define NFS_MNT_VERSION 1
|
||||||
#define NFS_MNT3_VERSION 3
|
#define NFS_MNT3_VERSION 3
|
||||||
|
|
||||||
#define NFS_PIPE_DIRNAME "/nfs"
|
#define NFS_PIPE_DIRNAME "nfs"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NFS stats. The good thing with these values is that NFSv3 errors are
|
* NFS stats. The good thing with these values is that NFSv3 errors are
|
||||||
|
@ -93,52 +93,89 @@ static void rpc_unregister_client(struct rpc_clnt *clnt)
|
|||||||
spin_unlock(&rpc_client_lock);
|
spin_unlock(&rpc_client_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void __rpc_clnt_remove_pipedir(struct rpc_clnt *clnt)
|
||||||
rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
|
{
|
||||||
|
if (clnt->cl_path.dentry)
|
||||||
|
rpc_remove_client_dir(clnt->cl_path.dentry);
|
||||||
|
clnt->cl_path.dentry = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rpc_clnt_remove_pipedir(struct rpc_clnt *clnt)
|
||||||
|
{
|
||||||
|
struct super_block *pipefs_sb;
|
||||||
|
int put_mnt = 0;
|
||||||
|
|
||||||
|
pipefs_sb = rpc_get_sb_net(clnt->cl_xprt->xprt_net);
|
||||||
|
if (pipefs_sb) {
|
||||||
|
if (clnt->cl_path.dentry)
|
||||||
|
put_mnt = 1;
|
||||||
|
__rpc_clnt_remove_pipedir(clnt);
|
||||||
|
rpc_put_sb_net(clnt->cl_xprt->xprt_net);
|
||||||
|
}
|
||||||
|
if (put_mnt)
|
||||||
|
rpc_put_mount();
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb,
|
||||||
|
struct rpc_clnt *clnt, char *dir_name)
|
||||||
{
|
{
|
||||||
static uint32_t clntid;
|
static uint32_t clntid;
|
||||||
struct path path, dir;
|
|
||||||
char name[15];
|
char name[15];
|
||||||
struct qstr q = {
|
struct qstr q = {
|
||||||
.name = name,
|
.name = name,
|
||||||
};
|
};
|
||||||
|
struct dentry *dir, *dentry;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
dir = rpc_d_lookup_sb(sb, dir_name);
|
||||||
|
if (dir == NULL)
|
||||||
|
return dir;
|
||||||
|
for (;;) {
|
||||||
|
q.len = snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++);
|
||||||
|
name[sizeof(name) - 1] = '\0';
|
||||||
|
q.hash = full_name_hash(q.name, q.len);
|
||||||
|
dentry = rpc_create_client_dir(dir, &q, clnt);
|
||||||
|
if (!IS_ERR(dentry))
|
||||||
|
break;
|
||||||
|
error = PTR_ERR(dentry);
|
||||||
|
if (error != -EEXIST) {
|
||||||
|
printk(KERN_INFO "RPC: Couldn't create pipefs entry"
|
||||||
|
" %s/%s, error %d\n",
|
||||||
|
dir_name, name, error);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dput(dir);
|
||||||
|
return dentry;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
|
||||||
|
{
|
||||||
|
struct super_block *pipefs_sb;
|
||||||
|
struct path path;
|
||||||
|
|
||||||
clnt->cl_path.mnt = ERR_PTR(-ENOENT);
|
clnt->cl_path.mnt = ERR_PTR(-ENOENT);
|
||||||
clnt->cl_path.dentry = ERR_PTR(-ENOENT);
|
clnt->cl_path.dentry = NULL;
|
||||||
if (dir_name == NULL)
|
if (dir_name == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
path.mnt = rpc_get_mount();
|
path.mnt = rpc_get_mount();
|
||||||
if (IS_ERR(path.mnt))
|
if (IS_ERR(path.mnt))
|
||||||
return PTR_ERR(path.mnt);
|
return PTR_ERR(path.mnt);
|
||||||
error = vfs_path_lookup(path.mnt->mnt_root, path.mnt, dir_name, 0, &dir);
|
pipefs_sb = rpc_get_sb_net(clnt->cl_xprt->xprt_net);
|
||||||
if (error)
|
if (!pipefs_sb) {
|
||||||
goto err;
|
rpc_put_mount();
|
||||||
|
return -ENOENT;
|
||||||
for (;;) {
|
}
|
||||||
q.len = snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++);
|
path.dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt, dir_name);
|
||||||
name[sizeof(name) - 1] = '\0';
|
rpc_put_sb_net(clnt->cl_xprt->xprt_net);
|
||||||
q.hash = full_name_hash(q.name, q.len);
|
if (IS_ERR(path.dentry)) {
|
||||||
path.dentry = rpc_create_client_dir(dir.dentry, &q, clnt);
|
rpc_put_mount();
|
||||||
if (!IS_ERR(path.dentry))
|
return PTR_ERR(path.dentry);
|
||||||
break;
|
|
||||||
error = PTR_ERR(path.dentry);
|
|
||||||
if (error != -EEXIST) {
|
|
||||||
printk(KERN_INFO "RPC: Couldn't create pipefs entry"
|
|
||||||
" %s/%s, error %d\n",
|
|
||||||
dir_name, name, error);
|
|
||||||
goto err_path_put;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
path_put(&dir);
|
|
||||||
clnt->cl_path = path;
|
clnt->cl_path = path;
|
||||||
return 0;
|
return 0;
|
||||||
err_path_put:
|
|
||||||
path_put(&dir);
|
|
||||||
err:
|
|
||||||
rpc_put_mount();
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt)
|
static 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
|
|||||||
return clnt;
|
return clnt;
|
||||||
|
|
||||||
out_no_auth:
|
out_no_auth:
|
||||||
if (!IS_ERR(clnt->cl_path.dentry)) {
|
rpc_clnt_remove_pipedir(clnt);
|
||||||
rpc_remove_client_dir(clnt->cl_path.dentry);
|
|
||||||
rpc_put_mount();
|
|
||||||
}
|
|
||||||
out_no_path:
|
out_no_path:
|
||||||
kfree(clnt->cl_principal);
|
kfree(clnt->cl_principal);
|
||||||
out_no_principal:
|
out_no_principal:
|
||||||
@ -474,10 +508,7 @@ rpc_free_client(struct rpc_clnt *clnt)
|
|||||||
{
|
{
|
||||||
dprintk("RPC: destroying %s client for %s\n",
|
dprintk("RPC: destroying %s client for %s\n",
|
||||||
clnt->cl_protname, clnt->cl_server);
|
clnt->cl_protname, clnt->cl_server);
|
||||||
if (!IS_ERR(clnt->cl_path.dentry)) {
|
rpc_clnt_remove_pipedir(clnt);
|
||||||
rpc_remove_client_dir(clnt->cl_path.dentry);
|
|
||||||
rpc_put_mount();
|
|
||||||
}
|
|
||||||
if (clnt->cl_parent != clnt) {
|
if (clnt->cl_parent != clnt) {
|
||||||
rpc_release_client(clnt->cl_parent);
|
rpc_release_client(clnt->cl_parent);
|
||||||
goto out_free;
|
goto out_free;
|
||||||
|
Loading…
Reference in New Issue
Block a user