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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'nfsd-6.2-1' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux

Pull more nfsd updates from Chuck Lever:
"This contains a number of crasher fixes that were not ready for the
initial pull request last week.

In particular, Jeff's patch attempts to address reference count
underflows in NFSD's filecache, which have been very difficult to
track down because there is no reliable reproducer.

Common failure modes:
https://bugzilla.kernel.org/show_bug.cgi?id=216691#c11
https://bugzilla.kernel.org/show_bug.cgi?id=216674#c6
https://bugzilla.redhat.com/show_bug.cgi?id=2138605

The race windows were found by inspection and the clean-ups appear
sensible and pass regression testing, so we include them here in the
hope that they address the problem. However we remain vigilant because
we don't have 100% certainty yet that the problem is fully addressed.

Summary:

- Address numerous reports of refcount underflows in NFSD's filecache

- Address a UAF in callback setup error handling

- Address a UAF during server-to-server copy"

* tag 'nfsd-6.2-1' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux:
NFSD: fix use-after-free in __nfs42_ssc_open()
nfsd: under NFSv4.1, fix double svc_xprt_put on rpc_create failure
nfsd: rework refcounting in filecache

+202 -201
+175 -153
fs/nfsd/filecache.c
··· 324 324 if (key->gc) 325 325 __set_bit(NFSD_FILE_GC, &nf->nf_flags); 326 326 nf->nf_inode = key->inode; 327 - /* nf_ref is pre-incremented for hash table */ 328 - refcount_set(&nf->nf_ref, 2); 327 + refcount_set(&nf->nf_ref, 1); 329 328 nf->nf_may = key->need; 330 329 nf->nf_mark = NULL; 331 330 } ··· 376 377 return false; 377 378 } 378 379 379 - static bool 380 + static void 380 381 nfsd_file_free(struct nfsd_file *nf) 381 382 { 382 383 s64 age = ktime_to_ms(ktime_sub(ktime_get(), nf->nf_birthtime)); 383 - bool flush = false; 384 384 385 385 trace_nfsd_file_free(nf); 386 386 387 387 this_cpu_inc(nfsd_file_releases); 388 388 this_cpu_add(nfsd_file_total_age, age); 389 + 390 + nfsd_file_unhash(nf); 391 + 392 + /* 393 + * We call fsync here in order to catch writeback errors. It's not 394 + * strictly required by the protocol, but an nfsd_file could get 395 + * evicted from the cache before a COMMIT comes in. If another 396 + * task were to open that file in the interim and scrape the error, 397 + * then the client may never see it. By calling fsync here, we ensure 398 + * that writeback happens before the entry is freed, and that any 399 + * errors reported result in the write verifier changing. 400 + */ 401 + nfsd_file_fsync(nf); 389 402 390 403 if (nf->nf_mark) 391 404 nfsd_file_mark_put(nf->nf_mark); ··· 405 394 get_file(nf->nf_file); 406 395 filp_close(nf->nf_file, NULL); 407 396 fput(nf->nf_file); 408 - flush = true; 409 397 } 410 398 411 399 /* ··· 412 402 * WARN and leak it to preserve system stability. 413 403 */ 414 404 if (WARN_ON_ONCE(!list_empty(&nf->nf_lru))) 415 - return flush; 405 + return; 416 406 417 407 call_rcu(&nf->nf_rcu, nfsd_file_slab_free); 418 - return flush; 419 408 } 420 409 421 410 static bool ··· 430 421 mapping_tagged(mapping, PAGECACHE_TAG_WRITEBACK); 431 422 } 432 423 433 - static void nfsd_file_lru_add(struct nfsd_file *nf) 424 + static bool nfsd_file_lru_add(struct nfsd_file *nf) 434 425 { 435 426 set_bit(NFSD_FILE_REFERENCED, &nf->nf_flags); 436 - if (list_lru_add(&nfsd_file_lru, &nf->nf_lru)) 427 + if (list_lru_add(&nfsd_file_lru, &nf->nf_lru)) { 437 428 trace_nfsd_file_lru_add(nf); 429 + return true; 430 + } 431 + return false; 438 432 } 439 433 440 - static void nfsd_file_lru_remove(struct nfsd_file *nf) 434 + static bool nfsd_file_lru_remove(struct nfsd_file *nf) 441 435 { 442 - if (list_lru_del(&nfsd_file_lru, &nf->nf_lru)) 436 + if (list_lru_del(&nfsd_file_lru, &nf->nf_lru)) { 443 437 trace_nfsd_file_lru_del(nf); 438 + return true; 439 + } 440 + return false; 444 441 } 445 442 446 443 struct nfsd_file * ··· 457 442 return NULL; 458 443 } 459 444 460 - static void 461 - nfsd_file_unhash_and_queue(struct nfsd_file *nf, struct list_head *dispose) 462 - { 463 - trace_nfsd_file_unhash_and_queue(nf); 464 - if (nfsd_file_unhash(nf)) { 465 - /* caller must call nfsd_file_dispose_list() later */ 466 - nfsd_file_lru_remove(nf); 467 - list_add(&nf->nf_lru, dispose); 468 - } 469 - } 470 - 471 - static void 472 - nfsd_file_put_noref(struct nfsd_file *nf) 473 - { 474 - trace_nfsd_file_put(nf); 475 - 476 - if (refcount_dec_and_test(&nf->nf_ref)) { 477 - WARN_ON(test_bit(NFSD_FILE_HASHED, &nf->nf_flags)); 478 - nfsd_file_lru_remove(nf); 479 - nfsd_file_free(nf); 480 - } 481 - } 482 - 483 - static void 484 - nfsd_file_unhash_and_put(struct nfsd_file *nf) 485 - { 486 - if (nfsd_file_unhash(nf)) 487 - nfsd_file_put_noref(nf); 488 - } 489 - 445 + /** 446 + * nfsd_file_put - put the reference to a nfsd_file 447 + * @nf: nfsd_file of which to put the reference 448 + * 449 + * Put a reference to a nfsd_file. In the non-GC case, we just put the 450 + * reference immediately. In the GC case, if the reference would be 451 + * the last one, the put it on the LRU instead to be cleaned up later. 452 + */ 490 453 void 491 454 nfsd_file_put(struct nfsd_file *nf) 492 455 { 493 456 might_sleep(); 457 + trace_nfsd_file_put(nf); 494 458 495 - if (test_bit(NFSD_FILE_GC, &nf->nf_flags)) 496 - nfsd_file_lru_add(nf); 497 - else if (refcount_read(&nf->nf_ref) == 2) 498 - nfsd_file_unhash_and_put(nf); 459 + if (test_bit(NFSD_FILE_GC, &nf->nf_flags) && 460 + test_bit(NFSD_FILE_HASHED, &nf->nf_flags)) { 461 + /* 462 + * If this is the last reference (nf_ref == 1), then try to 463 + * transfer it to the LRU. 464 + */ 465 + if (refcount_dec_not_one(&nf->nf_ref)) 466 + return; 499 467 500 - if (!test_bit(NFSD_FILE_HASHED, &nf->nf_flags)) { 501 - nfsd_file_fsync(nf); 502 - nfsd_file_put_noref(nf); 503 - } else if (nf->nf_file && test_bit(NFSD_FILE_GC, &nf->nf_flags)) { 504 - nfsd_file_put_noref(nf); 505 - nfsd_file_schedule_laundrette(); 506 - } else 507 - nfsd_file_put_noref(nf); 468 + /* Try to add it to the LRU. If that fails, decrement. */ 469 + if (nfsd_file_lru_add(nf)) { 470 + /* If it's still hashed, we're done */ 471 + if (test_bit(NFSD_FILE_HASHED, &nf->nf_flags)) { 472 + nfsd_file_schedule_laundrette(); 473 + return; 474 + } 475 + 476 + /* 477 + * We're racing with unhashing, so try to remove it from 478 + * the LRU. If removal fails, then someone else already 479 + * has our reference. 480 + */ 481 + if (!nfsd_file_lru_remove(nf)) 482 + return; 483 + } 484 + } 485 + if (refcount_dec_and_test(&nf->nf_ref)) 486 + nfsd_file_free(nf); 508 487 } 509 488 510 489 static void ··· 506 497 { 507 498 struct nfsd_file *nf; 508 499 509 - while(!list_empty(dispose)) { 500 + while (!list_empty(dispose)) { 510 501 nf = list_first_entry(dispose, struct nfsd_file, nf_lru); 511 502 list_del_init(&nf->nf_lru); 512 - nfsd_file_fsync(nf); 513 - nfsd_file_put_noref(nf); 503 + nfsd_file_free(nf); 514 504 } 515 - } 516 - 517 - static void 518 - nfsd_file_dispose_list_sync(struct list_head *dispose) 519 - { 520 - bool flush = false; 521 - struct nfsd_file *nf; 522 - 523 - while(!list_empty(dispose)) { 524 - nf = list_first_entry(dispose, struct nfsd_file, nf_lru); 525 - list_del_init(&nf->nf_lru); 526 - nfsd_file_fsync(nf); 527 - if (!refcount_dec_and_test(&nf->nf_ref)) 528 - continue; 529 - if (nfsd_file_free(nf)) 530 - flush = true; 531 - } 532 - if (flush) 533 - flush_delayed_fput(); 534 505 } 535 506 536 507 static void ··· 580 591 struct list_head *head = arg; 581 592 struct nfsd_file *nf = list_entry(item, struct nfsd_file, nf_lru); 582 593 583 - /* 584 - * Do a lockless refcount check. The hashtable holds one reference, so 585 - * we look to see if anything else has a reference, or if any have 586 - * been put since the shrinker last ran. Those don't get unhashed and 587 - * released. 588 - * 589 - * Note that in the put path, we set the flag and then decrement the 590 - * counter. Here we check the counter and then test and clear the flag. 591 - * That order is deliberate to ensure that we can do this locklessly. 592 - */ 593 - if (refcount_read(&nf->nf_ref) > 1) { 594 - list_lru_isolate(lru, &nf->nf_lru); 595 - trace_nfsd_file_gc_in_use(nf); 596 - return LRU_REMOVED; 597 - } 594 + /* We should only be dealing with GC entries here */ 595 + WARN_ON_ONCE(!test_bit(NFSD_FILE_GC, &nf->nf_flags)); 598 596 599 597 /* 600 598 * Don't throw out files that are still undergoing I/O or ··· 592 616 return LRU_SKIP; 593 617 } 594 618 619 + /* If it was recently added to the list, skip it */ 595 620 if (test_and_clear_bit(NFSD_FILE_REFERENCED, &nf->nf_flags)) { 596 621 trace_nfsd_file_gc_referenced(nf); 597 622 return LRU_ROTATE; 598 623 } 599 624 600 - if (!test_and_clear_bit(NFSD_FILE_HASHED, &nf->nf_flags)) { 601 - trace_nfsd_file_gc_hashed(nf); 602 - return LRU_SKIP; 625 + /* 626 + * Put the reference held on behalf of the LRU. If it wasn't the last 627 + * one, then just remove it from the LRU and ignore it. 628 + */ 629 + if (!refcount_dec_and_test(&nf->nf_ref)) { 630 + trace_nfsd_file_gc_in_use(nf); 631 + list_lru_isolate(lru, &nf->nf_lru); 632 + return LRU_REMOVED; 603 633 } 604 634 635 + /* Refcount went to zero. Unhash it and queue it to the dispose list */ 636 + nfsd_file_unhash(nf); 605 637 list_lru_isolate_move(lru, &nf->nf_lru, head); 606 638 this_cpu_inc(nfsd_file_evictions); 607 639 trace_nfsd_file_gc_disposed(nf); 608 640 return LRU_REMOVED; 609 - } 610 - 611 - /* 612 - * Unhash items on @dispose immediately, then queue them on the 613 - * disposal workqueue to finish releasing them in the background. 614 - * 615 - * cel: Note that between the time list_lru_shrink_walk runs and 616 - * now, these items are in the hash table but marked unhashed. 617 - * Why release these outside of lru_cb ? There's no lock ordering 618 - * problem since lru_cb currently takes no lock. 619 - */ 620 - static void nfsd_file_gc_dispose_list(struct list_head *dispose) 621 - { 622 - struct nfsd_file *nf; 623 - 624 - list_for_each_entry(nf, dispose, nf_lru) 625 - nfsd_file_hash_remove(nf); 626 - nfsd_file_dispose_list_delayed(dispose); 627 641 } 628 642 629 643 static void ··· 625 659 ret = list_lru_walk(&nfsd_file_lru, nfsd_file_lru_cb, 626 660 &dispose, list_lru_count(&nfsd_file_lru)); 627 661 trace_nfsd_file_gc_removed(ret, list_lru_count(&nfsd_file_lru)); 628 - nfsd_file_gc_dispose_list(&dispose); 662 + nfsd_file_dispose_list_delayed(&dispose); 629 663 } 630 664 631 665 static void ··· 651 685 ret = list_lru_shrink_walk(&nfsd_file_lru, sc, 652 686 nfsd_file_lru_cb, &dispose); 653 687 trace_nfsd_file_shrinker_removed(ret, list_lru_count(&nfsd_file_lru)); 654 - nfsd_file_gc_dispose_list(&dispose); 688 + nfsd_file_dispose_list_delayed(&dispose); 655 689 return ret; 656 690 } 657 691 ··· 661 695 .seeks = 1, 662 696 }; 663 697 664 - /* 665 - * Find all cache items across all net namespaces that match @inode and 666 - * move them to @dispose. The lookup is atomic wrt nfsd_file_acquire(). 698 + /** 699 + * nfsd_file_queue_for_close: try to close out any open nfsd_files for an inode 700 + * @inode: inode on which to close out nfsd_files 701 + * @dispose: list on which to gather nfsd_files to close out 702 + * 703 + * An nfsd_file represents a struct file being held open on behalf of nfsd. An 704 + * open file however can block other activity (such as leases), or cause 705 + * undesirable behavior (e.g. spurious silly-renames when reexporting NFS). 706 + * 707 + * This function is intended to find open nfsd_files when this sort of 708 + * conflicting access occurs and then attempt to close those files out. 709 + * 710 + * Populates the dispose list with entries that have already had their 711 + * refcounts go to zero. The actual free of an nfsd_file can be expensive, 712 + * so we leave it up to the caller whether it wants to wait or not. 667 713 */ 668 - static unsigned int 669 - __nfsd_file_close_inode(struct inode *inode, struct list_head *dispose) 714 + static void 715 + nfsd_file_queue_for_close(struct inode *inode, struct list_head *dispose) 670 716 { 671 717 struct nfsd_file_lookup_key key = { 672 718 .type = NFSD_FILE_KEY_INODE, 673 719 .inode = inode, 674 720 }; 675 - unsigned int count = 0; 676 721 struct nfsd_file *nf; 677 722 678 723 rcu_read_lock(); 679 724 do { 725 + int decrement = 1; 726 + 680 727 nf = rhashtable_lookup(&nfsd_file_rhash_tbl, &key, 681 728 nfsd_file_rhash_params); 682 729 if (!nf) 683 730 break; 684 - nfsd_file_unhash_and_queue(nf, dispose); 685 - count++; 731 + 732 + /* If we raced with someone else unhashing, ignore it */ 733 + if (!nfsd_file_unhash(nf)) 734 + continue; 735 + 736 + /* If we can't get a reference, ignore it */ 737 + if (!nfsd_file_get(nf)) 738 + continue; 739 + 740 + /* Extra decrement if we remove from the LRU */ 741 + if (nfsd_file_lru_remove(nf)) 742 + ++decrement; 743 + 744 + /* If refcount goes to 0, then put on the dispose list */ 745 + if (refcount_sub_and_test(decrement, &nf->nf_ref)) { 746 + list_add(&nf->nf_lru, dispose); 747 + trace_nfsd_file_closing(nf); 748 + } 686 749 } while (1); 687 750 rcu_read_unlock(); 688 - return count; 689 - } 690 - 691 - /** 692 - * nfsd_file_close_inode_sync - attempt to forcibly close a nfsd_file 693 - * @inode: inode of the file to attempt to remove 694 - * 695 - * Unhash and put, then flush and fput all cache items associated with @inode. 696 - */ 697 - void 698 - nfsd_file_close_inode_sync(struct inode *inode) 699 - { 700 - LIST_HEAD(dispose); 701 - unsigned int count; 702 - 703 - count = __nfsd_file_close_inode(inode, &dispose); 704 - trace_nfsd_file_close_inode_sync(inode, count); 705 - nfsd_file_dispose_list_sync(&dispose); 706 751 } 707 752 708 753 /** 709 754 * nfsd_file_close_inode - attempt a delayed close of a nfsd_file 710 755 * @inode: inode of the file to attempt to remove 711 756 * 712 - * Unhash and put all cache item associated with @inode. 757 + * Close out any open nfsd_files that can be reaped for @inode. The 758 + * actual freeing is deferred to the dispose_list_delayed infrastructure. 759 + * 760 + * This is used by the fsnotify callbacks and setlease notifier. 713 761 */ 714 762 static void 715 763 nfsd_file_close_inode(struct inode *inode) 716 764 { 717 765 LIST_HEAD(dispose); 718 - unsigned int count; 719 766 720 - count = __nfsd_file_close_inode(inode, &dispose); 721 - trace_nfsd_file_close_inode(inode, count); 767 + nfsd_file_queue_for_close(inode, &dispose); 722 768 nfsd_file_dispose_list_delayed(&dispose); 769 + } 770 + 771 + /** 772 + * nfsd_file_close_inode_sync - attempt to forcibly close a nfsd_file 773 + * @inode: inode of the file to attempt to remove 774 + * 775 + * Close out any open nfsd_files that can be reaped for @inode. The 776 + * nfsd_files are closed out synchronously. 777 + * 778 + * This is called from nfsd_rename and nfsd_unlink to avoid silly-renames 779 + * when reexporting NFS. 780 + */ 781 + void 782 + nfsd_file_close_inode_sync(struct inode *inode) 783 + { 784 + struct nfsd_file *nf; 785 + LIST_HEAD(dispose); 786 + 787 + trace_nfsd_file_close(inode); 788 + 789 + nfsd_file_queue_for_close(inode, &dispose); 790 + while (!list_empty(&dispose)) { 791 + nf = list_first_entry(&dispose, struct nfsd_file, nf_lru); 792 + list_del_init(&nf->nf_lru); 793 + nfsd_file_free(nf); 794 + } 795 + flush_delayed_fput(); 723 796 } 724 797 725 798 /** 726 799 * nfsd_file_delayed_close - close unused nfsd_files 727 800 * @work: dummy 728 801 * 729 - * Walk the LRU list and close any entries that have not been used since 802 + * Walk the LRU list and destroy any entries that have not been used since 730 803 * the last scan. 731 804 */ 732 805 static void ··· 787 782 788 783 /* Only close files for F_SETLEASE leases */ 789 784 if (fl->fl_flags & FL_LEASE) 790 - nfsd_file_close_inode_sync(file_inode(fl->fl_file)); 785 + nfsd_file_close_inode(file_inode(fl->fl_file)); 791 786 return 0; 792 787 } 793 788 ··· 908 903 goto out; 909 904 } 910 905 906 + /** 907 + * __nfsd_file_cache_purge: clean out the cache for shutdown 908 + * @net: net-namespace to shut down the cache (may be NULL) 909 + * 910 + * Walk the nfsd_file cache and close out any that match @net. If @net is NULL, 911 + * then close out everything. Called when an nfsd instance is being shut down. 912 + */ 911 913 static void 912 914 __nfsd_file_cache_purge(struct net *net) 913 915 { ··· 928 916 929 917 nf = rhashtable_walk_next(&iter); 930 918 while (!IS_ERR_OR_NULL(nf)) { 931 - if (!net || nf->nf_net == net) 932 - nfsd_file_unhash_and_queue(nf, &dispose); 919 + if (!net || nf->nf_net == net) { 920 + nfsd_file_unhash(nf); 921 + nfsd_file_lru_remove(nf); 922 + list_add(&nf->nf_lru, &dispose); 923 + } 933 924 nf = rhashtable_walk_next(&iter); 934 925 } 935 926 ··· 1099 1084 if (nf) 1100 1085 nf = nfsd_file_get(nf); 1101 1086 rcu_read_unlock(); 1102 - if (nf) 1087 + 1088 + if (nf) { 1089 + if (nfsd_file_lru_remove(nf)) 1090 + WARN_ON_ONCE(refcount_dec_and_test(&nf->nf_ref)); 1103 1091 goto wait_for_construction; 1092 + } 1104 1093 1105 1094 nf = nfsd_file_alloc(&key, may_flags); 1106 1095 if (!nf) { ··· 1137 1118 goto out; 1138 1119 } 1139 1120 open_retry = false; 1140 - nfsd_file_put_noref(nf); 1121 + if (refcount_dec_and_test(&nf->nf_ref)) 1122 + nfsd_file_free(nf); 1141 1123 goto retry; 1142 1124 } 1143 1125 1144 - nfsd_file_lru_remove(nf); 1145 1126 this_cpu_inc(nfsd_file_cache_hits); 1146 1127 1147 1128 status = nfserrno(nfsd_open_break_lease(file_inode(nf->nf_file), may_flags)); ··· 1151 1132 this_cpu_inc(nfsd_file_acquisitions); 1152 1133 *pnf = nf; 1153 1134 } else { 1154 - nfsd_file_put(nf); 1135 + if (refcount_dec_and_test(&nf->nf_ref)) 1136 + nfsd_file_free(nf); 1155 1137 nf = NULL; 1156 1138 } 1157 1139 ··· 1178 1158 * If construction failed, or we raced with a call to unlink() 1179 1159 * then unhash. 1180 1160 */ 1181 - if (status != nfs_ok || key.inode->i_nlink == 0) 1182 - nfsd_file_unhash_and_put(nf); 1161 + if (status == nfs_ok && key.inode->i_nlink == 0) 1162 + status = nfserr_jukebox; 1163 + if (status != nfs_ok) 1164 + nfsd_file_unhash(nf); 1183 1165 clear_bit_unlock(NFSD_FILE_PENDING, &nf->nf_flags); 1184 1166 smp_mb__after_atomic(); 1185 1167 wake_up_bit(&nf->nf_flags, NFSD_FILE_PENDING);
+3 -1
fs/nfsd/nfs4callback.c
··· 988 988 } else { 989 989 if (!conn->cb_xprt) 990 990 return -EINVAL; 991 - clp->cl_cb_conn.cb_xprt = conn->cb_xprt; 992 991 clp->cl_cb_session = ses; 993 992 args.bc_xprt = conn->cb_xprt; 994 993 args.prognumber = clp->cl_cb_session->se_cb_prog; ··· 1007 1008 rpc_shutdown_client(client); 1008 1009 return -ENOMEM; 1009 1010 } 1011 + 1012 + if (clp->cl_minorversion != 0) 1013 + clp->cl_cb_conn.cb_xprt = conn->cb_xprt; 1010 1014 clp->cl_cb_client = client; 1011 1015 clp->cl_cb_cred = cred; 1012 1016 rcu_read_lock();
+5 -15
fs/nfsd/nfs4proc.c
··· 1461 1461 return status; 1462 1462 } 1463 1463 1464 - static void 1465 - nfsd4_interssc_disconnect(struct vfsmount *ss_mnt) 1466 - { 1467 - nfs_do_sb_deactive(ss_mnt->mnt_sb); 1468 - mntput(ss_mnt); 1469 - } 1470 - 1471 1464 /* 1472 1465 * Verify COPY destination stateid. 1473 1466 * ··· 1560 1567 static void 1561 1568 nfsd4_cleanup_inter_ssc(struct vfsmount *ss_mnt, struct file *filp, 1562 1569 struct nfsd_file *dst) 1563 - { 1564 - } 1565 - 1566 - static void 1567 - nfsd4_interssc_disconnect(struct vfsmount *ss_mnt) 1568 1570 { 1569 1571 } 1570 1572 ··· 1758 1770 default: 1759 1771 nfserr = nfserr_offload_denied; 1760 1772 } 1761 - nfsd4_interssc_disconnect(copy->ss_mnt); 1773 + /* ss_mnt will be unmounted by the laundromat */ 1762 1774 goto do_callback; 1763 1775 } 1764 1776 nfserr = nfsd4_do_copy(copy, filp, copy->nf_dst->nf_file, ··· 1839 1851 if (async_copy) 1840 1852 cleanup_async_copy(async_copy); 1841 1853 status = nfserrno(-ENOMEM); 1842 - if (nfsd4_ssc_is_inter(copy)) 1843 - nfsd4_interssc_disconnect(copy->ss_mnt); 1854 + /* 1855 + * source's vfsmount of inter-copy will be unmounted 1856 + * by the laundromat 1857 + */ 1844 1858 goto out; 1845 1859 } 1846 1860
+19 -32
fs/nfsd/trace.h
··· 876 876 __print_flags(val, "|", \ 877 877 { 1 << NFSD_FILE_HASHED, "HASHED" }, \ 878 878 { 1 << NFSD_FILE_PENDING, "PENDING" }, \ 879 - { 1 << NFSD_FILE_REFERENCED, "REFERENCED"}, \ 880 - { 1 << NFSD_FILE_GC, "GC"}) 879 + { 1 << NFSD_FILE_REFERENCED, "REFERENCED" }, \ 880 + { 1 << NFSD_FILE_GC, "GC" }) 881 881 882 882 DECLARE_EVENT_CLASS(nfsd_file_class, 883 883 TP_PROTO(struct nfsd_file *nf), ··· 912 912 DEFINE_NFSD_FILE_EVENT(nfsd_file_free); 913 913 DEFINE_NFSD_FILE_EVENT(nfsd_file_unhash); 914 914 DEFINE_NFSD_FILE_EVENT(nfsd_file_put); 915 + DEFINE_NFSD_FILE_EVENT(nfsd_file_closing); 915 916 DEFINE_NFSD_FILE_EVENT(nfsd_file_unhash_and_queue); 916 917 917 918 TRACE_EVENT(nfsd_file_alloc, ··· 1104 1103 __entry->nf_file) 1105 1104 ) 1106 1105 1107 - DECLARE_EVENT_CLASS(nfsd_file_search_class, 1108 - TP_PROTO( 1109 - const struct inode *inode, 1110 - unsigned int count 1111 - ), 1112 - TP_ARGS(inode, count), 1113 - TP_STRUCT__entry( 1114 - __field(const struct inode *, inode) 1115 - __field(unsigned int, count) 1116 - ), 1117 - TP_fast_assign( 1118 - __entry->inode = inode; 1119 - __entry->count = count; 1120 - ), 1121 - TP_printk("inode=%p count=%u", 1122 - __entry->inode, __entry->count) 1123 - ); 1124 - 1125 - #define DEFINE_NFSD_FILE_SEARCH_EVENT(name) \ 1126 - DEFINE_EVENT(nfsd_file_search_class, name, \ 1127 - TP_PROTO( \ 1128 - const struct inode *inode, \ 1129 - unsigned int count \ 1130 - ), \ 1131 - TP_ARGS(inode, count)) 1132 - 1133 - DEFINE_NFSD_FILE_SEARCH_EVENT(nfsd_file_close_inode_sync); 1134 - DEFINE_NFSD_FILE_SEARCH_EVENT(nfsd_file_close_inode); 1135 - 1136 1106 TRACE_EVENT(nfsd_file_is_cached, 1137 1107 TP_PROTO( 1138 1108 const struct inode *inode, ··· 1181 1209 DEFINE_NFSD_FILE_GC_EVENT(nfsd_file_gc_in_use); 1182 1210 DEFINE_NFSD_FILE_GC_EVENT(nfsd_file_gc_writeback); 1183 1211 DEFINE_NFSD_FILE_GC_EVENT(nfsd_file_gc_referenced); 1184 - DEFINE_NFSD_FILE_GC_EVENT(nfsd_file_gc_hashed); 1185 1212 DEFINE_NFSD_FILE_GC_EVENT(nfsd_file_gc_disposed); 1186 1213 1187 1214 DECLARE_EVENT_CLASS(nfsd_file_lruwalk_class, ··· 1211 1240 1212 1241 DEFINE_NFSD_FILE_LRUWALK_EVENT(nfsd_file_gc_removed); 1213 1242 DEFINE_NFSD_FILE_LRUWALK_EVENT(nfsd_file_shrinker_removed); 1243 + 1244 + TRACE_EVENT(nfsd_file_close, 1245 + TP_PROTO( 1246 + const struct inode *inode 1247 + ), 1248 + TP_ARGS(inode), 1249 + TP_STRUCT__entry( 1250 + __field(const void *, inode) 1251 + ), 1252 + TP_fast_assign( 1253 + __entry->inode = inode; 1254 + ), 1255 + TP_printk("inode=%p", 1256 + __entry->inode 1257 + ) 1258 + ); 1214 1259 1215 1260 TRACE_EVENT(nfsd_file_fsync, 1216 1261 TP_PROTO(