Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+345 -18
+12
Documentation/filesystems/caching/backend-api.txt
··· 308 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 323 (*) Discard object [mandatory]: 312 324 313 325 void (*drop_object)(struct fscache_object *object)
+38 -8
Documentation/filesystems/caching/netfs-api.txt
··· 35 35 (12) Index and data file update 36 36 (13) Miscellaneous cookie operations 37 37 (14) Cookie unregistration 38 - (15) Index and data file invalidation 39 - (16) FS-Cache specific page flags. 38 + (15) Index invalidation 39 + (16) Data file invalidation 40 + (17) FS-Cache specific page flags. 40 41 41 42 42 43 ============================= ··· 768 767 first. 769 768 770 769 771 - ================================ 772 - INDEX AND DATA FILE INVALIDATION 773 - ================================ 770 + ================== 771 + INDEX INVALIDATION 772 + ================== 774 773 775 - There is no direct way to invalidate an index subtree or a data file. To do 776 - this, the caller should relinquish and retire the cookie they have, and then 777 - acquire a new one. 774 + There is no direct way to invalidate an index subtree. To do this, the caller 775 + should relinquish and retire the cookie they have, and then acquire a new one. 776 + 777 + 778 + ====================== 779 + DATA FILE INVALIDATION 780 + ====================== 781 + 782 + Sometimes it will be necessary to invalidate an object that contains data. 783 + Typically this will be necessary when the server tells the netfs of a foreign 784 + change - at which point the netfs has to throw away all the state it had for an 785 + inode and reload from the server. 786 + 787 + To indicate that a cache object should be invalidated, the following function 788 + can be called: 789 + 790 + void fscache_invalidate(struct fscache_cookie *cookie); 791 + 792 + This can be called with spinlocks held as it defers the work to a thread pool. 793 + All extant storage, retrieval and attribute change ops at this point are 794 + cancelled and discarded. Some future operations will be rejected until the 795 + cache has had a chance to insert a barrier in the operations queue. After 796 + that, operations will be queued again behind the invalidation operation. 797 + 798 + The invalidation operation will perform an attribute change operation and an 799 + auxiliary data update operation as it is very likely these will have changed. 800 + 801 + Using the following function, the netfs can wait for the invalidation operation 802 + to have reached a point at which it can start submitting ordinary operations 803 + once again: 804 + 805 + void fscache_wait_on_invalidate(struct fscache_cookie *cookie); 778 806 779 807 780 808 ===========================
+15 -8
Documentation/filesystems/caching/object.txt
··· 216 216 The normal running state. In this state, requests the netfs makes will be 217 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 228 The state machine comes here to update the object in the cache from the 222 229 netfs's records. This involves updating the auxiliary data that is used ··· 232 225 And there are terminal states in which an object cleans itself up, deallocates 233 226 memory and potentially deletes stuff from disk: 234 227 235 - (7) State FSCACHE_OBJECT_LC_DYING. 228 + (8) State FSCACHE_OBJECT_LC_DYING. 236 229 237 230 The object comes here if it is dying because of a lookup or creation 238 231 error. This would be due to a disk error or system error of some sort. 239 232 Temporary data is cleaned up, and the parent is released. 240 233 241 - (8) State FSCACHE_OBJECT_DYING. 234 + (9) State FSCACHE_OBJECT_DYING. 242 235 243 236 The object comes here if it is dying due to an error, because its parent 244 237 cookie has been relinquished by the netfs or because the cache is being ··· 248 241 can destroy themselves. This object waits for all its children to go away 249 242 before advancing to the next state. 250 243 251 - (9) State FSCACHE_OBJECT_ABORT_INIT. 244 + (10) State FSCACHE_OBJECT_ABORT_INIT. 252 245 253 246 The object comes to this state if it was waiting on its parent in 254 247 FSCACHE_OBJECT_INIT, but its parent died. The object will destroy itself 255 248 so that the parent may proceed from the FSCACHE_OBJECT_DYING state. 256 249 257 - (10) State FSCACHE_OBJECT_RELEASING. 258 - (11) State FSCACHE_OBJECT_RECYCLING. 250 + (11) State FSCACHE_OBJECT_RELEASING. 251 + (12) State FSCACHE_OBJECT_RECYCLING. 259 252 260 253 The object comes to one of these two states when dying once it is rid of 261 254 all its children, if it is dying because the netfs relinquished its 262 255 cookie. In the first state, the cached data is expected to persist, and 263 256 in the second it will be deleted. 264 257 265 - (12) State FSCACHE_OBJECT_WITHDRAWING. 258 + (13) State FSCACHE_OBJECT_WITHDRAWING. 266 259 267 260 The object transits to this state if the cache decides it wants to 268 261 withdraw the object from service, perhaps to make space, but also due to 269 262 error or just because the whole cache is being withdrawn. 270 263 271 - (13) State FSCACHE_OBJECT_DEAD. 264 + (14) State FSCACHE_OBJECT_DEAD. 272 265 273 266 The object transits to this state when the in-memory object record is 274 267 ready to be deleted. The object processor shouldn't ever see an object in
+60
fs/fscache/cookie.c
··· 370 370 } 371 371 372 372 /* 373 + * Invalidate an object. Callable with spinlocks held. 374 + */ 375 + void __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 + } 415 + EXPORT_SYMBOL(__fscache_invalidate); 416 + 417 + /* 418 + * Wait for object invalidation to complete. 419 + */ 420 + void __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 + } 430 + EXPORT_SYMBOL(__fscache_wait_on_invalidate); 431 + 432 + /* 373 433 * update the index entries backing a cookie 374 434 */ 375 435 void __fscache_update_cookie(struct fscache_cookie *cookie)
+10
fs/fscache/internal.h
··· 122 122 extern int fscache_submit_op(struct fscache_object *, 123 123 struct fscache_operation *); 124 124 extern int fscache_cancel_op(struct fscache_operation *); 125 + extern void fscache_cancel_all_ops(struct fscache_object *); 125 126 extern void fscache_abort_object(struct fscache_object *); 126 127 extern void fscache_start_operations(struct fscache_object *); 127 128 extern void fscache_operation_gc(struct work_struct *); 129 + 130 + /* 131 + * page.c 132 + */ 133 + extern void fscache_invalidate_writes(struct fscache_cookie *); 128 134 129 135 /* 130 136 * proc.c ··· 211 205 extern atomic_t fscache_n_acquires_nobufs; 212 206 extern atomic_t fscache_n_acquires_oom; 213 207 208 + extern atomic_t fscache_n_invalidates; 209 + extern atomic_t fscache_n_invalidates_run; 210 + 214 211 extern atomic_t fscache_n_updates; 215 212 extern atomic_t fscache_n_updates_null; 216 213 extern atomic_t fscache_n_updates_run; ··· 246 237 extern atomic_t fscache_n_cop_lookup_object; 247 238 extern atomic_t fscache_n_cop_lookup_complete; 248 239 extern atomic_t fscache_n_cop_grab_object; 240 + extern atomic_t fscache_n_cop_invalidate_object; 249 241 extern atomic_t fscache_n_cop_update_object; 250 242 extern atomic_t fscache_n_cop_drop_object; 251 243 extern atomic_t fscache_n_cop_put_object;
+72
fs/fscache/object.c
··· 14 14 15 15 #define FSCACHE_DEBUG_LEVEL COOKIE 16 16 #include <linux/module.h> 17 + #include <linux/slab.h> 17 18 #include "internal.h" 18 19 19 20 const char *fscache_object_states[FSCACHE_OBJECT__NSTATES] = { ··· 23 22 [FSCACHE_OBJECT_CREATING] = "OBJECT_CREATING", 24 23 [FSCACHE_OBJECT_AVAILABLE] = "OBJECT_AVAILABLE", 25 24 [FSCACHE_OBJECT_ACTIVE] = "OBJECT_ACTIVE", 25 + [FSCACHE_OBJECT_INVALIDATING] = "OBJECT_INVALIDATING", 26 26 [FSCACHE_OBJECT_UPDATING] = "OBJECT_UPDATING", 27 27 [FSCACHE_OBJECT_DYING] = "OBJECT_DYING", 28 28 [FSCACHE_OBJECT_LC_DYING] = "OBJECT_LC_DYING", ··· 41 39 [FSCACHE_OBJECT_CREATING] = "CRTN", 42 40 [FSCACHE_OBJECT_AVAILABLE] = "AVBL", 43 41 [FSCACHE_OBJECT_ACTIVE] = "ACTV", 42 + [FSCACHE_OBJECT_INVALIDATING] = "INVL", 44 43 [FSCACHE_OBJECT_UPDATING] = "UPDT", 45 44 [FSCACHE_OBJECT_DYING] = "DYNG", 46 45 [FSCACHE_OBJECT_LC_DYING] = "LCDY", ··· 57 54 static void fscache_initialise_object(struct fscache_object *); 58 55 static void fscache_lookup_object(struct fscache_object *); 59 56 static void fscache_object_available(struct fscache_object *); 57 + static void fscache_invalidate_object(struct fscache_object *); 60 58 static void fscache_release_object(struct fscache_object *); 61 59 static void fscache_withdraw_object(struct fscache_object *); 62 60 static void fscache_enqueue_dependents(struct fscache_object *); ··· 80 76 if (parent->n_ops == 0) 81 77 fscache_raise_event(parent, FSCACHE_OBJECT_EV_CLEARED); 82 78 spin_unlock(&parent->lock); 79 + } 80 + 81 + /* 82 + * Notify netfs of invalidation completion. 83 + */ 84 + static inline void fscache_invalidation_complete(struct fscache_cookie *cookie) 85 + { 86 + if (test_and_clear_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags)) 87 + wake_up_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING); 83 88 } 84 89 85 90 /* ··· 136 123 137 124 /* normal running state */ 138 125 case FSCACHE_OBJECT_ACTIVE: 126 + goto active_transit; 127 + 128 + /* Invalidate an object on disk */ 129 + case FSCACHE_OBJECT_INVALIDATING: 130 + clear_bit(FSCACHE_OBJECT_EV_INVALIDATE, &object->events); 131 + fscache_stat(&fscache_n_invalidates_run); 132 + fscache_stat(&fscache_n_cop_invalidate_object); 133 + fscache_invalidate_object(object); 134 + fscache_stat_d(&fscache_n_cop_invalidate_object); 135 + fscache_raise_event(object, FSCACHE_OBJECT_EV_UPDATE); 139 136 goto active_transit; 140 137 141 138 /* update the object metadata on disk */ ··· 297 274 case FSCACHE_OBJECT_EV_RELEASE: 298 275 case FSCACHE_OBJECT_EV_ERROR: 299 276 new_state = FSCACHE_OBJECT_DYING; 277 + goto change_state; 278 + case FSCACHE_OBJECT_EV_INVALIDATE: 279 + new_state = FSCACHE_OBJECT_INVALIDATING; 300 280 goto change_state; 301 281 case FSCACHE_OBJECT_EV_UPDATE: 302 282 new_state = FSCACHE_OBJECT_UPDATING; ··· 705 679 if (object->cookie == cookie) { 706 680 hlist_del_init(&object->cookie_link); 707 681 object->cookie = NULL; 682 + fscache_invalidation_complete(cookie); 708 683 detached = true; 709 684 } 710 685 spin_unlock(&cookie->lock); ··· 915 888 return result; 916 889 } 917 890 EXPORT_SYMBOL(fscache_check_aux); 891 + 892 + /* 893 + * Asynchronously invalidate an object. 894 + */ 895 + static void fscache_invalidate_object(struct fscache_object *object) 896 + { 897 + struct fscache_operation *op; 898 + struct fscache_cookie *cookie = object->cookie; 899 + 900 + _enter("{OBJ%x}", object->debug_id); 901 + 902 + /* Reject any new read/write ops and abort any that are pending. */ 903 + fscache_invalidate_writes(cookie); 904 + clear_bit(FSCACHE_OBJECT_PENDING_WRITE, &object->flags); 905 + fscache_cancel_all_ops(object); 906 + 907 + /* Now we have to wait for in-progress reads and writes */ 908 + op = kzalloc(sizeof(*op), GFP_KERNEL); 909 + if (!op) { 910 + fscache_raise_event(object, FSCACHE_OBJECT_EV_ERROR); 911 + _leave(" [ENOMEM]"); 912 + return; 913 + } 914 + 915 + fscache_operation_init(op, object->cache->ops->invalidate_object, NULL); 916 + op->flags = FSCACHE_OP_ASYNC | (1 << FSCACHE_OP_EXCLUSIVE); 917 + 918 + spin_lock(&cookie->lock); 919 + if (fscache_submit_exclusive_op(object, op) < 0) 920 + BUG(); 921 + spin_unlock(&cookie->lock); 922 + fscache_put_operation(op); 923 + 924 + /* Once we've completed the invalidation, we know there will be no data 925 + * stored in the cache and thus we can reinstate the data-check-skip 926 + * optimisation. 927 + */ 928 + set_bit(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags); 929 + 930 + /* We can allow read and write requests to come in once again. They'll 931 + * queue up behind our exclusive invalidation operation. 932 + */ 933 + fscache_invalidation_complete(cookie); 934 + _leave(""); 935 + }
+32
fs/fscache/operation.c
··· 324 324 } 325 325 326 326 /* 327 + * Cancel all pending operations on an object 328 + */ 329 + void 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 359 * Record the completion of an in-progress operation. 328 360 */ 329 361 void fscache_op_complete(struct fscache_operation *op)
+51
fs/fscache/page.c
··· 361 361 if (hlist_empty(&cookie->backing_objects)) 362 362 goto nobufs; 363 363 364 + if (test_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags)) { 365 + _leave(" = -ENOBUFS [invalidating]"); 366 + return -ENOBUFS; 367 + } 368 + 364 369 ASSERTCMP(cookie->def->type, !=, FSCACHE_COOKIE_TYPE_INDEX); 365 370 ASSERTCMP(page, !=, NULL); 366 371 ··· 488 483 if (hlist_empty(&cookie->backing_objects)) 489 484 goto nobufs; 490 485 486 + if (test_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags)) { 487 + _leave(" = -ENOBUFS [invalidating]"); 488 + return -ENOBUFS; 489 + } 490 + 491 491 ASSERTCMP(cookie->def->type, !=, FSCACHE_COOKIE_TYPE_INDEX); 492 492 ASSERTCMP(*nr_pages, >, 0); 493 493 ASSERT(!list_empty(pages)); ··· 600 590 601 591 ASSERTCMP(cookie->def->type, !=, FSCACHE_COOKIE_TYPE_INDEX); 602 592 ASSERTCMP(page, !=, NULL); 593 + 594 + if (test_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags)) { 595 + _leave(" = -ENOBUFS [invalidating]"); 596 + return -ENOBUFS; 597 + } 603 598 604 599 if (fscache_wait_for_deferred_lookup(cookie) < 0) 605 600 return -ERESTARTSYS; ··· 746 731 } 747 732 748 733 /* 734 + * Clear the pages pending writing for invalidation 735 + */ 736 + void fscache_invalidate_writes(struct fscache_cookie *cookie) 737 + { 738 + struct page *page; 739 + void *results[16]; 740 + int n, i; 741 + 742 + _enter(""); 743 + 744 + while (spin_lock(&cookie->stores_lock), 745 + n = radix_tree_gang_lookup_tag(&cookie->stores, results, 0, 746 + ARRAY_SIZE(results), 747 + FSCACHE_COOKIE_PENDING_TAG), 748 + n > 0) { 749 + for (i = n - 1; i >= 0; i--) { 750 + page = results[i]; 751 + radix_tree_delete(&cookie->stores, page->index); 752 + } 753 + 754 + spin_unlock(&cookie->stores_lock); 755 + 756 + for (i = n - 1; i >= 0; i--) 757 + page_cache_release(results[i]); 758 + } 759 + 760 + spin_unlock(&cookie->stores_lock); 761 + _leave(""); 762 + } 763 + 764 + /* 749 765 * request a page be stored in the cache 750 766 * - returns: 751 767 * -ENOMEM - out of memory, nothing done ··· 821 775 ASSERT(PageFsCache(page)); 822 776 823 777 fscache_stat(&fscache_n_stores); 778 + 779 + if (test_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags)) { 780 + _leave(" = -ENOBUFS [invalidating]"); 781 + return -ENOBUFS; 782 + } 824 783 825 784 op = kzalloc(sizeof(*op), GFP_NOIO | __GFP_NOMEMALLOC | __GFP_NORETRY); 826 785 if (!op)
+10 -1
fs/fscache/stats.c
··· 80 80 atomic_t fscache_n_acquires_nobufs; 81 81 atomic_t fscache_n_acquires_oom; 82 82 83 + atomic_t fscache_n_invalidates; 84 + atomic_t fscache_n_invalidates_run; 85 + 83 86 atomic_t fscache_n_updates; 84 87 atomic_t fscache_n_updates_null; 85 88 atomic_t fscache_n_updates_run; ··· 115 112 atomic_t fscache_n_cop_lookup_object; 116 113 atomic_t fscache_n_cop_lookup_complete; 117 114 atomic_t fscache_n_cop_grab_object; 115 + atomic_t fscache_n_cop_invalidate_object; 118 116 atomic_t fscache_n_cop_update_object; 119 117 atomic_t fscache_n_cop_drop_object; 120 118 atomic_t fscache_n_cop_put_object; ··· 171 167 atomic_read(&fscache_n_object_lookups_positive), 172 168 atomic_read(&fscache_n_object_created), 173 169 atomic_read(&fscache_n_object_lookups_timed_out)); 170 + 171 + seq_printf(m, "Invals : n=%u run=%u\n", 172 + atomic_read(&fscache_n_invalidates), 173 + atomic_read(&fscache_n_invalidates_run)); 174 174 175 175 seq_printf(m, "Updates: n=%u nul=%u run=%u\n", 176 176 atomic_read(&fscache_n_updates), ··· 254 246 atomic_read(&fscache_n_cop_lookup_object), 255 247 atomic_read(&fscache_n_cop_lookup_complete), 256 248 atomic_read(&fscache_n_cop_grab_object)); 257 - seq_printf(m, "CacheOp: upo=%d dro=%d pto=%d atc=%d syn=%d\n", 249 + seq_printf(m, "CacheOp: inv=%d upo=%d dro=%d pto=%d atc=%d syn=%d\n", 250 + atomic_read(&fscache_n_cop_invalidate_object), 258 251 atomic_read(&fscache_n_cop_update_object), 259 252 atomic_read(&fscache_n_cop_drop_object), 260 253 atomic_read(&fscache_n_cop_put_object),
+7 -1
include/linux/fscache-cache.h
··· 254 254 /* store the updated auxiliary data on an object */ 255 255 void (*update_object)(struct fscache_object *object); 256 256 257 + /* Invalidate an object */ 258 + void (*invalidate_object)(struct fscache_operation *op); 259 + 257 260 /* discard the resources pinned by an object and effect retirement if 258 261 * necessary */ 259 262 void (*drop_object)(struct fscache_object *object); ··· 332 329 #define FSCACHE_COOKIE_FILLING 4 /* T if filling object incrementally */ 333 330 #define FSCACHE_COOKIE_UNAVAILABLE 5 /* T if cookie is unavailable (error, etc) */ 334 331 #define FSCACHE_COOKIE_WAITING_ON_READS 6 /* T if cookie is waiting on reads */ 332 + #define FSCACHE_COOKIE_INVALIDATING 7 /* T if cookie is being invalidated */ 335 333 }; 336 334 337 335 extern struct fscache_cookie fscache_fsdef_index; ··· 349 345 /* active states */ 350 346 FSCACHE_OBJECT_AVAILABLE, /* cleaning up object after creation */ 351 347 FSCACHE_OBJECT_ACTIVE, /* object is usable */ 348 + FSCACHE_OBJECT_INVALIDATING, /* object is invalidating */ 352 349 FSCACHE_OBJECT_UPDATING, /* object is updating */ 353 350 354 351 /* terminal states */ ··· 383 378 #define FSCACHE_OBJECT_EV_RELEASE 4 /* T if netfs requested object release */ 384 379 #define FSCACHE_OBJECT_EV_RETIRE 5 /* T if netfs requested object retirement */ 385 380 #define FSCACHE_OBJECT_EV_WITHDRAW 6 /* T if cache requested object withdrawal */ 386 - #define FSCACHE_OBJECT_EVENTS_MASK 0x7f /* mask of all events*/ 381 + #define FSCACHE_OBJECT_EV_INVALIDATE 7 /* T if cache requested object invalidation */ 382 + #define FSCACHE_OBJECT_EVENTS_MASK 0xff /* mask of all events*/ 387 383 388 384 unsigned long flags; 389 385 #define FSCACHE_OBJECT_LOCK 0 /* T if object is busy being processed */
+38
include/linux/fscache.h
··· 185 185 extern void __fscache_relinquish_cookie(struct fscache_cookie *, int); 186 186 extern void __fscache_update_cookie(struct fscache_cookie *); 187 187 extern int __fscache_attr_changed(struct fscache_cookie *); 188 + extern void __fscache_invalidate(struct fscache_cookie *); 189 + extern void __fscache_wait_on_invalidate(struct fscache_cookie *); 188 190 extern int __fscache_read_or_alloc_page(struct fscache_cookie *, 189 191 struct page *, 190 192 fscache_rw_complete_t, ··· 389 387 return __fscache_attr_changed(cookie); 390 388 else 391 389 return -ENOBUFS; 390 + } 391 + 392 + /** 393 + * fscache_invalidate - Notify cache that an object needs invalidation 394 + * @cookie: The cookie representing the cache object 395 + * 396 + * Notify the cache that an object is needs to be invalidated and that it 397 + * should abort any retrievals or stores it is doing on the cache. The object 398 + * is then marked non-caching until such time as the invalidation is complete. 399 + * 400 + * This can be called with spinlocks held. 401 + * 402 + * See Documentation/filesystems/caching/netfs-api.txt for a complete 403 + * description. 404 + */ 405 + static inline 406 + void fscache_invalidate(struct fscache_cookie *cookie) 407 + { 408 + if (fscache_cookie_valid(cookie)) 409 + __fscache_invalidate(cookie); 410 + } 411 + 412 + /** 413 + * fscache_wait_on_invalidate - Wait for invalidation to complete 414 + * @cookie: The cookie representing the cache object 415 + * 416 + * Wait for the invalidation of an object to complete. 417 + * 418 + * See Documentation/filesystems/caching/netfs-api.txt for a complete 419 + * description. 420 + */ 421 + static inline 422 + void fscache_wait_on_invalidate(struct fscache_cookie *cookie) 423 + { 424 + if (fscache_cookie_valid(cookie)) 425 + __fscache_wait_on_invalidate(cookie); 392 426 } 393 427 394 428 /**