Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+53 -15
+5 -2
fs/fscache/cookie.c
··· 568 568 { 569 569 struct fscache_operation *op; 570 570 struct fscache_object *object; 571 + bool wake_cookie = false; 571 572 int ret; 572 573 573 574 _enter("%p,", cookie); ··· 601 600 602 601 op->debug_id = atomic_inc_return(&fscache_op_debug_id); 603 602 604 - atomic_inc(&cookie->n_active); 603 + __fscache_use_cookie(cookie); 605 604 if (fscache_submit_op(object, op) < 0) 606 605 goto submit_failed; 607 606 ··· 623 622 return ret; 624 623 625 624 submit_failed: 626 - atomic_dec(&cookie->n_active); 625 + wake_cookie = __fscache_unuse_cookie(cookie); 627 626 inconsistent: 628 627 spin_unlock(&cookie->lock); 628 + if (wake_cookie) 629 + __fscache_wake_unused_cookie(cookie); 629 630 kfree(op); 630 631 _leave(" = -ESTALE"); 631 632 return -ESTALE;
+31 -11
fs/fscache/page.c
··· 163 163 164 164 fscache_stat(&fscache_n_attr_changed_calls); 165 165 166 - if (fscache_object_is_active(object) && 167 - fscache_use_cookie(object)) { 166 + if (fscache_object_is_active(object)) { 168 167 fscache_stat(&fscache_n_cop_attr_changed); 169 168 ret = object->cache->ops->attr_changed(object); 170 169 fscache_stat_d(&fscache_n_cop_attr_changed); 171 - fscache_unuse_cookie(object); 172 170 if (ret < 0) 173 171 fscache_abort_object(object); 174 172 } ··· 182 184 { 183 185 struct fscache_operation *op; 184 186 struct fscache_object *object; 187 + bool wake_cookie; 185 188 186 189 _enter("%p", cookie); 187 190 ··· 198 199 } 199 200 200 201 fscache_operation_init(op, fscache_attr_changed_op, NULL); 201 - op->flags = FSCACHE_OP_ASYNC | (1 << FSCACHE_OP_EXCLUSIVE); 202 + op->flags = FSCACHE_OP_ASYNC | 203 + (1 << FSCACHE_OP_EXCLUSIVE) | 204 + (1 << FSCACHE_OP_UNUSE_COOKIE); 202 205 203 206 spin_lock(&cookie->lock); 204 207 ··· 209 208 object = hlist_entry(cookie->backing_objects.first, 210 209 struct fscache_object, cookie_link); 211 210 211 + __fscache_use_cookie(cookie); 212 212 if (fscache_submit_exclusive_op(object, op) < 0) 213 213 goto nobufs; 214 214 spin_unlock(&cookie->lock); ··· 219 217 return 0; 220 218 221 219 nobufs: 220 + wake_cookie = __fscache_unuse_cookie(cookie); 222 221 spin_unlock(&cookie->lock); 223 222 kfree(op); 223 + if (wake_cookie) 224 + __fscache_wake_unused_cookie(cookie); 224 225 fscache_stat(&fscache_n_attr_changed_nobufs); 225 226 _leave(" = %d", -ENOBUFS); 226 227 return -ENOBUFS; ··· 268 263 } 269 264 270 265 fscache_operation_init(&op->op, NULL, fscache_release_retrieval_op); 271 - atomic_inc(&cookie->n_active); 272 266 op->op.flags = FSCACHE_OP_MYTHREAD | 273 267 (1UL << FSCACHE_OP_WAITING) | 274 268 (1UL << FSCACHE_OP_UNUSE_COOKIE); ··· 388 384 { 389 385 struct fscache_retrieval *op; 390 386 struct fscache_object *object; 387 + bool wake_cookie = false; 391 388 int ret; 392 389 393 390 _enter("%p,%p,,,", cookie, page); ··· 426 421 427 422 ASSERT(test_bit(FSCACHE_OBJECT_IS_LOOKED_UP, &object->flags)); 428 423 424 + __fscache_use_cookie(cookie); 429 425 atomic_inc(&object->n_reads); 430 426 __set_bit(FSCACHE_OP_DEC_READ_CNT, &op->op.flags); 431 427 ··· 481 475 482 476 nobufs_unlock_dec: 483 477 atomic_dec(&object->n_reads); 478 + wake_cookie = __fscache_unuse_cookie(cookie); 484 479 nobufs_unlock: 485 480 spin_unlock(&cookie->lock); 486 - atomic_dec(&cookie->n_active); 481 + if (wake_cookie) 482 + __fscache_wake_unused_cookie(cookie); 487 483 kfree(op); 488 484 nobufs: 489 485 fscache_stat(&fscache_n_retrievals_nobufs); ··· 522 514 { 523 515 struct fscache_retrieval *op; 524 516 struct fscache_object *object; 517 + bool wake_cookie = false; 525 518 int ret; 526 519 527 520 _enter("%p,,%d,,,", cookie, *nr_pages); ··· 556 547 object = hlist_entry(cookie->backing_objects.first, 557 548 struct fscache_object, cookie_link); 558 549 550 + __fscache_use_cookie(cookie); 559 551 atomic_inc(&object->n_reads); 560 552 __set_bit(FSCACHE_OP_DEC_READ_CNT, &op->op.flags); 561 553 ··· 611 601 612 602 nobufs_unlock_dec: 613 603 atomic_dec(&object->n_reads); 604 + wake_cookie = __fscache_unuse_cookie(cookie); 614 605 nobufs_unlock: 615 606 spin_unlock(&cookie->lock); 616 - atomic_dec(&cookie->n_active); 617 607 kfree(op); 608 + if (wake_cookie) 609 + __fscache_wake_unused_cookie(cookie); 618 610 nobufs: 619 611 fscache_stat(&fscache_n_retrievals_nobufs); 620 612 _leave(" = -ENOBUFS"); ··· 638 626 { 639 627 struct fscache_retrieval *op; 640 628 struct fscache_object *object; 629 + bool wake_cookie = false; 641 630 int ret; 642 631 643 632 _enter("%p,%p,,,", cookie, page); ··· 671 658 object = hlist_entry(cookie->backing_objects.first, 672 659 struct fscache_object, cookie_link); 673 660 661 + __fscache_use_cookie(cookie); 674 662 if (fscache_submit_op(object, &op->op) < 0) 675 - goto nobufs_unlock; 663 + goto nobufs_unlock_dec; 676 664 spin_unlock(&cookie->lock); 677 665 678 666 fscache_stat(&fscache_n_alloc_ops); ··· 703 689 _leave(" = %d", ret); 704 690 return ret; 705 691 692 + nobufs_unlock_dec: 693 + wake_cookie = __fscache_unuse_cookie(cookie); 706 694 nobufs_unlock: 707 695 spin_unlock(&cookie->lock); 708 - atomic_dec(&cookie->n_active); 709 696 kfree(op); 697 + if (wake_cookie) 698 + __fscache_wake_unused_cookie(cookie); 710 699 nobufs: 711 700 fscache_stat(&fscache_n_allocs_nobufs); 712 701 _leave(" = -ENOBUFS"); ··· 906 889 { 907 890 struct fscache_storage *op; 908 891 struct fscache_object *object; 892 + bool wake_cookie = false; 909 893 int ret; 910 894 911 895 _enter("%p,%x,", cookie, (u32) page->flags); ··· 975 957 op->op.debug_id = atomic_inc_return(&fscache_op_debug_id); 976 958 op->store_limit = object->store_limit; 977 959 978 - atomic_inc(&cookie->n_active); 960 + __fscache_use_cookie(cookie); 979 961 if (fscache_submit_op(object, &op->op) < 0) 980 962 goto submit_failed; 981 963 ··· 1002 984 return 0; 1003 985 1004 986 submit_failed: 1005 - atomic_dec(&cookie->n_active); 1006 987 spin_lock(&cookie->stores_lock); 1007 988 radix_tree_delete(&cookie->stores, page->index); 1008 989 spin_unlock(&cookie->stores_lock); 990 + wake_cookie = __fscache_unuse_cookie(cookie); 1009 991 page_cache_release(page); 1010 992 ret = -ENOBUFS; 1011 993 goto nobufs; ··· 1017 999 spin_unlock(&cookie->lock); 1018 1000 radix_tree_preload_end(); 1019 1001 kfree(op); 1002 + if (wake_cookie) 1003 + __fscache_wake_unused_cookie(cookie); 1020 1004 fscache_stat(&fscache_n_stores_nobufs); 1021 1005 _leave(" = -ENOBUFS"); 1022 1006 return -ENOBUFS;
+17 -2
include/linux/fscache-cache.h
··· 511 511 op->end_io_func(page, op->context, error); 512 512 } 513 513 514 + static inline void __fscache_use_cookie(struct fscache_cookie *cookie) 515 + { 516 + atomic_inc(&cookie->n_active); 517 + } 518 + 514 519 /** 515 520 * fscache_use_cookie - Request usage of cookie attached to an object 516 521 * @object: Object description ··· 529 524 return atomic_inc_not_zero(&cookie->n_active) != 0; 530 525 } 531 526 527 + static inline bool __fscache_unuse_cookie(struct fscache_cookie *cookie) 528 + { 529 + return atomic_dec_and_test(&cookie->n_active); 530 + } 531 + 532 + static inline void __fscache_wake_unused_cookie(struct fscache_cookie *cookie) 533 + { 534 + wake_up_atomic_t(&cookie->n_active); 535 + } 536 + 532 537 /** 533 538 * fscache_unuse_cookie - Cease usage of cookie attached to an object 534 539 * @object: Object description ··· 549 534 static inline void fscache_unuse_cookie(struct fscache_object *object) 550 535 { 551 536 struct fscache_cookie *cookie = object->cookie; 552 - if (atomic_dec_and_test(&cookie->n_active)) 553 - wake_up_atomic_t(&cookie->n_active); 537 + if (__fscache_unuse_cookie(cookie)) 538 + __fscache_wake_unused_cookie(cookie); 554 539 } 555 540 556 541 /*