FS-Cache: Put an aborted initialised op so that it is accounted correctly
authorDavid Howells <dhowells@redhat.com>
Wed, 25 Feb 2015 14:22:40 +0000 (14:22 +0000)
committerDavid Howells <dhowells@redhat.com>
Thu, 2 Apr 2015 13:28:53 +0000 (14:28 +0100)
Call fscache_put_operation() or a wrapper on any op that has gone through
fscache_operation_init() so that the accounting shown in /proc is done
correctly, specifically fscache_n_op_release.

fscache_put_operation() therefore now allows an op in the INITIALISED state as
well as in the CANCELLED and COMPLETE states.

Note that this means that an operation can get put that doesn't have its
->object pointer filled in, so anything that depends on the object needs to be
conditional in fscache_put_operation().

Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Steve Dickson <steved@redhat.com>
Acked-by: Jeff Layton <jeff.layton@primarydata.com>
fs/fscache/operation.c
fs/fscache/page.c

index b6bf5f399d70edbd3a9dcc651ee7f4ee01c2fd5b..c76c097307682d195a5b3e9c827b36698deed5d1 100644 (file)
@@ -472,7 +472,8 @@ void fscache_put_operation(struct fscache_operation *op)
                return;
 
        _debug("PUT OP");
-       ASSERTIFCMP(op->state != FSCACHE_OP_ST_COMPLETE,
+       ASSERTIFCMP(op->state != FSCACHE_OP_ST_INITIALISED &&
+                   op->state != FSCACHE_OP_ST_COMPLETE,
                    op->state, ==, FSCACHE_OP_ST_CANCELLED);
        op->state = FSCACHE_OP_ST_DEAD;
 
@@ -484,35 +485,36 @@ void fscache_put_operation(struct fscache_operation *op)
        }
 
        object = op->object;
+       if (likely(object)) {
+               if (test_bit(FSCACHE_OP_DEC_READ_CNT, &op->flags))
+                       atomic_dec(&object->n_reads);
+               if (test_bit(FSCACHE_OP_UNUSE_COOKIE, &op->flags))
+                       fscache_unuse_cookie(object);
+
+               /* now... we may get called with the object spinlock held, so we
+                * complete the cleanup here only if we can immediately acquire the
+                * lock, and defer it otherwise */
+               if (!spin_trylock(&object->lock)) {
+                       _debug("defer put");
+                       fscache_stat(&fscache_n_op_deferred_release);
+
+                       cache = object->cache;
+                       spin_lock(&cache->op_gc_list_lock);
+                       list_add_tail(&op->pend_link, &cache->op_gc_list);
+                       spin_unlock(&cache->op_gc_list_lock);
+                       schedule_work(&cache->op_gc);
+                       _leave(" [defer]");
+                       return;
+               }
 
-       if (test_bit(FSCACHE_OP_DEC_READ_CNT, &op->flags))
-               atomic_dec(&object->n_reads);
-       if (test_bit(FSCACHE_OP_UNUSE_COOKIE, &op->flags))
-               fscache_unuse_cookie(object);
-
-       /* now... we may get called with the object spinlock held, so we
-        * complete the cleanup here only if we can immediately acquire the
-        * lock, and defer it otherwise */
-       if (!spin_trylock(&object->lock)) {
-               _debug("defer put");
-               fscache_stat(&fscache_n_op_deferred_release);
+               ASSERTCMP(object->n_ops, >, 0);
+               object->n_ops--;
+               if (object->n_ops == 0)
+                       fscache_raise_event(object, FSCACHE_OBJECT_EV_CLEARED);
 
-               cache = object->cache;
-               spin_lock(&cache->op_gc_list_lock);
-               list_add_tail(&op->pend_link, &cache->op_gc_list);
-               spin_unlock(&cache->op_gc_list_lock);
-               schedule_work(&cache->op_gc);
-               _leave(" [defer]");
-               return;
+               spin_unlock(&object->lock);
        }
 
-       ASSERTCMP(object->n_ops, >, 0);
-       object->n_ops--;
-       if (object->n_ops == 0)
-               fscache_raise_event(object, FSCACHE_OBJECT_EV_CLEARED);
-
-       spin_unlock(&object->lock);
-
        kfree(op);
        _leave(" [done]");
 }
index 433cae927eca6d0b926c6694908e15d6ba2ff13d..7db9752252ef1086c3616a9349405502f34f5003 100644 (file)
@@ -239,7 +239,7 @@ nobufs_dec:
        wake_cookie = __fscache_unuse_cookie(cookie);
 nobufs:
        spin_unlock(&cookie->lock);
-       kfree(op);
+       fscache_put_operation(op);
        if (wake_cookie)
                __fscache_wake_unused_cookie(cookie);
        fscache_stat(&fscache_n_attr_changed_nobufs);
@@ -505,7 +505,7 @@ nobufs_unlock:
        spin_unlock(&cookie->lock);
        if (wake_cookie)
                __fscache_wake_unused_cookie(cookie);
-       kfree(op);
+       fscache_put_retrieval(op);
 nobufs:
        fscache_stat(&fscache_n_retrievals_nobufs);
        _leave(" = -ENOBUFS");
@@ -634,7 +634,7 @@ nobufs_unlock_dec:
        wake_cookie = __fscache_unuse_cookie(cookie);
 nobufs_unlock:
        spin_unlock(&cookie->lock);
-       kfree(op);
+       fscache_put_retrieval(op);
        if (wake_cookie)
                __fscache_wake_unused_cookie(cookie);
 nobufs:
@@ -728,7 +728,7 @@ nobufs_unlock_dec:
        wake_cookie = __fscache_unuse_cookie(cookie);
 nobufs_unlock:
        spin_unlock(&cookie->lock);
-       kfree(op);
+       fscache_put_retrieval(op);
        if (wake_cookie)
                __fscache_wake_unused_cookie(cookie);
 nobufs:
@@ -1018,7 +1018,7 @@ already_pending:
        spin_unlock(&object->lock);
        spin_unlock(&cookie->lock);
        radix_tree_preload_end();
-       kfree(op);
+       fscache_put_operation(&op->op);
        fscache_stat(&fscache_n_stores_ok);
        _leave(" = 0");
        return 0;
@@ -1038,7 +1038,7 @@ nobufs_unlock_obj:
 nobufs:
        spin_unlock(&cookie->lock);
        radix_tree_preload_end();
-       kfree(op);
+       fscache_put_operation(&op->op);
        if (wake_cookie)
                __fscache_wake_unused_cookie(cookie);
        fscache_stat(&fscache_n_stores_nobufs);
@@ -1046,7 +1046,7 @@ nobufs:
        return -ENOBUFS;
 
 nomem_free:
-       kfree(op);
+       fscache_put_operation(&op->op);
 nomem:
        fscache_stat(&fscache_n_stores_oom);
        _leave(" = -ENOMEM");