diff options
author | Jeff Layton <jlayton@primarydata.com> | 2014-07-29 21:34:12 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2014-07-31 14:20:07 -0400 |
commit | 1c755dc1ada95adc9aa41102baada73659397b80 (patch) | |
tree | f0a71a29d1b9a834dfacc9086c86bb9c77ac45dd /fs/nfsd/nfs4state.c | |
parent | b49e084d8c7df1632bb2b94ae1a21c8a4cf2d8a4 (diff) |
nfsd: Add locking to protect the state owner lists
Change to using the clp->cl_lock for this. For now, there's a lot of
cl_lock thrashing, but in later patches we'll eliminate that and close
the potential races that can occur when releasing the cl_lock while
walking the lists. For now, the client_mutex prevents those races.
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 8ce5894133aa..3ac6e2fdabe5 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -893,6 +893,8 @@ static void unhash_generic_stateid(struct nfs4_ol_stateid *stp) | |||
893 | { | 893 | { |
894 | struct nfs4_file *fp = stp->st_stid.sc_file; | 894 | struct nfs4_file *fp = stp->st_stid.sc_file; |
895 | 895 | ||
896 | lockdep_assert_held(&stp->st_stateowner->so_client->cl_lock); | ||
897 | |||
896 | spin_lock(&fp->fi_lock); | 898 | spin_lock(&fp->fi_lock); |
897 | list_del(&stp->st_perfile); | 899 | list_del(&stp->st_perfile); |
898 | spin_unlock(&fp->fi_lock); | 900 | spin_unlock(&fp->fi_lock); |
@@ -921,9 +923,13 @@ static void nfs4_free_lock_stateid(struct nfs4_stid *stid) | |||
921 | 923 | ||
922 | static void __release_lock_stateid(struct nfs4_ol_stateid *stp) | 924 | static void __release_lock_stateid(struct nfs4_ol_stateid *stp) |
923 | { | 925 | { |
926 | struct nfs4_openowner *oo = openowner(stp->st_openstp->st_stateowner); | ||
927 | |||
928 | spin_lock(&oo->oo_owner.so_client->cl_lock); | ||
924 | list_del(&stp->st_locks); | 929 | list_del(&stp->st_locks); |
925 | unhash_generic_stateid(stp); | 930 | unhash_generic_stateid(stp); |
926 | unhash_stid(&stp->st_stid); | 931 | unhash_stid(&stp->st_stid); |
932 | spin_unlock(&oo->oo_owner.so_client->cl_lock); | ||
927 | nfs4_put_stid(&stp->st_stid); | 933 | nfs4_put_stid(&stp->st_stid); |
928 | } | 934 | } |
929 | 935 | ||
@@ -967,20 +973,26 @@ static void release_lock_stateid(struct nfs4_ol_stateid *stp) | |||
967 | } | 973 | } |
968 | 974 | ||
969 | static void release_open_stateid_locks(struct nfs4_ol_stateid *open_stp) | 975 | static void release_open_stateid_locks(struct nfs4_ol_stateid *open_stp) |
976 | __releases(&open_stp->st_stateowner->so_client->cl_lock) | ||
977 | __acquires(&open_stp->st_stateowner->so_client->cl_lock) | ||
970 | { | 978 | { |
971 | struct nfs4_ol_stateid *stp; | 979 | struct nfs4_ol_stateid *stp; |
972 | 980 | ||
973 | while (!list_empty(&open_stp->st_locks)) { | 981 | while (!list_empty(&open_stp->st_locks)) { |
974 | stp = list_entry(open_stp->st_locks.next, | 982 | stp = list_entry(open_stp->st_locks.next, |
975 | struct nfs4_ol_stateid, st_locks); | 983 | struct nfs4_ol_stateid, st_locks); |
984 | spin_unlock(&open_stp->st_stateowner->so_client->cl_lock); | ||
976 | release_lock_stateid(stp); | 985 | release_lock_stateid(stp); |
986 | spin_lock(&open_stp->st_stateowner->so_client->cl_lock); | ||
977 | } | 987 | } |
978 | } | 988 | } |
979 | 989 | ||
980 | static void unhash_open_stateid(struct nfs4_ol_stateid *stp) | 990 | static void unhash_open_stateid(struct nfs4_ol_stateid *stp) |
981 | { | 991 | { |
992 | spin_lock(&stp->st_stateowner->so_client->cl_lock); | ||
982 | unhash_generic_stateid(stp); | 993 | unhash_generic_stateid(stp); |
983 | release_open_stateid_locks(stp); | 994 | release_open_stateid_locks(stp); |
995 | spin_unlock(&stp->st_stateowner->so_client->cl_lock); | ||
984 | } | 996 | } |
985 | 997 | ||
986 | static void release_open_stateid(struct nfs4_ol_stateid *stp) | 998 | static void release_open_stateid(struct nfs4_ol_stateid *stp) |
@@ -2996,16 +3008,18 @@ static void init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp, | |||
2996 | 3008 | ||
2997 | stp->st_stid.sc_type = NFS4_OPEN_STID; | 3009 | stp->st_stid.sc_type = NFS4_OPEN_STID; |
2998 | INIT_LIST_HEAD(&stp->st_locks); | 3010 | INIT_LIST_HEAD(&stp->st_locks); |
2999 | list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids); | ||
3000 | stp->st_stateowner = &oo->oo_owner; | 3011 | stp->st_stateowner = &oo->oo_owner; |
3001 | get_nfs4_file(fp); | 3012 | get_nfs4_file(fp); |
3002 | stp->st_stid.sc_file = fp; | 3013 | stp->st_stid.sc_file = fp; |
3003 | stp->st_access_bmap = 0; | 3014 | stp->st_access_bmap = 0; |
3004 | stp->st_deny_bmap = 0; | 3015 | stp->st_deny_bmap = 0; |
3005 | stp->st_openstp = NULL; | 3016 | stp->st_openstp = NULL; |
3017 | spin_lock(&oo->oo_owner.so_client->cl_lock); | ||
3018 | list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids); | ||
3006 | spin_lock(&fp->fi_lock); | 3019 | spin_lock(&fp->fi_lock); |
3007 | list_add(&stp->st_perfile, &fp->fi_stateids); | 3020 | list_add(&stp->st_perfile, &fp->fi_stateids); |
3008 | spin_unlock(&fp->fi_lock); | 3021 | spin_unlock(&fp->fi_lock); |
3022 | spin_unlock(&oo->oo_owner.so_client->cl_lock); | ||
3009 | } | 3023 | } |
3010 | 3024 | ||
3011 | static void | 3025 | static void |
@@ -4711,6 +4725,7 @@ alloc_init_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fp, | |||
4711 | struct nfs4_ol_stateid *open_stp) | 4725 | struct nfs4_ol_stateid *open_stp) |
4712 | { | 4726 | { |
4713 | struct nfs4_stid *s; | 4727 | struct nfs4_stid *s; |
4728 | struct nfs4_openowner *oo = openowner(open_stp->st_stateowner); | ||
4714 | struct nfs4_ol_stateid *stp; | 4729 | struct nfs4_ol_stateid *stp; |
4715 | struct nfs4_client *clp = lo->lo_owner.so_client; | 4730 | struct nfs4_client *clp = lo->lo_owner.so_client; |
4716 | 4731 | ||
@@ -4719,7 +4734,6 @@ alloc_init_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fp, | |||
4719 | return NULL; | 4734 | return NULL; |
4720 | stp = openlockstateid(s); | 4735 | stp = openlockstateid(s); |
4721 | stp->st_stid.sc_type = NFS4_LOCK_STID; | 4736 | stp->st_stid.sc_type = NFS4_LOCK_STID; |
4722 | list_add(&stp->st_perstateowner, &lo->lo_owner.so_stateids); | ||
4723 | stp->st_stateowner = &lo->lo_owner; | 4737 | stp->st_stateowner = &lo->lo_owner; |
4724 | get_nfs4_file(fp); | 4738 | get_nfs4_file(fp); |
4725 | stp->st_stid.sc_file = fp; | 4739 | stp->st_stid.sc_file = fp; |
@@ -4727,10 +4741,13 @@ alloc_init_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fp, | |||
4727 | stp->st_access_bmap = 0; | 4741 | stp->st_access_bmap = 0; |
4728 | stp->st_deny_bmap = open_stp->st_deny_bmap; | 4742 | stp->st_deny_bmap = open_stp->st_deny_bmap; |
4729 | stp->st_openstp = open_stp; | 4743 | stp->st_openstp = open_stp; |
4744 | spin_lock(&oo->oo_owner.so_client->cl_lock); | ||
4730 | list_add(&stp->st_locks, &open_stp->st_locks); | 4745 | list_add(&stp->st_locks, &open_stp->st_locks); |
4746 | list_add(&stp->st_perstateowner, &lo->lo_owner.so_stateids); | ||
4731 | spin_lock(&fp->fi_lock); | 4747 | spin_lock(&fp->fi_lock); |
4732 | list_add(&stp->st_perfile, &fp->fi_stateids); | 4748 | list_add(&stp->st_perfile, &fp->fi_stateids); |
4733 | spin_unlock(&fp->fi_lock); | 4749 | spin_unlock(&fp->fi_lock); |
4750 | spin_unlock(&oo->oo_owner.so_client->cl_lock); | ||
4734 | return stp; | 4751 | return stp; |
4735 | } | 4752 | } |
4736 | 4753 | ||