diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-06-30 11:48:38 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2014-07-08 17:14:37 -0400 |
commit | 3c87b9b7c05d7775a3d942de588296025023c6d2 (patch) | |
tree | 5f2f480974ad925b754b91cea2037d5237bc28e4 | |
parent | acf9295b1c4e60fc205e21b7a5c9dc6e1cb2764a (diff) |
nfsd: lock owners are not per open stateid
In the NFSv4 spec, lock stateids are per-file objects. Lockowners are not.
This patch replaces the current list of lock owners in the open stateids
with a list of lock stateids.
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r-- | fs/nfsd/nfs4state.c | 53 | ||||
-rw-r--r-- | fs/nfsd/state.h | 3 |
2 files changed, 36 insertions, 20 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 1e973f67999d..137fdcce9023 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -695,10 +695,11 @@ static void free_generic_stateid(struct nfs4_ol_stateid *stp) | |||
695 | nfs4_free_stid(stateid_slab, &stp->st_stid); | 695 | nfs4_free_stid(stateid_slab, &stp->st_stid); |
696 | } | 696 | } |
697 | 697 | ||
698 | static void release_lock_stateid(struct nfs4_ol_stateid *stp) | 698 | static void __release_lock_stateid(struct nfs4_ol_stateid *stp) |
699 | { | 699 | { |
700 | struct file *file; | 700 | struct file *file; |
701 | 701 | ||
702 | list_del(&stp->st_locks); | ||
702 | unhash_generic_stateid(stp); | 703 | unhash_generic_stateid(stp); |
703 | unhash_stid(&stp->st_stid); | 704 | unhash_stid(&stp->st_stid); |
704 | file = find_any_file(stp->st_file); | 705 | file = find_any_file(stp->st_file); |
@@ -713,12 +714,11 @@ static void unhash_lockowner(struct nfs4_lockowner *lo) | |||
713 | struct nfs4_ol_stateid *stp; | 714 | struct nfs4_ol_stateid *stp; |
714 | 715 | ||
715 | list_del(&lo->lo_owner.so_strhash); | 716 | list_del(&lo->lo_owner.so_strhash); |
716 | list_del(&lo->lo_perstateid); | ||
717 | list_del(&lo->lo_owner_ino_hash); | 717 | list_del(&lo->lo_owner_ino_hash); |
718 | while (!list_empty(&lo->lo_owner.so_stateids)) { | 718 | while (!list_empty(&lo->lo_owner.so_stateids)) { |
719 | stp = list_first_entry(&lo->lo_owner.so_stateids, | 719 | stp = list_first_entry(&lo->lo_owner.so_stateids, |
720 | struct nfs4_ol_stateid, st_perstateowner); | 720 | struct nfs4_ol_stateid, st_perstateowner); |
721 | release_lock_stateid(stp); | 721 | __release_lock_stateid(stp); |
722 | } | 722 | } |
723 | } | 723 | } |
724 | 724 | ||
@@ -734,22 +734,36 @@ static void release_lockowner(struct nfs4_lockowner *lo) | |||
734 | nfs4_free_lockowner(lo); | 734 | nfs4_free_lockowner(lo); |
735 | } | 735 | } |
736 | 736 | ||
737 | static void | 737 | static void release_lockowner_if_empty(struct nfs4_lockowner *lo) |
738 | release_stateid_lockowners(struct nfs4_ol_stateid *open_stp) | 738 | { |
739 | if (list_empty(&lo->lo_owner.so_stateids)) | ||
740 | release_lockowner(lo); | ||
741 | } | ||
742 | |||
743 | static void release_lock_stateid(struct nfs4_ol_stateid *stp) | ||
739 | { | 744 | { |
740 | struct nfs4_lockowner *lo; | 745 | struct nfs4_lockowner *lo; |
741 | 746 | ||
742 | while (!list_empty(&open_stp->st_lockowners)) { | 747 | lo = lockowner(stp->st_stateowner); |
743 | lo = list_entry(open_stp->st_lockowners.next, | 748 | __release_lock_stateid(stp); |
744 | struct nfs4_lockowner, lo_perstateid); | 749 | release_lockowner_if_empty(lo); |
745 | release_lockowner(lo); | 750 | } |
751 | |||
752 | static void release_open_stateid_locks(struct nfs4_ol_stateid *open_stp) | ||
753 | { | ||
754 | struct nfs4_ol_stateid *stp; | ||
755 | |||
756 | while (!list_empty(&open_stp->st_locks)) { | ||
757 | stp = list_entry(open_stp->st_locks.next, | ||
758 | struct nfs4_ol_stateid, st_locks); | ||
759 | release_lock_stateid(stp); | ||
746 | } | 760 | } |
747 | } | 761 | } |
748 | 762 | ||
749 | static void unhash_open_stateid(struct nfs4_ol_stateid *stp) | 763 | static void unhash_open_stateid(struct nfs4_ol_stateid *stp) |
750 | { | 764 | { |
751 | unhash_generic_stateid(stp); | 765 | unhash_generic_stateid(stp); |
752 | release_stateid_lockowners(stp); | 766 | release_open_stateid_locks(stp); |
753 | close_generic_stateid(stp); | 767 | close_generic_stateid(stp); |
754 | } | 768 | } |
755 | 769 | ||
@@ -2744,7 +2758,7 @@ static void init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp, | |||
2744 | struct nfs4_openowner *oo = open->op_openowner; | 2758 | struct nfs4_openowner *oo = open->op_openowner; |
2745 | 2759 | ||
2746 | stp->st_stid.sc_type = NFS4_OPEN_STID; | 2760 | stp->st_stid.sc_type = NFS4_OPEN_STID; |
2747 | INIT_LIST_HEAD(&stp->st_lockowners); | 2761 | INIT_LIST_HEAD(&stp->st_locks); |
2748 | list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids); | 2762 | list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids); |
2749 | list_add(&stp->st_perfile, &fp->fi_stateids); | 2763 | list_add(&stp->st_perfile, &fp->fi_stateids); |
2750 | stp->st_stateowner = &oo->oo_owner; | 2764 | stp->st_stateowner = &oo->oo_owner; |
@@ -4335,7 +4349,6 @@ static void hash_lockowner(struct nfs4_lockowner *lo, unsigned int strhashval, s | |||
4335 | 4349 | ||
4336 | list_add(&lo->lo_owner.so_strhash, &nn->ownerstr_hashtbl[strhashval]); | 4350 | list_add(&lo->lo_owner.so_strhash, &nn->ownerstr_hashtbl[strhashval]); |
4337 | list_add(&lo->lo_owner_ino_hash, &nn->lockowner_ino_hashtbl[inohash]); | 4351 | list_add(&lo->lo_owner_ino_hash, &nn->lockowner_ino_hashtbl[inohash]); |
4338 | list_add(&lo->lo_perstateid, &open_stp->st_lockowners); | ||
4339 | } | 4352 | } |
4340 | 4353 | ||
4341 | /* | 4354 | /* |
@@ -4380,6 +4393,7 @@ alloc_init_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fp, struct | |||
4380 | stp->st_access_bmap = 0; | 4393 | stp->st_access_bmap = 0; |
4381 | stp->st_deny_bmap = open_stp->st_deny_bmap; | 4394 | stp->st_deny_bmap = open_stp->st_deny_bmap; |
4382 | stp->st_openstp = open_stp; | 4395 | stp->st_openstp = open_stp; |
4396 | list_add(&stp->st_locks, &open_stp->st_locks); | ||
4383 | return stp; | 4397 | return stp; |
4384 | } | 4398 | } |
4385 | 4399 | ||
@@ -4967,18 +4981,21 @@ static void nfsd_print_count(struct nfs4_client *clp, unsigned int count, | |||
4967 | printk(KERN_INFO "NFS Client: %s has %u %s\n", buf, count, type); | 4981 | printk(KERN_INFO "NFS Client: %s has %u %s\n", buf, count, type); |
4968 | } | 4982 | } |
4969 | 4983 | ||
4970 | static u64 nfsd_foreach_client_lock(struct nfs4_client *clp, u64 max, void (*func)(struct nfs4_lockowner *)) | 4984 | static u64 nfsd_foreach_client_lock(struct nfs4_client *clp, u64 max, |
4985 | void (*func)(struct nfs4_ol_stateid *)) | ||
4971 | { | 4986 | { |
4972 | struct nfs4_openowner *oop; | 4987 | struct nfs4_openowner *oop; |
4973 | struct nfs4_lockowner *lop, *lo_next; | ||
4974 | struct nfs4_ol_stateid *stp, *st_next; | 4988 | struct nfs4_ol_stateid *stp, *st_next; |
4989 | struct nfs4_ol_stateid *lst, *lst_next; | ||
4975 | u64 count = 0; | 4990 | u64 count = 0; |
4976 | 4991 | ||
4977 | list_for_each_entry(oop, &clp->cl_openowners, oo_perclient) { | 4992 | list_for_each_entry(oop, &clp->cl_openowners, oo_perclient) { |
4978 | list_for_each_entry_safe(stp, st_next, &oop->oo_owner.so_stateids, st_perstateowner) { | 4993 | list_for_each_entry_safe(stp, st_next, |
4979 | list_for_each_entry_safe(lop, lo_next, &stp->st_lockowners, lo_perstateid) { | 4994 | &oop->oo_owner.so_stateids, st_perstateowner) { |
4995 | list_for_each_entry_safe(lst, lst_next, | ||
4996 | &stp->st_locks, st_locks) { | ||
4980 | if (func) | 4997 | if (func) |
4981 | func(lop); | 4998 | func(lst); |
4982 | if (++count == max) | 4999 | if (++count == max) |
4983 | return count; | 5000 | return count; |
4984 | } | 5001 | } |
@@ -4990,7 +5007,7 @@ static u64 nfsd_foreach_client_lock(struct nfs4_client *clp, u64 max, void (*fun | |||
4990 | 5007 | ||
4991 | u64 nfsd_forget_client_locks(struct nfs4_client *clp, u64 max) | 5008 | u64 nfsd_forget_client_locks(struct nfs4_client *clp, u64 max) |
4992 | { | 5009 | { |
4993 | return nfsd_foreach_client_lock(clp, max, release_lockowner); | 5010 | return nfsd_foreach_client_lock(clp, max, release_lock_stateid); |
4994 | } | 5011 | } |
4995 | 5012 | ||
4996 | u64 nfsd_print_client_locks(struct nfs4_client *clp, u64 max) | 5013 | u64 nfsd_print_client_locks(struct nfs4_client *clp, u64 max) |
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 62f33b7ec10c..c1e384a0a40a 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h | |||
@@ -365,7 +365,6 @@ struct nfs4_openowner { | |||
365 | struct nfs4_lockowner { | 365 | struct nfs4_lockowner { |
366 | struct nfs4_stateowner lo_owner; /* must be first element */ | 366 | struct nfs4_stateowner lo_owner; /* must be first element */ |
367 | struct list_head lo_owner_ino_hash; /* hash by owner,file */ | 367 | struct list_head lo_owner_ino_hash; /* hash by owner,file */ |
368 | struct list_head lo_perstateid; | ||
369 | struct list_head lo_list; /* for temporary uses */ | 368 | struct list_head lo_list; /* for temporary uses */ |
370 | }; | 369 | }; |
371 | 370 | ||
@@ -433,7 +432,7 @@ struct nfs4_ol_stateid { | |||
433 | struct nfs4_stid st_stid; /* must be first field */ | 432 | struct nfs4_stid st_stid; /* must be first field */ |
434 | struct list_head st_perfile; | 433 | struct list_head st_perfile; |
435 | struct list_head st_perstateowner; | 434 | struct list_head st_perstateowner; |
436 | struct list_head st_lockowners; | 435 | struct list_head st_locks; |
437 | struct nfs4_stateowner * st_stateowner; | 436 | struct nfs4_stateowner * st_stateowner; |
438 | struct nfs4_file * st_file; | 437 | struct nfs4_file * st_file; |
439 | unsigned long st_access_bmap; | 438 | unsigned long st_access_bmap; |