diff options
Diffstat (limited to 'fs/fscache/page.c')
-rw-r--r-- | fs/fscache/page.c | 112 |
1 files changed, 55 insertions, 57 deletions
diff --git a/fs/fscache/page.c b/fs/fscache/page.c index fc76798bd968..c598ea4c4e7d 100644 --- a/fs/fscache/page.c +++ b/fs/fscache/page.c | |||
@@ -314,6 +314,43 @@ static int fscache_wait_for_deferred_lookup(struct fscache_cookie *cookie) | |||
314 | } | 314 | } |
315 | 315 | ||
316 | /* | 316 | /* |
317 | * wait for an object to become active (or dead) | ||
318 | */ | ||
319 | static int fscache_wait_for_retrieval_activation(struct fscache_object *object, | ||
320 | struct fscache_retrieval *op, | ||
321 | atomic_t *stat_op_waits, | ||
322 | atomic_t *stat_object_dead) | ||
323 | { | ||
324 | int ret; | ||
325 | |||
326 | if (!test_bit(FSCACHE_OP_WAITING, &op->op.flags)) | ||
327 | goto check_if_dead; | ||
328 | |||
329 | _debug(">>> WT"); | ||
330 | fscache_stat(stat_op_waits); | ||
331 | if (wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING, | ||
332 | fscache_wait_bit_interruptible, | ||
333 | TASK_INTERRUPTIBLE) < 0) { | ||
334 | ret = fscache_cancel_op(&op->op); | ||
335 | if (ret == 0) | ||
336 | return -ERESTARTSYS; | ||
337 | |||
338 | /* it's been removed from the pending queue by another party, | ||
339 | * so we should get to run shortly */ | ||
340 | wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING, | ||
341 | fscache_wait_bit, TASK_UNINTERRUPTIBLE); | ||
342 | } | ||
343 | _debug("<<< GO"); | ||
344 | |||
345 | check_if_dead: | ||
346 | if (unlikely(fscache_object_is_dead(object))) { | ||
347 | fscache_stat(stat_object_dead); | ||
348 | return -ENOBUFS; | ||
349 | } | ||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | /* | ||
317 | * read a page from the cache or allocate a block in which to store it | 354 | * read a page from the cache or allocate a block in which to store it |
318 | * - we return: | 355 | * - we return: |
319 | * -ENOMEM - out of memory, nothing done | 356 | * -ENOMEM - out of memory, nothing done |
@@ -376,25 +413,12 @@ int __fscache_read_or_alloc_page(struct fscache_cookie *cookie, | |||
376 | 413 | ||
377 | /* we wait for the operation to become active, and then process it | 414 | /* we wait for the operation to become active, and then process it |
378 | * *here*, in this thread, and not in the thread pool */ | 415 | * *here*, in this thread, and not in the thread pool */ |
379 | if (test_bit(FSCACHE_OP_WAITING, &op->op.flags)) { | 416 | ret = fscache_wait_for_retrieval_activation( |
380 | _debug(">>> WT"); | 417 | object, op, |
381 | fscache_stat(&fscache_n_retrieval_op_waits); | 418 | __fscache_stat(&fscache_n_retrieval_op_waits), |
382 | if (wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING, | 419 | __fscache_stat(&fscache_n_retrievals_object_dead)); |
383 | fscache_wait_bit_interruptible, | 420 | if (ret < 0) |
384 | TASK_INTERRUPTIBLE) < 0) { | 421 | goto error; |
385 | ret = fscache_cancel_op(&op->op); | ||
386 | if (ret == 0) { | ||
387 | ret = -ERESTARTSYS; | ||
388 | goto error; | ||
389 | } | ||
390 | |||
391 | /* it's been removed from the pending queue by another | ||
392 | * party, so we should get to run shortly */ | ||
393 | wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING, | ||
394 | fscache_wait_bit, TASK_UNINTERRUPTIBLE); | ||
395 | } | ||
396 | _debug("<<< GO"); | ||
397 | } | ||
398 | 422 | ||
399 | /* ask the cache to honour the operation */ | 423 | /* ask the cache to honour the operation */ |
400 | if (test_bit(FSCACHE_COOKIE_NO_DATA_YET, &object->cookie->flags)) { | 424 | if (test_bit(FSCACHE_COOKIE_NO_DATA_YET, &object->cookie->flags)) { |
@@ -506,25 +530,12 @@ int __fscache_read_or_alloc_pages(struct fscache_cookie *cookie, | |||
506 | 530 | ||
507 | /* we wait for the operation to become active, and then process it | 531 | /* we wait for the operation to become active, and then process it |
508 | * *here*, in this thread, and not in the thread pool */ | 532 | * *here*, in this thread, and not in the thread pool */ |
509 | if (test_bit(FSCACHE_OP_WAITING, &op->op.flags)) { | 533 | ret = fscache_wait_for_retrieval_activation( |
510 | _debug(">>> WT"); | 534 | object, op, |
511 | fscache_stat(&fscache_n_retrieval_op_waits); | 535 | __fscache_stat(&fscache_n_retrieval_op_waits), |
512 | if (wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING, | 536 | __fscache_stat(&fscache_n_retrievals_object_dead)); |
513 | fscache_wait_bit_interruptible, | 537 | if (ret < 0) |
514 | TASK_INTERRUPTIBLE) < 0) { | 538 | goto error; |
515 | ret = fscache_cancel_op(&op->op); | ||
516 | if (ret == 0) { | ||
517 | ret = -ERESTARTSYS; | ||
518 | goto error; | ||
519 | } | ||
520 | |||
521 | /* it's been removed from the pending queue by another | ||
522 | * party, so we should get to run shortly */ | ||
523 | wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING, | ||
524 | fscache_wait_bit, TASK_UNINTERRUPTIBLE); | ||
525 | } | ||
526 | _debug("<<< GO"); | ||
527 | } | ||
528 | 539 | ||
529 | /* ask the cache to honour the operation */ | 540 | /* ask the cache to honour the operation */ |
530 | if (test_bit(FSCACHE_COOKIE_NO_DATA_YET, &object->cookie->flags)) { | 541 | if (test_bit(FSCACHE_COOKIE_NO_DATA_YET, &object->cookie->flags)) { |
@@ -612,25 +623,12 @@ int __fscache_alloc_page(struct fscache_cookie *cookie, | |||
612 | 623 | ||
613 | fscache_stat(&fscache_n_alloc_ops); | 624 | fscache_stat(&fscache_n_alloc_ops); |
614 | 625 | ||
615 | if (test_bit(FSCACHE_OP_WAITING, &op->op.flags)) { | 626 | ret = fscache_wait_for_retrieval_activation( |
616 | _debug(">>> WT"); | 627 | object, op, |
617 | fscache_stat(&fscache_n_alloc_op_waits); | 628 | __fscache_stat(&fscache_n_alloc_op_waits), |
618 | if (wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING, | 629 | __fscache_stat(&fscache_n_allocs_object_dead)); |
619 | fscache_wait_bit_interruptible, | 630 | if (ret < 0) |
620 | TASK_INTERRUPTIBLE) < 0) { | 631 | goto error; |
621 | ret = fscache_cancel_op(&op->op); | ||
622 | if (ret == 0) { | ||
623 | ret = -ERESTARTSYS; | ||
624 | goto error; | ||
625 | } | ||
626 | |||
627 | /* it's been removed from the pending queue by another | ||
628 | * party, so we should get to run shortly */ | ||
629 | wait_on_bit(&op->op.flags, FSCACHE_OP_WAITING, | ||
630 | fscache_wait_bit, TASK_UNINTERRUPTIBLE); | ||
631 | } | ||
632 | _debug("<<< GO"); | ||
633 | } | ||
634 | 632 | ||
635 | /* ask the cache to honour the operation */ | 633 | /* ask the cache to honour the operation */ |
636 | fscache_stat(&fscache_n_cop_allocate_page); | 634 | fscache_stat(&fscache_n_cop_allocate_page); |