aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Staubach <staubach@redhat.com>2008-12-23 15:21:56 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-12-23 15:21:56 -0500
commit64672d55d93c26fb4035fd1a84a803cbc09cb058 (patch)
tree6873f9335b925e4c6a5336544a6f6fc1d789604f
parentdc0b027dfadfcb8a5504f7d8052754bf8d501ab9 (diff)
optimize attribute timeouts for "noac" and "actimeo=0"
Hi. I've been looking at a bugzilla which describes a problem where a customer was advised to use either the "noac" or "actimeo=0" mount options to solve a consistency problem that they were seeing in the file attributes. It turned out that this solution did not work reliably for them because sometimes, the local attribute cache was believed to be valid and not timed out. (With an attribute cache timeout of 0, the cache should always appear to be timed out.) In looking at this situation, it appears to me that the problem is that the attribute cache timeout code has an off-by-one error in it. It is assuming that the cache is valid in the region, [read_cache_jiffies, read_cache_jiffies + attrtimeo]. The cache should be considered valid only in the region, [read_cache_jiffies, read_cache_jiffies + attrtimeo). With this change, the options, "noac" and "actimeo=0", work as originally expected. This problem was previously addressed by special casing the attrtimeo == 0 case. However, since the problem is only an off- by-one error, the cleaner solution is address the off-by-one error and thus, not require the special case. Thanx... ps Signed-off-by: Peter Staubach <staubach@redhat.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/dir.c2
-rw-r--r--fs/nfs/inode.c11
-rw-r--r--include/linux/jiffies.h10
-rw-r--r--include/linux/nfs_fs.h5
-rw-r--r--net/sunrpc/auth.c2
5 files changed, 18 insertions, 12 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index ed7024c34885..e35c8199f82f 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1798,7 +1798,7 @@ static int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, str
1798 if (cache == NULL) 1798 if (cache == NULL)
1799 goto out; 1799 goto out;
1800 if (!nfs_have_delegation(inode, FMODE_READ) && 1800 if (!nfs_have_delegation(inode, FMODE_READ) &&
1801 !time_in_range(jiffies, cache->jiffies, cache->jiffies + nfsi->attrtimeo)) 1801 !time_in_range_open(jiffies, cache->jiffies, cache->jiffies + nfsi->attrtimeo))
1802 goto out_stale; 1802 goto out_stale;
1803 res->jiffies = cache->jiffies; 1803 res->jiffies = cache->jiffies;
1804 res->cred = cache->cred; 1804 res->cred = cache->cred;
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 1cf39202c3ea..0c381686171e 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -712,14 +712,7 @@ int nfs_attribute_timeout(struct inode *inode)
712 712
713 if (nfs_have_delegation(inode, FMODE_READ)) 713 if (nfs_have_delegation(inode, FMODE_READ))
714 return 0; 714 return 0;
715 /* 715 return !time_in_range_open(jiffies, nfsi->read_cache_jiffies, nfsi->read_cache_jiffies + nfsi->attrtimeo);
716 * Special case: if the attribute timeout is set to 0, then always
717 * treat the cache as having expired (unless holding
718 * a delegation).
719 */
720 if (nfsi->attrtimeo == 0)
721 return 1;
722 return !time_in_range(jiffies, nfsi->read_cache_jiffies, nfsi->read_cache_jiffies + nfsi->attrtimeo);
723} 716}
724 717
725/** 718/**
@@ -1182,7 +1175,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
1182 nfsi->attrtimeo_timestamp = now; 1175 nfsi->attrtimeo_timestamp = now;
1183 nfsi->attr_gencount = nfs_inc_attr_generation_counter(); 1176 nfsi->attr_gencount = nfs_inc_attr_generation_counter();
1184 } else { 1177 } else {
1185 if (!time_in_range(now, nfsi->attrtimeo_timestamp, nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) { 1178 if (!time_in_range_open(now, nfsi->attrtimeo_timestamp, nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) {
1186 if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode)) 1179 if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode))
1187 nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode); 1180 nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode);
1188 nfsi->attrtimeo_timestamp = now; 1181 nfsi->attrtimeo_timestamp = now;
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
index abb6ac639e8e..1a9cf78bfce5 100644
--- a/include/linux/jiffies.h
+++ b/include/linux/jiffies.h
@@ -115,10 +115,20 @@ static inline u64 get_jiffies_64(void)
115 ((long)(a) - (long)(b) >= 0)) 115 ((long)(a) - (long)(b) >= 0))
116#define time_before_eq(a,b) time_after_eq(b,a) 116#define time_before_eq(a,b) time_after_eq(b,a)
117 117
118/*
119 * Calculate whether a is in the range of [b, c].
120 */
118#define time_in_range(a,b,c) \ 121#define time_in_range(a,b,c) \
119 (time_after_eq(a,b) && \ 122 (time_after_eq(a,b) && \
120 time_before_eq(a,c)) 123 time_before_eq(a,c))
121 124
125/*
126 * Calculate whether a is in the range of [b, c).
127 */
128#define time_in_range_open(a,b,c) \
129 (time_after_eq(a,b) && \
130 time_before(a,c))
131
122/* Same as above, but does so with platform independent 64bit types. 132/* Same as above, but does so with platform independent 64bit types.
123 * These must be used when utilizing jiffies_64 (i.e. return value of 133 * These must be used when utilizing jiffies_64 (i.e. return value of
124 * get_jiffies_64() */ 134 * get_jiffies_64() */
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index b8d9c6dd4f63..db867b04ac3c 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -130,7 +130,10 @@ struct nfs_inode {
130 * 130 *
131 * We need to revalidate the cached attrs for this inode if 131 * We need to revalidate the cached attrs for this inode if
132 * 132 *
133 * jiffies - read_cache_jiffies > attrtimeo 133 * jiffies - read_cache_jiffies >= attrtimeo
134 *
135 * Please note the comparison is greater than or equal
136 * so that zero timeout values can be specified.
134 */ 137 */
135 unsigned long read_cache_jiffies; 138 unsigned long read_cache_jiffies;
136 unsigned long attrtimeo; 139 unsigned long attrtimeo;
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 6e28744b1709..050e4e84d9e3 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -234,7 +234,7 @@ rpcauth_prune_expired(struct list_head *free, int nr_to_scan)
234 list_for_each_entry_safe(cred, next, &cred_unused, cr_lru) { 234 list_for_each_entry_safe(cred, next, &cred_unused, cr_lru) {
235 235
236 /* Enforce a 60 second garbage collection moratorium */ 236 /* Enforce a 60 second garbage collection moratorium */
237 if (time_in_range(cred->cr_expire, expired, jiffies) && 237 if (time_in_range_open(cred->cr_expire, expired, jiffies) &&
238 test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) 238 test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0)
239 continue; 239 continue;
240 240