aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cachefiles/namei.c
diff options
context:
space:
mode:
authorKiran Kumar Modukuri <kiran.modukuri@gmail.com>2018-06-21 16:25:53 -0400
committerDavid Howells <dhowells@redhat.com>2018-07-25 09:49:00 -0400
commit5ce83d4bb7d8e11e8c1c687d09f4b5ae67ef3ce3 (patch)
treeb2c096773a06825b1d82304cfe125175d091e79a /fs/cachefiles/namei.c
parentf29507ce66701084c39aeb1b0ae71690cbff3554 (diff)
cachefiles: Fix missing clear of the CACHEFILES_OBJECT_ACTIVE flag
In cachefiles_mark_object_active(), the new object is marked active and then we try to add it to the active object tree. If a conflicting object is already present, we want to wait for that to go away. After the wait, we go round again and try to re-mark the object as being active - but it's already marked active from the first time we went through and a BUG is issued. Fix this by clearing the CACHEFILES_OBJECT_ACTIVE flag before we try again. Analysis from Kiran Kumar Modukuri: [Impact] Oops during heavy NFS + FSCache + Cachefiles CacheFiles: Error: Overlong wait for old active object to go away. BUG: unable to handle kernel NULL pointer dereference at 0000000000000002 CacheFiles: Error: Object already active kernel BUG at fs/cachefiles/namei.c:163! [Cause] In a heavily loaded system with big files being read and truncated, an fscache object for a cookie is being dropped and a new object being looked. The new object being looked for has to wait for the old object to go away before the new object is moved to active state. [Fix] Clear the flag 'CACHEFILES_OBJECT_ACTIVE' for the new object when retrying the object lookup. [Testcase] Have run ~100 hours of NFS stress tests and have not seen this bug recur. [Regression Potential] - Limited to fscache/cachefiles. Fixes: 9ae326a69004 ("CacheFiles: A cache that backs onto a mounted filesystem") Signed-off-by: Kiran Kumar Modukuri <kiran.modukuri@gmail.com> Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'fs/cachefiles/namei.c')
-rw-r--r--fs/cachefiles/namei.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c
index ab0bbe93b398..b5d6dd72dfa0 100644
--- a/fs/cachefiles/namei.c
+++ b/fs/cachefiles/namei.c
@@ -186,6 +186,7 @@ try_again:
186 * need to wait for it to be destroyed */ 186 * need to wait for it to be destroyed */
187wait_for_old_object: 187wait_for_old_object:
188 trace_cachefiles_wait_active(object, dentry, xobject); 188 trace_cachefiles_wait_active(object, dentry, xobject);
189 clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags);
189 190
190 if (fscache_object_is_live(&xobject->fscache)) { 191 if (fscache_object_is_live(&xobject->fscache)) {
191 pr_err("\n"); 192 pr_err("\n");
@@ -248,7 +249,6 @@ wait_for_old_object:
248 goto try_again; 249 goto try_again;
249 250
250requeue: 251requeue:
251 clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags);
252 cache->cache.ops->put_object(&xobject->fscache, cachefiles_obj_put_wait_timeo); 252 cache->cache.ops->put_object(&xobject->fscache, cachefiles_obj_put_wait_timeo);
253 _leave(" = -ETIMEDOUT"); 253 _leave(" = -ETIMEDOUT");
254 return -ETIMEDOUT; 254 return -ETIMEDOUT;