diff options
author | David Howells <dhowells@redhat.com> | 2013-09-20 19:09:31 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2013-09-27 13:40:25 -0400 |
commit | 8fb883f3e30065529e4f35d4b4f355193dcdb7a2 (patch) | |
tree | 2a1096b66c9465539fb6e13daa16137d730f3ea3 /fs/fscache | |
parent | 2457aaf73a97a97c8596ed3903bd09601976f3bc (diff) |
FS-Cache: Add use/unuse/wake cookie wrappers
Add wrapper functions for dealing with cookie->n_active:
(*) __fscache_use_cookie() to increment it.
(*) __fscache_unuse_cookie() to decrement and test against zero.
(*) __fscache_wake_unused_cookie() to wake up anyone waiting for it to reach
zero.
The second and third are split so that the third can be done after cookie->lock
has been released in case the waiter wakes up whilst we're still holding it and
tries to get it.
We will need to wake-on-zero once the cookie disablement patch is applied
because it will then be possible to see n_active become zero without the cookie
being relinquished.
Also move the cookie usement out of fscache_attr_changed_op() and into
fscache_attr_changed() and the operation struct so that cookie disablement
will be able to track it.
Whilst we're at it, only increment n_active if we're about to do
fscache_submit_op() so that we don't have to deal with undoing it if anything
earlier fails. Possibly this should be moved into fscache_submit_op() which
could look at FSCACHE_OP_UNUSE_COOKIE.
Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'fs/fscache')
-rw-r--r-- | fs/fscache/cookie.c | 7 | ||||
-rw-r--r-- | fs/fscache/page.c | 42 |
2 files changed, 36 insertions, 13 deletions
diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c index b2a86e324aac..d851aa555d28 100644 --- a/fs/fscache/cookie.c +++ b/fs/fscache/cookie.c | |||
@@ -568,6 +568,7 @@ int __fscache_check_consistency(struct fscache_cookie *cookie) | |||
568 | { | 568 | { |
569 | struct fscache_operation *op; | 569 | struct fscache_operation *op; |
570 | struct fscache_object *object; | 570 | struct fscache_object *object; |
571 | bool wake_cookie = false; | ||
571 | int ret; | 572 | int ret; |
572 | 573 | ||
573 | _enter("%p,", cookie); | 574 | _enter("%p,", cookie); |
@@ -600,7 +601,7 @@ int __fscache_check_consistency(struct fscache_cookie *cookie) | |||
600 | 601 | ||
601 | op->debug_id = atomic_inc_return(&fscache_op_debug_id); | 602 | op->debug_id = atomic_inc_return(&fscache_op_debug_id); |
602 | 603 | ||
603 | atomic_inc(&cookie->n_active); | 604 | __fscache_use_cookie(cookie); |
604 | if (fscache_submit_op(object, op) < 0) | 605 | if (fscache_submit_op(object, op) < 0) |
605 | goto submit_failed; | 606 | goto submit_failed; |
606 | 607 | ||
@@ -622,9 +623,11 @@ int __fscache_check_consistency(struct fscache_cookie *cookie) | |||
622 | return ret; | 623 | return ret; |
623 | 624 | ||
624 | submit_failed: | 625 | submit_failed: |
625 | atomic_dec(&cookie->n_active); | 626 | wake_cookie = __fscache_unuse_cookie(cookie); |
626 | inconsistent: | 627 | inconsistent: |
627 | spin_unlock(&cookie->lock); | 628 | spin_unlock(&cookie->lock); |
629 | if (wake_cookie) | ||
630 | __fscache_wake_unused_cookie(cookie); | ||
628 | kfree(op); | 631 | kfree(op); |
629 | _leave(" = -ESTALE"); | 632 | _leave(" = -ESTALE"); |
630 | return -ESTALE; | 633 | return -ESTALE; |
diff --git a/fs/fscache/page.c b/fs/fscache/page.c index 73899c1c3449..0fe42a6d0e9c 100644 --- a/fs/fscache/page.c +++ b/fs/fscache/page.c | |||
@@ -163,12 +163,10 @@ 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)) { | ||
168 | fscache_stat(&fscache_n_cop_attr_changed); | 167 | fscache_stat(&fscache_n_cop_attr_changed); |
169 | ret = object->cache->ops->attr_changed(object); | 168 | ret = object->cache->ops->attr_changed(object); |
170 | fscache_stat_d(&fscache_n_cop_attr_changed); | 169 | fscache_stat_d(&fscache_n_cop_attr_changed); |
171 | fscache_unuse_cookie(object); | ||
172 | if (ret < 0) | 170 | if (ret < 0) |
173 | fscache_abort_object(object); | 171 | fscache_abort_object(object); |
174 | } | 172 | } |
@@ -184,6 +182,7 @@ int __fscache_attr_changed(struct fscache_cookie *cookie) | |||
184 | { | 182 | { |
185 | struct fscache_operation *op; | 183 | struct fscache_operation *op; |
186 | struct fscache_object *object; | 184 | struct fscache_object *object; |
185 | bool wake_cookie; | ||
187 | 186 | ||
188 | _enter("%p", cookie); | 187 | _enter("%p", cookie); |
189 | 188 | ||
@@ -199,7 +198,9 @@ int __fscache_attr_changed(struct fscache_cookie *cookie) | |||
199 | } | 198 | } |
200 | 199 | ||
201 | fscache_operation_init(op, fscache_attr_changed_op, NULL); | 200 | fscache_operation_init(op, fscache_attr_changed_op, NULL); |
202 | op->flags = FSCACHE_OP_ASYNC | (1 << FSCACHE_OP_EXCLUSIVE); | 201 | op->flags = FSCACHE_OP_ASYNC | |
202 | (1 << FSCACHE_OP_EXCLUSIVE) | | ||
203 | (1 << FSCACHE_OP_UNUSE_COOKIE); | ||
203 | 204 | ||
204 | spin_lock(&cookie->lock); | 205 | spin_lock(&cookie->lock); |
205 | 206 | ||
@@ -208,6 +209,7 @@ int __fscache_attr_changed(struct fscache_cookie *cookie) | |||
208 | object = hlist_entry(cookie->backing_objects.first, | 209 | object = hlist_entry(cookie->backing_objects.first, |
209 | struct fscache_object, cookie_link); | 210 | struct fscache_object, cookie_link); |
210 | 211 | ||
212 | __fscache_use_cookie(cookie); | ||
211 | if (fscache_submit_exclusive_op(object, op) < 0) | 213 | if (fscache_submit_exclusive_op(object, op) < 0) |
212 | goto nobufs; | 214 | goto nobufs; |
213 | spin_unlock(&cookie->lock); | 215 | spin_unlock(&cookie->lock); |
@@ -217,8 +219,11 @@ int __fscache_attr_changed(struct fscache_cookie *cookie) | |||
217 | return 0; | 219 | return 0; |
218 | 220 | ||
219 | nobufs: | 221 | nobufs: |
222 | wake_cookie = __fscache_unuse_cookie(cookie); | ||
220 | spin_unlock(&cookie->lock); | 223 | spin_unlock(&cookie->lock); |
221 | kfree(op); | 224 | kfree(op); |
225 | if (wake_cookie) | ||
226 | __fscache_wake_unused_cookie(cookie); | ||
222 | fscache_stat(&fscache_n_attr_changed_nobufs); | 227 | fscache_stat(&fscache_n_attr_changed_nobufs); |
223 | _leave(" = %d", -ENOBUFS); | 228 | _leave(" = %d", -ENOBUFS); |
224 | return -ENOBUFS; | 229 | return -ENOBUFS; |
@@ -263,7 +268,6 @@ static struct fscache_retrieval *fscache_alloc_retrieval( | |||
263 | } | 268 | } |
264 | 269 | ||
265 | fscache_operation_init(&op->op, NULL, fscache_release_retrieval_op); | 270 | fscache_operation_init(&op->op, NULL, fscache_release_retrieval_op); |
266 | atomic_inc(&cookie->n_active); | ||
267 | op->op.flags = FSCACHE_OP_MYTHREAD | | 271 | op->op.flags = FSCACHE_OP_MYTHREAD | |
268 | (1UL << FSCACHE_OP_WAITING) | | 272 | (1UL << FSCACHE_OP_WAITING) | |
269 | (1UL << FSCACHE_OP_UNUSE_COOKIE); | 273 | (1UL << FSCACHE_OP_UNUSE_COOKIE); |
@@ -384,6 +388,7 @@ int __fscache_read_or_alloc_page(struct fscache_cookie *cookie, | |||
384 | { | 388 | { |
385 | struct fscache_retrieval *op; | 389 | struct fscache_retrieval *op; |
386 | struct fscache_object *object; | 390 | struct fscache_object *object; |
391 | bool wake_cookie = false; | ||
387 | int ret; | 392 | int ret; |
388 | 393 | ||
389 | _enter("%p,%p,,,", cookie, page); | 394 | _enter("%p,%p,,,", cookie, page); |
@@ -421,6 +426,7 @@ int __fscache_read_or_alloc_page(struct fscache_cookie *cookie, | |||
421 | 426 | ||
422 | ASSERT(test_bit(FSCACHE_OBJECT_IS_LOOKED_UP, &object->flags)); | 427 | ASSERT(test_bit(FSCACHE_OBJECT_IS_LOOKED_UP, &object->flags)); |
423 | 428 | ||
429 | __fscache_use_cookie(cookie); | ||
424 | atomic_inc(&object->n_reads); | 430 | atomic_inc(&object->n_reads); |
425 | __set_bit(FSCACHE_OP_DEC_READ_CNT, &op->op.flags); | 431 | __set_bit(FSCACHE_OP_DEC_READ_CNT, &op->op.flags); |
426 | 432 | ||
@@ -475,9 +481,11 @@ error: | |||
475 | 481 | ||
476 | nobufs_unlock_dec: | 482 | nobufs_unlock_dec: |
477 | atomic_dec(&object->n_reads); | 483 | atomic_dec(&object->n_reads); |
484 | wake_cookie = __fscache_unuse_cookie(cookie); | ||
478 | nobufs_unlock: | 485 | nobufs_unlock: |
479 | spin_unlock(&cookie->lock); | 486 | spin_unlock(&cookie->lock); |
480 | atomic_dec(&cookie->n_active); | 487 | if (wake_cookie) |
488 | __fscache_wake_unused_cookie(cookie); | ||
481 | kfree(op); | 489 | kfree(op); |
482 | nobufs: | 490 | nobufs: |
483 | fscache_stat(&fscache_n_retrievals_nobufs); | 491 | fscache_stat(&fscache_n_retrievals_nobufs); |
@@ -514,6 +522,7 @@ int __fscache_read_or_alloc_pages(struct fscache_cookie *cookie, | |||
514 | { | 522 | { |
515 | struct fscache_retrieval *op; | 523 | struct fscache_retrieval *op; |
516 | struct fscache_object *object; | 524 | struct fscache_object *object; |
525 | bool wake_cookie = false; | ||
517 | int ret; | 526 | int ret; |
518 | 527 | ||
519 | _enter("%p,,%d,,,", cookie, *nr_pages); | 528 | _enter("%p,,%d,,,", cookie, *nr_pages); |
@@ -547,6 +556,7 @@ int __fscache_read_or_alloc_pages(struct fscache_cookie *cookie, | |||
547 | object = hlist_entry(cookie->backing_objects.first, | 556 | object = hlist_entry(cookie->backing_objects.first, |
548 | struct fscache_object, cookie_link); | 557 | struct fscache_object, cookie_link); |
549 | 558 | ||
559 | __fscache_use_cookie(cookie); | ||
550 | atomic_inc(&object->n_reads); | 560 | atomic_inc(&object->n_reads); |
551 | __set_bit(FSCACHE_OP_DEC_READ_CNT, &op->op.flags); | 561 | __set_bit(FSCACHE_OP_DEC_READ_CNT, &op->op.flags); |
552 | 562 | ||
@@ -601,10 +611,12 @@ error: | |||
601 | 611 | ||
602 | nobufs_unlock_dec: | 612 | nobufs_unlock_dec: |
603 | atomic_dec(&object->n_reads); | 613 | atomic_dec(&object->n_reads); |
614 | wake_cookie = __fscache_unuse_cookie(cookie); | ||
604 | nobufs_unlock: | 615 | nobufs_unlock: |
605 | spin_unlock(&cookie->lock); | 616 | spin_unlock(&cookie->lock); |
606 | atomic_dec(&cookie->n_active); | ||
607 | kfree(op); | 617 | kfree(op); |
618 | if (wake_cookie) | ||
619 | __fscache_wake_unused_cookie(cookie); | ||
608 | nobufs: | 620 | nobufs: |
609 | fscache_stat(&fscache_n_retrievals_nobufs); | 621 | fscache_stat(&fscache_n_retrievals_nobufs); |
610 | _leave(" = -ENOBUFS"); | 622 | _leave(" = -ENOBUFS"); |
@@ -626,6 +638,7 @@ int __fscache_alloc_page(struct fscache_cookie *cookie, | |||
626 | { | 638 | { |
627 | struct fscache_retrieval *op; | 639 | struct fscache_retrieval *op; |
628 | struct fscache_object *object; | 640 | struct fscache_object *object; |
641 | bool wake_cookie = false; | ||
629 | int ret; | 642 | int ret; |
630 | 643 | ||
631 | _enter("%p,%p,,,", cookie, page); | 644 | _enter("%p,%p,,,", cookie, page); |
@@ -658,8 +671,9 @@ int __fscache_alloc_page(struct fscache_cookie *cookie, | |||
658 | object = hlist_entry(cookie->backing_objects.first, | 671 | object = hlist_entry(cookie->backing_objects.first, |
659 | struct fscache_object, cookie_link); | 672 | struct fscache_object, cookie_link); |
660 | 673 | ||
674 | __fscache_use_cookie(cookie); | ||
661 | if (fscache_submit_op(object, &op->op) < 0) | 675 | if (fscache_submit_op(object, &op->op) < 0) |
662 | goto nobufs_unlock; | 676 | goto nobufs_unlock_dec; |
663 | spin_unlock(&cookie->lock); | 677 | spin_unlock(&cookie->lock); |
664 | 678 | ||
665 | fscache_stat(&fscache_n_alloc_ops); | 679 | fscache_stat(&fscache_n_alloc_ops); |
@@ -689,10 +703,13 @@ error: | |||
689 | _leave(" = %d", ret); | 703 | _leave(" = %d", ret); |
690 | return ret; | 704 | return ret; |
691 | 705 | ||
706 | nobufs_unlock_dec: | ||
707 | wake_cookie = __fscache_unuse_cookie(cookie); | ||
692 | nobufs_unlock: | 708 | nobufs_unlock: |
693 | spin_unlock(&cookie->lock); | 709 | spin_unlock(&cookie->lock); |
694 | atomic_dec(&cookie->n_active); | ||
695 | kfree(op); | 710 | kfree(op); |
711 | if (wake_cookie) | ||
712 | __fscache_wake_unused_cookie(cookie); | ||
696 | nobufs: | 713 | nobufs: |
697 | fscache_stat(&fscache_n_allocs_nobufs); | 714 | fscache_stat(&fscache_n_allocs_nobufs); |
698 | _leave(" = -ENOBUFS"); | 715 | _leave(" = -ENOBUFS"); |
@@ -889,6 +906,7 @@ int __fscache_write_page(struct fscache_cookie *cookie, | |||
889 | { | 906 | { |
890 | struct fscache_storage *op; | 907 | struct fscache_storage *op; |
891 | struct fscache_object *object; | 908 | struct fscache_object *object; |
909 | bool wake_cookie = false; | ||
892 | int ret; | 910 | int ret; |
893 | 911 | ||
894 | _enter("%p,%x,", cookie, (u32) page->flags); | 912 | _enter("%p,%x,", cookie, (u32) page->flags); |
@@ -957,7 +975,7 @@ int __fscache_write_page(struct fscache_cookie *cookie, | |||
957 | op->op.debug_id = atomic_inc_return(&fscache_op_debug_id); | 975 | op->op.debug_id = atomic_inc_return(&fscache_op_debug_id); |
958 | op->store_limit = object->store_limit; | 976 | op->store_limit = object->store_limit; |
959 | 977 | ||
960 | atomic_inc(&cookie->n_active); | 978 | __fscache_use_cookie(cookie); |
961 | if (fscache_submit_op(object, &op->op) < 0) | 979 | if (fscache_submit_op(object, &op->op) < 0) |
962 | goto submit_failed; | 980 | goto submit_failed; |
963 | 981 | ||
@@ -984,10 +1002,10 @@ already_pending: | |||
984 | return 0; | 1002 | return 0; |
985 | 1003 | ||
986 | submit_failed: | 1004 | submit_failed: |
987 | atomic_dec(&cookie->n_active); | ||
988 | spin_lock(&cookie->stores_lock); | 1005 | spin_lock(&cookie->stores_lock); |
989 | radix_tree_delete(&cookie->stores, page->index); | 1006 | radix_tree_delete(&cookie->stores, page->index); |
990 | spin_unlock(&cookie->stores_lock); | 1007 | spin_unlock(&cookie->stores_lock); |
1008 | wake_cookie = __fscache_unuse_cookie(cookie); | ||
991 | page_cache_release(page); | 1009 | page_cache_release(page); |
992 | ret = -ENOBUFS; | 1010 | ret = -ENOBUFS; |
993 | goto nobufs; | 1011 | goto nobufs; |
@@ -999,6 +1017,8 @@ nobufs: | |||
999 | spin_unlock(&cookie->lock); | 1017 | spin_unlock(&cookie->lock); |
1000 | radix_tree_preload_end(); | 1018 | radix_tree_preload_end(); |
1001 | kfree(op); | 1019 | kfree(op); |
1020 | if (wake_cookie) | ||
1021 | __fscache_wake_unused_cookie(cookie); | ||
1002 | fscache_stat(&fscache_n_stores_nobufs); | 1022 | fscache_stat(&fscache_n_stores_nobufs); |
1003 | _leave(" = -ENOBUFS"); | 1023 | _leave(" = -ENOBUFS"); |
1004 | return -ENOBUFS; | 1024 | return -ENOBUFS; |