From 43948b5c94fdcf1de20176470da890468742bb6c Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 20 Dec 2012 21:52:35 +0000 Subject: [PATCH] --- yaml --- r: 347819 b: refs/heads/master c: ef46ed888efb1e8da33be5d33c9b54476289a43b h: refs/heads/master i: 347817: 8285f2d85ac29bec2605e4bbb71b7ae3948197db 347815: 0bfcf03cbc3620f6a6678f3a4a0afd40a20f64b4 v: v3 --- [refs] | 2 +- trunk/fs/fscache/cookie.c | 18 ++++++++++++++---- trunk/fs/fscache/operation.c | 10 ++++++++-- trunk/include/linux/fscache-cache.h | 1 + 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/[refs] b/[refs] index e8f27e56a9a7..83943c72efb0 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 37491a1339df26259b06dfa33f30e574e9e52034 +refs/heads/master: ef46ed888efb1e8da33be5d33c9b54476289a43b diff --git a/trunk/fs/fscache/cookie.c b/trunk/fs/fscache/cookie.c index 0666996adf80..66be9eccede0 100644 --- a/trunk/fs/fscache/cookie.c +++ b/trunk/fs/fscache/cookie.c @@ -442,22 +442,32 @@ void __fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire) event = retire ? FSCACHE_OBJECT_EV_RETIRE : FSCACHE_OBJECT_EV_RELEASE; +try_again: spin_lock(&cookie->lock); /* break links with all the active objects */ while (!hlist_empty(&cookie->backing_objects)) { + int n_reads; object = hlist_entry(cookie->backing_objects.first, struct fscache_object, cookie_link); _debug("RELEASE OBJ%x", object->debug_id); - if (atomic_read(&object->n_reads)) { + set_bit(FSCACHE_COOKIE_WAITING_ON_READS, &cookie->flags); + n_reads = atomic_read(&object->n_reads); + if (n_reads) { + int n_ops = object->n_ops; + int n_in_progress = object->n_in_progress; spin_unlock(&cookie->lock); printk(KERN_ERR "FS-Cache:" - " Cookie '%s' still has %d outstanding reads\n", - cookie->def->name, atomic_read(&object->n_reads)); - BUG(); + " Cookie '%s' still has %d outstanding reads (%d,%d)\n", + cookie->def->name, + n_reads, n_ops, n_in_progress); + wait_on_bit(&cookie->flags, FSCACHE_COOKIE_WAITING_ON_READS, + fscache_wait_bit, TASK_UNINTERRUPTIBLE); + printk("Wait finished\n"); + goto try_again; } /* detach each cache object from the object cookie */ diff --git a/trunk/fs/fscache/operation.c b/trunk/fs/fscache/operation.c index 30afdfa7aec7..c857ab824d6e 100644 --- a/trunk/fs/fscache/operation.c +++ b/trunk/fs/fscache/operation.c @@ -340,8 +340,14 @@ void fscache_put_operation(struct fscache_operation *op) object = op->object; - if (test_bit(FSCACHE_OP_DEC_READ_CNT, &op->flags)) - atomic_dec(&object->n_reads); + if (test_bit(FSCACHE_OP_DEC_READ_CNT, &op->flags)) { + if (atomic_dec_and_test(&object->n_reads)) { + clear_bit(FSCACHE_COOKIE_WAITING_ON_READS, + &object->cookie->flags); + wake_up_bit(&object->cookie->flags, + FSCACHE_COOKIE_WAITING_ON_READS); + } + } /* now... we may get called with the object spinlock held, so we * complete the cleanup here only if we can immediately acquire the diff --git a/trunk/include/linux/fscache-cache.h b/trunk/include/linux/fscache-cache.h index 9879183b55d8..e3d6d939d959 100644 --- a/trunk/include/linux/fscache-cache.h +++ b/trunk/include/linux/fscache-cache.h @@ -301,6 +301,7 @@ struct fscache_cookie { #define FSCACHE_COOKIE_PENDING_FILL 3 /* T if pending initial fill on object */ #define FSCACHE_COOKIE_FILLING 4 /* T if filling object incrementally */ #define FSCACHE_COOKIE_UNAVAILABLE 5 /* T if cookie is unavailable (error, etc) */ +#define FSCACHE_COOKIE_WAITING_ON_READS 6 /* T if cookie is waiting on reads */ }; extern struct fscache_cookie fscache_fsdef_index;