diff options
-rw-r--r-- | fs/nfs/dir.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 062e108fac50..37c1dd642184 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -637,7 +637,7 @@ int nfs_fsync_dir(struct file *filp, struct dentry *dentry, int datasync) | |||
637 | * In the case it has, we assume that the dentries are untrustworthy | 637 | * In the case it has, we assume that the dentries are untrustworthy |
638 | * and may need to be looked up again. | 638 | * and may need to be looked up again. |
639 | */ | 639 | */ |
640 | static inline int nfs_check_verifier(struct inode *dir, struct dentry *dentry) | 640 | static int nfs_check_verifier(struct inode *dir, struct dentry *dentry) |
641 | { | 641 | { |
642 | if (IS_ROOT(dentry)) | 642 | if (IS_ROOT(dentry)) |
643 | return 1; | 643 | return 1; |
@@ -652,6 +652,12 @@ static inline void nfs_set_verifier(struct dentry * dentry, unsigned long verf) | |||
652 | dentry->d_fsdata = (void *)verf; | 652 | dentry->d_fsdata = (void *)verf; |
653 | } | 653 | } |
654 | 654 | ||
655 | static void nfs_refresh_verifier(struct dentry * dentry, unsigned long verf) | ||
656 | { | ||
657 | if (time_after(verf, (unsigned long)dentry->d_fsdata)) | ||
658 | nfs_set_verifier(dentry, verf); | ||
659 | } | ||
660 | |||
655 | /* | 661 | /* |
656 | * Whenever an NFS operation succeeds, we know that the dentry | 662 | * Whenever an NFS operation succeeds, we know that the dentry |
657 | * is valid, so we update the revalidation timestamp. | 663 | * is valid, so we update the revalidation timestamp. |
@@ -785,7 +791,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd) | |||
785 | goto out_bad; | 791 | goto out_bad; |
786 | 792 | ||
787 | nfs_renew_times(dentry); | 793 | nfs_renew_times(dentry); |
788 | nfs_set_verifier(dentry, verifier); | 794 | nfs_refresh_verifier(dentry, verifier); |
789 | out_valid: | 795 | out_valid: |
790 | unlock_kernel(); | 796 | unlock_kernel(); |
791 | dput(parent); | 797 | dput(parent); |
@@ -1085,7 +1091,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1085 | verifier = nfs_save_change_attribute(dir); | 1091 | verifier = nfs_save_change_attribute(dir); |
1086 | ret = nfs4_open_revalidate(dir, dentry, openflags, nd); | 1092 | ret = nfs4_open_revalidate(dir, dentry, openflags, nd); |
1087 | if (!ret) | 1093 | if (!ret) |
1088 | nfs_set_verifier(dentry, verifier); | 1094 | nfs_refresh_verifier(dentry, verifier); |
1089 | unlock_kernel(); | 1095 | unlock_kernel(); |
1090 | out: | 1096 | out: |
1091 | dput(parent); | 1097 | dput(parent); |
@@ -1159,10 +1165,13 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc) | |||
1159 | dentry = alias; | 1165 | dentry = alias; |
1160 | } | 1166 | } |
1161 | 1167 | ||
1162 | out_renew: | ||
1163 | nfs_renew_times(dentry); | 1168 | nfs_renew_times(dentry); |
1164 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1169 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1165 | return dentry; | 1170 | return dentry; |
1171 | out_renew: | ||
1172 | nfs_renew_times(dentry); | ||
1173 | nfs_refresh_verifier(dentry, nfs_save_change_attribute(dir)); | ||
1174 | return dentry; | ||
1166 | } | 1175 | } |
1167 | 1176 | ||
1168 | /* | 1177 | /* |
@@ -1700,7 +1709,7 @@ out: | |||
1700 | if (!error) { | 1709 | if (!error) { |
1701 | d_move(old_dentry, new_dentry); | 1710 | d_move(old_dentry, new_dentry); |
1702 | nfs_renew_times(new_dentry); | 1711 | nfs_renew_times(new_dentry); |
1703 | nfs_set_verifier(new_dentry, nfs_save_change_attribute(new_dir)); | 1712 | nfs_refresh_verifier(new_dentry, nfs_save_change_attribute(new_dir)); |
1704 | } | 1713 | } |
1705 | 1714 | ||
1706 | /* new dentry created? */ | 1715 | /* new dentry created? */ |