diff options
-rw-r--r-- | fs/nfs/delegation.c | 42 | ||||
-rw-r--r-- | fs/nfs/delegation.h | 2 | ||||
-rw-r--r-- | fs/nfs/dns_resolve.c | 4 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 28 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 67 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 2 | ||||
-rw-r--r-- | net/sunrpc/auth.c | 39 | ||||
-rw-r--r-- | net/sunrpc/xprt.c | 4 |
8 files changed, 110 insertions, 78 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 6dd48a4405b4..eeecd69c130c 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
@@ -92,7 +92,7 @@ out: | |||
92 | return status; | 92 | return status; |
93 | } | 93 | } |
94 | 94 | ||
95 | static void nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid) | 95 | static int nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid) |
96 | { | 96 | { |
97 | struct nfs_inode *nfsi = NFS_I(inode); | 97 | struct nfs_inode *nfsi = NFS_I(inode); |
98 | struct nfs_open_context *ctx; | 98 | struct nfs_open_context *ctx; |
@@ -116,10 +116,11 @@ again: | |||
116 | err = nfs_delegation_claim_locks(ctx, state); | 116 | err = nfs_delegation_claim_locks(ctx, state); |
117 | put_nfs_open_context(ctx); | 117 | put_nfs_open_context(ctx); |
118 | if (err != 0) | 118 | if (err != 0) |
119 | return; | 119 | return err; |
120 | goto again; | 120 | goto again; |
121 | } | 121 | } |
122 | spin_unlock(&inode->i_lock); | 122 | spin_unlock(&inode->i_lock); |
123 | return 0; | ||
123 | } | 124 | } |
124 | 125 | ||
125 | /* | 126 | /* |
@@ -261,30 +262,34 @@ static void nfs_msync_inode(struct inode *inode) | |||
261 | /* | 262 | /* |
262 | * Basic procedure for returning a delegation to the server | 263 | * Basic procedure for returning a delegation to the server |
263 | */ | 264 | */ |
264 | static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation) | 265 | static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync) |
265 | { | 266 | { |
266 | struct nfs_inode *nfsi = NFS_I(inode); | 267 | struct nfs_inode *nfsi = NFS_I(inode); |
268 | int err; | ||
267 | 269 | ||
268 | nfs_msync_inode(inode); | ||
269 | /* | 270 | /* |
270 | * Guard against new delegated open/lock/unlock calls and against | 271 | * Guard against new delegated open/lock/unlock calls and against |
271 | * state recovery | 272 | * state recovery |
272 | */ | 273 | */ |
273 | down_write(&nfsi->rwsem); | 274 | down_write(&nfsi->rwsem); |
274 | nfs_delegation_claim_opens(inode, &delegation->stateid); | 275 | err = nfs_delegation_claim_opens(inode, &delegation->stateid); |
275 | up_write(&nfsi->rwsem); | 276 | up_write(&nfsi->rwsem); |
276 | nfs_msync_inode(inode); | 277 | if (err) |
278 | goto out; | ||
277 | 279 | ||
278 | return nfs_do_return_delegation(inode, delegation, 1); | 280 | err = nfs_do_return_delegation(inode, delegation, issync); |
281 | out: | ||
282 | return err; | ||
279 | } | 283 | } |
280 | 284 | ||
281 | /* | 285 | /* |
282 | * Return all delegations that have been marked for return | 286 | * Return all delegations that have been marked for return |
283 | */ | 287 | */ |
284 | void nfs_client_return_marked_delegations(struct nfs_client *clp) | 288 | int nfs_client_return_marked_delegations(struct nfs_client *clp) |
285 | { | 289 | { |
286 | struct nfs_delegation *delegation; | 290 | struct nfs_delegation *delegation; |
287 | struct inode *inode; | 291 | struct inode *inode; |
292 | int err = 0; | ||
288 | 293 | ||
289 | restart: | 294 | restart: |
290 | rcu_read_lock(); | 295 | rcu_read_lock(); |
@@ -298,12 +303,18 @@ restart: | |||
298 | delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL); | 303 | delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL); |
299 | spin_unlock(&clp->cl_lock); | 304 | spin_unlock(&clp->cl_lock); |
300 | rcu_read_unlock(); | 305 | rcu_read_unlock(); |
301 | if (delegation != NULL) | 306 | if (delegation != NULL) { |
302 | __nfs_inode_return_delegation(inode, delegation); | 307 | filemap_flush(inode->i_mapping); |
308 | err = __nfs_inode_return_delegation(inode, delegation, 0); | ||
309 | } | ||
303 | iput(inode); | 310 | iput(inode); |
304 | goto restart; | 311 | if (!err) |
312 | goto restart; | ||
313 | set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state); | ||
314 | return err; | ||
305 | } | 315 | } |
306 | rcu_read_unlock(); | 316 | rcu_read_unlock(); |
317 | return 0; | ||
307 | } | 318 | } |
308 | 319 | ||
309 | /* | 320 | /* |
@@ -338,8 +349,10 @@ int nfs_inode_return_delegation(struct inode *inode) | |||
338 | spin_lock(&clp->cl_lock); | 349 | spin_lock(&clp->cl_lock); |
339 | delegation = nfs_detach_delegation_locked(nfsi, NULL); | 350 | delegation = nfs_detach_delegation_locked(nfsi, NULL); |
340 | spin_unlock(&clp->cl_lock); | 351 | spin_unlock(&clp->cl_lock); |
341 | if (delegation != NULL) | 352 | if (delegation != NULL) { |
342 | err = __nfs_inode_return_delegation(inode, delegation); | 353 | nfs_msync_inode(inode); |
354 | err = __nfs_inode_return_delegation(inode, delegation, 1); | ||
355 | } | ||
343 | } | 356 | } |
344 | return err; | 357 | return err; |
345 | } | 358 | } |
@@ -368,7 +381,8 @@ void nfs_super_return_all_delegations(struct super_block *sb) | |||
368 | spin_unlock(&delegation->lock); | 381 | spin_unlock(&delegation->lock); |
369 | } | 382 | } |
370 | rcu_read_unlock(); | 383 | rcu_read_unlock(); |
371 | nfs_client_return_marked_delegations(clp); | 384 | if (nfs_client_return_marked_delegations(clp) != 0) |
385 | nfs4_schedule_state_manager(clp); | ||
372 | } | 386 | } |
373 | 387 | ||
374 | static void nfs_client_mark_return_all_delegations(struct nfs_client *clp) | 388 | static void nfs_client_mark_return_all_delegations(struct nfs_client *clp) |
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h index 09f383795174..e225a1290127 100644 --- a/fs/nfs/delegation.h +++ b/fs/nfs/delegation.h | |||
@@ -42,7 +42,7 @@ void nfs_super_return_all_delegations(struct super_block *sb); | |||
42 | void nfs_expire_all_delegations(struct nfs_client *clp); | 42 | void nfs_expire_all_delegations(struct nfs_client *clp); |
43 | void nfs_expire_unreferenced_delegations(struct nfs_client *clp); | 43 | void nfs_expire_unreferenced_delegations(struct nfs_client *clp); |
44 | void nfs_handle_cb_pathdown(struct nfs_client *clp); | 44 | void nfs_handle_cb_pathdown(struct nfs_client *clp); |
45 | void nfs_client_return_marked_delegations(struct nfs_client *clp); | 45 | int nfs_client_return_marked_delegations(struct nfs_client *clp); |
46 | 46 | ||
47 | void nfs_delegation_mark_reclaim(struct nfs_client *clp); | 47 | void nfs_delegation_mark_reclaim(struct nfs_client *clp); |
48 | void nfs_delegation_reap_unclaimed(struct nfs_client *clp); | 48 | void nfs_delegation_reap_unclaimed(struct nfs_client *clp); |
diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c index f4d54ba97cc6..95e1ca765d47 100644 --- a/fs/nfs/dns_resolve.c +++ b/fs/nfs/dns_resolve.c | |||
@@ -146,7 +146,7 @@ static int nfs_dns_show(struct seq_file *m, struct cache_detail *cd, | |||
146 | return 0; | 146 | return 0; |
147 | } | 147 | } |
148 | 148 | ||
149 | struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd, | 149 | static struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd, |
150 | struct nfs_dns_ent *key) | 150 | struct nfs_dns_ent *key) |
151 | { | 151 | { |
152 | struct cache_head *ch; | 152 | struct cache_head *ch; |
@@ -159,7 +159,7 @@ struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd, | |||
159 | return container_of(ch, struct nfs_dns_ent, h); | 159 | return container_of(ch, struct nfs_dns_ent, h); |
160 | } | 160 | } |
161 | 161 | ||
162 | struct nfs_dns_ent *nfs_dns_update(struct cache_detail *cd, | 162 | static struct nfs_dns_ent *nfs_dns_update(struct cache_detail *cd, |
163 | struct nfs_dns_ent *new, | 163 | struct nfs_dns_ent *new, |
164 | struct nfs_dns_ent *key) | 164 | struct nfs_dns_ent *key) |
165 | { | 165 | { |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 40da0d5bc5fc..0f9b7541e049 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -1495,7 +1495,7 @@ static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *s | |||
1495 | return ret; | 1495 | return ret; |
1496 | } | 1496 | } |
1497 | 1497 | ||
1498 | static inline int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state) | 1498 | static int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state) |
1499 | { | 1499 | { |
1500 | struct nfs_server *server = NFS_SERVER(state->inode); | 1500 | struct nfs_server *server = NFS_SERVER(state->inode); |
1501 | struct nfs4_exception exception = { }; | 1501 | struct nfs4_exception exception = { }; |
@@ -1503,10 +1503,16 @@ static inline int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4 | |||
1503 | 1503 | ||
1504 | do { | 1504 | do { |
1505 | err = _nfs4_open_expired(ctx, state); | 1505 | err = _nfs4_open_expired(ctx, state); |
1506 | if (err != -NFS4ERR_DELAY) | 1506 | switch (err) { |
1507 | break; | 1507 | default: |
1508 | nfs4_handle_exception(server, err, &exception); | 1508 | goto out; |
1509 | case -NFS4ERR_GRACE: | ||
1510 | case -NFS4ERR_DELAY: | ||
1511 | nfs4_handle_exception(server, err, &exception); | ||
1512 | err = 0; | ||
1513 | } | ||
1509 | } while (exception.retry); | 1514 | } while (exception.retry); |
1515 | out: | ||
1510 | return err; | 1516 | return err; |
1511 | } | 1517 | } |
1512 | 1518 | ||
@@ -1988,7 +1994,7 @@ out_drop: | |||
1988 | return 0; | 1994 | return 0; |
1989 | } | 1995 | } |
1990 | 1996 | ||
1991 | void nfs4_close_context(struct nfs_open_context *ctx, int is_sync) | 1997 | static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync) |
1992 | { | 1998 | { |
1993 | if (ctx->state == NULL) | 1999 | if (ctx->state == NULL) |
1994 | return; | 2000 | return; |
@@ -4056,10 +4062,16 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request | |||
4056 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) | 4062 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) |
4057 | return 0; | 4063 | return 0; |
4058 | err = _nfs4_do_setlk(state, F_SETLK, request, 0); | 4064 | err = _nfs4_do_setlk(state, F_SETLK, request, 0); |
4059 | if (err != -NFS4ERR_DELAY) | 4065 | switch (err) { |
4060 | break; | 4066 | default: |
4061 | nfs4_handle_exception(server, err, &exception); | 4067 | goto out; |
4068 | case -NFS4ERR_GRACE: | ||
4069 | case -NFS4ERR_DELAY: | ||
4070 | nfs4_handle_exception(server, err, &exception); | ||
4071 | err = 0; | ||
4072 | } | ||
4062 | } while (exception.retry); | 4073 | } while (exception.retry); |
4074 | out: | ||
4063 | return err; | 4075 | return err; |
4064 | } | 4076 | } |
4065 | 4077 | ||
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 3004089e97b1..2eb0059bd693 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -1054,20 +1054,19 @@ static void nfs4_state_start_reclaim_nograce(struct nfs_client *clp) | |||
1054 | nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce); | 1054 | nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce); |
1055 | } | 1055 | } |
1056 | 1056 | ||
1057 | static void nfs4_state_end_reclaim_nograce(struct nfs_client *clp) | 1057 | static int nfs4_recovery_handle_error(struct nfs_client *clp, int error) |
1058 | { | ||
1059 | clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state); | ||
1060 | } | ||
1061 | |||
1062 | static void nfs4_recovery_handle_error(struct nfs_client *clp, int error) | ||
1063 | { | 1058 | { |
1064 | switch (error) { | 1059 | switch (error) { |
1065 | case -NFS4ERR_CB_PATH_DOWN: | 1060 | case -NFS4ERR_CB_PATH_DOWN: |
1066 | nfs_handle_cb_pathdown(clp); | 1061 | nfs_handle_cb_pathdown(clp); |
1067 | break; | 1062 | return 0; |
1063 | case -NFS4ERR_NO_GRACE: | ||
1064 | nfs4_state_end_reclaim_reboot(clp); | ||
1065 | return 0; | ||
1068 | case -NFS4ERR_STALE_CLIENTID: | 1066 | case -NFS4ERR_STALE_CLIENTID: |
1069 | case -NFS4ERR_LEASE_MOVED: | 1067 | case -NFS4ERR_LEASE_MOVED: |
1070 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); | 1068 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); |
1069 | nfs4_state_end_reclaim_reboot(clp); | ||
1071 | nfs4_state_start_reclaim_reboot(clp); | 1070 | nfs4_state_start_reclaim_reboot(clp); |
1072 | break; | 1071 | break; |
1073 | case -NFS4ERR_EXPIRED: | 1072 | case -NFS4ERR_EXPIRED: |
@@ -1082,6 +1081,7 @@ static void nfs4_recovery_handle_error(struct nfs_client *clp, int error) | |||
1082 | case -NFS4ERR_SEQ_MISORDERED: | 1081 | case -NFS4ERR_SEQ_MISORDERED: |
1083 | set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state); | 1082 | set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state); |
1084 | } | 1083 | } |
1084 | return error; | ||
1085 | } | 1085 | } |
1086 | 1086 | ||
1087 | static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recovery_ops *ops) | 1087 | static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recovery_ops *ops) |
@@ -1101,8 +1101,7 @@ restart: | |||
1101 | if (status < 0) { | 1101 | if (status < 0) { |
1102 | set_bit(ops->owner_flag_bit, &sp->so_flags); | 1102 | set_bit(ops->owner_flag_bit, &sp->so_flags); |
1103 | nfs4_put_state_owner(sp); | 1103 | nfs4_put_state_owner(sp); |
1104 | nfs4_recovery_handle_error(clp, status); | 1104 | return nfs4_recovery_handle_error(clp, status); |
1105 | return status; | ||
1106 | } | 1105 | } |
1107 | nfs4_put_state_owner(sp); | 1106 | nfs4_put_state_owner(sp); |
1108 | goto restart; | 1107 | goto restart; |
@@ -1132,8 +1131,7 @@ static int nfs4_check_lease(struct nfs_client *clp) | |||
1132 | status = ops->renew_lease(clp, cred); | 1131 | status = ops->renew_lease(clp, cred); |
1133 | put_rpccred(cred); | 1132 | put_rpccred(cred); |
1134 | out: | 1133 | out: |
1135 | nfs4_recovery_handle_error(clp, status); | 1134 | return nfs4_recovery_handle_error(clp, status); |
1136 | return status; | ||
1137 | } | 1135 | } |
1138 | 1136 | ||
1139 | static int nfs4_reclaim_lease(struct nfs_client *clp) | 1137 | static int nfs4_reclaim_lease(struct nfs_client *clp) |
@@ -1242,7 +1240,8 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
1242 | status = nfs4_reclaim_lease(clp); | 1240 | status = nfs4_reclaim_lease(clp); |
1243 | if (status) { | 1241 | if (status) { |
1244 | nfs4_set_lease_expired(clp, status); | 1242 | nfs4_set_lease_expired(clp, status); |
1245 | if (status == -EAGAIN) | 1243 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, |
1244 | &clp->cl_state)) | ||
1246 | continue; | 1245 | continue; |
1247 | if (clp->cl_cons_state == | 1246 | if (clp->cl_cons_state == |
1248 | NFS_CS_SESSION_INITING) | 1247 | NFS_CS_SESSION_INITING) |
@@ -1254,9 +1253,12 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
1254 | 1253 | ||
1255 | if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) { | 1254 | if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) { |
1256 | status = nfs4_check_lease(clp); | 1255 | status = nfs4_check_lease(clp); |
1257 | if (status != 0) | 1256 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) |
1258 | continue; | 1257 | continue; |
1258 | if (status < 0 && status != -NFS4ERR_CB_PATH_DOWN) | ||
1259 | goto out_error; | ||
1259 | } | 1260 | } |
1261 | |||
1260 | /* Initialize or reset the session */ | 1262 | /* Initialize or reset the session */ |
1261 | if (test_and_clear_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state) | 1263 | if (test_and_clear_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state) |
1262 | && nfs4_has_session(clp)) { | 1264 | && nfs4_has_session(clp)) { |
@@ -1264,41 +1266,36 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
1264 | status = nfs4_initialize_session(clp); | 1266 | status = nfs4_initialize_session(clp); |
1265 | else | 1267 | else |
1266 | status = nfs4_reset_session(clp); | 1268 | status = nfs4_reset_session(clp); |
1267 | if (status) { | 1269 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) |
1268 | if (status == -NFS4ERR_STALE_CLIENTID) | 1270 | continue; |
1269 | continue; | 1271 | if (status < 0) |
1270 | goto out_error; | 1272 | goto out_error; |
1271 | } | ||
1272 | } | 1273 | } |
1274 | |||
1273 | /* First recover reboot state... */ | 1275 | /* First recover reboot state... */ |
1274 | if (test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) { | 1276 | if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) { |
1275 | status = nfs4_do_reclaim(clp, | 1277 | status = nfs4_do_reclaim(clp, |
1276 | nfs4_reboot_recovery_ops[clp->cl_minorversion]); | 1278 | nfs4_reboot_recovery_ops[clp->cl_minorversion]); |
1277 | if (status == -NFS4ERR_STALE_CLIENTID) | 1279 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || |
1278 | continue; | 1280 | test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state)) |
1279 | if (test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state)) | ||
1280 | continue; | 1281 | continue; |
1281 | nfs4_state_end_reclaim_reboot(clp); | 1282 | nfs4_state_end_reclaim_reboot(clp); |
1282 | continue; | 1283 | if (test_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) |
1284 | continue; | ||
1285 | if (status < 0) | ||
1286 | goto out_error; | ||
1283 | } | 1287 | } |
1284 | 1288 | ||
1285 | /* Now recover expired state... */ | 1289 | /* Now recover expired state... */ |
1286 | if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) { | 1290 | if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) { |
1287 | status = nfs4_do_reclaim(clp, | 1291 | status = nfs4_do_reclaim(clp, |
1288 | nfs4_nograce_recovery_ops[clp->cl_minorversion]); | 1292 | nfs4_nograce_recovery_ops[clp->cl_minorversion]); |
1289 | if (status < 0) { | 1293 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || |
1290 | set_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state); | 1294 | test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state) || |
1291 | if (status == -NFS4ERR_STALE_CLIENTID) | 1295 | test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) |
1292 | continue; | 1296 | continue; |
1293 | if (status == -NFS4ERR_EXPIRED) | 1297 | if (status < 0) |
1294 | continue; | ||
1295 | if (test_bit(NFS4CLNT_SESSION_SETUP, | ||
1296 | &clp->cl_state)) | ||
1297 | continue; | ||
1298 | goto out_error; | 1298 | goto out_error; |
1299 | } else | ||
1300 | nfs4_state_end_reclaim_nograce(clp); | ||
1301 | continue; | ||
1302 | } | 1299 | } |
1303 | 1300 | ||
1304 | if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) { | 1301 | if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) { |
@@ -1317,8 +1314,6 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
1317 | out_error: | 1314 | out_error: |
1318 | printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s" | 1315 | printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s" |
1319 | " with error %d\n", clp->cl_hostname, -status); | 1316 | " with error %d\n", clp->cl_hostname, -status); |
1320 | if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) | ||
1321 | nfs4_state_end_reclaim_reboot(clp); | ||
1322 | nfs4_clear_state_manager_bit(clp); | 1317 | nfs4_clear_state_manager_bit(clp); |
1323 | } | 1318 | } |
1324 | 1319 | ||
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 20b4e30e6c82..3a71b40a990a 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -2096,7 +2096,7 @@ nfs4_xdr_enc_getacl(struct rpc_rqst *req, __be32 *p, | |||
2096 | encode_compound_hdr(&xdr, req, &hdr); | 2096 | encode_compound_hdr(&xdr, req, &hdr); |
2097 | encode_sequence(&xdr, &args->seq_args, &hdr); | 2097 | encode_sequence(&xdr, &args->seq_args, &hdr); |
2098 | encode_putfh(&xdr, args->fh, &hdr); | 2098 | encode_putfh(&xdr, args->fh, &hdr); |
2099 | replen = hdr.replen + nfs4_fattr_bitmap_maxsz + 1; | 2099 | replen = hdr.replen + op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz + 1; |
2100 | encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0, &hdr); | 2100 | encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0, &hdr); |
2101 | 2101 | ||
2102 | xdr_inline_pages(&req->rq_rcv_buf, replen << 2, | 2102 | xdr_inline_pages(&req->rq_rcv_buf, replen << 2, |
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 54a4e042f104..7ee6f7eaddfb 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
@@ -123,16 +123,19 @@ rpcauth_unhash_cred_locked(struct rpc_cred *cred) | |||
123 | clear_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags); | 123 | clear_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags); |
124 | } | 124 | } |
125 | 125 | ||
126 | static void | 126 | static int |
127 | rpcauth_unhash_cred(struct rpc_cred *cred) | 127 | rpcauth_unhash_cred(struct rpc_cred *cred) |
128 | { | 128 | { |
129 | spinlock_t *cache_lock; | 129 | spinlock_t *cache_lock; |
130 | int ret; | ||
130 | 131 | ||
131 | cache_lock = &cred->cr_auth->au_credcache->lock; | 132 | cache_lock = &cred->cr_auth->au_credcache->lock; |
132 | spin_lock(cache_lock); | 133 | spin_lock(cache_lock); |
133 | if (atomic_read(&cred->cr_count) == 0) | 134 | ret = atomic_read(&cred->cr_count) == 0; |
135 | if (ret) | ||
134 | rpcauth_unhash_cred_locked(cred); | 136 | rpcauth_unhash_cred_locked(cred); |
135 | spin_unlock(cache_lock); | 137 | spin_unlock(cache_lock); |
138 | return ret; | ||
136 | } | 139 | } |
137 | 140 | ||
138 | /* | 141 | /* |
@@ -446,31 +449,35 @@ void | |||
446 | put_rpccred(struct rpc_cred *cred) | 449 | put_rpccred(struct rpc_cred *cred) |
447 | { | 450 | { |
448 | /* Fast path for unhashed credentials */ | 451 | /* Fast path for unhashed credentials */ |
449 | if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) | 452 | if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) == 0) { |
450 | goto need_lock; | 453 | if (atomic_dec_and_test(&cred->cr_count)) |
451 | 454 | cred->cr_ops->crdestroy(cred); | |
452 | if (!atomic_dec_and_test(&cred->cr_count)) | ||
453 | return; | 455 | return; |
454 | goto out_destroy; | 456 | } |
455 | need_lock: | 457 | |
456 | if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock)) | 458 | if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock)) |
457 | return; | 459 | return; |
458 | if (!list_empty(&cred->cr_lru)) { | 460 | if (!list_empty(&cred->cr_lru)) { |
459 | number_cred_unused--; | 461 | number_cred_unused--; |
460 | list_del_init(&cred->cr_lru); | 462 | list_del_init(&cred->cr_lru); |
461 | } | 463 | } |
462 | if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0) | ||
463 | rpcauth_unhash_cred(cred); | ||
464 | if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) { | 464 | if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) { |
465 | cred->cr_expire = jiffies; | 465 | if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0) { |
466 | list_add_tail(&cred->cr_lru, &cred_unused); | 466 | cred->cr_expire = jiffies; |
467 | number_cred_unused++; | 467 | list_add_tail(&cred->cr_lru, &cred_unused); |
468 | spin_unlock(&rpc_credcache_lock); | 468 | number_cred_unused++; |
469 | return; | 469 | goto out_nodestroy; |
470 | } | ||
471 | if (!rpcauth_unhash_cred(cred)) { | ||
472 | /* We were hashed and someone looked us up... */ | ||
473 | goto out_nodestroy; | ||
474 | } | ||
470 | } | 475 | } |
471 | spin_unlock(&rpc_credcache_lock); | 476 | spin_unlock(&rpc_credcache_lock); |
472 | out_destroy: | ||
473 | cred->cr_ops->crdestroy(cred); | 477 | cred->cr_ops->crdestroy(cred); |
478 | return; | ||
479 | out_nodestroy: | ||
480 | spin_unlock(&rpc_credcache_lock); | ||
474 | } | 481 | } |
475 | EXPORT_SYMBOL_GPL(put_rpccred); | 482 | EXPORT_SYMBOL_GPL(put_rpccred); |
476 | 483 | ||
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index fd46d42afa89..469de292c23c 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -700,6 +700,10 @@ void xprt_connect(struct rpc_task *task) | |||
700 | } | 700 | } |
701 | if (!xprt_lock_write(xprt, task)) | 701 | if (!xprt_lock_write(xprt, task)) |
702 | return; | 702 | return; |
703 | |||
704 | if (test_and_clear_bit(XPRT_CLOSE_WAIT, &xprt->state)) | ||
705 | xprt->ops->close(xprt); | ||
706 | |||
703 | if (xprt_connected(xprt)) | 707 | if (xprt_connected(xprt)) |
704 | xprt_release_write(xprt, task); | 708 | xprt_release_write(xprt, task); |
705 | else { | 709 | else { |