filecache.c (bb13f35b96f4c83dc4015d71fa2b543c665fbdae) | filecache.c (5e113224c17e2fb156b785ddbbc48a0209fddb0c) |
---|---|
1/* 2 * Open file cache. 3 * 4 * (c) 2015 - Jeff Layton <jeff.layton@primarydata.com> 5 */ 6 7#include <linux/hash.h> 8#include <linux/slab.h> 9#include <linux/file.h> 10#include <linux/sched.h> 11#include <linux/list_lru.h> 12#include <linux/fsnotify_backend.h> 13#include <linux/fsnotify.h> 14#include <linux/seq_file.h> 15 16#include "vfs.h" 17#include "nfsd.h" 18#include "nfsfh.h" | 1/* 2 * Open file cache. 3 * 4 * (c) 2015 - Jeff Layton <jeff.layton@primarydata.com> 5 */ 6 7#include <linux/hash.h> 8#include <linux/slab.h> 9#include <linux/file.h> 10#include <linux/sched.h> 11#include <linux/list_lru.h> 12#include <linux/fsnotify_backend.h> 13#include <linux/fsnotify.h> 14#include <linux/seq_file.h> 15 16#include "vfs.h" 17#include "nfsd.h" 18#include "nfsfh.h" |
19#include "netns.h" |
|
19#include "filecache.h" 20#include "trace.h" 21 22#define NFSDDBG_FACILITY NFSDDBG_FH 23 24/* FIXME: dynamically size this for the machine somehow? */ 25#define NFSD_FILE_HASH_BITS 12 26#define NFSD_FILE_HASH_SIZE (1 << NFSD_FILE_HASH_BITS) --- 135 unchanged lines hidden (view full) --- 162 else 163 fsnotify_put_mark(&new->nfm_mark); 164 } while (unlikely(err == -EEXIST)); 165 166 return nfm; 167} 168 169static struct nfsd_file * | 20#include "filecache.h" 21#include "trace.h" 22 23#define NFSDDBG_FACILITY NFSDDBG_FH 24 25/* FIXME: dynamically size this for the machine somehow? */ 26#define NFSD_FILE_HASH_BITS 12 27#define NFSD_FILE_HASH_SIZE (1 << NFSD_FILE_HASH_BITS) --- 135 unchanged lines hidden (view full) --- 163 else 164 fsnotify_put_mark(&new->nfm_mark); 165 } while (unlikely(err == -EEXIST)); 166 167 return nfm; 168} 169 170static struct nfsd_file * |
170nfsd_file_alloc(struct inode *inode, unsigned int may, unsigned int hashval) | 171nfsd_file_alloc(struct inode *inode, unsigned int may, unsigned int hashval, 172 struct net *net) |
171{ 172 struct nfsd_file *nf; 173 174 nf = kmem_cache_alloc(nfsd_file_slab, GFP_KERNEL); 175 if (nf) { 176 INIT_HLIST_NODE(&nf->nf_node); 177 INIT_LIST_HEAD(&nf->nf_lru); 178 nf->nf_file = NULL; 179 nf->nf_cred = get_current_cred(); | 173{ 174 struct nfsd_file *nf; 175 176 nf = kmem_cache_alloc(nfsd_file_slab, GFP_KERNEL); 177 if (nf) { 178 INIT_HLIST_NODE(&nf->nf_node); 179 INIT_LIST_HEAD(&nf->nf_lru); 180 nf->nf_file = NULL; 181 nf->nf_cred = get_current_cred(); |
182 nf->nf_net = net; |
|
180 nf->nf_flags = 0; 181 nf->nf_inode = inode; 182 nf->nf_hashval = hashval; 183 atomic_set(&nf->nf_ref, 1); 184 nf->nf_may = may & NFSD_FILE_MAY_MASK; 185 if (may & NFSD_MAY_NOT_BREAK_LEASE) { 186 if (may & NFSD_MAY_WRITE) 187 __set_bit(NFSD_FILE_BREAK_WRITE, &nf->nf_flags); --- 414 unchanged lines hidden (view full) --- 602 nfsd_file_hashtbl = NULL; 603 goto out; 604} 605 606/* 607 * Note this can deadlock with nfsd_file_lru_cb. 608 */ 609void | 183 nf->nf_flags = 0; 184 nf->nf_inode = inode; 185 nf->nf_hashval = hashval; 186 atomic_set(&nf->nf_ref, 1); 187 nf->nf_may = may & NFSD_FILE_MAY_MASK; 188 if (may & NFSD_MAY_NOT_BREAK_LEASE) { 189 if (may & NFSD_MAY_WRITE) 190 __set_bit(NFSD_FILE_BREAK_WRITE, &nf->nf_flags); --- 414 unchanged lines hidden (view full) --- 605 nfsd_file_hashtbl = NULL; 606 goto out; 607} 608 609/* 610 * Note this can deadlock with nfsd_file_lru_cb. 611 */ 612void |
610nfsd_file_cache_purge(void) | 613nfsd_file_cache_purge(struct net *net) |
611{ 612 unsigned int i; 613 struct nfsd_file *nf; | 614{ 615 unsigned int i; 616 struct nfsd_file *nf; |
617 struct hlist_node *next; |
|
614 LIST_HEAD(dispose); 615 bool del; 616 617 if (!nfsd_file_hashtbl) 618 return; 619 620 for (i = 0; i < NFSD_FILE_HASH_SIZE; i++) { | 618 LIST_HEAD(dispose); 619 bool del; 620 621 if (!nfsd_file_hashtbl) 622 return; 623 624 for (i = 0; i < NFSD_FILE_HASH_SIZE; i++) { |
621 spin_lock(&nfsd_file_hashtbl[i].nfb_lock); 622 while(!hlist_empty(&nfsd_file_hashtbl[i].nfb_head)) { 623 nf = hlist_entry(nfsd_file_hashtbl[i].nfb_head.first, 624 struct nfsd_file, nf_node); | 625 struct nfsd_fcache_bucket *nfb = &nfsd_file_hashtbl[i]; 626 627 spin_lock(&nfb->nfb_lock); 628 hlist_for_each_entry_safe(nf, next, &nfb->nfb_head, nf_node) { 629 if (net && nf->nf_net != net) 630 continue; |
625 del = nfsd_file_unhash_and_release_locked(nf, &dispose); 626 627 /* 628 * Deadlock detected! Something marked this entry as 629 * unhased, but hasn't removed it from the hash list. 630 */ 631 WARN_ON_ONCE(!del); 632 } | 631 del = nfsd_file_unhash_and_release_locked(nf, &dispose); 632 633 /* 634 * Deadlock detected! Something marked this entry as 635 * unhased, but hasn't removed it from the hash list. 636 */ 637 WARN_ON_ONCE(!del); 638 } |
633 spin_unlock(&nfsd_file_hashtbl[i].nfb_lock); | 639 spin_unlock(&nfb->nfb_lock); |
634 nfsd_file_dispose_list(&dispose); 635 } 636} 637 638void 639nfsd_file_cache_shutdown(void) 640{ 641 LIST_HEAD(dispose); 642 643 set_bit(NFSD_FILE_SHUTDOWN, &nfsd_file_lru_flags); 644 645 lease_unregister_notifier(&nfsd_file_lease_notifier); 646 unregister_shrinker(&nfsd_file_shrinker); 647 /* 648 * make sure all callers of nfsd_file_lru_cb are done before 649 * calling nfsd_file_cache_purge 650 */ 651 cancel_delayed_work_sync(&nfsd_filecache_laundrette); | 640 nfsd_file_dispose_list(&dispose); 641 } 642} 643 644void 645nfsd_file_cache_shutdown(void) 646{ 647 LIST_HEAD(dispose); 648 649 set_bit(NFSD_FILE_SHUTDOWN, &nfsd_file_lru_flags); 650 651 lease_unregister_notifier(&nfsd_file_lease_notifier); 652 unregister_shrinker(&nfsd_file_shrinker); 653 /* 654 * make sure all callers of nfsd_file_lru_cb are done before 655 * calling nfsd_file_cache_purge 656 */ 657 cancel_delayed_work_sync(&nfsd_filecache_laundrette); |
652 nfsd_file_cache_purge(); | 658 nfsd_file_cache_purge(NULL); |
653 list_lru_destroy(&nfsd_file_lru); 654 rcu_barrier(); 655 fsnotify_put_group(nfsd_file_fsnotify_group); 656 nfsd_file_fsnotify_group = NULL; 657 kmem_cache_destroy(nfsd_file_slab); 658 nfsd_file_slab = NULL; 659 fsnotify_wait_marks_destroyed(); 660 kmem_cache_destroy(nfsd_file_mark_slab); --- 19 unchanged lines hidden (view full) --- 680 if (!gid_eq(c1->group_info->gid[i], c2->group_info->gid[i])) 681 return false; 682 } 683 return true; 684} 685 686static struct nfsd_file * 687nfsd_file_find_locked(struct inode *inode, unsigned int may_flags, | 659 list_lru_destroy(&nfsd_file_lru); 660 rcu_barrier(); 661 fsnotify_put_group(nfsd_file_fsnotify_group); 662 nfsd_file_fsnotify_group = NULL; 663 kmem_cache_destroy(nfsd_file_slab); 664 nfsd_file_slab = NULL; 665 fsnotify_wait_marks_destroyed(); 666 kmem_cache_destroy(nfsd_file_mark_slab); --- 19 unchanged lines hidden (view full) --- 686 if (!gid_eq(c1->group_info->gid[i], c2->group_info->gid[i])) 687 return false; 688 } 689 return true; 690} 691 692static struct nfsd_file * 693nfsd_file_find_locked(struct inode *inode, unsigned int may_flags, |
688 unsigned int hashval) | 694 unsigned int hashval, struct net *net) |
689{ 690 struct nfsd_file *nf; 691 unsigned char need = may_flags & NFSD_FILE_MAY_MASK; 692 693 hlist_for_each_entry_rcu(nf, &nfsd_file_hashtbl[hashval].nfb_head, 694 nf_node) { 695 if ((need & nf->nf_may) != need) 696 continue; 697 if (nf->nf_inode != inode) 698 continue; | 695{ 696 struct nfsd_file *nf; 697 unsigned char need = may_flags & NFSD_FILE_MAY_MASK; 698 699 hlist_for_each_entry_rcu(nf, &nfsd_file_hashtbl[hashval].nfb_head, 700 nf_node) { 701 if ((need & nf->nf_may) != need) 702 continue; 703 if (nf->nf_inode != inode) 704 continue; |
705 if (nf->nf_net != net) 706 continue; |
|
699 if (!nfsd_match_cred(nf->nf_cred, current_cred())) 700 continue; 701 if (nfsd_file_get(nf) != NULL) 702 return nf; 703 } 704 return NULL; 705} 706 --- 26 unchanged lines hidden (view full) --- 733 return ret; 734} 735 736__be32 737nfsd_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp, 738 unsigned int may_flags, struct nfsd_file **pnf) 739{ 740 __be32 status; | 707 if (!nfsd_match_cred(nf->nf_cred, current_cred())) 708 continue; 709 if (nfsd_file_get(nf) != NULL) 710 return nf; 711 } 712 return NULL; 713} 714 --- 26 unchanged lines hidden (view full) --- 741 return ret; 742} 743 744__be32 745nfsd_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp, 746 unsigned int may_flags, struct nfsd_file **pnf) 747{ 748 __be32 status; |
749 struct net *net = SVC_NET(rqstp); |
|
741 struct nfsd_file *nf, *new; 742 struct inode *inode; 743 unsigned int hashval; 744 745 /* FIXME: skip this if fh_dentry is already set? */ 746 status = fh_verify(rqstp, fhp, S_IFREG, 747 may_flags|NFSD_MAY_OWNER_OVERRIDE); 748 if (status != nfs_ok) 749 return status; 750 751 inode = d_inode(fhp->fh_dentry); 752 hashval = (unsigned int)hash_long(inode->i_ino, NFSD_FILE_HASH_BITS); 753retry: 754 rcu_read_lock(); | 750 struct nfsd_file *nf, *new; 751 struct inode *inode; 752 unsigned int hashval; 753 754 /* FIXME: skip this if fh_dentry is already set? */ 755 status = fh_verify(rqstp, fhp, S_IFREG, 756 may_flags|NFSD_MAY_OWNER_OVERRIDE); 757 if (status != nfs_ok) 758 return status; 759 760 inode = d_inode(fhp->fh_dentry); 761 hashval = (unsigned int)hash_long(inode->i_ino, NFSD_FILE_HASH_BITS); 762retry: 763 rcu_read_lock(); |
755 nf = nfsd_file_find_locked(inode, may_flags, hashval); | 764 nf = nfsd_file_find_locked(inode, may_flags, hashval, net); |
756 rcu_read_unlock(); 757 if (nf) 758 goto wait_for_construction; 759 | 765 rcu_read_unlock(); 766 if (nf) 767 goto wait_for_construction; 768 |
760 new = nfsd_file_alloc(inode, may_flags, hashval); | 769 new = nfsd_file_alloc(inode, may_flags, hashval, net); |
761 if (!new) { 762 trace_nfsd_file_acquire(rqstp, hashval, inode, may_flags, 763 NULL, nfserr_jukebox); 764 return nfserr_jukebox; 765 } 766 767 spin_lock(&nfsd_file_hashtbl[hashval].nfb_lock); | 770 if (!new) { 771 trace_nfsd_file_acquire(rqstp, hashval, inode, may_flags, 772 NULL, nfserr_jukebox); 773 return nfserr_jukebox; 774 } 775 776 spin_lock(&nfsd_file_hashtbl[hashval].nfb_lock); |
768 nf = nfsd_file_find_locked(inode, may_flags, hashval); | 777 nf = nfsd_file_find_locked(inode, may_flags, hashval, net); |
769 if (nf == NULL) 770 goto open_file; 771 spin_unlock(&nfsd_file_hashtbl[hashval].nfb_lock); 772 nfsd_file_slab_free(&new->nf_rcu); 773 774wait_for_construction: 775 wait_on_bit(&nf->nf_flags, NFSD_FILE_PENDING, TASK_UNINTERRUPTIBLE); 776 --- 108 unchanged lines hidden --- | 778 if (nf == NULL) 779 goto open_file; 780 spin_unlock(&nfsd_file_hashtbl[hashval].nfb_lock); 781 nfsd_file_slab_free(&new->nf_rcu); 782 783wait_for_construction: 784 wait_on_bit(&nf->nf_flags, NFSD_FILE_PENDING, TASK_UNINTERRUPTIBLE); 785 --- 108 unchanged lines hidden --- |