aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2012-12-20 16:52:35 -0500
committerDavid Howells <dhowells@redhat.com>2012-12-20 16:58:25 -0500
commitef46ed888efb1e8da33be5d33c9b54476289a43b (patch)
treed538dc01a075162f95da416da1fb5d6fd676445a
parent37491a1339df26259b06dfa33f30e574e9e52034 (diff)
FS-Cache: Make cookie relinquishment wait for outstanding reads
Make fscache_relinquish_cookie() log a warning and wait if there are any outstanding reads left on the cookie it was given. Signed-off-by: David Howells <dhowells@redhat.com>
-rw-r--r--fs/fscache/cookie.c18
-rw-r--r--fs/fscache/operation.c10
-rw-r--r--include/linux/fscache-cache.h1
3 files changed, 23 insertions, 6 deletions
diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c
index 0666996adf80..66be9eccede0 100644
--- a/fs/fscache/cookie.c
+++ b/fs/fscache/cookie.c
@@ -442,22 +442,32 @@ void __fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire)
442 442
443 event = retire ? FSCACHE_OBJECT_EV_RETIRE : FSCACHE_OBJECT_EV_RELEASE; 443 event = retire ? FSCACHE_OBJECT_EV_RETIRE : FSCACHE_OBJECT_EV_RELEASE;
444 444
445try_again:
445 spin_lock(&cookie->lock); 446 spin_lock(&cookie->lock);
446 447
447 /* break links with all the active objects */ 448 /* break links with all the active objects */
448 while (!hlist_empty(&cookie->backing_objects)) { 449 while (!hlist_empty(&cookie->backing_objects)) {
450 int n_reads;
449 object = hlist_entry(cookie->backing_objects.first, 451 object = hlist_entry(cookie->backing_objects.first,
450 struct fscache_object, 452 struct fscache_object,
451 cookie_link); 453 cookie_link);
452 454
453 _debug("RELEASE OBJ%x", object->debug_id); 455 _debug("RELEASE OBJ%x", object->debug_id);
454 456
455 if (atomic_read(&object->n_reads)) { 457 set_bit(FSCACHE_COOKIE_WAITING_ON_READS, &cookie->flags);
458 n_reads = atomic_read(&object->n_reads);
459 if (n_reads) {
460 int n_ops = object->n_ops;
461 int n_in_progress = object->n_in_progress;
456 spin_unlock(&cookie->lock); 462 spin_unlock(&cookie->lock);
457 printk(KERN_ERR "FS-Cache:" 463 printk(KERN_ERR "FS-Cache:"
458 " Cookie '%s' still has %d outstanding reads\n", 464 " Cookie '%s' still has %d outstanding reads (%d,%d)\n",
459 cookie->def->name, atomic_read(&object->n_reads)); 465 cookie->def->name,
460 BUG(); 466 n_reads, n_ops, n_in_progress);
467 wait_on_bit(&cookie->flags, FSCACHE_COOKIE_WAITING_ON_READS,
468 fscache_wait_bit, TASK_UNINTERRUPTIBLE);
469 printk("Wait finished\n");
470 goto try_again;
461 } 471 }
462 472
463 /* detach each cache object from the object cookie */ 473 /* detach each cache object from the object cookie */
diff --git a/fs/fscache/operation.c b/fs/fscache/operation.c
index 30afdfa7aec7..c857ab824d6e 100644
--- a/fs/fscache/operation.c
+++ b/fs/fscache/operation.c
@@ -340,8 +340,14 @@ void fscache_put_operation(struct fscache_operation *op)
340 340
341 object = op->object; 341 object = op->object;
342 342
343 if (test_bit(FSCACHE_OP_DEC_READ_CNT, &op->flags)) 343 if (test_bit(FSCACHE_OP_DEC_READ_CNT, &op->flags)) {
344 atomic_dec(&object->n_reads); 344 if (atomic_dec_and_test(&object->n_reads)) {
345 clear_bit(FSCACHE_COOKIE_WAITING_ON_READS,
346 &object->cookie->flags);
347 wake_up_bit(&object->cookie->flags,
348 FSCACHE_COOKIE_WAITING_ON_READS);
349 }
350 }
345 351
346 /* now... we may get called with the object spinlock held, so we 352 /* now... we may get called with the object spinlock held, so we
347 * complete the cleanup here only if we can immediately acquire the 353 * complete the cleanup here only if we can immediately acquire the
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h
index 9879183b55d8..e3d6d939d959 100644
--- a/include/linux/fscache-cache.h
+++ b/include/linux/fscache-cache.h
@@ -301,6 +301,7 @@ struct fscache_cookie {
301#define FSCACHE_COOKIE_PENDING_FILL 3 /* T if pending initial fill on object */ 301#define FSCACHE_COOKIE_PENDING_FILL 3 /* T if pending initial fill on object */
302#define FSCACHE_COOKIE_FILLING 4 /* T if filling object incrementally */ 302#define FSCACHE_COOKIE_FILLING 4 /* T if filling object incrementally */
303#define FSCACHE_COOKIE_UNAVAILABLE 5 /* T if cookie is unavailable (error, etc) */ 303#define FSCACHE_COOKIE_UNAVAILABLE 5 /* T if cookie is unavailable (error, etc) */
304#define FSCACHE_COOKIE_WAITING_ON_READS 6 /* T if cookie is waiting on reads */
304}; 305};
305 306
306extern struct fscache_cookie fscache_fsdef_index; 307extern struct fscache_cookie fscache_fsdef_index;