提交 ac6fecee 编写于 作者: T Trond Myklebust

SUNRPC: Clean up rpc_populate/depopulate

Signed-off-by: NTrond Myklebust <Trond.Myklebust@netapp.com>
上级 cfeaa4a3
...@@ -401,7 +401,6 @@ static const struct file_operations rpc_info_operations = { ...@@ -401,7 +401,6 @@ static const struct file_operations rpc_info_operations = {
* We have a single directory with 1 node in it. * We have a single directory with 1 node in it.
*/ */
enum { enum {
RPCAUTH_Root = 1,
RPCAUTH_lockd, RPCAUTH_lockd,
RPCAUTH_mount, RPCAUTH_mount,
RPCAUTH_nfs, RPCAUTH_nfs,
...@@ -415,12 +414,12 @@ enum { ...@@ -415,12 +414,12 @@ enum {
* Description of fs contents. * Description of fs contents.
*/ */
struct rpc_filelist { struct rpc_filelist {
char *name; const char *name;
const struct file_operations *i_fop; const struct file_operations *i_fop;
umode_t mode; umode_t mode;
}; };
static struct rpc_filelist files[] = { static const struct rpc_filelist files[] = {
[RPCAUTH_lockd] = { [RPCAUTH_lockd] = {
.name = "lockd", .name = "lockd",
.mode = S_IFDIR | S_IRUGO | S_IXUGO, .mode = S_IFDIR | S_IRUGO | S_IXUGO,
...@@ -448,11 +447,11 @@ static struct rpc_filelist files[] = { ...@@ -448,11 +447,11 @@ static struct rpc_filelist files[] = {
}; };
enum { enum {
RPCAUTH_info = 2, RPCAUTH_info,
RPCAUTH_EOF RPCAUTH_EOF
}; };
static struct rpc_filelist authfiles[] = { static const struct rpc_filelist authfiles[] = {
[RPCAUTH_info] = { [RPCAUTH_info] = {
.name = "info", .name = "info",
.i_fop = &rpc_info_operations, .i_fop = &rpc_info_operations,
...@@ -564,6 +563,20 @@ static int __rpc_create_common(struct inode *dir, struct dentry *dentry, ...@@ -564,6 +563,20 @@ static int __rpc_create_common(struct inode *dir, struct dentry *dentry,
return -ENOMEM; return -ENOMEM;
} }
static int __rpc_create(struct inode *dir, struct dentry *dentry,
umode_t mode,
const struct file_operations *i_fop,
void *private)
{
int err;
err = __rpc_create_common(dir, dentry, S_IFREG | mode, i_fop, private);
if (err)
return err;
fsnotify_create(dir, dentry);
return 0;
}
static int __rpc_mkdir(struct inode *dir, struct dentry *dentry, static int __rpc_mkdir(struct inode *dir, struct dentry *dentry,
umode_t mode, umode_t mode,
const struct file_operations *i_fop, const struct file_operations *i_fop,
...@@ -601,6 +614,17 @@ static int __rpc_mkpipe(struct inode *dir, struct dentry *dentry, ...@@ -601,6 +614,17 @@ static int __rpc_mkpipe(struct inode *dir, struct dentry *dentry,
return 0; return 0;
} }
static int __rpc_rmdir(struct inode *dir, struct dentry *dentry)
{
int ret;
dget(dentry);
ret = simple_rmdir(dir, dentry);
d_delete(dentry);
dput(dentry);
return ret;
}
static int __rpc_unlink(struct inode *dir, struct dentry *dentry) static int __rpc_unlink(struct inode *dir, struct dentry *dentry)
{ {
int ret; int ret;
...@@ -678,100 +702,96 @@ static struct dentry *rpc_lookup_negative(const char *path, ...@@ -678,100 +702,96 @@ static struct dentry *rpc_lookup_negative(const char *path,
/* /*
* FIXME: This probably has races. * FIXME: This probably has races.
*/ */
static void rpc_depopulate(struct dentry *parent, static void __rpc_depopulate(struct dentry *parent,
unsigned long start, unsigned long eof) const struct rpc_filelist *files,
int start, int eof)
{ {
struct inode *dir = parent->d_inode; struct inode *dir = parent->d_inode;
struct list_head *pos, *next; struct dentry *dentry;
struct dentry *dentry, *dvec[10]; struct qstr name;
int n = 0; int i;
mutex_lock_nested(&dir->i_mutex, I_MUTEX_CHILD); for (i = start; i < eof; i++) {
repeat: name.name = files[i].name;
spin_lock(&dcache_lock); name.len = strlen(files[i].name);
list_for_each_safe(pos, next, &parent->d_subdirs) { name.hash = full_name_hash(name.name, name.len);
dentry = list_entry(pos, struct dentry, d_u.d_child); dentry = d_lookup(parent, &name);
if (!dentry->d_inode ||
dentry->d_inode->i_ino < start || if (dentry == NULL)
dentry->d_inode->i_ino >= eof)
continue; continue;
spin_lock(&dentry->d_lock); if (dentry->d_inode == NULL)
if (!d_unhashed(dentry)) { goto next;
dget_locked(dentry); switch (dentry->d_inode->i_mode & S_IFMT) {
__d_drop(dentry); default:
spin_unlock(&dentry->d_lock); BUG();
dvec[n++] = dentry; case S_IFREG:
if (n == ARRAY_SIZE(dvec)) __rpc_unlink(dir, dentry);
break; break;
} else case S_IFDIR:
spin_unlock(&dentry->d_lock); __rpc_rmdir(dir, dentry);
} }
spin_unlock(&dcache_lock); next:
if (n) {
do {
dentry = dvec[--n];
if (S_ISREG(dentry->d_inode->i_mode))
simple_unlink(dir, dentry);
else if (S_ISDIR(dentry->d_inode->i_mode))
simple_rmdir(dir, dentry);
d_delete(dentry);
dput(dentry); dput(dentry);
} while (n);
goto repeat;
} }
mutex_unlock(&dir->i_mutex);
} }
static int static void rpc_depopulate(struct dentry *parent,
rpc_populate(struct dentry *parent, const struct rpc_filelist *files,
struct rpc_filelist *files,
int start, int eof) int start, int eof)
{ {
struct inode *inode, *dir = parent->d_inode; struct inode *dir = parent->d_inode;
void *private = RPC_I(dir)->private;
mutex_lock_nested(&dir->i_mutex, I_MUTEX_CHILD);
__rpc_depopulate(parent, files, start, eof);
mutex_unlock(&dir->i_mutex);
}
static int rpc_populate(struct dentry *parent,
const struct rpc_filelist *files,
int start, int eof,
void *private)
{
struct inode *dir = parent->d_inode;
struct dentry *dentry; struct dentry *dentry;
umode_t mode; int i, err;
int i;
mutex_lock(&dir->i_mutex); mutex_lock(&dir->i_mutex);
for (i = start; i < eof; i++) { for (i = start; i < eof; i++) {
dentry = d_alloc_name(parent, files[i].name); struct qstr q;
if (!dentry)
goto out_bad; q.name = files[i].name;
dentry->d_op = &rpc_dentry_operations; q.len = strlen(files[i].name);
mode = files[i].mode; q.hash = full_name_hash(q.name, q.len);
inode = rpc_get_inode(dir->i_sb, mode); dentry = __rpc_lookup_create_exclusive(parent, &q);
if (!inode) { err = PTR_ERR(dentry);
dput(dentry); if (IS_ERR(dentry))
goto out_bad; goto out_bad;
switch (files[i].mode & S_IFMT) {
default:
BUG();
case S_IFREG:
err = __rpc_create(dir, dentry,
files[i].mode,
files[i].i_fop,
private);
break;
case S_IFDIR:
err = __rpc_mkdir(dir, dentry,
files[i].mode,
NULL,
private);
} }
inode->i_ino = i; if (err != 0)
if (files[i].i_fop) goto out_bad;
inode->i_fop = files[i].i_fop;
if (private)
rpc_inode_setowner(inode, private);
if (S_ISDIR(mode))
inc_nlink(dir);
d_add(dentry, inode);
fsnotify_create(dir, dentry);
} }
mutex_unlock(&dir->i_mutex); mutex_unlock(&dir->i_mutex);
return 0; return 0;
out_bad: out_bad:
__rpc_depopulate(parent, files, start, eof);
mutex_unlock(&dir->i_mutex); mutex_unlock(&dir->i_mutex);
printk(KERN_WARNING "%s: %s failed to populate directory %s\n", printk(KERN_WARNING "%s: %s failed to populate directory %s\n",
__FILE__, __func__, parent->d_name.name); __FILE__, __func__, parent->d_name.name);
return -ENOMEM; return err;
}
static int
__rpc_rmdir(struct inode *dir, struct dentry *dentry)
{
int error;
error = simple_rmdir(dir, dentry);
if (!error)
d_delete(dentry);
return error;
} }
/** /**
...@@ -800,16 +820,14 @@ rpc_mkdir(char *path, struct rpc_clnt *rpc_client) ...@@ -800,16 +820,14 @@ rpc_mkdir(char *path, struct rpc_clnt *rpc_client)
if (error != 0) if (error != 0)
goto out_err; goto out_err;
error = rpc_populate(dentry, authfiles, error = rpc_populate(dentry, authfiles,
RPCAUTH_info, RPCAUTH_EOF); RPCAUTH_info, RPCAUTH_EOF, rpc_client);
if (error) if (error)
goto err_depopulate; goto err_rmdir;
dget(dentry);
out: out:
mutex_unlock(&dir->i_mutex); mutex_unlock(&dir->i_mutex);
rpc_release_path(&nd); rpc_release_path(&nd);
return dentry; return dentry;
err_depopulate: err_rmdir:
rpc_depopulate(dentry, RPCAUTH_info, RPCAUTH_EOF);
__rpc_rmdir(dir, dentry); __rpc_rmdir(dir, dentry);
out_err: out_err:
printk(KERN_WARNING "%s: %s() failed to create directory %s (errno = %d)\n", printk(KERN_WARNING "%s: %s() failed to create directory %s (errno = %d)\n",
...@@ -832,9 +850,8 @@ rpc_rmdir(struct dentry *dentry) ...@@ -832,9 +850,8 @@ rpc_rmdir(struct dentry *dentry)
parent = dget_parent(dentry); parent = dget_parent(dentry);
dir = parent->d_inode; dir = parent->d_inode;
mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
rpc_depopulate(dentry, RPCAUTH_info, RPCAUTH_EOF); rpc_depopulate(dentry, authfiles, RPCAUTH_info, RPCAUTH_EOF);
error = __rpc_rmdir(dir, dentry); error = __rpc_rmdir(dir, dentry);
dput(dentry);
mutex_unlock(&dir->i_mutex); mutex_unlock(&dir->i_mutex);
dput(parent); dput(parent);
return error; return error;
...@@ -900,7 +917,6 @@ struct dentry *rpc_mkpipe(struct dentry *parent, const char *name, ...@@ -900,7 +917,6 @@ struct dentry *rpc_mkpipe(struct dentry *parent, const char *name,
private, ops, flags); private, ops, flags);
if (err) if (err)
goto out_err; goto out_err;
dget(dentry);
out: out:
mutex_unlock(&dir->i_mutex); mutex_unlock(&dir->i_mutex);
return dentry; return dentry;
...@@ -932,7 +948,6 @@ rpc_unlink(struct dentry *dentry) ...@@ -932,7 +948,6 @@ rpc_unlink(struct dentry *dentry)
dir = parent->d_inode; dir = parent->d_inode;
mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
error = __rpc_rmpipe(dir, dentry); error = __rpc_rmpipe(dir, dentry);
dput(dentry);
mutex_unlock(&dir->i_mutex); mutex_unlock(&dir->i_mutex);
dput(parent); dput(parent);
return error; return error;
...@@ -970,7 +985,7 @@ rpc_fill_super(struct super_block *sb, void *data, int silent) ...@@ -970,7 +985,7 @@ rpc_fill_super(struct super_block *sb, void *data, int silent)
iput(inode); iput(inode);
return -ENOMEM; return -ENOMEM;
} }
if (rpc_populate(root, files, RPCAUTH_Root + 1, RPCAUTH_RootEOF)) if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL))
goto out; goto out;
sb->s_root = root; sb->s_root = root;
return 0; return 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册