diff options
Diffstat (limited to 'fs/fscache/page.c')
-rw-r--r-- | fs/fscache/page.c | 65 |
1 files changed, 41 insertions, 24 deletions
diff --git a/fs/fscache/page.c b/fs/fscache/page.c index ff000e52072d..d479ab3c63e4 100644 --- a/fs/fscache/page.c +++ b/fs/fscache/page.c | |||
@@ -109,7 +109,7 @@ page_busy: | |||
109 | * allocator as the work threads writing to the cache may all end up | 109 | * allocator as the work threads writing to the cache may all end up |
110 | * sleeping on memory allocation, so we may need to impose a timeout | 110 | * sleeping on memory allocation, so we may need to impose a timeout |
111 | * too. */ | 111 | * too. */ |
112 | if (!(gfp & __GFP_WAIT)) { | 112 | if (!(gfp & __GFP_WAIT) || !(gfp & __GFP_FS)) { |
113 | fscache_stat(&fscache_n_store_vmscan_busy); | 113 | fscache_stat(&fscache_n_store_vmscan_busy); |
114 | return false; | 114 | return false; |
115 | } | 115 | } |
@@ -163,10 +163,12 @@ static void fscache_attr_changed_op(struct fscache_operation *op) | |||
163 | 163 | ||
164 | fscache_stat(&fscache_n_attr_changed_calls); | 164 | fscache_stat(&fscache_n_attr_changed_calls); |
165 | 165 | ||
166 | if (fscache_object_is_active(object)) { | 166 | if (fscache_object_is_active(object) && |
167 | fscache_use_cookie(object)) { | ||
167 | fscache_stat(&fscache_n_cop_attr_changed); | 168 | fscache_stat(&fscache_n_cop_attr_changed); |
168 | ret = object->cache->ops->attr_changed(object); | 169 | ret = object->cache->ops->attr_changed(object); |
169 | fscache_stat_d(&fscache_n_cop_attr_changed); | 170 | fscache_stat_d(&fscache_n_cop_attr_changed); |
171 | fscache_unuse_cookie(object); | ||
170 | if (ret < 0) | 172 | if (ret < 0) |
171 | fscache_abort_object(object); | 173 | fscache_abort_object(object); |
172 | } | 174 | } |
@@ -233,7 +235,7 @@ static void fscache_release_retrieval_op(struct fscache_operation *_op) | |||
233 | 235 | ||
234 | _enter("{OP%x}", op->op.debug_id); | 236 | _enter("{OP%x}", op->op.debug_id); |
235 | 237 | ||
236 | ASSERTCMP(op->n_pages, ==, 0); | 238 | ASSERTCMP(atomic_read(&op->n_pages), ==, 0); |
237 | 239 | ||
238 | fscache_hist(fscache_retrieval_histogram, op->start_time); | 240 | fscache_hist(fscache_retrieval_histogram, op->start_time); |
239 | if (op->context) | 241 | if (op->context) |
@@ -246,6 +248,7 @@ static void fscache_release_retrieval_op(struct fscache_operation *_op) | |||
246 | * allocate a retrieval op | 248 | * allocate a retrieval op |
247 | */ | 249 | */ |
248 | static struct fscache_retrieval *fscache_alloc_retrieval( | 250 | static struct fscache_retrieval *fscache_alloc_retrieval( |
251 | struct fscache_cookie *cookie, | ||
249 | struct address_space *mapping, | 252 | struct address_space *mapping, |
250 | fscache_rw_complete_t end_io_func, | 253 | fscache_rw_complete_t end_io_func, |
251 | void *context) | 254 | void *context) |
@@ -260,7 +263,10 @@ static struct fscache_retrieval *fscache_alloc_retrieval( | |||
260 | } | 263 | } |
261 | 264 | ||
262 | fscache_operation_init(&op->op, NULL, fscache_release_retrieval_op); | 265 | fscache_operation_init(&op->op, NULL, fscache_release_retrieval_op); |
263 | op->op.flags = FSCACHE_OP_MYTHREAD | (1 << FSCACHE_OP_WAITING); | 266 | atomic_inc(&cookie->n_active); |
267 | op->op.flags = FSCACHE_OP_MYTHREAD | | ||
268 | (1UL << FSCACHE_OP_WAITING) | | ||
269 | (1UL << FSCACHE_OP_UNUSE_COOKIE); | ||
264 | op->mapping = mapping; | 270 | op->mapping = mapping; |
265 | op->end_io_func = end_io_func; | 271 | op->end_io_func = end_io_func; |
266 | op->context = context; | 272 | op->context = context; |
@@ -310,7 +316,7 @@ static void fscache_do_cancel_retrieval(struct fscache_operation *_op) | |||
310 | struct fscache_retrieval *op = | 316 | struct fscache_retrieval *op = |
311 | container_of(_op, struct fscache_retrieval, op); | 317 | container_of(_op, struct fscache_retrieval, op); |
312 | 318 | ||
313 | op->n_pages = 0; | 319 | atomic_set(&op->n_pages, 0); |
314 | } | 320 | } |
315 | 321 | ||
316 | /* | 322 | /* |
@@ -394,12 +400,13 @@ int __fscache_read_or_alloc_page(struct fscache_cookie *cookie, | |||
394 | if (fscache_wait_for_deferred_lookup(cookie) < 0) | 400 | if (fscache_wait_for_deferred_lookup(cookie) < 0) |
395 | return -ERESTARTSYS; | 401 | return -ERESTARTSYS; |
396 | 402 | ||
397 | op = fscache_alloc_retrieval(page->mapping, end_io_func, context); | 403 | op = fscache_alloc_retrieval(cookie, page->mapping, |
404 | end_io_func,context); | ||
398 | if (!op) { | 405 | if (!op) { |
399 | _leave(" = -ENOMEM"); | 406 | _leave(" = -ENOMEM"); |
400 | return -ENOMEM; | 407 | return -ENOMEM; |
401 | } | 408 | } |
402 | op->n_pages = 1; | 409 | atomic_set(&op->n_pages, 1); |
403 | 410 | ||
404 | spin_lock(&cookie->lock); | 411 | spin_lock(&cookie->lock); |
405 | 412 | ||
@@ -408,7 +415,7 @@ int __fscache_read_or_alloc_page(struct fscache_cookie *cookie, | |||
408 | object = hlist_entry(cookie->backing_objects.first, | 415 | object = hlist_entry(cookie->backing_objects.first, |
409 | struct fscache_object, cookie_link); | 416 | struct fscache_object, cookie_link); |
410 | 417 | ||
411 | ASSERTCMP(object->state, >, FSCACHE_OBJECT_LOOKING_UP); | 418 | ASSERT(test_bit(FSCACHE_OBJECT_IS_LOOKED_UP, &object->flags)); |
412 | 419 | ||
413 | atomic_inc(&object->n_reads); | 420 | atomic_inc(&object->n_reads); |
414 | __set_bit(FSCACHE_OP_DEC_READ_CNT, &op->op.flags); | 421 | __set_bit(FSCACHE_OP_DEC_READ_CNT, &op->op.flags); |
@@ -465,6 +472,7 @@ nobufs_unlock_dec: | |||
465 | atomic_dec(&object->n_reads); | 472 | atomic_dec(&object->n_reads); |
466 | nobufs_unlock: | 473 | nobufs_unlock: |
467 | spin_unlock(&cookie->lock); | 474 | spin_unlock(&cookie->lock); |
475 | atomic_dec(&cookie->n_active); | ||
468 | kfree(op); | 476 | kfree(op); |
469 | nobufs: | 477 | nobufs: |
470 | fscache_stat(&fscache_n_retrievals_nobufs); | 478 | fscache_stat(&fscache_n_retrievals_nobufs); |
@@ -522,10 +530,10 @@ int __fscache_read_or_alloc_pages(struct fscache_cookie *cookie, | |||
522 | if (fscache_wait_for_deferred_lookup(cookie) < 0) | 530 | if (fscache_wait_for_deferred_lookup(cookie) < 0) |
523 | return -ERESTARTSYS; | 531 | return -ERESTARTSYS; |
524 | 532 | ||
525 | op = fscache_alloc_retrieval(mapping, end_io_func, context); | 533 | op = fscache_alloc_retrieval(cookie, mapping, end_io_func, context); |
526 | if (!op) | 534 | if (!op) |
527 | return -ENOMEM; | 535 | return -ENOMEM; |
528 | op->n_pages = *nr_pages; | 536 | atomic_set(&op->n_pages, *nr_pages); |
529 | 537 | ||
530 | spin_lock(&cookie->lock); | 538 | spin_lock(&cookie->lock); |
531 | 539 | ||
@@ -589,6 +597,7 @@ nobufs_unlock_dec: | |||
589 | atomic_dec(&object->n_reads); | 597 | atomic_dec(&object->n_reads); |
590 | nobufs_unlock: | 598 | nobufs_unlock: |
591 | spin_unlock(&cookie->lock); | 599 | spin_unlock(&cookie->lock); |
600 | atomic_dec(&cookie->n_active); | ||
592 | kfree(op); | 601 | kfree(op); |
593 | nobufs: | 602 | nobufs: |
594 | fscache_stat(&fscache_n_retrievals_nobufs); | 603 | fscache_stat(&fscache_n_retrievals_nobufs); |
@@ -631,10 +640,10 @@ int __fscache_alloc_page(struct fscache_cookie *cookie, | |||
631 | if (fscache_wait_for_deferred_lookup(cookie) < 0) | 640 | if (fscache_wait_for_deferred_lookup(cookie) < 0) |
632 | return -ERESTARTSYS; | 641 | return -ERESTARTSYS; |
633 | 642 | ||
634 | op = fscache_alloc_retrieval(page->mapping, NULL, NULL); | 643 | op = fscache_alloc_retrieval(cookie, page->mapping, NULL, NULL); |
635 | if (!op) | 644 | if (!op) |
636 | return -ENOMEM; | 645 | return -ENOMEM; |
637 | op->n_pages = 1; | 646 | atomic_set(&op->n_pages, 1); |
638 | 647 | ||
639 | spin_lock(&cookie->lock); | 648 | spin_lock(&cookie->lock); |
640 | 649 | ||
@@ -675,6 +684,7 @@ error: | |||
675 | 684 | ||
676 | nobufs_unlock: | 685 | nobufs_unlock: |
677 | spin_unlock(&cookie->lock); | 686 | spin_unlock(&cookie->lock); |
687 | atomic_dec(&cookie->n_active); | ||
678 | kfree(op); | 688 | kfree(op); |
679 | nobufs: | 689 | nobufs: |
680 | fscache_stat(&fscache_n_allocs_nobufs); | 690 | fscache_stat(&fscache_n_allocs_nobufs); |
@@ -729,8 +739,9 @@ static void fscache_write_op(struct fscache_operation *_op) | |||
729 | */ | 739 | */ |
730 | spin_unlock(&object->lock); | 740 | spin_unlock(&object->lock); |
731 | fscache_op_complete(&op->op, false); | 741 | fscache_op_complete(&op->op, false); |
732 | _leave(" [cancel] op{f=%lx s=%u} obj{s=%u f=%lx}", | 742 | _leave(" [cancel] op{f=%lx s=%u} obj{s=%s f=%lx}", |
733 | _op->flags, _op->state, object->state, object->flags); | 743 | _op->flags, _op->state, object->state->short_name, |
744 | object->flags); | ||
734 | return; | 745 | return; |
735 | } | 746 | } |
736 | 747 | ||
@@ -796,11 +807,16 @@ void fscache_invalidate_writes(struct fscache_cookie *cookie) | |||
796 | 807 | ||
797 | _enter(""); | 808 | _enter(""); |
798 | 809 | ||
799 | while (spin_lock(&cookie->stores_lock), | 810 | for (;;) { |
800 | n = radix_tree_gang_lookup_tag(&cookie->stores, results, 0, | 811 | spin_lock(&cookie->stores_lock); |
801 | ARRAY_SIZE(results), | 812 | n = radix_tree_gang_lookup_tag(&cookie->stores, results, 0, |
802 | FSCACHE_COOKIE_PENDING_TAG), | 813 | ARRAY_SIZE(results), |
803 | n > 0) { | 814 | FSCACHE_COOKIE_PENDING_TAG); |
815 | if (n == 0) { | ||
816 | spin_unlock(&cookie->stores_lock); | ||
817 | break; | ||
818 | } | ||
819 | |||
804 | for (i = n - 1; i >= 0; i--) { | 820 | for (i = n - 1; i >= 0; i--) { |
805 | page = results[i]; | 821 | page = results[i]; |
806 | radix_tree_delete(&cookie->stores, page->index); | 822 | radix_tree_delete(&cookie->stores, page->index); |
@@ -812,7 +828,6 @@ void fscache_invalidate_writes(struct fscache_cookie *cookie) | |||
812 | page_cache_release(results[i]); | 828 | page_cache_release(results[i]); |
813 | } | 829 | } |
814 | 830 | ||
815 | spin_unlock(&cookie->stores_lock); | ||
816 | _leave(""); | 831 | _leave(""); |
817 | } | 832 | } |
818 | 833 | ||
@@ -829,14 +844,12 @@ void fscache_invalidate_writes(struct fscache_cookie *cookie) | |||
829 | * (1) negative lookup, object not yet created (FSCACHE_COOKIE_CREATING is | 844 | * (1) negative lookup, object not yet created (FSCACHE_COOKIE_CREATING is |
830 | * set) | 845 | * set) |
831 | * | 846 | * |
832 | * (a) no writes yet (set FSCACHE_COOKIE_PENDING_FILL and queue deferred | 847 | * (a) no writes yet |
833 | * fill op) | ||
834 | * | 848 | * |
835 | * (b) writes deferred till post-creation (mark page for writing and | 849 | * (b) writes deferred till post-creation (mark page for writing and |
836 | * return immediately) | 850 | * return immediately) |
837 | * | 851 | * |
838 | * (2) negative lookup, object created, initial fill being made from netfs | 852 | * (2) negative lookup, object created, initial fill being made from netfs |
839 | * (FSCACHE_COOKIE_INITIAL_FILL is set) | ||
840 | * | 853 | * |
841 | * (a) fill point not yet reached this page (mark page for writing and | 854 | * (a) fill point not yet reached this page (mark page for writing and |
842 | * return) | 855 | * return) |
@@ -873,7 +886,9 @@ int __fscache_write_page(struct fscache_cookie *cookie, | |||
873 | 886 | ||
874 | fscache_operation_init(&op->op, fscache_write_op, | 887 | fscache_operation_init(&op->op, fscache_write_op, |
875 | fscache_release_write_op); | 888 | fscache_release_write_op); |
876 | op->op.flags = FSCACHE_OP_ASYNC | (1 << FSCACHE_OP_WAITING); | 889 | op->op.flags = FSCACHE_OP_ASYNC | |
890 | (1 << FSCACHE_OP_WAITING) | | ||
891 | (1 << FSCACHE_OP_UNUSE_COOKIE); | ||
877 | 892 | ||
878 | ret = radix_tree_preload(gfp & ~__GFP_HIGHMEM); | 893 | ret = radix_tree_preload(gfp & ~__GFP_HIGHMEM); |
879 | if (ret < 0) | 894 | if (ret < 0) |
@@ -919,6 +934,7 @@ int __fscache_write_page(struct fscache_cookie *cookie, | |||
919 | op->op.debug_id = atomic_inc_return(&fscache_op_debug_id); | 934 | op->op.debug_id = atomic_inc_return(&fscache_op_debug_id); |
920 | op->store_limit = object->store_limit; | 935 | op->store_limit = object->store_limit; |
921 | 936 | ||
937 | atomic_inc(&cookie->n_active); | ||
922 | if (fscache_submit_op(object, &op->op) < 0) | 938 | if (fscache_submit_op(object, &op->op) < 0) |
923 | goto submit_failed; | 939 | goto submit_failed; |
924 | 940 | ||
@@ -945,6 +961,7 @@ already_pending: | |||
945 | return 0; | 961 | return 0; |
946 | 962 | ||
947 | submit_failed: | 963 | submit_failed: |
964 | atomic_dec(&cookie->n_active); | ||
948 | spin_lock(&cookie->stores_lock); | 965 | spin_lock(&cookie->stores_lock); |
949 | radix_tree_delete(&cookie->stores, page->index); | 966 | radix_tree_delete(&cookie->stores, page->index); |
950 | spin_unlock(&cookie->stores_lock); | 967 | spin_unlock(&cookie->stores_lock); |