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>
This commit is contained in:
Родитель
37491a1339
Коммит
ef46ed888e
|
@ -442,22 +442,32 @@ void __fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire)
|
||||||
|
|
||||||
event = retire ? FSCACHE_OBJECT_EV_RETIRE : FSCACHE_OBJECT_EV_RELEASE;
|
event = retire ? FSCACHE_OBJECT_EV_RETIRE : FSCACHE_OBJECT_EV_RELEASE;
|
||||||
|
|
||||||
|
try_again:
|
||||||
spin_lock(&cookie->lock);
|
spin_lock(&cookie->lock);
|
||||||
|
|
||||||
/* break links with all the active objects */
|
/* break links with all the active objects */
|
||||||
while (!hlist_empty(&cookie->backing_objects)) {
|
while (!hlist_empty(&cookie->backing_objects)) {
|
||||||
|
int n_reads;
|
||||||
object = hlist_entry(cookie->backing_objects.first,
|
object = hlist_entry(cookie->backing_objects.first,
|
||||||
struct fscache_object,
|
struct fscache_object,
|
||||||
cookie_link);
|
cookie_link);
|
||||||
|
|
||||||
_debug("RELEASE OBJ%x", object->debug_id);
|
_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);
|
spin_unlock(&cookie->lock);
|
||||||
printk(KERN_ERR "FS-Cache:"
|
printk(KERN_ERR "FS-Cache:"
|
||||||
" Cookie '%s' still has %d outstanding reads\n",
|
" Cookie '%s' still has %d outstanding reads (%d,%d)\n",
|
||||||
cookie->def->name, atomic_read(&object->n_reads));
|
cookie->def->name,
|
||||||
BUG();
|
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 */
|
/* detach each cache object from the object cookie */
|
||||||
|
|
|
@ -340,8 +340,14 @@ void fscache_put_operation(struct fscache_operation *op)
|
||||||
|
|
||||||
object = op->object;
|
object = op->object;
|
||||||
|
|
||||||
if (test_bit(FSCACHE_OP_DEC_READ_CNT, &op->flags))
|
if (test_bit(FSCACHE_OP_DEC_READ_CNT, &op->flags)) {
|
||||||
atomic_dec(&object->n_reads);
|
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
|
/* now... we may get called with the object spinlock held, so we
|
||||||
* complete the cleanup here only if we can immediately acquire the
|
* complete the cleanup here only if we can immediately acquire the
|
||||||
|
|
|
@ -301,6 +301,7 @@ struct fscache_cookie {
|
||||||
#define FSCACHE_COOKIE_PENDING_FILL 3 /* T if pending initial fill on object */
|
#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_FILLING 4 /* T if filling object incrementally */
|
||||||
#define FSCACHE_COOKIE_UNAVAILABLE 5 /* T if cookie is unavailable (error, etc) */
|
#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;
|
extern struct fscache_cookie fscache_fsdef_index;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче