diff options
Diffstat (limited to 'fs/fscache/object.c')
-rw-r--r-- | fs/fscache/object.c | 72 |
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 | ||
19 | const char *fscache_object_states[FSCACHE_OBJECT__NSTATES] = { | 20 | const 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 *); | |||
54 | static void fscache_initialise_object(struct fscache_object *); | 57 | static void fscache_initialise_object(struct fscache_object *); |
55 | static void fscache_lookup_object(struct fscache_object *); | 58 | static void fscache_lookup_object(struct fscache_object *); |
56 | static void fscache_object_available(struct fscache_object *); | 59 | static void fscache_object_available(struct fscache_object *); |
60 | static void fscache_invalidate_object(struct fscache_object *); | ||
57 | static void fscache_release_object(struct fscache_object *); | 61 | static void fscache_release_object(struct fscache_object *); |
58 | static void fscache_withdraw_object(struct fscache_object *); | 62 | static void fscache_withdraw_object(struct fscache_object *); |
59 | static void fscache_enqueue_dependents(struct fscache_object *); | 63 | static 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 | */ | ||
88 | static 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 | } |
890 | EXPORT_SYMBOL(fscache_check_aux); | 917 | EXPORT_SYMBOL(fscache_check_aux); |
918 | |||
919 | /* | ||
920 | * Asynchronously invalidate an object. | ||
921 | */ | ||
922 | static 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 | } | ||