aboutsummaryrefslogtreecommitdiff
path: root/fs/nfsd/nfs4recover.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-04-06 13:25:56 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-06 13:25:56 -0700
commita63856252d2112e7c452696037a86ceb12f47f80 (patch)
treeb1ad03fe441349069f80e58de425b3f72af9e5b7 /fs/nfsd/nfs4recover.c
parentb24241a09208874d5d770bee30791daae41ad762 (diff)
parent04826f43d4f0a4d56423eb8abb9f2ec9987df5b5 (diff)
Merge branch 'for-2.6.30' of git://linux-nfs.org/~bfields/linux
* 'for-2.6.30' of git://linux-nfs.org/~bfields/linux: (81 commits) nfsd41: define nfsd4_set_statp as noop for !CONFIG_NFSD_V4 nfsd41: define NFSD_DRC_SIZE_SHIFT in set_max_drc nfsd41: Documentation/filesystems/nfs41-server.txt nfsd41: CREATE_EXCLUSIVE4_1 nfsd41: SUPPATTR_EXCLCREAT attribute nfsd41: support for 3-word long attribute bitmask nfsd: dynamically skip encoded fattr bitmap in _nfsd4_verify nfsd41: pass writable attrs mask to nfsd4_decode_fattr nfsd41: provide support for minor version 1 at rpc level nfsd41: control nfsv4.1 svc via /proc/fs/nfsd/versions nfsd41: add OPEN4_SHARE_ACCESS_WANT nfs4_stateid bmap nfsd41: access_valid nfsd41: clientid handling nfsd41: check encode size for sessions maxresponse cached nfsd41: stateid handling nfsd: pass nfsd4_compound_state* to nfs4_preprocess_{state,seq}id_op nfsd41: destroy_session operation nfsd41: non-page DRC for solo sequence responses nfsd41: Add a create session replay cache nfsd41: create_session operation ...
Diffstat (limited to 'fs/nfsd/nfs4recover.c')
-rw-r--r--fs/nfsd/nfs4recover.c74
1 files changed, 33 insertions, 41 deletions
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 74f7b67567f..3444c0052a8 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -182,36 +182,26 @@ out_unlock:
typedef int (recdir_func)(struct dentry *, struct dentry *);
-struct dentry_list {
- struct dentry *dentry;
+struct name_list {
+ char name[HEXDIR_LEN];
struct list_head list;
};
-struct dentry_list_arg {
- struct list_head dentries;
- struct dentry *parent;
-};
-
static int
-nfsd4_build_dentrylist(void *arg, const char *name, int namlen,
+nfsd4_build_namelist(void *arg, const char *name, int namlen,
loff_t offset, u64 ino, unsigned int d_type)
{
- struct dentry_list_arg *dla = arg;
- struct list_head *dentries = &dla->dentries;
- struct dentry *parent = dla->parent;
- struct dentry *dentry;
- struct dentry_list *child;
+ struct list_head *names = arg;
+ struct name_list *entry;
- if (name && isdotent(name, namlen))
+ if (namlen != HEXDIR_LEN - 1)
return 0;
- dentry = lookup_one_len(name, parent, namlen);
- if (IS_ERR(dentry))
- return PTR_ERR(dentry);
- child = kmalloc(sizeof(*child), GFP_KERNEL);
- if (child == NULL)
+ entry = kmalloc(sizeof(struct name_list), GFP_KERNEL);
+ if (entry == NULL)
return -ENOMEM;
- child->dentry = dentry;
- list_add(&child->list, dentries);
+ memcpy(entry->name, name, HEXDIR_LEN - 1);
+ entry->name[HEXDIR_LEN - 1] = '\0';
+ list_add(&entry->list, names);
return 0;
}
@@ -220,11 +210,9 @@ nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
{
const struct cred *original_cred;
struct file *filp;
- struct dentry_list_arg dla = {
- .parent = dir,
- };
- struct list_head *dentries = &dla.dentries;
- struct dentry_list *child;
+ LIST_HEAD(names);
+ struct name_list *entry;
+ struct dentry *dentry;
int status;
if (!rec_dir_init)
@@ -233,31 +221,34 @@ nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
status = nfs4_save_creds(&original_cred);
if (status < 0)
return status;
- INIT_LIST_HEAD(dentries);
filp = dentry_open(dget(dir), mntget(rec_dir.mnt), O_RDONLY,
current_cred());
status = PTR_ERR(filp);
if (IS_ERR(filp))
goto out;
- INIT_LIST_HEAD(dentries);
- status = vfs_readdir(filp, nfsd4_build_dentrylist, &dla);
+ status = vfs_readdir(filp, nfsd4_build_namelist, &names);
fput(filp);
- while (!list_empty(dentries)) {
- child = list_entry(dentries->next, struct dentry_list, list);
- status = f(dir, child->dentry);
+ while (!list_empty(&names)) {
+ entry = list_entry(names.next, struct name_list, list);
+
+ dentry = lookup_one_len(entry->name, dir, HEXDIR_LEN-1);
+ if (IS_ERR(dentry)) {
+ status = PTR_ERR(dentry);
+ goto out;
+ }
+ status = f(dir, dentry);
+ dput(dentry);
if (status)
goto out;
- list_del(&child->list);
- dput(child->dentry);
- kfree(child);
+ list_del(&entry->list);
+ kfree(entry);
}
out:
- while (!list_empty(dentries)) {
- child = list_entry(dentries->next, struct dentry_list, list);
- list_del(&child->list);
- dput(child->dentry);
- kfree(child);
+ while (!list_empty(&names)) {
+ entry = list_entry(names.next, struct name_list, list);
+ list_del(&entry->list);
+ kfree(entry);
}
nfs4_reset_creds(original_cred);
return status;
@@ -353,7 +344,8 @@ purge_old(struct dentry *parent, struct dentry *child)
{
int status;
- if (nfs4_has_reclaimed_state(child->d_name.name))
+ /* note: we currently use this path only for minorversion 0 */
+ if (nfs4_has_reclaimed_state(child->d_name.name, false))
return 0;
status = nfsd4_clear_clid_dir(parent, child);