Skip to content

Commit

Permalink
NFS: Dont clobber more uptodate values in nfs_set_verifier()
Browse files Browse the repository at this point in the history
nfs_lookup_revalidate and friends are not serialised, so it is currently
quite possible for the dentry to be revalidated, and then have the
updated verifier replaced with an older value by another process.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
  • Loading branch information
Trond Myklebust authored and Trond Myklebust committed Feb 3, 2007
1 parent ef75c79 commit c79ba78
Showing 1 changed file with 14 additions and 5 deletions.
19 changes: 14 additions & 5 deletions fs/nfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,7 @@ int nfs_fsync_dir(struct file *filp, struct dentry *dentry, int datasync)
* In the case it has, we assume that the dentries are untrustworthy
* and may need to be looked up again.
*/
static inline int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
static int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
{
if (IS_ROOT(dentry))
return 1;
Expand All @@ -652,6 +652,12 @@ static inline void nfs_set_verifier(struct dentry * dentry, unsigned long verf)
dentry->d_fsdata = (void *)verf;
}

static void nfs_refresh_verifier(struct dentry * dentry, unsigned long verf)
{
if (time_after(verf, (unsigned long)dentry->d_fsdata))
nfs_set_verifier(dentry, verf);
}

/*
* Whenever an NFS operation succeeds, we know that the dentry
* is valid, so we update the revalidation timestamp.
Expand Down Expand Up @@ -785,7 +791,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
goto out_bad;

nfs_renew_times(dentry);
nfs_set_verifier(dentry, verifier);
nfs_refresh_verifier(dentry, verifier);
out_valid:
unlock_kernel();
dput(parent);
Expand Down Expand Up @@ -1085,7 +1091,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
verifier = nfs_save_change_attribute(dir);
ret = nfs4_open_revalidate(dir, dentry, openflags, nd);
if (!ret)
nfs_set_verifier(dentry, verifier);
nfs_refresh_verifier(dentry, verifier);
unlock_kernel();
out:
dput(parent);
Expand Down Expand Up @@ -1159,10 +1165,13 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc)
dentry = alias;
}

out_renew:
nfs_renew_times(dentry);
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
return dentry;
out_renew:
nfs_renew_times(dentry);
nfs_refresh_verifier(dentry, nfs_save_change_attribute(dir));
return dentry;
}

/*
Expand Down Expand Up @@ -1700,7 +1709,7 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (!error) {
d_move(old_dentry, new_dentry);
nfs_renew_times(new_dentry);
nfs_set_verifier(new_dentry, nfs_save_change_attribute(new_dir));
nfs_refresh_verifier(new_dentry, nfs_save_change_attribute(new_dir));
}

/* new dentry created? */
Expand Down

0 comments on commit c79ba78

Please sign in to comment.