aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fscache/page.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2009-11-19 13:11:19 -0500
committerDavid Howells <dhowells@redhat.com>2009-11-19 13:11:19 -0500
commit5753c441889253e4323eee85f791a1d64cf08196 (patch)
tree55a0de053d0593d96e99710f978277df668412d1 /fs/fscache/page.c
parentb34df792b4e9e311db47fad27949095d0629c197 (diff)
FS-Cache: Permit cache retrieval ops to be interrupted in the initial wait phase
Permit the operations to retrieve data from the cache or to allocate space in the cache for future writes to be interrupted whilst they're waiting for permission for the operation to proceed. Typically this wait occurs whilst the cache object is being looked up on disk in the background. If an interruption occurs, and the operation has not yet been given the go-ahead to run, the operation is dequeued and cancelled, and control returns to the read operation of the netfs routine with none of the requested pages having been read or in any way marked as known by the cache. This means that the initial wait is done interruptibly rather than uninterruptibly. In addition, extra stats values are made available to show the number of ops cancelled and the number of cache space allocations interrupted. Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'fs/fscache/page.c')
-rw-r--r--fs/fscache/page.c55
1 files changed, 48 insertions, 7 deletions
diff --git a/fs/fscache/page.c b/fs/fscache/page.c
index 250dfd34c07b..e6f2e61133a1 100644
--- a/fs/fscache/page.c
+++ b/fs/fscache/page.c
@@ -295,8 +295,20 @@ int __fscache_read_or_alloc_page(struct fscache_cookie *cookie,
295 if (test_bit(FSCACHE_OP_WAITING, &op->op.flags)) { 295 if (test_bit(FSCACHE_OP_WAITING, &op->op.flags)) {
296 _debug(">>> WT"); 296 _debug(">>> WT");
297 fscache_stat(&fscache_n_retrieval_op_waits); 297 fscache_stat(&fscache_n_retrieval_op_waits);
298 wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING, 298 if (wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING,
299 fscache_wait_bit, TASK_UNINTERRUPTIBLE); 299 fscache_wait_bit_interruptible,
300 TASK_INTERRUPTIBLE) < 0) {
301 ret = fscache_cancel_op(&op->op);
302 if (ret == 0) {
303 ret = -ERESTARTSYS;
304 goto error;
305 }
306
307 /* it's been removed from the pending queue by another
308 * party, so we should get to run shortly */
309 wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING,
310 fscache_wait_bit, TASK_UNINTERRUPTIBLE);
311 }
300 _debug("<<< GO"); 312 _debug("<<< GO");
301 } 313 }
302 314
@@ -313,6 +325,7 @@ int __fscache_read_or_alloc_page(struct fscache_cookie *cookie,
313 fscache_stat_d(&fscache_n_cop_read_or_alloc_page); 325 fscache_stat_d(&fscache_n_cop_read_or_alloc_page);
314 } 326 }
315 327
328error:
316 if (ret == -ENOMEM) 329 if (ret == -ENOMEM)
317 fscache_stat(&fscache_n_retrievals_nomem); 330 fscache_stat(&fscache_n_retrievals_nomem);
318 else if (ret == -ERESTARTSYS) 331 else if (ret == -ERESTARTSYS)
@@ -412,8 +425,20 @@ int __fscache_read_or_alloc_pages(struct fscache_cookie *cookie,
412 if (test_bit(FSCACHE_OP_WAITING, &op->op.flags)) { 425 if (test_bit(FSCACHE_OP_WAITING, &op->op.flags)) {
413 _debug(">>> WT"); 426 _debug(">>> WT");
414 fscache_stat(&fscache_n_retrieval_op_waits); 427 fscache_stat(&fscache_n_retrieval_op_waits);
415 wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING, 428 if (wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING,
416 fscache_wait_bit, TASK_UNINTERRUPTIBLE); 429 fscache_wait_bit_interruptible,
430 TASK_INTERRUPTIBLE) < 0) {
431 ret = fscache_cancel_op(&op->op);
432 if (ret == 0) {
433 ret = -ERESTARTSYS;
434 goto error;
435 }
436
437 /* it's been removed from the pending queue by another
438 * party, so we should get to run shortly */
439 wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING,
440 fscache_wait_bit, TASK_UNINTERRUPTIBLE);
441 }
417 _debug("<<< GO"); 442 _debug("<<< GO");
418 } 443 }
419 444
@@ -430,6 +455,7 @@ int __fscache_read_or_alloc_pages(struct fscache_cookie *cookie,
430 fscache_stat_d(&fscache_n_cop_read_or_alloc_pages); 455 fscache_stat_d(&fscache_n_cop_read_or_alloc_pages);
431 } 456 }
432 457
458error:
433 if (ret == -ENOMEM) 459 if (ret == -ENOMEM)
434 fscache_stat(&fscache_n_retrievals_nomem); 460 fscache_stat(&fscache_n_retrievals_nomem);
435 else if (ret == -ERESTARTSYS) 461 else if (ret == -ERESTARTSYS)
@@ -505,8 +531,20 @@ int __fscache_alloc_page(struct fscache_cookie *cookie,
505 if (test_bit(FSCACHE_OP_WAITING, &op->op.flags)) { 531 if (test_bit(FSCACHE_OP_WAITING, &op->op.flags)) {
506 _debug(">>> WT"); 532 _debug(">>> WT");
507 fscache_stat(&fscache_n_alloc_op_waits); 533 fscache_stat(&fscache_n_alloc_op_waits);
508 wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING, 534 if (wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING,
509 fscache_wait_bit, TASK_UNINTERRUPTIBLE); 535 fscache_wait_bit_interruptible,
536 TASK_INTERRUPTIBLE) < 0) {
537 ret = fscache_cancel_op(&op->op);
538 if (ret == 0) {
539 ret = -ERESTARTSYS;
540 goto error;
541 }
542
543 /* it's been removed from the pending queue by another
544 * party, so we should get to run shortly */
545 wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING,
546 fscache_wait_bit, TASK_UNINTERRUPTIBLE);
547 }
510 _debug("<<< GO"); 548 _debug("<<< GO");
511 } 549 }
512 550
@@ -515,7 +553,10 @@ int __fscache_alloc_page(struct fscache_cookie *cookie,
515 ret = object->cache->ops->allocate_page(op, page, gfp); 553 ret = object->cache->ops->allocate_page(op, page, gfp);
516 fscache_stat_d(&fscache_n_cop_allocate_page); 554 fscache_stat_d(&fscache_n_cop_allocate_page);
517 555
518 if (ret < 0) 556error:
557 if (ret == -ERESTARTSYS)
558 fscache_stat(&fscache_n_allocs_intr);
559 else if (ret < 0)
519 fscache_stat(&fscache_n_allocs_nobufs); 560 fscache_stat(&fscache_n_allocs_nobufs);
520 else 561 else
521 fscache_stat(&fscache_n_allocs_ok); 562 fscache_stat(&fscache_n_allocs_ok);