diff options
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/nfs4state.c | 58 |
1 files changed, 36 insertions, 22 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index af88d1d7ccae..f318e706cb35 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -1009,16 +1009,20 @@ static void nfs4_put_stateowner(struct nfs4_stateowner *sop) | |||
1009 | nfs4_free_stateowner(sop); | 1009 | nfs4_free_stateowner(sop); |
1010 | } | 1010 | } |
1011 | 1011 | ||
1012 | static void unhash_ol_stateid(struct nfs4_ol_stateid *stp) | 1012 | static bool unhash_ol_stateid(struct nfs4_ol_stateid *stp) |
1013 | { | 1013 | { |
1014 | struct nfs4_file *fp = stp->st_stid.sc_file; | 1014 | struct nfs4_file *fp = stp->st_stid.sc_file; |
1015 | 1015 | ||
1016 | lockdep_assert_held(&stp->st_stateowner->so_client->cl_lock); | 1016 | lockdep_assert_held(&stp->st_stateowner->so_client->cl_lock); |
1017 | 1017 | ||
1018 | if (list_empty(&stp->st_perfile)) | ||
1019 | return false; | ||
1020 | |||
1018 | spin_lock(&fp->fi_lock); | 1021 | spin_lock(&fp->fi_lock); |
1019 | list_del(&stp->st_perfile); | 1022 | list_del_init(&stp->st_perfile); |
1020 | spin_unlock(&fp->fi_lock); | 1023 | spin_unlock(&fp->fi_lock); |
1021 | list_del(&stp->st_perstateowner); | 1024 | list_del(&stp->st_perstateowner); |
1025 | return true; | ||
1022 | } | 1026 | } |
1023 | 1027 | ||
1024 | static void nfs4_free_ol_stateid(struct nfs4_stid *stid) | 1028 | static void nfs4_free_ol_stateid(struct nfs4_stid *stid) |
@@ -1068,25 +1072,27 @@ static void put_ol_stateid_locked(struct nfs4_ol_stateid *stp, | |||
1068 | list_add(&stp->st_locks, reaplist); | 1072 | list_add(&stp->st_locks, reaplist); |
1069 | } | 1073 | } |
1070 | 1074 | ||
1071 | static void unhash_lock_stateid(struct nfs4_ol_stateid *stp) | 1075 | static bool unhash_lock_stateid(struct nfs4_ol_stateid *stp) |
1072 | { | 1076 | { |
1073 | struct nfs4_openowner *oo = openowner(stp->st_openstp->st_stateowner); | 1077 | struct nfs4_openowner *oo = openowner(stp->st_openstp->st_stateowner); |
1074 | 1078 | ||
1075 | lockdep_assert_held(&oo->oo_owner.so_client->cl_lock); | 1079 | lockdep_assert_held(&oo->oo_owner.so_client->cl_lock); |
1076 | 1080 | ||
1077 | list_del_init(&stp->st_locks); | 1081 | list_del_init(&stp->st_locks); |
1078 | unhash_ol_stateid(stp); | ||
1079 | nfs4_unhash_stid(&stp->st_stid); | 1082 | nfs4_unhash_stid(&stp->st_stid); |
1083 | return unhash_ol_stateid(stp); | ||
1080 | } | 1084 | } |
1081 | 1085 | ||
1082 | static void release_lock_stateid(struct nfs4_ol_stateid *stp) | 1086 | static void release_lock_stateid(struct nfs4_ol_stateid *stp) |
1083 | { | 1087 | { |
1084 | struct nfs4_openowner *oo = openowner(stp->st_openstp->st_stateowner); | 1088 | struct nfs4_openowner *oo = openowner(stp->st_openstp->st_stateowner); |
1089 | bool unhashed; | ||
1085 | 1090 | ||
1086 | spin_lock(&oo->oo_owner.so_client->cl_lock); | 1091 | spin_lock(&oo->oo_owner.so_client->cl_lock); |
1087 | unhash_lock_stateid(stp); | 1092 | unhashed = unhash_lock_stateid(stp); |
1088 | spin_unlock(&oo->oo_owner.so_client->cl_lock); | 1093 | spin_unlock(&oo->oo_owner.so_client->cl_lock); |
1089 | nfs4_put_stid(&stp->st_stid); | 1094 | if (unhashed) |
1095 | nfs4_put_stid(&stp->st_stid); | ||
1090 | } | 1096 | } |
1091 | 1097 | ||
1092 | static void unhash_lockowner_locked(struct nfs4_lockowner *lo) | 1098 | static void unhash_lockowner_locked(struct nfs4_lockowner *lo) |
@@ -1134,7 +1140,7 @@ static void release_lockowner(struct nfs4_lockowner *lo) | |||
1134 | while (!list_empty(&lo->lo_owner.so_stateids)) { | 1140 | while (!list_empty(&lo->lo_owner.so_stateids)) { |
1135 | stp = list_first_entry(&lo->lo_owner.so_stateids, | 1141 | stp = list_first_entry(&lo->lo_owner.so_stateids, |
1136 | struct nfs4_ol_stateid, st_perstateowner); | 1142 | struct nfs4_ol_stateid, st_perstateowner); |
1137 | unhash_lock_stateid(stp); | 1143 | WARN_ON(!unhash_lock_stateid(stp)); |
1138 | put_ol_stateid_locked(stp, &reaplist); | 1144 | put_ol_stateid_locked(stp, &reaplist); |
1139 | } | 1145 | } |
1140 | spin_unlock(&clp->cl_lock); | 1146 | spin_unlock(&clp->cl_lock); |
@@ -1147,21 +1153,26 @@ static void release_open_stateid_locks(struct nfs4_ol_stateid *open_stp, | |||
1147 | { | 1153 | { |
1148 | struct nfs4_ol_stateid *stp; | 1154 | struct nfs4_ol_stateid *stp; |
1149 | 1155 | ||
1156 | lockdep_assert_held(&open_stp->st_stid.sc_client->cl_lock); | ||
1157 | |||
1150 | while (!list_empty(&open_stp->st_locks)) { | 1158 | while (!list_empty(&open_stp->st_locks)) { |
1151 | stp = list_entry(open_stp->st_locks.next, | 1159 | stp = list_entry(open_stp->st_locks.next, |
1152 | struct nfs4_ol_stateid, st_locks); | 1160 | struct nfs4_ol_stateid, st_locks); |
1153 | unhash_lock_stateid(stp); | 1161 | WARN_ON(!unhash_lock_stateid(stp)); |
1154 | put_ol_stateid_locked(stp, reaplist); | 1162 | put_ol_stateid_locked(stp, reaplist); |
1155 | } | 1163 | } |
1156 | } | 1164 | } |
1157 | 1165 | ||
1158 | static void unhash_open_stateid(struct nfs4_ol_stateid *stp, | 1166 | static bool unhash_open_stateid(struct nfs4_ol_stateid *stp, |
1159 | struct list_head *reaplist) | 1167 | struct list_head *reaplist) |
1160 | { | 1168 | { |
1169 | bool unhashed; | ||
1170 | |||
1161 | lockdep_assert_held(&stp->st_stid.sc_client->cl_lock); | 1171 | lockdep_assert_held(&stp->st_stid.sc_client->cl_lock); |
1162 | 1172 | ||
1163 | unhash_ol_stateid(stp); | 1173 | unhashed = unhash_ol_stateid(stp); |
1164 | release_open_stateid_locks(stp, reaplist); | 1174 | release_open_stateid_locks(stp, reaplist); |
1175 | return unhashed; | ||
1165 | } | 1176 | } |
1166 | 1177 | ||
1167 | static void release_open_stateid(struct nfs4_ol_stateid *stp) | 1178 | static void release_open_stateid(struct nfs4_ol_stateid *stp) |
@@ -1169,8 +1180,8 @@ static void release_open_stateid(struct nfs4_ol_stateid *stp) | |||
1169 | LIST_HEAD(reaplist); | 1180 | LIST_HEAD(reaplist); |
1170 | 1181 | ||
1171 | spin_lock(&stp->st_stid.sc_client->cl_lock); | 1182 | spin_lock(&stp->st_stid.sc_client->cl_lock); |
1172 | unhash_open_stateid(stp, &reaplist); | 1183 | if (unhash_open_stateid(stp, &reaplist)) |
1173 | put_ol_stateid_locked(stp, &reaplist); | 1184 | put_ol_stateid_locked(stp, &reaplist); |
1174 | spin_unlock(&stp->st_stid.sc_client->cl_lock); | 1185 | spin_unlock(&stp->st_stid.sc_client->cl_lock); |
1175 | free_ol_stateid_reaplist(&reaplist); | 1186 | free_ol_stateid_reaplist(&reaplist); |
1176 | } | 1187 | } |
@@ -1215,8 +1226,8 @@ static void release_openowner(struct nfs4_openowner *oo) | |||
1215 | while (!list_empty(&oo->oo_owner.so_stateids)) { | 1226 | while (!list_empty(&oo->oo_owner.so_stateids)) { |
1216 | stp = list_first_entry(&oo->oo_owner.so_stateids, | 1227 | stp = list_first_entry(&oo->oo_owner.so_stateids, |
1217 | struct nfs4_ol_stateid, st_perstateowner); | 1228 | struct nfs4_ol_stateid, st_perstateowner); |
1218 | unhash_open_stateid(stp, &reaplist); | 1229 | if (unhash_open_stateid(stp, &reaplist)) |
1219 | put_ol_stateid_locked(stp, &reaplist); | 1230 | put_ol_stateid_locked(stp, &reaplist); |
1220 | } | 1231 | } |
1221 | spin_unlock(&clp->cl_lock); | 1232 | spin_unlock(&clp->cl_lock); |
1222 | free_ol_stateid_reaplist(&reaplist); | 1233 | free_ol_stateid_reaplist(&reaplist); |
@@ -4752,7 +4763,7 @@ nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
4752 | if (check_for_locks(stp->st_stid.sc_file, | 4763 | if (check_for_locks(stp->st_stid.sc_file, |
4753 | lockowner(stp->st_stateowner))) | 4764 | lockowner(stp->st_stateowner))) |
4754 | break; | 4765 | break; |
4755 | unhash_lock_stateid(stp); | 4766 | WARN_ON(!unhash_lock_stateid(stp)); |
4756 | spin_unlock(&cl->cl_lock); | 4767 | spin_unlock(&cl->cl_lock); |
4757 | nfs4_put_stid(s); | 4768 | nfs4_put_stid(s); |
4758 | ret = nfs_ok; | 4769 | ret = nfs_ok; |
@@ -4968,20 +4979,23 @@ out: | |||
4968 | static void nfsd4_close_open_stateid(struct nfs4_ol_stateid *s) | 4979 | static void nfsd4_close_open_stateid(struct nfs4_ol_stateid *s) |
4969 | { | 4980 | { |
4970 | struct nfs4_client *clp = s->st_stid.sc_client; | 4981 | struct nfs4_client *clp = s->st_stid.sc_client; |
4982 | bool unhashed; | ||
4971 | LIST_HEAD(reaplist); | 4983 | LIST_HEAD(reaplist); |
4972 | 4984 | ||
4973 | s->st_stid.sc_type = NFS4_CLOSED_STID; | 4985 | s->st_stid.sc_type = NFS4_CLOSED_STID; |
4974 | spin_lock(&clp->cl_lock); | 4986 | spin_lock(&clp->cl_lock); |
4975 | unhash_open_stateid(s, &reaplist); | 4987 | unhashed = unhash_open_stateid(s, &reaplist); |
4976 | 4988 | ||
4977 | if (clp->cl_minorversion) { | 4989 | if (clp->cl_minorversion) { |
4978 | put_ol_stateid_locked(s, &reaplist); | 4990 | if (unhashed) |
4991 | put_ol_stateid_locked(s, &reaplist); | ||
4979 | spin_unlock(&clp->cl_lock); | 4992 | spin_unlock(&clp->cl_lock); |
4980 | free_ol_stateid_reaplist(&reaplist); | 4993 | free_ol_stateid_reaplist(&reaplist); |
4981 | } else { | 4994 | } else { |
4982 | spin_unlock(&clp->cl_lock); | 4995 | spin_unlock(&clp->cl_lock); |
4983 | free_ol_stateid_reaplist(&reaplist); | 4996 | free_ol_stateid_reaplist(&reaplist); |
4984 | move_to_close_lru(s, clp->net); | 4997 | if (unhashed) |
4998 | move_to_close_lru(s, clp->net); | ||
4985 | } | 4999 | } |
4986 | } | 5000 | } |
4987 | 5001 | ||
@@ -6014,7 +6028,7 @@ nfsd_inject_add_lock_to_list(struct nfs4_ol_stateid *lst, | |||
6014 | 6028 | ||
6015 | static u64 nfsd_foreach_client_lock(struct nfs4_client *clp, u64 max, | 6029 | static u64 nfsd_foreach_client_lock(struct nfs4_client *clp, u64 max, |
6016 | struct list_head *collect, | 6030 | struct list_head *collect, |
6017 | void (*func)(struct nfs4_ol_stateid *)) | 6031 | bool (*func)(struct nfs4_ol_stateid *)) |
6018 | { | 6032 | { |
6019 | struct nfs4_openowner *oop; | 6033 | struct nfs4_openowner *oop; |
6020 | struct nfs4_ol_stateid *stp, *st_next; | 6034 | struct nfs4_ol_stateid *stp, *st_next; |
@@ -6028,9 +6042,9 @@ static u64 nfsd_foreach_client_lock(struct nfs4_client *clp, u64 max, | |||
6028 | list_for_each_entry_safe(lst, lst_next, | 6042 | list_for_each_entry_safe(lst, lst_next, |
6029 | &stp->st_locks, st_locks) { | 6043 | &stp->st_locks, st_locks) { |
6030 | if (func) { | 6044 | if (func) { |
6031 | func(lst); | 6045 | if (func(lst)) |
6032 | nfsd_inject_add_lock_to_list(lst, | 6046 | nfsd_inject_add_lock_to_list(lst, |
6033 | collect); | 6047 | collect); |
6034 | } | 6048 | } |
6035 | ++count; | 6049 | ++count; |
6036 | /* | 6050 | /* |