diff options
author | Jeff Layton <jlayton@primarydata.com> | 2014-07-30 08:27:11 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2014-08-01 16:28:24 -0400 |
commit | 217526e7ecc9f6f243e976772e81eab7ab986a4c (patch) | |
tree | 07a271d7b7592f682ad8ff8ff08ddd2c61bfc860 | |
parent | 0a880a28f8add9b134a26f6e058c40199a2ffbc8 (diff) |
nfsd: protect the close_lru list and oo_last_closed_stid with client_lock
Currently, it's protected by the client_mutex. Move it so that the list
and the fields in the openowner are protected by the client_lock.
Signed-off-by: Jeff Layton <jlayton@primarydata.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r-- | fs/nfsd/nfs4state.c | 38 |
1 files changed, 31 insertions, 7 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index e7dfd4e9d942..818480035453 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -1122,13 +1122,19 @@ static void unhash_openowner_locked(struct nfs4_openowner *oo) | |||
1122 | 1122 | ||
1123 | static void release_last_closed_stateid(struct nfs4_openowner *oo) | 1123 | static void release_last_closed_stateid(struct nfs4_openowner *oo) |
1124 | { | 1124 | { |
1125 | struct nfs4_ol_stateid *s = oo->oo_last_closed_stid; | 1125 | struct nfsd_net *nn = net_generic(oo->oo_owner.so_client->net, |
1126 | nfsd_net_id); | ||
1127 | struct nfs4_ol_stateid *s; | ||
1126 | 1128 | ||
1129 | spin_lock(&nn->client_lock); | ||
1130 | s = oo->oo_last_closed_stid; | ||
1127 | if (s) { | 1131 | if (s) { |
1128 | list_del_init(&oo->oo_close_lru); | 1132 | list_del_init(&oo->oo_close_lru); |
1129 | oo->oo_last_closed_stid = NULL; | 1133 | oo->oo_last_closed_stid = NULL; |
1130 | nfs4_put_stid(&s->st_stid); | ||
1131 | } | 1134 | } |
1135 | spin_unlock(&nn->client_lock); | ||
1136 | if (s) | ||
1137 | nfs4_put_stid(&s->st_stid); | ||
1132 | } | 1138 | } |
1133 | 1139 | ||
1134 | static void release_openowner(struct nfs4_openowner *oo) | 1140 | static void release_openowner(struct nfs4_openowner *oo) |
@@ -3265,6 +3271,7 @@ static void init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp, | |||
3265 | static void | 3271 | static void |
3266 | move_to_close_lru(struct nfs4_ol_stateid *s, struct net *net) | 3272 | move_to_close_lru(struct nfs4_ol_stateid *s, struct net *net) |
3267 | { | 3273 | { |
3274 | struct nfs4_ol_stateid *last; | ||
3268 | struct nfs4_openowner *oo = openowner(s->st_stateowner); | 3275 | struct nfs4_openowner *oo = openowner(s->st_stateowner); |
3269 | struct nfsd_net *nn = net_generic(s->st_stid.sc_client->net, | 3276 | struct nfsd_net *nn = net_generic(s->st_stid.sc_client->net, |
3270 | nfsd_net_id); | 3277 | nfsd_net_id); |
@@ -3287,10 +3294,15 @@ move_to_close_lru(struct nfs4_ol_stateid *s, struct net *net) | |||
3287 | put_nfs4_file(s->st_stid.sc_file); | 3294 | put_nfs4_file(s->st_stid.sc_file); |
3288 | s->st_stid.sc_file = NULL; | 3295 | s->st_stid.sc_file = NULL; |
3289 | } | 3296 | } |
3290 | release_last_closed_stateid(oo); | 3297 | |
3298 | spin_lock(&nn->client_lock); | ||
3299 | last = oo->oo_last_closed_stid; | ||
3291 | oo->oo_last_closed_stid = s; | 3300 | oo->oo_last_closed_stid = s; |
3292 | list_move_tail(&oo->oo_close_lru, &nn->close_lru); | 3301 | list_move_tail(&oo->oo_close_lru, &nn->close_lru); |
3293 | oo->oo_time = get_seconds(); | 3302 | oo->oo_time = get_seconds(); |
3303 | spin_unlock(&nn->client_lock); | ||
3304 | if (last) | ||
3305 | nfs4_put_stid(&last->st_stid); | ||
3294 | } | 3306 | } |
3295 | 3307 | ||
3296 | /* search file_hashtbl[] for file */ | 3308 | /* search file_hashtbl[] for file */ |
@@ -4148,6 +4160,7 @@ nfs4_laundromat(struct nfsd_net *nn) | |||
4148 | struct nfs4_client *clp; | 4160 | struct nfs4_client *clp; |
4149 | struct nfs4_openowner *oo; | 4161 | struct nfs4_openowner *oo; |
4150 | struct nfs4_delegation *dp; | 4162 | struct nfs4_delegation *dp; |
4163 | struct nfs4_ol_stateid *stp; | ||
4151 | struct list_head *pos, *next, reaplist; | 4164 | struct list_head *pos, *next, reaplist; |
4152 | time_t cutoff = get_seconds() - nn->nfsd4_lease; | 4165 | time_t cutoff = get_seconds() - nn->nfsd4_lease; |
4153 | time_t t, new_timeo = nn->nfsd4_lease; | 4166 | time_t t, new_timeo = nn->nfsd4_lease; |
@@ -4201,15 +4214,26 @@ nfs4_laundromat(struct nfsd_net *nn) | |||
4201 | list_del_init(&dp->dl_recall_lru); | 4214 | list_del_init(&dp->dl_recall_lru); |
4202 | revoke_delegation(dp); | 4215 | revoke_delegation(dp); |
4203 | } | 4216 | } |
4204 | list_for_each_safe(pos, next, &nn->close_lru) { | 4217 | |
4205 | oo = container_of(pos, struct nfs4_openowner, oo_close_lru); | 4218 | spin_lock(&nn->client_lock); |
4206 | if (time_after((unsigned long)oo->oo_time, (unsigned long)cutoff)) { | 4219 | while (!list_empty(&nn->close_lru)) { |
4220 | oo = list_first_entry(&nn->close_lru, struct nfs4_openowner, | ||
4221 | oo_close_lru); | ||
4222 | if (time_after((unsigned long)oo->oo_time, | ||
4223 | (unsigned long)cutoff)) { | ||
4207 | t = oo->oo_time - cutoff; | 4224 | t = oo->oo_time - cutoff; |
4208 | new_timeo = min(new_timeo, t); | 4225 | new_timeo = min(new_timeo, t); |
4209 | break; | 4226 | break; |
4210 | } | 4227 | } |
4211 | release_last_closed_stateid(oo); | 4228 | list_del_init(&oo->oo_close_lru); |
4229 | stp = oo->oo_last_closed_stid; | ||
4230 | oo->oo_last_closed_stid = NULL; | ||
4231 | spin_unlock(&nn->client_lock); | ||
4232 | nfs4_put_stid(&stp->st_stid); | ||
4233 | spin_lock(&nn->client_lock); | ||
4212 | } | 4234 | } |
4235 | spin_unlock(&nn->client_lock); | ||
4236 | |||
4213 | new_timeo = max_t(time_t, new_timeo, NFSD_LAUNDROMAT_MINTIMEOUT); | 4237 | new_timeo = max_t(time_t, new_timeo, NFSD_LAUNDROMAT_MINTIMEOUT); |
4214 | nfs4_unlock_state(); | 4238 | nfs4_unlock_state(); |
4215 | return new_timeo; | 4239 | return new_timeo; |