aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2013-08-21 17:29:38 -0400
committerDavid Howells <dhowells@redhat.com>2013-09-06 04:17:30 -0400
commitda9803bc8812f5bd3b26baaa90e515b843c65ff7 (patch)
tree889b39ec88863fb46606cf345eeb4fdf8a90a67e /fs
parent6e4664525b1db28f8c4e1130957f70a94c19213e (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.c71
-rw-r--r--fs/fscache/internal.h6
-rw-r--r--fs/fscache/page.c55
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 */
567int __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
623submit_failed:
624 atomic_dec(&cookie->n_active);
625inconsistent:
626 spin_unlock(&cookie->lock);
627 kfree(op);
628 _leave(" = -ESTALE");
629 return -ESTALE;
630}
631EXPORT_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 */
133extern int fscache_wait_for_deferred_lookup(struct fscache_cookie *);
134extern int fscache_wait_for_operation_activation(struct fscache_object *,
135 struct fscache_operation *,
136 atomic_t *,
137 atomic_t *,
138 void (*)(struct fscache_operation *));
133extern void fscache_invalidate_writes(struct fscache_cookie *); 139extern 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 */
281static int fscache_wait_for_deferred_lookup(struct fscache_cookie *cookie) 281int 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 */
325static int fscache_wait_for_retrieval_activation(struct fscache_object *object, 325int 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
351check_if_dead: 353check_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