aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/delegation.c42
-rw-r--r--fs/nfs/delegation.h2
-rw-r--r--fs/nfs/dns_resolve.c4
-rw-r--r--fs/nfs/nfs4proc.c28
-rw-r--r--fs/nfs/nfs4state.c67
-rw-r--r--fs/nfs/nfs4xdr.c2
-rw-r--r--net/sunrpc/auth.c39
-rw-r--r--net/sunrpc/xprt.c4
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
95static void nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid) 95static 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 */
264static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation) 265static 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);
281out:
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 */
284void nfs_client_return_marked_delegations(struct nfs_client *clp) 288int 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
289restart: 294restart:
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
374static void nfs_client_mark_return_all_delegations(struct nfs_client *clp) 388static 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);
42void nfs_expire_all_delegations(struct nfs_client *clp); 42void nfs_expire_all_delegations(struct nfs_client *clp);
43void nfs_expire_unreferenced_delegations(struct nfs_client *clp); 43void nfs_expire_unreferenced_delegations(struct nfs_client *clp);
44void nfs_handle_cb_pathdown(struct nfs_client *clp); 44void nfs_handle_cb_pathdown(struct nfs_client *clp);
45void nfs_client_return_marked_delegations(struct nfs_client *clp); 45int nfs_client_return_marked_delegations(struct nfs_client *clp);
46 46
47void nfs_delegation_mark_reclaim(struct nfs_client *clp); 47void nfs_delegation_mark_reclaim(struct nfs_client *clp);
48void nfs_delegation_reap_unclaimed(struct nfs_client *clp); 48void 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
149struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd, 149static 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
162struct nfs_dns_ent *nfs_dns_update(struct cache_detail *cd, 162static 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
1498static inline int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state) 1498static 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);
1515out:
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
1991void nfs4_close_context(struct nfs_open_context *ctx, int is_sync) 1997static 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);
4074out:
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
1057static void nfs4_state_end_reclaim_nograce(struct nfs_client *clp) 1057static int nfs4_recovery_handle_error(struct nfs_client *clp, int error)
1058{
1059 clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state);
1060}
1061
1062static 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
1087static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recovery_ops *ops) 1087static 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);
1134out: 1133out:
1135 nfs4_recovery_handle_error(clp, status); 1134 return nfs4_recovery_handle_error(clp, status);
1136 return status;
1137} 1135}
1138 1136
1139static int nfs4_reclaim_lease(struct nfs_client *clp) 1137static 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)
1317out_error: 1314out_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
126static void 126static int
127rpcauth_unhash_cred(struct rpc_cred *cred) 127rpcauth_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
446put_rpccred(struct rpc_cred *cred) 449put_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 }
455need_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);
472out_destroy:
473 cred->cr_ops->crdestroy(cred); 477 cred->cr_ops->crdestroy(cred);
478 return;
479out_nodestroy:
480 spin_unlock(&rpc_credcache_lock);
474} 481}
475EXPORT_SYMBOL_GPL(put_rpccred); 482EXPORT_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 {