aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--Documentation/filesystems/caching/backend-api.txt12
-rw-r--r--Documentation/filesystems/caching/netfs-api.txt46
-rw-r--r--Documentation/filesystems/caching/object.txt23
-rw-r--r--fs/fscache/cookie.c60
-rw-r--r--fs/fscache/internal.h10
-rw-r--r--fs/fscache/object.c72
-rw-r--r--fs/fscache/operation.c32
-rw-r--r--fs/fscache/page.c51
-rw-r--r--fs/fscache/stats.c11
-rw-r--r--include/linux/fscache-cache.h8
-rw-r--r--include/linux/fscache.h38
11 files changed, 345 insertions, 18 deletions
diff --git a/Documentation/filesystems/caching/backend-api.txt b/Documentation/filesystems/caching/backend-api.txt
index f4769b9399df..d78bab9622c6 100644
--- a/Documentation/filesystems/caching/backend-api.txt
+++ b/Documentation/filesystems/caching/backend-api.txt
@@ -308,6 +308,18 @@ performed on the denizens of the cache. These are held in a structure of type:
308 obtained by calling object->cookie->def->get_aux()/get_attr(). 308 obtained by calling object->cookie->def->get_aux()/get_attr().
309 309
310 310
311 (*) Invalidate data object [mandatory]:
312
313 int (*invalidate_object)(struct fscache_operation *op)
314
315 This is called to invalidate a data object (as pointed to by op->object).
316 All the data stored for this object should be discarded and an
317 attr_changed operation should be performed. The caller will follow up
318 with an object update operation.
319
320 fscache_op_complete() must be called on op before returning.
321
322
311 (*) Discard object [mandatory]: 323 (*) Discard object [mandatory]:
312 324
313 void (*drop_object)(struct fscache_object *object) 325 void (*drop_object)(struct fscache_object *object)
diff --git a/Documentation/filesystems/caching/netfs-api.txt b/Documentation/filesystems/caching/netfs-api.txt
index 7cc6bf2871eb..97e6c0ecc5ef 100644
--- a/Documentation/filesystems/caching/netfs-api.txt
+++ b/Documentation/filesystems/caching/netfs-api.txt
@@ -35,8 +35,9 @@ This document contains the following sections:
35 (12) Index and data file update 35 (12) Index and data file update
36 (13) Miscellaneous cookie operations 36 (13) Miscellaneous cookie operations
37 (14) Cookie unregistration 37 (14) Cookie unregistration
38 (15) Index and data file invalidation 38 (15) Index invalidation
39 (16) FS-Cache specific page flags. 39 (16) Data file invalidation
40 (17) FS-Cache specific page flags.
40 41
41 42
42============================= 43=============================
@@ -767,13 +768,42 @@ the cookies for "child" indices, objects and pages have been relinquished
767first. 768first.
768 769
769 770
770================================ 771==================
771INDEX AND DATA FILE INVALIDATION 772INDEX INVALIDATION
772================================ 773==================
774
775There is no direct way to invalidate an index subtree. To do this, the caller
776should relinquish and retire the cookie they have, and then acquire a new one.
777
778
779======================
780DATA FILE INVALIDATION
781======================
782
783Sometimes it will be necessary to invalidate an object that contains data.
784Typically this will be necessary when the server tells the netfs of a foreign
785change - at which point the netfs has to throw away all the state it had for an
786inode and reload from the server.
787
788To indicate that a cache object should be invalidated, the following function
789can be called:
790
791 void fscache_invalidate(struct fscache_cookie *cookie);
792
793This can be called with spinlocks held as it defers the work to a thread pool.
794All extant storage, retrieval and attribute change ops at this point are
795cancelled and discarded. Some future operations will be rejected until the
796cache has had a chance to insert a barrier in the operations queue. After
797that, operations will be queued again behind the invalidation operation.
798
799The invalidation operation will perform an attribute change operation and an
800auxiliary data update operation as it is very likely these will have changed.
801
802Using the following function, the netfs can wait for the invalidation operation
803to have reached a point at which it can start submitting ordinary operations
804once again:
773 805
774There is no direct way to invalidate an index subtree or a data file. To do 806 void fscache_wait_on_invalidate(struct fscache_cookie *cookie);
775this, the caller should relinquish and retire the cookie they have, and then
776acquire a new one.
777 807
778 808
779=========================== 809===========================
diff --git a/Documentation/filesystems/caching/object.txt b/Documentation/filesystems/caching/object.txt
index 58313348da87..100ff41127e4 100644
--- a/Documentation/filesystems/caching/object.txt
+++ b/Documentation/filesystems/caching/object.txt
@@ -216,7 +216,14 @@ servicing netfs requests:
216 The normal running state. In this state, requests the netfs makes will be 216 The normal running state. In this state, requests the netfs makes will be
217 passed on to the cache. 217 passed on to the cache.
218 218
219 (6) State FSCACHE_OBJECT_UPDATING. 219 (6) State FSCACHE_OBJECT_INVALIDATING.
220
221 The object is undergoing invalidation. When the state comes here, it
222 discards all pending read, write and attribute change operations as it is
223 going to clear out the cache entirely and reinitialise it. It will then
224 continue to the FSCACHE_OBJECT_UPDATING state.
225
226 (7) State FSCACHE_OBJECT_UPDATING.
220 227
221 The state machine comes here to update the object in the cache from the 228 The state machine comes here to update the object in the cache from the
222 netfs's records. This involves updating the auxiliary data that is used 229 netfs's records. This involves updating the auxiliary data that is used
@@ -225,13 +232,13 @@ servicing netfs requests:
225And there are terminal states in which an object cleans itself up, deallocates 232And there are terminal states in which an object cleans itself up, deallocates
226memory and potentially deletes stuff from disk: 233memory and potentially deletes stuff from disk:
227 234
228 (7) State FSCACHE_OBJECT_LC_DYING. 235 (8) State FSCACHE_OBJECT_LC_DYING.
229 236
230 The object comes here if it is dying because of a lookup or creation 237 The object comes here if it is dying because of a lookup or creation
231 error. This would be due to a disk error or system error of some sort. 238 error. This would be due to a disk error or system error of some sort.
232 Temporary data is cleaned up, and the parent is released. 239 Temporary data is cleaned up, and the parent is released.
233 240
234 (8) State FSCACHE_OBJECT_DYING. 241 (9) State FSCACHE_OBJECT_DYING.
235 242
236 The object comes here if it is dying due to an error, because its parent 243 The object comes here if it is dying due to an error, because its parent
237 cookie has been relinquished by the netfs or because the cache is being 244 cookie has been relinquished by the netfs or because the cache is being
@@ -241,27 +248,27 @@ memory and potentially deletes stuff from disk:
241 can destroy themselves. This object waits for all its children to go away 248 can destroy themselves. This object waits for all its children to go away
242 before advancing to the next state. 249 before advancing to the next state.
243 250
244 (9) State FSCACHE_OBJECT_ABORT_INIT. 251(10) State FSCACHE_OBJECT_ABORT_INIT.
245 252
246 The object comes to this state if it was waiting on its parent in 253 The object comes to this state if it was waiting on its parent in
247 FSCACHE_OBJECT_INIT, but its parent died. The object will destroy itself 254 FSCACHE_OBJECT_INIT, but its parent died. The object will destroy itself
248 so that the parent may proceed from the FSCACHE_OBJECT_DYING state. 255 so that the parent may proceed from the FSCACHE_OBJECT_DYING state.
249 256
250(10) State FSCACHE_OBJECT_RELEASING. 257(11) State FSCACHE_OBJECT_RELEASING.
251(11) State FSCACHE_OBJECT_RECYCLING. 258(12) State FSCACHE_OBJECT_RECYCLING.
252 259
253 The object comes to one of these two states when dying once it is rid of 260 The object comes to one of these two states when dying once it is rid of
254 all its children, if it is dying because the netfs relinquished its 261 all its children, if it is dying because the netfs relinquished its
255 cookie. In the first state, the cached data is expected to persist, and 262 cookie. In the first state, the cached data is expected to persist, and
256 in the second it will be deleted. 263 in the second it will be deleted.
257 264
258(12) State FSCACHE_OBJECT_WITHDRAWING. 265(13) State FSCACHE_OBJECT_WITHDRAWING.
259 266
260 The object transits to this state if the cache decides it wants to 267 The object transits to this state if the cache decides it wants to
261 withdraw the object from service, perhaps to make space, but also due to 268 withdraw the object from service, perhaps to make space, but also due to
262 error or just because the whole cache is being withdrawn. 269 error or just because the whole cache is being withdrawn.
263 270
264(13) State FSCACHE_OBJECT_DEAD. 271(14) State FSCACHE_OBJECT_DEAD.
265 272
266 The object transits to this state when the in-memory object record is 273 The object transits to this state when the in-memory object record is
267 ready to be deleted. The object processor shouldn't ever see an object in 274 ready to be deleted. The object processor shouldn't ever see an object in
diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c
index 66be9eccede0..8dcb114758e3 100644
--- a/fs/fscache/cookie.c
+++ b/fs/fscache/cookie.c
@@ -370,6 +370,66 @@ cant_attach_object:
370} 370}
371 371
372/* 372/*
373 * Invalidate an object. Callable with spinlocks held.
374 */
375void __fscache_invalidate(struct fscache_cookie *cookie)
376{
377 struct fscache_object *object;
378
379 _enter("{%s}", cookie->def->name);
380
381 fscache_stat(&fscache_n_invalidates);
382
383 /* Only permit invalidation of data files. Invalidating an index will
384 * require the caller to release all its attachments to the tree rooted
385 * there, and if it's doing that, it may as well just retire the
386 * cookie.
387 */
388 ASSERTCMP(cookie->def->type, ==, FSCACHE_COOKIE_TYPE_DATAFILE);
389
390 /* We will be updating the cookie too. */
391 BUG_ON(!cookie->def->get_aux);
392
393 /* If there's an object, we tell the object state machine to handle the
394 * invalidation on our behalf, otherwise there's nothing to do.
395 */
396 if (!hlist_empty(&cookie->backing_objects)) {
397 spin_lock(&cookie->lock);
398
399 if (!hlist_empty(&cookie->backing_objects) &&
400 !test_and_set_bit(FSCACHE_COOKIE_INVALIDATING,
401 &cookie->flags)) {
402 object = hlist_entry(cookie->backing_objects.first,
403 struct fscache_object,
404 cookie_link);
405 if (object->state < FSCACHE_OBJECT_DYING)
406 fscache_raise_event(
407 object, FSCACHE_OBJECT_EV_INVALIDATE);
408 }
409
410 spin_unlock(&cookie->lock);
411 }
412
413 _leave("");
414}
415EXPORT_SYMBOL(__fscache_invalidate);
416
417/*
418 * Wait for object invalidation to complete.
419 */
420void __fscache_wait_on_invalidate(struct fscache_cookie *cookie)
421{
422 _enter("%p", cookie);
423
424 wait_on_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING,
425 fscache_wait_bit_interruptible,
426 TASK_UNINTERRUPTIBLE);
427
428 _leave("");
429}
430EXPORT_SYMBOL(__fscache_wait_on_invalidate);
431
432/*
373 * update the index entries backing a cookie 433 * update the index entries backing a cookie
374 */ 434 */
375void __fscache_update_cookie(struct fscache_cookie *cookie) 435void __fscache_update_cookie(struct fscache_cookie *cookie)
diff --git a/fs/fscache/internal.h b/fs/fscache/internal.h
index f6aad48d38a8..c81179303930 100644
--- a/fs/fscache/internal.h
+++ b/fs/fscache/internal.h
@@ -122,11 +122,17 @@ extern int fscache_submit_exclusive_op(struct fscache_object *,
122extern int fscache_submit_op(struct fscache_object *, 122extern int fscache_submit_op(struct fscache_object *,
123 struct fscache_operation *); 123 struct fscache_operation *);
124extern int fscache_cancel_op(struct fscache_operation *); 124extern int fscache_cancel_op(struct fscache_operation *);
125extern void fscache_cancel_all_ops(struct fscache_object *);
125extern void fscache_abort_object(struct fscache_object *); 126extern void fscache_abort_object(struct fscache_object *);
126extern void fscache_start_operations(struct fscache_object *); 127extern void fscache_start_operations(struct fscache_object *);
127extern void fscache_operation_gc(struct work_struct *); 128extern void fscache_operation_gc(struct work_struct *);
128 129
129/* 130/*
131 * page.c
132 */
133extern void fscache_invalidate_writes(struct fscache_cookie *);
134
135/*
130 * proc.c 136 * proc.c
131 */ 137 */
132#ifdef CONFIG_PROC_FS 138#ifdef CONFIG_PROC_FS
@@ -205,6 +211,9 @@ extern atomic_t fscache_n_acquires_ok;
205extern atomic_t fscache_n_acquires_nobufs; 211extern atomic_t fscache_n_acquires_nobufs;
206extern atomic_t fscache_n_acquires_oom; 212extern atomic_t fscache_n_acquires_oom;
207 213
214extern atomic_t fscache_n_invalidates;
215extern atomic_t fscache_n_invalidates_run;
216
208extern atomic_t fscache_n_updates; 217extern atomic_t fscache_n_updates;
209extern atomic_t fscache_n_updates_null; 218extern atomic_t fscache_n_updates_null;
210extern atomic_t fscache_n_updates_run; 219extern atomic_t fscache_n_updates_run;
@@ -237,6 +246,7 @@ extern atomic_t fscache_n_cop_alloc_object;
237extern atomic_t fscache_n_cop_lookup_object; 246extern atomic_t fscache_n_cop_lookup_object;
238extern atomic_t fscache_n_cop_lookup_complete; 247extern atomic_t fscache_n_cop_lookup_complete;
239extern atomic_t fscache_n_cop_grab_object; 248extern atomic_t fscache_n_cop_grab_object;
249extern atomic_t fscache_n_cop_invalidate_object;
240extern atomic_t fscache_n_cop_update_object; 250extern atomic_t fscache_n_cop_update_object;
241extern atomic_t fscache_n_cop_drop_object; 251extern atomic_t fscache_n_cop_drop_object;
242extern atomic_t fscache_n_cop_put_object; 252extern atomic_t fscache_n_cop_put_object;
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}
diff --git a/fs/fscache/operation.c b/fs/fscache/operation.c
index 748f9553c2cb..c58dbe613266 100644
--- a/fs/fscache/operation.c
+++ b/fs/fscache/operation.c
@@ -324,6 +324,38 @@ int fscache_cancel_op(struct fscache_operation *op)
324} 324}
325 325
326/* 326/*
327 * Cancel all pending operations on an object
328 */
329void fscache_cancel_all_ops(struct fscache_object *object)
330{
331 struct fscache_operation *op;
332
333 _enter("OBJ%x", object->debug_id);
334
335 spin_lock(&object->lock);
336
337 while (!list_empty(&object->pending_ops)) {
338 op = list_entry(object->pending_ops.next,
339 struct fscache_operation, pend_link);
340 fscache_stat(&fscache_n_op_cancelled);
341 list_del_init(&op->pend_link);
342
343 ASSERTCMP(op->state, ==, FSCACHE_OP_ST_PENDING);
344 op->state = FSCACHE_OP_ST_CANCELLED;
345
346 if (test_bit(FSCACHE_OP_EXCLUSIVE, &op->flags))
347 object->n_exclusive--;
348 if (test_and_clear_bit(FSCACHE_OP_WAITING, &op->flags))
349 wake_up_bit(&op->flags, FSCACHE_OP_WAITING);
350 fscache_put_operation(op);
351 cond_resched_lock(&object->lock);
352 }
353
354 spin_unlock(&object->lock);
355 _leave("");
356}
357
358/*
327 * Record the completion of an in-progress operation. 359 * Record the completion of an in-progress operation.
328 */ 360 */
329void fscache_op_complete(struct fscache_operation *op) 361void fscache_op_complete(struct fscache_operation *op)
diff --git a/fs/fscache/page.c b/fs/fscache/page.c
index b38b13d2a555..7bf9d2557052 100644
--- a/fs/fscache/page.c
+++ b/fs/fscache/page.c
@@ -361,6 +361,11 @@ int __fscache_read_or_alloc_page(struct fscache_cookie *cookie,
361 if (hlist_empty(&cookie->backing_objects)) 361 if (hlist_empty(&cookie->backing_objects))
362 goto nobufs; 362 goto nobufs;
363 363
364 if (test_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags)) {
365 _leave(" = -ENOBUFS [invalidating]");
366 return -ENOBUFS;
367 }
368
364 ASSERTCMP(cookie->def->type, !=, FSCACHE_COOKIE_TYPE_INDEX); 369 ASSERTCMP(cookie->def->type, !=, FSCACHE_COOKIE_TYPE_INDEX);
365 ASSERTCMP(page, !=, NULL); 370 ASSERTCMP(page, !=, NULL);
366 371
@@ -483,6 +488,11 @@ int __fscache_read_or_alloc_pages(struct fscache_cookie *cookie,
483 if (hlist_empty(&cookie->backing_objects)) 488 if (hlist_empty(&cookie->backing_objects))
484 goto nobufs; 489 goto nobufs;
485 490
491 if (test_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags)) {
492 _leave(" = -ENOBUFS [invalidating]");
493 return -ENOBUFS;
494 }
495
486 ASSERTCMP(cookie->def->type, !=, FSCACHE_COOKIE_TYPE_INDEX); 496 ASSERTCMP(cookie->def->type, !=, FSCACHE_COOKIE_TYPE_INDEX);
487 ASSERTCMP(*nr_pages, >, 0); 497 ASSERTCMP(*nr_pages, >, 0);
488 ASSERT(!list_empty(pages)); 498 ASSERT(!list_empty(pages));
@@ -591,6 +601,11 @@ int __fscache_alloc_page(struct fscache_cookie *cookie,
591 ASSERTCMP(cookie->def->type, !=, FSCACHE_COOKIE_TYPE_INDEX); 601 ASSERTCMP(cookie->def->type, !=, FSCACHE_COOKIE_TYPE_INDEX);
592 ASSERTCMP(page, !=, NULL); 602 ASSERTCMP(page, !=, NULL);
593 603
604 if (test_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags)) {
605 _leave(" = -ENOBUFS [invalidating]");
606 return -ENOBUFS;
607 }
608
594 if (fscache_wait_for_deferred_lookup(cookie) < 0) 609 if (fscache_wait_for_deferred_lookup(cookie) < 0)
595 return -ERESTARTSYS; 610 return -ERESTARTSYS;
596 611
@@ -731,6 +746,37 @@ superseded:
731} 746}
732 747
733/* 748/*
749 * Clear the pages pending writing for invalidation
750 */
751void fscache_invalidate_writes(struct fscache_cookie *cookie)
752{
753 struct page *page;
754 void *results[16];
755 int n, i;
756
757 _enter("");
758
759 while (spin_lock(&cookie->stores_lock),
760 n = radix_tree_gang_lookup_tag(&cookie->stores, results, 0,
761 ARRAY_SIZE(results),
762 FSCACHE_COOKIE_PENDING_TAG),
763 n > 0) {
764 for (i = n - 1; i >= 0; i--) {
765 page = results[i];
766 radix_tree_delete(&cookie->stores, page->index);
767 }
768
769 spin_unlock(&cookie->stores_lock);
770
771 for (i = n - 1; i >= 0; i--)
772 page_cache_release(results[i]);
773 }
774
775 spin_unlock(&cookie->stores_lock);
776 _leave("");
777}
778
779/*
734 * request a page be stored in the cache 780 * request a page be stored in the cache
735 * - returns: 781 * - returns:
736 * -ENOMEM - out of memory, nothing done 782 * -ENOMEM - out of memory, nothing done
@@ -776,6 +822,11 @@ int __fscache_write_page(struct fscache_cookie *cookie,
776 822
777 fscache_stat(&fscache_n_stores); 823 fscache_stat(&fscache_n_stores);
778 824
825 if (test_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags)) {
826 _leave(" = -ENOBUFS [invalidating]");
827 return -ENOBUFS;
828 }
829
779 op = kzalloc(sizeof(*op), GFP_NOIO | __GFP_NOMEMALLOC | __GFP_NORETRY); 830 op = kzalloc(sizeof(*op), GFP_NOIO | __GFP_NOMEMALLOC | __GFP_NORETRY);
780 if (!op) 831 if (!op)
781 goto nomem; 832 goto nomem;
diff --git a/fs/fscache/stats.c b/fs/fscache/stats.c
index 4765190d537f..51cdaee14109 100644
--- a/fs/fscache/stats.c
+++ b/fs/fscache/stats.c
@@ -80,6 +80,9 @@ atomic_t fscache_n_acquires_ok;
80atomic_t fscache_n_acquires_nobufs; 80atomic_t fscache_n_acquires_nobufs;
81atomic_t fscache_n_acquires_oom; 81atomic_t fscache_n_acquires_oom;
82 82
83atomic_t fscache_n_invalidates;
84atomic_t fscache_n_invalidates_run;
85
83atomic_t fscache_n_updates; 86atomic_t fscache_n_updates;
84atomic_t fscache_n_updates_null; 87atomic_t fscache_n_updates_null;
85atomic_t fscache_n_updates_run; 88atomic_t fscache_n_updates_run;
@@ -112,6 +115,7 @@ atomic_t fscache_n_cop_alloc_object;
112atomic_t fscache_n_cop_lookup_object; 115atomic_t fscache_n_cop_lookup_object;
113atomic_t fscache_n_cop_lookup_complete; 116atomic_t fscache_n_cop_lookup_complete;
114atomic_t fscache_n_cop_grab_object; 117atomic_t fscache_n_cop_grab_object;
118atomic_t fscache_n_cop_invalidate_object;
115atomic_t fscache_n_cop_update_object; 119atomic_t fscache_n_cop_update_object;
116atomic_t fscache_n_cop_drop_object; 120atomic_t fscache_n_cop_drop_object;
117atomic_t fscache_n_cop_put_object; 121atomic_t fscache_n_cop_put_object;
@@ -168,6 +172,10 @@ static int fscache_stats_show(struct seq_file *m, void *v)
168 atomic_read(&fscache_n_object_created), 172 atomic_read(&fscache_n_object_created),
169 atomic_read(&fscache_n_object_lookups_timed_out)); 173 atomic_read(&fscache_n_object_lookups_timed_out));
170 174
175 seq_printf(m, "Invals : n=%u run=%u\n",
176 atomic_read(&fscache_n_invalidates),
177 atomic_read(&fscache_n_invalidates_run));
178
171 seq_printf(m, "Updates: n=%u nul=%u run=%u\n", 179 seq_printf(m, "Updates: n=%u nul=%u run=%u\n",
172 atomic_read(&fscache_n_updates), 180 atomic_read(&fscache_n_updates),
173 atomic_read(&fscache_n_updates_null), 181 atomic_read(&fscache_n_updates_null),
@@ -246,7 +254,8 @@ static int fscache_stats_show(struct seq_file *m, void *v)
246 atomic_read(&fscache_n_cop_lookup_object), 254 atomic_read(&fscache_n_cop_lookup_object),
247 atomic_read(&fscache_n_cop_lookup_complete), 255 atomic_read(&fscache_n_cop_lookup_complete),
248 atomic_read(&fscache_n_cop_grab_object)); 256 atomic_read(&fscache_n_cop_grab_object));
249 seq_printf(m, "CacheOp: upo=%d dro=%d pto=%d atc=%d syn=%d\n", 257 seq_printf(m, "CacheOp: inv=%d upo=%d dro=%d pto=%d atc=%d syn=%d\n",
258 atomic_read(&fscache_n_cop_invalidate_object),
250 atomic_read(&fscache_n_cop_update_object), 259 atomic_read(&fscache_n_cop_update_object),
251 atomic_read(&fscache_n_cop_drop_object), 260 atomic_read(&fscache_n_cop_drop_object),
252 atomic_read(&fscache_n_cop_put_object), 261 atomic_read(&fscache_n_cop_put_object),
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h
index f5facd1d333f..1e454ad7a832 100644
--- a/include/linux/fscache-cache.h
+++ b/include/linux/fscache-cache.h
@@ -254,6 +254,9 @@ struct fscache_cache_ops {
254 /* store the updated auxiliary data on an object */ 254 /* store the updated auxiliary data on an object */
255 void (*update_object)(struct fscache_object *object); 255 void (*update_object)(struct fscache_object *object);
256 256
257 /* Invalidate an object */
258 void (*invalidate_object)(struct fscache_operation *op);
259
257 /* discard the resources pinned by an object and effect retirement if 260 /* discard the resources pinned by an object and effect retirement if
258 * necessary */ 261 * necessary */
259 void (*drop_object)(struct fscache_object *object); 262 void (*drop_object)(struct fscache_object *object);
@@ -329,6 +332,7 @@ struct fscache_cookie {
329#define FSCACHE_COOKIE_FILLING 4 /* T if filling object incrementally */ 332#define FSCACHE_COOKIE_FILLING 4 /* T if filling object incrementally */
330#define FSCACHE_COOKIE_UNAVAILABLE 5 /* T if cookie is unavailable (error, etc) */ 333#define FSCACHE_COOKIE_UNAVAILABLE 5 /* T if cookie is unavailable (error, etc) */
331#define FSCACHE_COOKIE_WAITING_ON_READS 6 /* T if cookie is waiting on reads */ 334#define FSCACHE_COOKIE_WAITING_ON_READS 6 /* T if cookie is waiting on reads */
335#define FSCACHE_COOKIE_INVALIDATING 7 /* T if cookie is being invalidated */
332}; 336};
333 337
334extern struct fscache_cookie fscache_fsdef_index; 338extern struct fscache_cookie fscache_fsdef_index;
@@ -345,6 +349,7 @@ struct fscache_object {
345 /* active states */ 349 /* active states */
346 FSCACHE_OBJECT_AVAILABLE, /* cleaning up object after creation */ 350 FSCACHE_OBJECT_AVAILABLE, /* cleaning up object after creation */
347 FSCACHE_OBJECT_ACTIVE, /* object is usable */ 351 FSCACHE_OBJECT_ACTIVE, /* object is usable */
352 FSCACHE_OBJECT_INVALIDATING, /* object is invalidating */
348 FSCACHE_OBJECT_UPDATING, /* object is updating */ 353 FSCACHE_OBJECT_UPDATING, /* object is updating */
349 354
350 /* terminal states */ 355 /* terminal states */
@@ -378,7 +383,8 @@ struct fscache_object {
378#define FSCACHE_OBJECT_EV_RELEASE 4 /* T if netfs requested object release */ 383#define FSCACHE_OBJECT_EV_RELEASE 4 /* T if netfs requested object release */
379#define FSCACHE_OBJECT_EV_RETIRE 5 /* T if netfs requested object retirement */ 384#define FSCACHE_OBJECT_EV_RETIRE 5 /* T if netfs requested object retirement */
380#define FSCACHE_OBJECT_EV_WITHDRAW 6 /* T if cache requested object withdrawal */ 385#define FSCACHE_OBJECT_EV_WITHDRAW 6 /* T if cache requested object withdrawal */
381#define FSCACHE_OBJECT_EVENTS_MASK 0x7f /* mask of all events*/ 386#define FSCACHE_OBJECT_EV_INVALIDATE 7 /* T if cache requested object invalidation */
387#define FSCACHE_OBJECT_EVENTS_MASK 0xff /* mask of all events*/
382 388
383 unsigned long flags; 389 unsigned long flags;
384#define FSCACHE_OBJECT_LOCK 0 /* T if object is busy being processed */ 390#define FSCACHE_OBJECT_LOCK 0 /* T if object is busy being processed */
diff --git a/include/linux/fscache.h b/include/linux/fscache.h
index f4b6353543bf..7a086235da4b 100644
--- a/include/linux/fscache.h
+++ b/include/linux/fscache.h
@@ -185,6 +185,8 @@ extern struct fscache_cookie *__fscache_acquire_cookie(
185extern void __fscache_relinquish_cookie(struct fscache_cookie *, int); 185extern void __fscache_relinquish_cookie(struct fscache_cookie *, int);
186extern void __fscache_update_cookie(struct fscache_cookie *); 186extern void __fscache_update_cookie(struct fscache_cookie *);
187extern int __fscache_attr_changed(struct fscache_cookie *); 187extern int __fscache_attr_changed(struct fscache_cookie *);
188extern void __fscache_invalidate(struct fscache_cookie *);
189extern void __fscache_wait_on_invalidate(struct fscache_cookie *);
188extern int __fscache_read_or_alloc_page(struct fscache_cookie *, 190extern int __fscache_read_or_alloc_page(struct fscache_cookie *,
189 struct page *, 191 struct page *,
190 fscache_rw_complete_t, 192 fscache_rw_complete_t,
@@ -390,6 +392,42 @@ int fscache_attr_changed(struct fscache_cookie *cookie)
390} 392}
391 393
392/** 394/**
395 * fscache_invalidate - Notify cache that an object needs invalidation
396 * @cookie: The cookie representing the cache object
397 *
398 * Notify the cache that an object is needs to be invalidated and that it
399 * should abort any retrievals or stores it is doing on the cache. The object
400 * is then marked non-caching until such time as the invalidation is complete.
401 *
402 * This can be called with spinlocks held.
403 *
404 * See Documentation/filesystems/caching/netfs-api.txt for a complete
405 * description.
406 */
407static inline
408void fscache_invalidate(struct fscache_cookie *cookie)
409{
410 if (fscache_cookie_valid(cookie))
411 __fscache_invalidate(cookie);
412}
413
414/**
415 * fscache_wait_on_invalidate - Wait for invalidation to complete
416 * @cookie: The cookie representing the cache object
417 *
418 * Wait for the invalidation of an object to complete.
419 *
420 * See Documentation/filesystems/caching/netfs-api.txt for a complete
421 * description.
422 */
423static inline
424void fscache_wait_on_invalidate(struct fscache_cookie *cookie)
425{
426 if (fscache_cookie_valid(cookie))
427 __fscache_wait_on_invalidate(cookie);
428}
429
430/**
393 * fscache_reserve_space - Reserve data space for a cached object 431 * fscache_reserve_space - Reserve data space for a cached object
394 * @cookie: The cookie representing the cache object 432 * @cookie: The cookie representing the cache object
395 * @i_size: The amount of space to be reserved 433 * @i_size: The amount of space to be reserved