aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fscache/object.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2012-12-20 16:52:36 -0500
committerDavid Howells <dhowells@redhat.com>2012-12-20 17:04:07 -0500
commitef778e7ae67cd426c30cad43378b908f5eb0bad5 (patch)
tree4893f19487cb99e8ec0eb835ec4391d952641a9c /fs/fscache/object.c
parent9f10523f891928330b7529da54c1a3cc65180b1a (diff)
FS-Cache: Provide proper invalidation
Provide a proper invalidation method rather than relying on the netfs retiring the cookie it has and getting a new one. The problem with this is that isn't easy for the netfs to make sure that it has completed/cancelled all its outstanding storage and retrieval operations on the cookie it is retiring. Instead, have the cache provide an invalidation method that will cancel or wait for all currently outstanding operations before invalidating the cache, and will cause new operations to queue up behind that. Whilst invalidation is in progress, some requests will be rejected until the cache can stack a barrier on the operation queue to cause new operations to be deferred behind it. Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'fs/fscache/object.c')
-rw-r--r--fs/fscache/object.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/fs/fscache/object.c b/fs/fscache/object.c
index 773bc798a416..80b549141ea6 100644
--- a/fs/fscache/object.c
+++ b/fs/fscache/object.c
@@ -14,6 +14,7 @@
14 14
15#define FSCACHE_DEBUG_LEVEL COOKIE 15#define FSCACHE_DEBUG_LEVEL COOKIE
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/slab.h>
17#include "internal.h" 18#include "internal.h"
18 19
19const char *fscache_object_states[FSCACHE_OBJECT__NSTATES] = { 20const char *fscache_object_states[FSCACHE_OBJECT__NSTATES] = {
@@ -22,6 +23,7 @@ const char *fscache_object_states[FSCACHE_OBJECT__NSTATES] = {
22 [FSCACHE_OBJECT_CREATING] = "OBJECT_CREATING", 23 [FSCACHE_OBJECT_CREATING] = "OBJECT_CREATING",
23 [FSCACHE_OBJECT_AVAILABLE] = "OBJECT_AVAILABLE", 24 [FSCACHE_OBJECT_AVAILABLE] = "OBJECT_AVAILABLE",
24 [FSCACHE_OBJECT_ACTIVE] = "OBJECT_ACTIVE", 25 [FSCACHE_OBJECT_ACTIVE] = "OBJECT_ACTIVE",
26 [FSCACHE_OBJECT_INVALIDATING] = "OBJECT_INVALIDATING",
25 [FSCACHE_OBJECT_UPDATING] = "OBJECT_UPDATING", 27 [FSCACHE_OBJECT_UPDATING] = "OBJECT_UPDATING",
26 [FSCACHE_OBJECT_DYING] = "OBJECT_DYING", 28 [FSCACHE_OBJECT_DYING] = "OBJECT_DYING",
27 [FSCACHE_OBJECT_LC_DYING] = "OBJECT_LC_DYING", 29 [FSCACHE_OBJECT_LC_DYING] = "OBJECT_LC_DYING",
@@ -39,6 +41,7 @@ const char fscache_object_states_short[FSCACHE_OBJECT__NSTATES][5] = {
39 [FSCACHE_OBJECT_CREATING] = "CRTN", 41 [FSCACHE_OBJECT_CREATING] = "CRTN",
40 [FSCACHE_OBJECT_AVAILABLE] = "AVBL", 42 [FSCACHE_OBJECT_AVAILABLE] = "AVBL",
41 [FSCACHE_OBJECT_ACTIVE] = "ACTV", 43 [FSCACHE_OBJECT_ACTIVE] = "ACTV",
44 [FSCACHE_OBJECT_INVALIDATING] = "INVL",
42 [FSCACHE_OBJECT_UPDATING] = "UPDT", 45 [FSCACHE_OBJECT_UPDATING] = "UPDT",
43 [FSCACHE_OBJECT_DYING] = "DYNG", 46 [FSCACHE_OBJECT_DYING] = "DYNG",
44 [FSCACHE_OBJECT_LC_DYING] = "LCDY", 47 [FSCACHE_OBJECT_LC_DYING] = "LCDY",
@@ -54,6 +57,7 @@ static void fscache_put_object(struct fscache_object *);
54static void fscache_initialise_object(struct fscache_object *); 57static void fscache_initialise_object(struct fscache_object *);
55static void fscache_lookup_object(struct fscache_object *); 58static void fscache_lookup_object(struct fscache_object *);
56static void fscache_object_available(struct fscache_object *); 59static void fscache_object_available(struct fscache_object *);
60static void fscache_invalidate_object(struct fscache_object *);
57static void fscache_release_object(struct fscache_object *); 61static void fscache_release_object(struct fscache_object *);
58static void fscache_withdraw_object(struct fscache_object *); 62static void fscache_withdraw_object(struct fscache_object *);
59static void fscache_enqueue_dependents(struct fscache_object *); 63static void fscache_enqueue_dependents(struct fscache_object *);
@@ -79,6 +83,15 @@ static inline void fscache_done_parent_op(struct fscache_object *object)
79} 83}
80 84
81/* 85/*
86 * Notify netfs of invalidation completion.
87 */
88static inline void fscache_invalidation_complete(struct fscache_cookie *cookie)
89{
90 if (test_and_clear_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags))
91 wake_up_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING);
92}
93
94/*
82 * process events that have been sent to an object's state machine 95 * process events that have been sent to an object's state machine
83 * - initiates parent lookup 96 * - initiates parent lookup
84 * - does object lookup 97 * - does object lookup
@@ -125,6 +138,16 @@ static void fscache_object_state_machine(struct fscache_object *object)
125 case FSCACHE_OBJECT_ACTIVE: 138 case FSCACHE_OBJECT_ACTIVE:
126 goto active_transit; 139 goto active_transit;
127 140
141 /* Invalidate an object on disk */
142 case FSCACHE_OBJECT_INVALIDATING:
143 clear_bit(FSCACHE_OBJECT_EV_INVALIDATE, &object->events);
144 fscache_stat(&fscache_n_invalidates_run);
145 fscache_stat(&fscache_n_cop_invalidate_object);
146 fscache_invalidate_object(object);
147 fscache_stat_d(&fscache_n_cop_invalidate_object);
148 fscache_raise_event(object, FSCACHE_OBJECT_EV_UPDATE);
149 goto active_transit;
150
128 /* update the object metadata on disk */ 151 /* update the object metadata on disk */
129 case FSCACHE_OBJECT_UPDATING: 152 case FSCACHE_OBJECT_UPDATING:
130 clear_bit(FSCACHE_OBJECT_EV_UPDATE, &object->events); 153 clear_bit(FSCACHE_OBJECT_EV_UPDATE, &object->events);
@@ -275,6 +298,9 @@ active_transit:
275 case FSCACHE_OBJECT_EV_ERROR: 298 case FSCACHE_OBJECT_EV_ERROR:
276 new_state = FSCACHE_OBJECT_DYING; 299 new_state = FSCACHE_OBJECT_DYING;
277 goto change_state; 300 goto change_state;
301 case FSCACHE_OBJECT_EV_INVALIDATE:
302 new_state = FSCACHE_OBJECT_INVALIDATING;
303 goto change_state;
278 case FSCACHE_OBJECT_EV_UPDATE: 304 case FSCACHE_OBJECT_EV_UPDATE:
279 new_state = FSCACHE_OBJECT_UPDATING; 305 new_state = FSCACHE_OBJECT_UPDATING;
280 goto change_state; 306 goto change_state;
@@ -679,6 +705,7 @@ static void fscache_withdraw_object(struct fscache_object *object)
679 if (object->cookie == cookie) { 705 if (object->cookie == cookie) {
680 hlist_del_init(&object->cookie_link); 706 hlist_del_init(&object->cookie_link);
681 object->cookie = NULL; 707 object->cookie = NULL;
708 fscache_invalidation_complete(cookie);
682 detached = true; 709 detached = true;
683 } 710 }
684 spin_unlock(&cookie->lock); 711 spin_unlock(&cookie->lock);
@@ -888,3 +915,48 @@ enum fscache_checkaux fscache_check_aux(struct fscache_object *object,
888 return result; 915 return result;
889} 916}
890EXPORT_SYMBOL(fscache_check_aux); 917EXPORT_SYMBOL(fscache_check_aux);
918
919/*
920 * Asynchronously invalidate an object.
921 */
922static void fscache_invalidate_object(struct fscache_object *object)
923{
924 struct fscache_operation *op;
925 struct fscache_cookie *cookie = object->cookie;
926
927 _enter("{OBJ%x}", object->debug_id);
928
929 /* Reject any new read/write ops and abort any that are pending. */
930 fscache_invalidate_writes(cookie);
931 clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags);
932 fscache_cancel_all_ops(object);
933
934 /* Now we have to wait for in-progress reads and writes */
935 op = kzalloc(sizeof(*op), GFP_KERNEL);
936 if (!op) {
937 fscache_raise_event(object, FSCACHE_OBJECT_EV_ERROR);
938 _leave(" [ENOMEM]");
939 return;
940 }
941
942 fscache_operation_init(op, object->cache->ops->invalidate_object, NULL);
943 op->flags = FSCACHE_OP_ASYNC | (1 << FSCACHE_OP_EXCLUSIVE);
944
945 spin_lock(&cookie->lock);
946 if (fscache_submit_exclusive_op(object, op) < 0)
947 BUG();
948 spin_unlock(&cookie->lock);
949 fscache_put_operation(op);
950
951 /* Once we've completed the invalidation, we know there will be no data
952 * stored in the cache and thus we can reinstate the data-check-skip
953 * optimisation.
954 */
955 set_bit(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags);
956
957 /* We can allow read and write requests to come in once again. They'll
958 * queue up behind our exclusive invalidation operation.
959 */
960 fscache_invalidation_complete(cookie);
961 _leave("");
962}