diff options
author | David Howells <dhowells@redhat.com> | 2012-12-20 16:52:35 -0500 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2012-12-20 16:58:25 -0500 |
commit | ef46ed888efb1e8da33be5d33c9b54476289a43b (patch) | |
tree | d538dc01a075162f95da416da1fb5d6fd676445a /fs | |
parent | 37491a1339df26259b06dfa33f30e574e9e52034 (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>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/fscache/cookie.c | 18 | ||||
-rw-r--r-- | fs/fscache/operation.c | 10 |
2 files changed, 22 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 | ||
445 | try_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 |