summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/smb/client/inode.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c
index 31d138ad11bc..f16070888c06 100644
--- a/fs/smb/client/inode.c
+++ b/fs/smb/client/inode.c
@@ -2689,10 +2689,28 @@ cifs_dentry_needs_reval(struct dentry *dentry)
if (!lookupCacheEnabled)
return true;
- cfid = find_cached_dir(tcon->cfids, dentry->d_parent, CFID_LOOKUP_DENTRY);
- if (cfid) {
- close_cached_dir(cfid);
- return false;
+ if (!IS_ROOT(dentry)) {
+ cfid = find_cached_dir(tcon->cfids, dentry->d_parent, CFID_LOOKUP_DENTRY);
+ if (cfid) {
+ /*
+ * We hold a lease for the cached parent.
+ * So as long as this child is within cached dir lifetime, we don't need to
+ * revalidate it.
+ *
+ * Since cfid expiration is based on access time, use it for comparison
+ * instead of creation time.
+ */
+ if (time_after(cifs_i->time, cfid->atime - dir_cache_timeout * HZ)) {
+ close_cached_dir(cfid);
+ return true;
+ }
+
+ /*
+ * From cached dir perspective, we're done -- attr caching (ac*max) may
+ * have different requirements, so let the checks go through.
+ */
+ close_cached_dir(cfid);
+ }
}
/*