diff options
Diffstat (limited to 'include/linux/fscache-cache.h')
-rw-r--r-- | include/linux/fscache-cache.h | 175 |
1 files changed, 89 insertions, 86 deletions
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h index 5dfa0aa216b6..a9ff9a36b86d 100644 --- a/include/linux/fscache-cache.h +++ b/include/linux/fscache-cache.h | |||
@@ -97,7 +97,8 @@ struct fscache_operation { | |||
97 | #define FSCACHE_OP_WAITING 4 /* cleared when op is woken */ | 97 | #define FSCACHE_OP_WAITING 4 /* cleared when op is woken */ |
98 | #define FSCACHE_OP_EXCLUSIVE 5 /* exclusive op, other ops must wait */ | 98 | #define FSCACHE_OP_EXCLUSIVE 5 /* exclusive op, other ops must wait */ |
99 | #define FSCACHE_OP_DEC_READ_CNT 6 /* decrement object->n_reads on destruction */ | 99 | #define FSCACHE_OP_DEC_READ_CNT 6 /* decrement object->n_reads on destruction */ |
100 | #define FSCACHE_OP_KEEP_FLAGS 0x0070 /* flags to keep when repurposing an op */ | 100 | #define FSCACHE_OP_UNUSE_COOKIE 7 /* call fscache_unuse_cookie() on completion */ |
101 | #define FSCACHE_OP_KEEP_FLAGS 0x00f0 /* flags to keep when repurposing an op */ | ||
101 | 102 | ||
102 | enum fscache_operation_state state; | 103 | enum fscache_operation_state state; |
103 | atomic_t usage; | 104 | atomic_t usage; |
@@ -150,7 +151,7 @@ struct fscache_retrieval { | |||
150 | void *context; /* netfs read context (pinned) */ | 151 | void *context; /* netfs read context (pinned) */ |
151 | struct list_head to_do; /* list of things to be done by the backend */ | 152 | struct list_head to_do; /* list of things to be done by the backend */ |
152 | unsigned long start_time; /* time at which retrieval started */ | 153 | unsigned long start_time; /* time at which retrieval started */ |
153 | unsigned n_pages; /* number of pages to be retrieved */ | 154 | atomic_t n_pages; /* number of pages to be retrieved */ |
154 | }; | 155 | }; |
155 | 156 | ||
156 | typedef int (*fscache_page_retrieval_func_t)(struct fscache_retrieval *op, | 157 | typedef int (*fscache_page_retrieval_func_t)(struct fscache_retrieval *op, |
@@ -194,15 +195,14 @@ static inline void fscache_enqueue_retrieval(struct fscache_retrieval *op) | |||
194 | static inline void fscache_retrieval_complete(struct fscache_retrieval *op, | 195 | static inline void fscache_retrieval_complete(struct fscache_retrieval *op, |
195 | int n_pages) | 196 | int n_pages) |
196 | { | 197 | { |
197 | op->n_pages -= n_pages; | 198 | atomic_sub(n_pages, &op->n_pages); |
198 | if (op->n_pages <= 0) | 199 | if (atomic_read(&op->n_pages) <= 0) |
199 | fscache_op_complete(&op->op, true); | 200 | fscache_op_complete(&op->op, true); |
200 | } | 201 | } |
201 | 202 | ||
202 | /** | 203 | /** |
203 | * fscache_put_retrieval - Drop a reference to a retrieval operation | 204 | * fscache_put_retrieval - Drop a reference to a retrieval operation |
204 | * @op: The retrieval operation affected | 205 | * @op: The retrieval operation affected |
205 | * @n_pages: The number of pages to account for | ||
206 | * | 206 | * |
207 | * Drop a reference to a retrieval operation. | 207 | * Drop a reference to a retrieval operation. |
208 | */ | 208 | */ |
@@ -314,6 +314,7 @@ struct fscache_cache_ops { | |||
314 | struct fscache_cookie { | 314 | struct fscache_cookie { |
315 | atomic_t usage; /* number of users of this cookie */ | 315 | atomic_t usage; /* number of users of this cookie */ |
316 | atomic_t n_children; /* number of children of this cookie */ | 316 | atomic_t n_children; /* number of children of this cookie */ |
317 | atomic_t n_active; /* number of active users of netfs ptrs */ | ||
317 | spinlock_t lock; | 318 | spinlock_t lock; |
318 | spinlock_t stores_lock; /* lock on page store tree */ | 319 | spinlock_t stores_lock; /* lock on page store tree */ |
319 | struct hlist_head backing_objects; /* object(s) backing this file/index */ | 320 | struct hlist_head backing_objects; /* object(s) backing this file/index */ |
@@ -326,13 +327,11 @@ struct fscache_cookie { | |||
326 | 327 | ||
327 | unsigned long flags; | 328 | unsigned long flags; |
328 | #define FSCACHE_COOKIE_LOOKING_UP 0 /* T if non-index cookie being looked up still */ | 329 | #define FSCACHE_COOKIE_LOOKING_UP 0 /* T if non-index cookie being looked up still */ |
329 | #define FSCACHE_COOKIE_CREATING 1 /* T if non-index object being created still */ | 330 | #define FSCACHE_COOKIE_NO_DATA_YET 1 /* T if new object with no cached data yet */ |
330 | #define FSCACHE_COOKIE_NO_DATA_YET 2 /* T if new object with no cached data yet */ | 331 | #define FSCACHE_COOKIE_UNAVAILABLE 2 /* T if cookie is unavailable (error, etc) */ |
331 | #define FSCACHE_COOKIE_PENDING_FILL 3 /* T if pending initial fill on object */ | 332 | #define FSCACHE_COOKIE_INVALIDATING 3 /* T if cookie is being invalidated */ |
332 | #define FSCACHE_COOKIE_FILLING 4 /* T if filling object incrementally */ | 333 | #define FSCACHE_COOKIE_RELINQUISHED 4 /* T if cookie has been relinquished */ |
333 | #define FSCACHE_COOKIE_UNAVAILABLE 5 /* T if cookie is unavailable (error, etc) */ | 334 | #define FSCACHE_COOKIE_RETIRED 5 /* T if cookie was retired */ |
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 */ | ||
336 | }; | 335 | }; |
337 | 336 | ||
338 | extern struct fscache_cookie fscache_fsdef_index; | 337 | extern struct fscache_cookie fscache_fsdef_index; |
@@ -341,45 +340,40 @@ extern struct fscache_cookie fscache_fsdef_index; | |||
341 | * Event list for fscache_object::{event_mask,events} | 340 | * Event list for fscache_object::{event_mask,events} |
342 | */ | 341 | */ |
343 | enum { | 342 | enum { |
344 | FSCACHE_OBJECT_EV_REQUEUE, /* T if object should be requeued */ | 343 | FSCACHE_OBJECT_EV_NEW_CHILD, /* T if object has a new child */ |
344 | FSCACHE_OBJECT_EV_PARENT_READY, /* T if object's parent is ready */ | ||
345 | FSCACHE_OBJECT_EV_UPDATE, /* T if object should be updated */ | 345 | FSCACHE_OBJECT_EV_UPDATE, /* T if object should be updated */ |
346 | FSCACHE_OBJECT_EV_INVALIDATE, /* T if cache requested object invalidation */ | 346 | FSCACHE_OBJECT_EV_INVALIDATE, /* T if cache requested object invalidation */ |
347 | FSCACHE_OBJECT_EV_CLEARED, /* T if accessors all gone */ | 347 | FSCACHE_OBJECT_EV_CLEARED, /* T if accessors all gone */ |
348 | FSCACHE_OBJECT_EV_ERROR, /* T if fatal error occurred during processing */ | 348 | FSCACHE_OBJECT_EV_ERROR, /* T if fatal error occurred during processing */ |
349 | FSCACHE_OBJECT_EV_RELEASE, /* T if netfs requested object release */ | 349 | FSCACHE_OBJECT_EV_KILL, /* T if netfs relinquished or cache withdrew object */ |
350 | FSCACHE_OBJECT_EV_RETIRE, /* T if netfs requested object retirement */ | ||
351 | FSCACHE_OBJECT_EV_WITHDRAW, /* T if cache requested object withdrawal */ | ||
352 | NR_FSCACHE_OBJECT_EVENTS | 350 | NR_FSCACHE_OBJECT_EVENTS |
353 | }; | 351 | }; |
354 | 352 | ||
355 | #define FSCACHE_OBJECT_EVENTS_MASK ((1UL << NR_FSCACHE_OBJECT_EVENTS) - 1) | 353 | #define FSCACHE_OBJECT_EVENTS_MASK ((1UL << NR_FSCACHE_OBJECT_EVENTS) - 1) |
356 | 354 | ||
357 | /* | 355 | /* |
356 | * States for object state machine. | ||
357 | */ | ||
358 | struct fscache_transition { | ||
359 | unsigned long events; | ||
360 | const struct fscache_state *transit_to; | ||
361 | }; | ||
362 | |||
363 | struct fscache_state { | ||
364 | char name[24]; | ||
365 | char short_name[8]; | ||
366 | const struct fscache_state *(*work)(struct fscache_object *object, | ||
367 | int event); | ||
368 | const struct fscache_transition transitions[]; | ||
369 | }; | ||
370 | |||
371 | /* | ||
358 | * on-disk cache file or index handle | 372 | * on-disk cache file or index handle |
359 | */ | 373 | */ |
360 | struct fscache_object { | 374 | struct fscache_object { |
361 | enum fscache_object_state { | 375 | const struct fscache_state *state; /* Object state machine state */ |
362 | FSCACHE_OBJECT_INIT, /* object in initial unbound state */ | 376 | const struct fscache_transition *oob_table; /* OOB state transition table */ |
363 | FSCACHE_OBJECT_LOOKING_UP, /* looking up object */ | ||
364 | FSCACHE_OBJECT_CREATING, /* creating object */ | ||
365 | |||
366 | /* active states */ | ||
367 | FSCACHE_OBJECT_AVAILABLE, /* cleaning up object after creation */ | ||
368 | FSCACHE_OBJECT_ACTIVE, /* object is usable */ | ||
369 | FSCACHE_OBJECT_INVALIDATING, /* object is invalidating */ | ||
370 | FSCACHE_OBJECT_UPDATING, /* object is updating */ | ||
371 | |||
372 | /* terminal states */ | ||
373 | FSCACHE_OBJECT_DYING, /* object waiting for accessors to finish */ | ||
374 | FSCACHE_OBJECT_LC_DYING, /* object cleaning up after lookup/create */ | ||
375 | FSCACHE_OBJECT_ABORT_INIT, /* abort the init state */ | ||
376 | FSCACHE_OBJECT_RELEASING, /* releasing object */ | ||
377 | FSCACHE_OBJECT_RECYCLING, /* retiring object */ | ||
378 | FSCACHE_OBJECT_WITHDRAWING, /* withdrawing object */ | ||
379 | FSCACHE_OBJECT_DEAD, /* object is now dead */ | ||
380 | FSCACHE_OBJECT__NSTATES | ||
381 | } state; | ||
382 | |||
383 | int debug_id; /* debugging ID */ | 377 | int debug_id; /* debugging ID */ |
384 | int n_children; /* number of child objects */ | 378 | int n_children; /* number of child objects */ |
385 | int n_ops; /* number of extant ops on object */ | 379 | int n_ops; /* number of extant ops on object */ |
@@ -390,6 +384,7 @@ struct fscache_object { | |||
390 | spinlock_t lock; /* state and operations lock */ | 384 | spinlock_t lock; /* state and operations lock */ |
391 | 385 | ||
392 | unsigned long lookup_jif; /* time at which lookup started */ | 386 | unsigned long lookup_jif; /* time at which lookup started */ |
387 | unsigned long oob_event_mask; /* OOB events this object is interested in */ | ||
393 | unsigned long event_mask; /* events this object is interested in */ | 388 | unsigned long event_mask; /* events this object is interested in */ |
394 | unsigned long events; /* events to be processed by this object | 389 | unsigned long events; /* events to be processed by this object |
395 | * (order is important - using fls) */ | 390 | * (order is important - using fls) */ |
@@ -398,6 +393,9 @@ struct fscache_object { | |||
398 | #define FSCACHE_OBJECT_LOCK 0 /* T if object is busy being processed */ | 393 | #define FSCACHE_OBJECT_LOCK 0 /* T if object is busy being processed */ |
399 | #define FSCACHE_OBJECT_PENDING_WRITE 1 /* T if object has pending write */ | 394 | #define FSCACHE_OBJECT_PENDING_WRITE 1 /* T if object has pending write */ |
400 | #define FSCACHE_OBJECT_WAITING 2 /* T if object is waiting on its parent */ | 395 | #define FSCACHE_OBJECT_WAITING 2 /* T if object is waiting on its parent */ |
396 | #define FSCACHE_OBJECT_IS_LIVE 3 /* T if object is not withdrawn or relinquished */ | ||
397 | #define FSCACHE_OBJECT_IS_LOOKED_UP 4 /* T if object has been looked up */ | ||
398 | #define FSCACHE_OBJECT_IS_AVAILABLE 5 /* T if object has become active */ | ||
401 | 399 | ||
402 | struct list_head cache_link; /* link in cache->object_list */ | 400 | struct list_head cache_link; /* link in cache->object_list */ |
403 | struct hlist_node cookie_link; /* link in cookie->backing_objects */ | 401 | struct hlist_node cookie_link; /* link in cookie->backing_objects */ |
@@ -415,62 +413,40 @@ struct fscache_object { | |||
415 | loff_t store_limit_l; /* current storage limit */ | 413 | loff_t store_limit_l; /* current storage limit */ |
416 | }; | 414 | }; |
417 | 415 | ||
418 | extern const char *fscache_object_states[]; | 416 | extern void fscache_object_init(struct fscache_object *, struct fscache_cookie *, |
417 | struct fscache_cache *); | ||
418 | extern void fscache_object_destroy(struct fscache_object *); | ||
419 | 419 | ||
420 | #define fscache_object_is_active(obj) \ | 420 | extern void fscache_object_lookup_negative(struct fscache_object *object); |
421 | (!test_bit(FSCACHE_IOERROR, &(obj)->cache->flags) && \ | 421 | extern void fscache_obtained_object(struct fscache_object *object); |
422 | (obj)->state >= FSCACHE_OBJECT_AVAILABLE && \ | ||
423 | (obj)->state < FSCACHE_OBJECT_DYING) | ||
424 | 422 | ||
425 | #define fscache_object_is_dead(obj) \ | 423 | static inline bool fscache_object_is_live(struct fscache_object *object) |
426 | (test_bit(FSCACHE_IOERROR, &(obj)->cache->flags) && \ | 424 | { |
427 | (obj)->state >= FSCACHE_OBJECT_DYING) | 425 | return test_bit(FSCACHE_OBJECT_IS_LIVE, &object->flags); |
426 | } | ||
428 | 427 | ||
429 | extern void fscache_object_work_func(struct work_struct *work); | 428 | static inline bool fscache_object_is_dying(struct fscache_object *object) |
429 | { | ||
430 | return !fscache_object_is_live(object); | ||
431 | } | ||
430 | 432 | ||
431 | /** | 433 | static inline bool fscache_object_is_available(struct fscache_object *object) |
432 | * fscache_object_init - Initialise a cache object description | ||
433 | * @object: Object description | ||
434 | * | ||
435 | * Initialise a cache object description to its basic values. | ||
436 | * | ||
437 | * See Documentation/filesystems/caching/backend-api.txt for a complete | ||
438 | * description. | ||
439 | */ | ||
440 | static inline | ||
441 | void fscache_object_init(struct fscache_object *object, | ||
442 | struct fscache_cookie *cookie, | ||
443 | struct fscache_cache *cache) | ||
444 | { | 434 | { |
445 | atomic_inc(&cache->object_count); | 435 | return test_bit(FSCACHE_OBJECT_IS_AVAILABLE, &object->flags); |
446 | |||
447 | object->state = FSCACHE_OBJECT_INIT; | ||
448 | spin_lock_init(&object->lock); | ||
449 | INIT_LIST_HEAD(&object->cache_link); | ||
450 | INIT_HLIST_NODE(&object->cookie_link); | ||
451 | INIT_WORK(&object->work, fscache_object_work_func); | ||
452 | INIT_LIST_HEAD(&object->dependents); | ||
453 | INIT_LIST_HEAD(&object->dep_link); | ||
454 | INIT_LIST_HEAD(&object->pending_ops); | ||
455 | object->n_children = 0; | ||
456 | object->n_ops = object->n_in_progress = object->n_exclusive = 0; | ||
457 | object->events = object->event_mask = 0; | ||
458 | object->flags = 0; | ||
459 | object->store_limit = 0; | ||
460 | object->store_limit_l = 0; | ||
461 | object->cache = cache; | ||
462 | object->cookie = cookie; | ||
463 | object->parent = NULL; | ||
464 | } | 436 | } |
465 | 437 | ||
466 | extern void fscache_object_lookup_negative(struct fscache_object *object); | 438 | static inline bool fscache_object_is_active(struct fscache_object *object) |
467 | extern void fscache_obtained_object(struct fscache_object *object); | 439 | { |
440 | return fscache_object_is_available(object) && | ||
441 | fscache_object_is_live(object) && | ||
442 | !test_bit(FSCACHE_IOERROR, &object->cache->flags); | ||
443 | } | ||
468 | 444 | ||
469 | #ifdef CONFIG_FSCACHE_OBJECT_LIST | 445 | static inline bool fscache_object_is_dead(struct fscache_object *object) |
470 | extern void fscache_object_destroy(struct fscache_object *object); | 446 | { |
471 | #else | 447 | return fscache_object_is_dying(object) && |
472 | #define fscache_object_destroy(object) do {} while(0) | 448 | test_bit(FSCACHE_IOERROR, &object->cache->flags); |
473 | #endif | 449 | } |
474 | 450 | ||
475 | /** | 451 | /** |
476 | * fscache_object_destroyed - Note destruction of an object in a cache | 452 | * fscache_object_destroyed - Note destruction of an object in a cache |
@@ -531,6 +507,33 @@ static inline void fscache_end_io(struct fscache_retrieval *op, | |||
531 | op->end_io_func(page, op->context, error); | 507 | op->end_io_func(page, op->context, error); |
532 | } | 508 | } |
533 | 509 | ||
510 | /** | ||
511 | * fscache_use_cookie - Request usage of cookie attached to an object | ||
512 | * @object: Object description | ||
513 | * | ||
514 | * Request usage of the cookie attached to an object. NULL is returned if the | ||
515 | * relinquishment had reduced the cookie usage count to 0. | ||
516 | */ | ||
517 | static inline bool fscache_use_cookie(struct fscache_object *object) | ||
518 | { | ||
519 | struct fscache_cookie *cookie = object->cookie; | ||
520 | return atomic_inc_not_zero(&cookie->n_active) != 0; | ||
521 | } | ||
522 | |||
523 | /** | ||
524 | * fscache_unuse_cookie - Cease usage of cookie attached to an object | ||
525 | * @object: Object description | ||
526 | * | ||
527 | * Cease usage of the cookie attached to an object. When the users count | ||
528 | * reaches zero then the cookie relinquishment will be permitted to proceed. | ||
529 | */ | ||
530 | static inline void fscache_unuse_cookie(struct fscache_object *object) | ||
531 | { | ||
532 | struct fscache_cookie *cookie = object->cookie; | ||
533 | if (atomic_dec_and_test(&cookie->n_active)) | ||
534 | wake_up_atomic_t(&cookie->n_active); | ||
535 | } | ||
536 | |||
534 | /* | 537 | /* |
535 | * out-of-line cache backend functions | 538 | * out-of-line cache backend functions |
536 | */ | 539 | */ |