diff options
author | David Howells <dhowells@redhat.com> | 2013-08-21 17:29:38 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2013-09-06 04:17:30 -0400 |
commit | da9803bc8812f5bd3b26baaa90e515b843c65ff7 (patch) | |
tree | 889b39ec88863fb46606cf345eeb4fdf8a90a67e /fs | |
parent | 6e4664525b1db28f8c4e1130957f70a94c19213e (diff) |
FS-Cache: Add interface to check consistency of a cached object
Extend the fscache netfs API so that the netfs can ask as to whether a cache
object is up to date with respect to its corresponding netfs object:
int fscache_check_consistency(struct fscache_cookie *cookie)
This will call back to the netfs to check whether the auxiliary data associated
with a cookie is correct. It returns 0 if it is and -ESTALE if it isn't; it
may also return -ENOMEM and -ERESTARTSYS.
The backends now have to implement a mandatory operation pointer:
int (*check_consistency)(struct fscache_object *object)
that corresponds to the above API call. FS-Cache takes care of pinning the
object and the cookie in memory and managing this call with respect to the
object state.
Original-author: Hongyi Jia <jiayisuse@gmail.com>
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Hongyi Jia <jiayisuse@gmail.com>
cc: Milosz Tanski <milosz@adfin.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/fscache/cookie.c | 71 | ||||
-rw-r--r-- | fs/fscache/internal.h | 6 | ||||
-rw-r--r-- | fs/fscache/page.c | 55 |
3 files changed, 108 insertions, 24 deletions
diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c index 0e91a3c9fdb2..318e8433527c 100644 --- a/fs/fscache/cookie.c +++ b/fs/fscache/cookie.c | |||
@@ -558,3 +558,74 @@ void __fscache_cookie_put(struct fscache_cookie *cookie) | |||
558 | 558 | ||
559 | _leave(""); | 559 | _leave(""); |
560 | } | 560 | } |
561 | |||
562 | /* | ||
563 | * check the consistency between the netfs inode and the backing cache | ||
564 | * | ||
565 | * NOTE: it only serves no-index type | ||
566 | */ | ||
567 | int __fscache_check_consistency(struct fscache_cookie *cookie) | ||
568 | { | ||
569 | struct fscache_operation *op; | ||
570 | struct fscache_object *object; | ||
571 | int ret; | ||
572 | |||
573 | _enter("%p,", cookie); | ||
574 | |||
575 | ASSERTCMP(cookie->def->type, ==, FSCACHE_COOKIE_TYPE_DATAFILE); | ||
576 | |||
577 | if (fscache_wait_for_deferred_lookup(cookie) < 0) | ||
578 | return -ERESTARTSYS; | ||
579 | |||
580 | if (hlist_empty(&cookie->backing_objects)) | ||
581 | return 0; | ||
582 | |||
583 | op = kzalloc(sizeof(*op), GFP_NOIO | __GFP_NOMEMALLOC | __GFP_NORETRY); | ||
584 | if (!op) | ||
585 | return -ENOMEM; | ||
586 | |||
587 | fscache_operation_init(op, NULL, NULL); | ||
588 | op->flags = FSCACHE_OP_MYTHREAD | | ||
589 | (1 << FSCACHE_OP_WAITING); | ||
590 | |||
591 | spin_lock(&cookie->lock); | ||
592 | |||
593 | if (hlist_empty(&cookie->backing_objects)) | ||
594 | goto inconsistent; | ||
595 | object = hlist_entry(cookie->backing_objects.first, | ||
596 | struct fscache_object, cookie_link); | ||
597 | if (test_bit(FSCACHE_IOERROR, &object->cache->flags)) | ||
598 | goto inconsistent; | ||
599 | |||
600 | op->debug_id = atomic_inc_return(&fscache_op_debug_id); | ||
601 | |||
602 | atomic_inc(&cookie->n_active); | ||
603 | if (fscache_submit_op(object, op) < 0) | ||
604 | goto submit_failed; | ||
605 | |||
606 | /* the work queue now carries its own ref on the object */ | ||
607 | spin_unlock(&cookie->lock); | ||
608 | |||
609 | ret = fscache_wait_for_operation_activation(object, op, | ||
610 | NULL, NULL, NULL); | ||
611 | if (ret == 0) { | ||
612 | /* ask the cache to honour the operation */ | ||
613 | ret = object->cache->ops->check_consistency(op); | ||
614 | fscache_op_complete(op, false); | ||
615 | } else if (ret == -ENOBUFS) { | ||
616 | ret = 0; | ||
617 | } | ||
618 | |||
619 | fscache_put_operation(op); | ||
620 | _leave(" = %d", ret); | ||
621 | return ret; | ||
622 | |||
623 | submit_failed: | ||
624 | atomic_dec(&cookie->n_active); | ||
625 | inconsistent: | ||
626 | spin_unlock(&cookie->lock); | ||
627 | kfree(op); | ||
628 | _leave(" = -ESTALE"); | ||
629 | return -ESTALE; | ||
630 | } | ||
631 | EXPORT_SYMBOL(__fscache_check_consistency); | ||
diff --git a/fs/fscache/internal.h b/fs/fscache/internal.h index 12d505bedb5c..4226f6680b06 100644 --- a/fs/fscache/internal.h +++ b/fs/fscache/internal.h | |||
@@ -130,6 +130,12 @@ extern void fscache_operation_gc(struct work_struct *); | |||
130 | /* | 130 | /* |
131 | * page.c | 131 | * page.c |
132 | */ | 132 | */ |
133 | extern int fscache_wait_for_deferred_lookup(struct fscache_cookie *); | ||
134 | extern int fscache_wait_for_operation_activation(struct fscache_object *, | ||
135 | struct fscache_operation *, | ||
136 | atomic_t *, | ||
137 | atomic_t *, | ||
138 | void (*)(struct fscache_operation *)); | ||
133 | extern void fscache_invalidate_writes(struct fscache_cookie *); | 139 | extern void fscache_invalidate_writes(struct fscache_cookie *); |
134 | 140 | ||
135 | /* | 141 | /* |
diff --git a/fs/fscache/page.c b/fs/fscache/page.c index d479ab3c63e4..793e3d5ca4b5 100644 --- a/fs/fscache/page.c +++ b/fs/fscache/page.c | |||
@@ -278,7 +278,7 @@ static struct fscache_retrieval *fscache_alloc_retrieval( | |||
278 | /* | 278 | /* |
279 | * wait for a deferred lookup to complete | 279 | * wait for a deferred lookup to complete |
280 | */ | 280 | */ |
281 | static int fscache_wait_for_deferred_lookup(struct fscache_cookie *cookie) | 281 | int fscache_wait_for_deferred_lookup(struct fscache_cookie *cookie) |
282 | { | 282 | { |
283 | unsigned long jif; | 283 | unsigned long jif; |
284 | 284 | ||
@@ -322,42 +322,46 @@ static void fscache_do_cancel_retrieval(struct fscache_operation *_op) | |||
322 | /* | 322 | /* |
323 | * wait for an object to become active (or dead) | 323 | * wait for an object to become active (or dead) |
324 | */ | 324 | */ |
325 | static int fscache_wait_for_retrieval_activation(struct fscache_object *object, | 325 | int fscache_wait_for_operation_activation(struct fscache_object *object, |
326 | struct fscache_retrieval *op, | 326 | struct fscache_operation *op, |
327 | atomic_t *stat_op_waits, | 327 | atomic_t *stat_op_waits, |
328 | atomic_t *stat_object_dead) | 328 | atomic_t *stat_object_dead, |
329 | void (*do_cancel)(struct fscache_operation *)) | ||
329 | { | 330 | { |
330 | int ret; | 331 | int ret; |
331 | 332 | ||
332 | if (!test_bit(FSCACHE_OP_WAITING, &op->op.flags)) | 333 | if (!test_bit(FSCACHE_OP_WAITING, &op->flags)) |
333 | goto check_if_dead; | 334 | goto check_if_dead; |
334 | 335 | ||
335 | _debug(">>> WT"); | 336 | _debug(">>> WT"); |
336 | fscache_stat(stat_op_waits); | 337 | if (stat_op_waits) |
337 | if (wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING, | 338 | fscache_stat(stat_op_waits); |
339 | if (wait_on_bit(&op->flags, FSCACHE_OP_WAITING, | ||
338 | fscache_wait_bit_interruptible, | 340 | fscache_wait_bit_interruptible, |
339 | TASK_INTERRUPTIBLE) != 0) { | 341 | TASK_INTERRUPTIBLE) != 0) { |
340 | ret = fscache_cancel_op(&op->op, fscache_do_cancel_retrieval); | 342 | ret = fscache_cancel_op(op, do_cancel); |
341 | if (ret == 0) | 343 | if (ret == 0) |
342 | return -ERESTARTSYS; | 344 | return -ERESTARTSYS; |
343 | 345 | ||
344 | /* it's been removed from the pending queue by another party, | 346 | /* it's been removed from the pending queue by another party, |
345 | * so we should get to run shortly */ | 347 | * so we should get to run shortly */ |
346 | wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING, | 348 | wait_on_bit(&op->flags, FSCACHE_OP_WAITING, |
347 | fscache_wait_bit, TASK_UNINTERRUPTIBLE); | 349 | fscache_wait_bit, TASK_UNINTERRUPTIBLE); |
348 | } | 350 | } |
349 | _debug("<<< GO"); | 351 | _debug("<<< GO"); |
350 | 352 | ||
351 | check_if_dead: | 353 | check_if_dead: |
352 | if (op->op.state == FSCACHE_OP_ST_CANCELLED) { | 354 | if (op->state == FSCACHE_OP_ST_CANCELLED) { |
353 | fscache_stat(stat_object_dead); | 355 | if (stat_object_dead) |
356 | fscache_stat(stat_object_dead); | ||
354 | _leave(" = -ENOBUFS [cancelled]"); | 357 | _leave(" = -ENOBUFS [cancelled]"); |
355 | return -ENOBUFS; | 358 | return -ENOBUFS; |
356 | } | 359 | } |
357 | if (unlikely(fscache_object_is_dead(object))) { | 360 | if (unlikely(fscache_object_is_dead(object))) { |
358 | pr_err("%s() = -ENOBUFS [obj dead %d]\n", __func__, op->op.state); | 361 | pr_err("%s() = -ENOBUFS [obj dead %d]\n", __func__, op->state); |
359 | fscache_cancel_op(&op->op, fscache_do_cancel_retrieval); | 362 | fscache_cancel_op(op, do_cancel); |
360 | fscache_stat(stat_object_dead); | 363 | if (stat_object_dead) |
364 | fscache_stat(stat_object_dead); | ||
361 | return -ENOBUFS; | 365 | return -ENOBUFS; |
362 | } | 366 | } |
363 | return 0; | 367 | return 0; |
@@ -432,10 +436,11 @@ int __fscache_read_or_alloc_page(struct fscache_cookie *cookie, | |||
432 | 436 | ||
433 | /* we wait for the operation to become active, and then process it | 437 | /* we wait for the operation to become active, and then process it |
434 | * *here*, in this thread, and not in the thread pool */ | 438 | * *here*, in this thread, and not in the thread pool */ |
435 | ret = fscache_wait_for_retrieval_activation( | 439 | ret = fscache_wait_for_operation_activation( |
436 | object, op, | 440 | object, &op->op, |
437 | __fscache_stat(&fscache_n_retrieval_op_waits), | 441 | __fscache_stat(&fscache_n_retrieval_op_waits), |
438 | __fscache_stat(&fscache_n_retrievals_object_dead)); | 442 | __fscache_stat(&fscache_n_retrievals_object_dead), |
443 | fscache_do_cancel_retrieval); | ||
439 | if (ret < 0) | 444 | if (ret < 0) |
440 | goto error; | 445 | goto error; |
441 | 446 | ||
@@ -557,10 +562,11 @@ int __fscache_read_or_alloc_pages(struct fscache_cookie *cookie, | |||
557 | 562 | ||
558 | /* we wait for the operation to become active, and then process it | 563 | /* we wait for the operation to become active, and then process it |
559 | * *here*, in this thread, and not in the thread pool */ | 564 | * *here*, in this thread, and not in the thread pool */ |
560 | ret = fscache_wait_for_retrieval_activation( | 565 | ret = fscache_wait_for_operation_activation( |
561 | object, op, | 566 | object, &op->op, |
562 | __fscache_stat(&fscache_n_retrieval_op_waits), | 567 | __fscache_stat(&fscache_n_retrieval_op_waits), |
563 | __fscache_stat(&fscache_n_retrievals_object_dead)); | 568 | __fscache_stat(&fscache_n_retrievals_object_dead), |
569 | fscache_do_cancel_retrieval); | ||
564 | if (ret < 0) | 570 | if (ret < 0) |
565 | goto error; | 571 | goto error; |
566 | 572 | ||
@@ -658,10 +664,11 @@ int __fscache_alloc_page(struct fscache_cookie *cookie, | |||
658 | 664 | ||
659 | fscache_stat(&fscache_n_alloc_ops); | 665 | fscache_stat(&fscache_n_alloc_ops); |
660 | 666 | ||
661 | ret = fscache_wait_for_retrieval_activation( | 667 | ret = fscache_wait_for_operation_activation( |
662 | object, op, | 668 | object, &op->op, |
663 | __fscache_stat(&fscache_n_alloc_op_waits), | 669 | __fscache_stat(&fscache_n_alloc_op_waits), |
664 | __fscache_stat(&fscache_n_allocs_object_dead)); | 670 | __fscache_stat(&fscache_n_allocs_object_dead), |
671 | fscache_do_cancel_retrieval); | ||
665 | if (ret < 0) | 672 | if (ret < 0) |
666 | goto error; | 673 | goto error; |
667 | 674 | ||