From 49b04866bcfb883cad6f3f9783dbf843b48e6b51 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Thu, 13 Feb 2003 02:26:15 -0800 Subject: [PATCH] [PATCH] further rpc_pipefs cleanups... - Only set up pipefs entries for those RPC services that actually need them (for the moment NFS only). Portmap, lockd,... shouldn't need to make upcalls. - Add in missing semaphore in rpc_populate(). - Make inode/dentry variable names in rpc_depopulate/rpc_populate more consistent w.r.t other functions in rpc_pipe.c - Call shrink_dcache_parent() in order to clean up child entries before we rmdir(). --- fs/nfs/inode.c | 1 + include/linux/sunrpc/clnt.h | 1 + net/sunrpc/clnt.c | 35 ++++++++++++++++++++++++++++------- net/sunrpc/rpc_pipe.c | 30 ++++++++++++++++++------------ 4 files changed, 48 insertions(+), 19 deletions(-) diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 78d1f895740f..ea39aa340908 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -93,6 +93,7 @@ struct rpc_program nfs_program = { .nrvers = sizeof(nfs_version) / sizeof(nfs_version[0]), .version = nfs_version, .stats = &nfs_rpcstat, + .pipe_dir_name = "/nfs", }; static inline unsigned long diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index 26a73231ad16..99d57fec03a9 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h @@ -79,6 +79,7 @@ struct rpc_program { unsigned int nrvers; /* number of versions */ struct rpc_version ** version; /* version array */ struct rpc_stat * stats; /* statistics */ + char * pipe_dir_name; /* path to rpc_pipefs dir */ }; struct rpc_version { diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index f0da5234b109..d57c24e010a6 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -63,6 +63,32 @@ static u32 * call_header(struct rpc_task *task); static u32 * call_verify(struct rpc_task *task); +static int +rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name) +{ + static uint32_t clntid; + int maxlen = sizeof(clnt->cl_pathname); + int error; + + if (dir_name == NULL) + return 0; + for (;;) { + snprintf(clnt->cl_pathname, sizeof(clnt->cl_pathname), + "%s/clnt%x", dir_name, + (unsigned int)clntid++); + clnt->cl_pathname[sizeof(clnt->cl_pathname) - 1] = '\0'; + clnt->cl_dentry = rpc_mkdir(clnt->cl_pathname, clnt); + if (!IS_ERR(clnt->cl_dentry)) + return 0; + error = PTR_ERR(clnt->cl_dentry); + if (error != -EEXIST) { + printk(KERN_INFO "RPC: Couldn't create pipefs entry %s, error %d\n", + clnt->cl_pathname, error); + return error; + } + } +} + /* * Create an RPC client * FIXME: This should also take a flags argument (as in task->tk_flags). @@ -109,14 +135,9 @@ rpc_create_client(struct rpc_xprt *xprt, char *servname, rpc_init_rtt(&clnt->cl_rtt, xprt->timeout.to_initval); - snprintf(clnt->cl_pathname, sizeof(clnt->cl_pathname), - "/%s/clnt%p", clnt->cl_protname, clnt); - clnt->cl_dentry = rpc_mkdir(clnt->cl_pathname, clnt); - if (IS_ERR(clnt->cl_dentry)) { - printk(KERN_INFO "RPC: Couldn't create pipefs entry %s\n", - clnt->cl_pathname); + if (rpc_setup_pipedir(clnt, program->pipe_dir_name) < 0) goto out_no_path; - } + if (!rpcauth_create(flavor, clnt)) { printk(KERN_INFO "RPC: Couldn't create auth handle (flavor %u)\n", flavor); diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index f46ddb41c49f..b014047650a9 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -476,15 +476,16 @@ rpc_get_inode(struct super_block *sb, int mode) * FIXME: This probably has races. */ static void -rpc_depopulate(struct dentry *dir) +rpc_depopulate(struct dentry *parent) { + struct inode *dir = parent->d_inode; LIST_HEAD(head); struct list_head *pos, *next; struct dentry *dentry; - down(&dir->d_inode->i_sem); + down(&dir->i_sem); spin_lock(&dcache_lock); - list_for_each_safe(pos, next, &dir->d_subdirs) { + list_for_each_safe(pos, next, &parent->d_subdirs) { dentry = list_entry(pos, struct dentry, d_child); if (!d_unhashed(dentry)) { dget_locked(dentry); @@ -499,32 +500,34 @@ rpc_depopulate(struct dentry *dir) __d_drop(dentry); if (dentry->d_inode) { rpc_inode_setowner(dentry->d_inode, NULL); - simple_unlink(dir->d_inode, dentry); + simple_unlink(dir, dentry); } dput(dentry); } - up(&dir->d_inode->i_sem); + up(&dir->i_sem); } static int -rpc_populate(struct dentry *dir, +rpc_populate(struct dentry *parent, struct rpc_filelist *files, int start, int eof) { - void *private = RPC_I(dir->d_inode)->private; + struct inode *inode, *dir = parent->d_inode; + void *private = RPC_I(dir)->private; struct qstr name; struct dentry *dentry; - struct inode *inode; int mode, i; + + down(&dir->i_sem); for (i = start; i < eof; i++) { name.name = files[i].name; name.len = strlen(name.name); name.hash = full_name_hash(name.name, name.len); - dentry = d_alloc(dir, &name); + dentry = d_alloc(parent, &name); if (!dentry) goto out_bad; mode = files[i].mode; - inode = rpc_get_inode(dir->d_inode->i_sb, mode); + inode = rpc_get_inode(dir->i_sb, mode); if (!inode) { dput(dentry); goto out_bad; @@ -535,13 +538,15 @@ rpc_populate(struct dentry *dir, if (private) rpc_inode_setowner(inode, private); if (S_ISDIR(mode)) - dir->d_inode->i_nlink++; + dir->i_nlink++; d_add(dentry, inode); } + up(&dir->i_sem); return 0; out_bad: + up(&dir->i_sem); printk(KERN_WARNING "%s: %s failed to populate directory %s\n", - __FILE__, __FUNCTION__, dir->d_name.name); + __FILE__, __FUNCTION__, parent->d_name.name); return -ENOMEM; } @@ -570,6 +575,7 @@ __rpc_rmdir(struct inode *dir, struct dentry *dentry) { int error; + shrink_dcache_parent(dentry); rpc_inode_setowner(dentry->d_inode, NULL); if ((error = simple_rmdir(dir, dentry)) != 0) return error; -- 2.39.5