Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6

* 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6:
NFS: NFSROOT should default to "proto=udp"
nfs4: remove duplicated #include
NFSv4: nfs4_state_mark_reclaim_nograce() should be static
NFSv4: Fix the setlk error handler
NFSv4.1: Fix the handling of the SEQUENCE status bits
NFSv4/4.1: Fix nfs4_schedule_state_recovery abuses
NFSv4.1 reclaim complete must wait for completion
NFSv4: remove duplicate clientid in struct nfs_client
NFSv4.1: Retry CREATE_SESSION on NFS4ERR_DELAY
sunrpc: Propagate errors from xs_bind() through xs_create_sock()
(try3-resend) Fix nfs_compat_user_ino64 so it doesn't cause problems if bit 31 or 63 are set in fileid
nfs: fix compilation warning
nfs: add kmalloc return value check in decode_and_add_ds
SUNRPC: Remove resource leak in svc_rdma_send_error()
nfs: close NFSv4 COMMIT vs. CLOSE race
SUNRPC: Close a race in __rpc_wait_for_completion_task()

+178 -91
+6 -1
fs/nfs/inode.c
··· 37 37 #include <linux/inet.h> 38 38 #include <linux/nfs_xdr.h> 39 39 #include <linux/slab.h> 40 + #include <linux/compat.h> 40 41 41 42 #include <asm/system.h> 42 43 #include <asm/uaccess.h> ··· 90 89 */ 91 90 u64 nfs_compat_user_ino64(u64 fileid) 92 91 { 93 - int ino; 92 + #ifdef CONFIG_COMPAT 93 + compat_ulong_t ino; 94 + #else 95 + unsigned long ino; 96 + #endif 94 97 95 98 if (enable_ino64) 96 99 return fileid;
+7 -3
fs/nfs/nfs4_fs.h
··· 298 298 #if defined(CONFIG_NFS_V4_1) 299 299 struct rpc_cred *nfs4_get_machine_cred_locked(struct nfs_client *clp); 300 300 struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp); 301 + extern void nfs4_schedule_session_recovery(struct nfs4_session *); 302 + #else 303 + static inline void nfs4_schedule_session_recovery(struct nfs4_session *session) 304 + { 305 + } 301 306 #endif /* CONFIG_NFS_V4_1 */ 302 307 303 308 extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *); ··· 312 307 extern void nfs4_close_state(struct path *, struct nfs4_state *, fmode_t); 313 308 extern void nfs4_close_sync(struct path *, struct nfs4_state *, fmode_t); 314 309 extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t); 315 - extern void nfs4_schedule_state_recovery(struct nfs_client *); 310 + extern void nfs4_schedule_lease_recovery(struct nfs_client *); 316 311 extern void nfs4_schedule_state_manager(struct nfs_client *); 317 - extern int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state); 318 - extern int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state); 312 + extern void nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *); 319 313 extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags); 320 314 extern void nfs41_handle_recall_slot(struct nfs_client *clp); 321 315 extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
+4
fs/nfs/nfs4filelayoutdev.c
··· 219 219 goto out_err; 220 220 } 221 221 buf = kmalloc(rlen + 1, GFP_KERNEL); 222 + if (!buf) { 223 + dprintk("%s: Not enough memory\n", __func__); 224 + goto out_err; 225 + } 222 226 buf[rlen] = '\0'; 223 227 memcpy(buf, r_addr, rlen); 224 228
+52 -39
fs/nfs/nfs4proc.c
··· 51 51 #include <linux/sunrpc/bc_xprt.h> 52 52 #include <linux/xattr.h> 53 53 #include <linux/utsname.h> 54 - #include <linux/mm.h> 55 54 56 55 #include "nfs4_fs.h" 57 56 #include "delegation.h" ··· 256 257 case -NFS4ERR_OPENMODE: 257 258 if (state == NULL) 258 259 break; 259 - nfs4_state_mark_reclaim_nograce(clp, state); 260 - goto do_state_recovery; 260 + nfs4_schedule_stateid_recovery(server, state); 261 + goto wait_on_recovery; 261 262 case -NFS4ERR_STALE_STATEID: 262 263 case -NFS4ERR_STALE_CLIENTID: 263 264 case -NFS4ERR_EXPIRED: 264 - goto do_state_recovery; 265 + nfs4_schedule_lease_recovery(clp); 266 + goto wait_on_recovery; 265 267 #if defined(CONFIG_NFS_V4_1) 266 268 case -NFS4ERR_BADSESSION: 267 269 case -NFS4ERR_BADSLOT: ··· 273 273 case -NFS4ERR_SEQ_MISORDERED: 274 274 dprintk("%s ERROR: %d Reset session\n", __func__, 275 275 errorcode); 276 - nfs4_schedule_state_recovery(clp); 276 + nfs4_schedule_session_recovery(clp->cl_session); 277 277 exception->retry = 1; 278 278 break; 279 279 #endif /* defined(CONFIG_NFS_V4_1) */ ··· 296 296 } 297 297 /* We failed to handle the error */ 298 298 return nfs4_map_errors(ret); 299 - do_state_recovery: 300 - nfs4_schedule_state_recovery(clp); 299 + wait_on_recovery: 301 300 ret = nfs4_wait_clnt_recover(clp); 302 301 if (ret == 0) 303 302 exception->retry = 1; ··· 435 436 clp = res->sr_session->clp; 436 437 do_renew_lease(clp, timestamp); 437 438 /* Check sequence flags */ 438 - if (atomic_read(&clp->cl_count) > 1) 439 - nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags); 439 + if (res->sr_status_flags != 0) 440 + nfs4_schedule_lease_recovery(clp); 440 441 break; 441 442 case -NFS4ERR_DELAY: 442 443 /* The server detected a resend of the RPC call and ··· 1255 1256 case -NFS4ERR_BAD_HIGH_SLOT: 1256 1257 case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: 1257 1258 case -NFS4ERR_DEADSESSION: 1258 - nfs4_schedule_state_recovery( 1259 - server->nfs_client); 1259 + nfs4_schedule_session_recovery(server->nfs_client->cl_session); 1260 1260 goto out; 1261 1261 case -NFS4ERR_STALE_CLIENTID: 1262 1262 case -NFS4ERR_STALE_STATEID: 1263 1263 case -NFS4ERR_EXPIRED: 1264 1264 /* Don't recall a delegation if it was lost */ 1265 - nfs4_schedule_state_recovery(server->nfs_client); 1265 + nfs4_schedule_lease_recovery(server->nfs_client); 1266 1266 goto out; 1267 1267 case -ERESTARTSYS: 1268 1268 /* ··· 1270 1272 */ 1271 1273 case -NFS4ERR_ADMIN_REVOKED: 1272 1274 case -NFS4ERR_BAD_STATEID: 1273 - nfs4_state_mark_reclaim_nograce(server->nfs_client, state); 1275 + nfs4_schedule_stateid_recovery(server, state); 1274 1276 case -EKEYEXPIRED: 1275 1277 /* 1276 1278 * User RPCSEC_GSS context has expired. ··· 1586 1588 if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) && 1587 1589 !test_bit(NFS4CLNT_CHECK_LEASE,&clp->cl_state)) 1588 1590 break; 1589 - nfs4_schedule_state_recovery(clp); 1591 + nfs4_schedule_state_manager(clp); 1590 1592 ret = -EIO; 1591 1593 } 1592 1594 return ret; ··· 3177 3179 if (task->tk_status < 0) { 3178 3180 /* Unless we're shutting down, schedule state recovery! */ 3179 3181 if (test_bit(NFS_CS_RENEWD, &clp->cl_res_state) != 0) 3180 - nfs4_schedule_state_recovery(clp); 3182 + nfs4_schedule_lease_recovery(clp); 3181 3183 return; 3182 3184 } 3183 3185 do_renew_lease(clp, timestamp); ··· 3260 3262 spages = pages; 3261 3263 3262 3264 do { 3263 - len = min(PAGE_CACHE_SIZE, buflen); 3265 + len = min_t(size_t, PAGE_CACHE_SIZE, buflen); 3264 3266 newpage = alloc_page(GFP_KERNEL); 3265 3267 3266 3268 if (newpage == NULL) ··· 3502 3504 case -NFS4ERR_OPENMODE: 3503 3505 if (state == NULL) 3504 3506 break; 3505 - nfs4_state_mark_reclaim_nograce(clp, state); 3506 - goto do_state_recovery; 3507 + nfs4_schedule_stateid_recovery(server, state); 3508 + goto wait_on_recovery; 3507 3509 case -NFS4ERR_STALE_STATEID: 3508 3510 case -NFS4ERR_STALE_CLIENTID: 3509 3511 case -NFS4ERR_EXPIRED: 3510 - goto do_state_recovery; 3512 + nfs4_schedule_lease_recovery(clp); 3513 + goto wait_on_recovery; 3511 3514 #if defined(CONFIG_NFS_V4_1) 3512 3515 case -NFS4ERR_BADSESSION: 3513 3516 case -NFS4ERR_BADSLOT: ··· 3519 3520 case -NFS4ERR_SEQ_MISORDERED: 3520 3521 dprintk("%s ERROR %d, Reset session\n", __func__, 3521 3522 task->tk_status); 3522 - nfs4_schedule_state_recovery(clp); 3523 + nfs4_schedule_session_recovery(clp->cl_session); 3523 3524 task->tk_status = 0; 3524 3525 return -EAGAIN; 3525 3526 #endif /* CONFIG_NFS_V4_1 */ ··· 3536 3537 } 3537 3538 task->tk_status = nfs4_map_errors(task->tk_status); 3538 3539 return 0; 3539 - do_state_recovery: 3540 + wait_on_recovery: 3540 3541 rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL); 3541 - nfs4_schedule_state_recovery(clp); 3542 3542 if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0) 3543 3543 rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task); 3544 3544 task->tk_status = 0; ··· 4148 4150 task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp, 4149 4151 data->arg.lock_seqid); 4150 4152 if (!IS_ERR(task)) 4151 - rpc_put_task(task); 4153 + rpc_put_task_async(task); 4152 4154 dprintk("%s: cancelling lock!\n", __func__); 4153 4155 } else 4154 4156 nfs_free_seqid(data->arg.lock_seqid); ··· 4172 4174 4173 4175 static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_state *lsp, int new_lock_owner, int error) 4174 4176 { 4175 - struct nfs_client *clp = server->nfs_client; 4176 - struct nfs4_state *state = lsp->ls_state; 4177 - 4178 4177 switch (error) { 4179 4178 case -NFS4ERR_ADMIN_REVOKED: 4180 4179 case -NFS4ERR_BAD_STATEID: 4181 - case -NFS4ERR_EXPIRED: 4180 + lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; 4182 4181 if (new_lock_owner != 0 || 4183 4182 (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) 4184 - nfs4_state_mark_reclaim_nograce(clp, state); 4185 - lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; 4183 + nfs4_schedule_stateid_recovery(server, lsp->ls_state); 4186 4184 break; 4187 4185 case -NFS4ERR_STALE_STATEID: 4188 - if (new_lock_owner != 0 || 4189 - (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) 4190 - nfs4_state_mark_reclaim_reboot(clp, state); 4191 4186 lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; 4187 + case -NFS4ERR_EXPIRED: 4188 + nfs4_schedule_lease_recovery(server->nfs_client); 4192 4189 }; 4193 4190 } 4194 4191 ··· 4399 4406 case -NFS4ERR_EXPIRED: 4400 4407 case -NFS4ERR_STALE_CLIENTID: 4401 4408 case -NFS4ERR_STALE_STATEID: 4409 + nfs4_schedule_lease_recovery(server->nfs_client); 4410 + goto out; 4402 4411 case -NFS4ERR_BADSESSION: 4403 4412 case -NFS4ERR_BADSLOT: 4404 4413 case -NFS4ERR_BAD_HIGH_SLOT: 4405 4414 case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: 4406 4415 case -NFS4ERR_DEADSESSION: 4407 - nfs4_schedule_state_recovery(server->nfs_client); 4416 + nfs4_schedule_session_recovery(server->nfs_client->cl_session); 4408 4417 goto out; 4409 4418 case -ERESTARTSYS: 4410 4419 /* ··· 4416 4421 case -NFS4ERR_ADMIN_REVOKED: 4417 4422 case -NFS4ERR_BAD_STATEID: 4418 4423 case -NFS4ERR_OPENMODE: 4419 - nfs4_state_mark_reclaim_nograce(server->nfs_client, state); 4424 + nfs4_schedule_stateid_recovery(server, state); 4420 4425 err = 0; 4421 4426 goto out; 4422 4427 case -EKEYEXPIRED: ··· 5023 5028 int status; 5024 5029 unsigned *ptr; 5025 5030 struct nfs4_session *session = clp->cl_session; 5031 + long timeout = 0; 5032 + int err; 5026 5033 5027 5034 dprintk("--> %s clp=%p session=%p\n", __func__, clp, session); 5028 5035 5029 - status = _nfs4_proc_create_session(clp); 5036 + do { 5037 + status = _nfs4_proc_create_session(clp); 5038 + if (status == -NFS4ERR_DELAY) { 5039 + err = nfs4_delay(clp->cl_rpcclient, &timeout); 5040 + if (err) 5041 + status = err; 5042 + } 5043 + } while (status == -NFS4ERR_DELAY); 5044 + 5030 5045 if (status) 5031 5046 goto out; 5032 5047 ··· 5145 5140 rpc_delay(task, NFS4_POLL_RETRY_MAX); 5146 5141 return -EAGAIN; 5147 5142 default: 5148 - nfs4_schedule_state_recovery(clp); 5143 + nfs4_schedule_lease_recovery(clp); 5149 5144 } 5150 5145 return 0; 5151 5146 } ··· 5232 5227 if (IS_ERR(task)) 5233 5228 ret = PTR_ERR(task); 5234 5229 else 5235 - rpc_put_task(task); 5230 + rpc_put_task_async(task); 5236 5231 dprintk("<-- %s status=%d\n", __func__, ret); 5237 5232 return ret; 5238 5233 } ··· 5248 5243 goto out; 5249 5244 } 5250 5245 ret = rpc_wait_for_completion_task(task); 5251 - if (!ret) 5246 + if (!ret) { 5247 + struct nfs4_sequence_res *res = task->tk_msg.rpc_resp; 5248 + 5249 + if (task->tk_status == 0) 5250 + nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags); 5252 5251 ret = task->tk_status; 5252 + } 5253 5253 rpc_put_task(task); 5254 5254 out: 5255 5255 dprintk("<-- %s status=%d\n", __func__, ret); ··· 5291 5281 rpc_delay(task, NFS4_POLL_RETRY_MAX); 5292 5282 return -EAGAIN; 5293 5283 default: 5294 - nfs4_schedule_state_recovery(clp); 5284 + nfs4_schedule_lease_recovery(clp); 5295 5285 } 5296 5286 return 0; 5297 5287 } ··· 5359 5349 status = PTR_ERR(task); 5360 5350 goto out; 5361 5351 } 5352 + status = nfs4_wait_for_completion_rpc_task(task); 5353 + if (status == 0) 5354 + status = task->tk_status; 5362 5355 rpc_put_task(task); 5363 5356 return 0; 5364 5357 out:
+21 -8
fs/nfs/nfs4state.c
··· 1007 1007 } 1008 1008 1009 1009 /* 1010 - * Schedule a state recovery attempt 1010 + * Schedule a lease recovery attempt 1011 1011 */ 1012 - void nfs4_schedule_state_recovery(struct nfs_client *clp) 1012 + void nfs4_schedule_lease_recovery(struct nfs_client *clp) 1013 1013 { 1014 1014 if (!clp) 1015 1015 return; ··· 1018 1018 nfs4_schedule_state_manager(clp); 1019 1019 } 1020 1020 1021 - int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state) 1021 + static int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state) 1022 1022 { 1023 1023 1024 1024 set_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags); ··· 1032 1032 return 1; 1033 1033 } 1034 1034 1035 - int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state) 1035 + static int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state) 1036 1036 { 1037 1037 set_bit(NFS_STATE_RECLAIM_NOGRACE, &state->flags); 1038 1038 clear_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags); 1039 1039 set_bit(NFS_OWNER_RECLAIM_NOGRACE, &state->owner->so_flags); 1040 1040 set_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state); 1041 1041 return 1; 1042 + } 1043 + 1044 + void nfs4_schedule_stateid_recovery(const struct nfs_server *server, struct nfs4_state *state) 1045 + { 1046 + struct nfs_client *clp = server->nfs_client; 1047 + 1048 + nfs4_state_mark_reclaim_nograce(clp, state); 1049 + nfs4_schedule_state_manager(clp); 1042 1050 } 1043 1051 1044 1052 static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_recovery_ops *ops) ··· 1444 1436 } 1445 1437 1446 1438 #ifdef CONFIG_NFS_V4_1 1439 + void nfs4_schedule_session_recovery(struct nfs4_session *session) 1440 + { 1441 + nfs4_schedule_lease_recovery(session->clp); 1442 + } 1443 + 1447 1444 void nfs41_handle_recall_slot(struct nfs_client *clp) 1448 1445 { 1449 1446 set_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state); 1450 - nfs4_schedule_state_recovery(clp); 1447 + nfs4_schedule_state_manager(clp); 1451 1448 } 1452 1449 1453 1450 static void nfs4_reset_all_state(struct nfs_client *clp) ··· 1460 1447 if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) { 1461 1448 clp->cl_boot_time = CURRENT_TIME; 1462 1449 nfs4_state_start_reclaim_nograce(clp); 1463 - nfs4_schedule_state_recovery(clp); 1450 + nfs4_schedule_state_manager(clp); 1464 1451 } 1465 1452 } 1466 1453 ··· 1468 1455 { 1469 1456 if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) { 1470 1457 nfs4_state_start_reclaim_reboot(clp); 1471 - nfs4_schedule_state_recovery(clp); 1458 + nfs4_schedule_state_manager(clp); 1472 1459 } 1473 1460 } 1474 1461 ··· 1488 1475 { 1489 1476 nfs_expire_all_delegations(clp); 1490 1477 if (test_and_set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) == 0) 1491 - nfs4_schedule_state_recovery(clp); 1478 + nfs4_schedule_state_manager(clp); 1492 1479 } 1493 1480 1494 1481 void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags)
+2 -2
fs/nfs/nfs4xdr.c
··· 1660 1660 1661 1661 p = reserve_space(xdr, 20 + 2*28 + 20 + len + 12); 1662 1662 *p++ = cpu_to_be32(OP_CREATE_SESSION); 1663 - p = xdr_encode_hyper(p, clp->cl_ex_clid); 1663 + p = xdr_encode_hyper(p, clp->cl_clientid); 1664 1664 *p++ = cpu_to_be32(clp->cl_seqid); /*Sequence id */ 1665 1665 *p++ = cpu_to_be32(args->flags); /*flags */ 1666 1666 ··· 4694 4694 p = xdr_inline_decode(xdr, 8); 4695 4695 if (unlikely(!p)) 4696 4696 goto out_overflow; 4697 - xdr_decode_hyper(p, &clp->cl_ex_clid); 4697 + xdr_decode_hyper(p, &clp->cl_clientid); 4698 4698 p = xdr_inline_decode(xdr, 12); 4699 4699 if (unlikely(!p)) 4700 4700 goto out_overflow;
+14 -15
fs/nfs/nfsroot.c
··· 86 86 /* Default path we try to mount. "%s" gets replaced by our IP address */ 87 87 #define NFS_ROOT "/tftpboot/%s" 88 88 89 + /* Default NFSROOT mount options. */ 90 + #define NFS_DEF_OPTIONS "udp" 91 + 89 92 /* Parameters passed from the kernel command line */ 90 93 static char nfs_root_parms[256] __initdata = ""; 91 94 92 95 /* Text-based mount options passed to super.c */ 93 - static char nfs_root_options[256] __initdata = ""; 96 + static char nfs_root_options[256] __initdata = NFS_DEF_OPTIONS; 94 97 95 98 /* Address of NFS server */ 96 99 static __be32 servaddr __initdata = htonl(INADDR_NONE); ··· 163 160 } 164 161 165 162 static int __init root_nfs_cat(char *dest, const char *src, 166 - const size_t destlen) 163 + const size_t destlen) 167 164 { 165 + size_t len = strlen(dest); 166 + 167 + if (len && dest[len - 1] != ',') 168 + if (strlcat(dest, ",", destlen) > destlen) 169 + return -1; 170 + 168 171 if (strlcat(dest, src, destlen) > destlen) 169 172 return -1; 170 173 return 0; ··· 203 194 if (root_nfs_cat(nfs_root_options, incoming, 204 195 sizeof(nfs_root_options))) 205 196 return -1; 206 - 207 - /* 208 - * Possibly prepare for more options to be appended 209 - */ 210 - if (nfs_root_options[0] != '\0' && 211 - nfs_root_options[strlen(nfs_root_options)] != ',') 212 - if (root_nfs_cat(nfs_root_options, ",", 213 - sizeof(nfs_root_options))) 214 - return -1; 215 - 216 197 return 0; 217 198 } 218 199 ··· 216 217 */ 217 218 static int __init root_nfs_data(char *cmdline) 218 219 { 219 - char addr_option[sizeof("nolock,addr=") + INET_ADDRSTRLEN + 1]; 220 + char mand_options[sizeof("nolock,addr=") + INET_ADDRSTRLEN + 1]; 220 221 int len, retval = -1; 221 222 char *tmp = NULL; 222 223 const size_t tmplen = sizeof(nfs_export_path); ··· 243 244 * Append mandatory options for nfsroot so they override 244 245 * what has come before 245 246 */ 246 - snprintf(addr_option, sizeof(addr_option), "nolock,addr=%pI4", 247 + snprintf(mand_options, sizeof(mand_options), "nolock,addr=%pI4", 247 248 &servaddr); 248 - if (root_nfs_cat(nfs_root_options, addr_option, 249 + if (root_nfs_cat(nfs_root_options, mand_options, 249 250 sizeof(nfs_root_options))) 250 251 goto out_optionstoolong; 251 252
+1 -1
fs/nfs/unlink.c
··· 180 180 task_setup_data.rpc_client = NFS_CLIENT(dir); 181 181 task = rpc_run_task(&task_setup_data); 182 182 if (!IS_ERR(task)) 183 - rpc_put_task(task); 183 + rpc_put_task_async(task); 184 184 return 1; 185 185 } 186 186
+2
fs/nfs/write.c
··· 1292 1292 task = rpc_run_task(&task_setup_data); 1293 1293 if (IS_ERR(task)) 1294 1294 return PTR_ERR(task); 1295 + if (how & FLUSH_SYNC) 1296 + rpc_wait_for_completion_task(task); 1295 1297 rpc_put_task(task); 1296 1298 return 0; 1297 1299 }
+3 -7
include/linux/nfs_fs_sb.h
··· 68 68 unsigned char cl_id_uniquifier; 69 69 u32 cl_cb_ident; /* v4.0 callback identifier */ 70 70 const struct nfs4_minor_version_ops *cl_mvops; 71 - #endif /* CONFIG_NFS_V4 */ 72 71 73 - #ifdef CONFIG_NFS_V4_1 74 - /* clientid returned from EXCHANGE_ID, used by session operations */ 75 - u64 cl_ex_clid; 76 72 /* The sequence id to use for the next CREATE_SESSION */ 77 73 u32 cl_seqid; 78 74 /* The flags used for obtaining the clientid during EXCHANGE_ID */ ··· 76 80 struct nfs4_session *cl_session; /* sharred session */ 77 81 struct list_head cl_layouts; 78 82 struct pnfs_deviceid_cache *cl_devid_cache; /* pNFS deviceid cache */ 79 - #endif /* CONFIG_NFS_V4_1 */ 83 + #endif /* CONFIG_NFS_V4 */ 80 84 81 85 #ifdef CONFIG_NFS_FSCACHE 82 86 struct fscache_cookie *fscache; /* client index cache cookie */ ··· 181 185 /* maximum number of slots to use */ 182 186 #define NFS4_MAX_SLOT_TABLE RPC_MAX_SLOT_TABLE 183 187 184 - #if defined(CONFIG_NFS_V4_1) 188 + #if defined(CONFIG_NFS_V4) 185 189 186 190 /* Sessions */ 187 191 #define SLOT_TABLE_SZ (NFS4_MAX_SLOT_TABLE/(8*sizeof(long))) ··· 221 225 struct nfs_client *clp; 222 226 }; 223 227 224 - #endif /* CONFIG_NFS_V4_1 */ 228 + #endif /* CONFIG_NFS_V4 */ 225 229 #endif
+1
include/linux/sunrpc/sched.h
··· 212 212 struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req, 213 213 const struct rpc_call_ops *ops); 214 214 void rpc_put_task(struct rpc_task *); 215 + void rpc_put_task_async(struct rpc_task *); 215 216 void rpc_exit_task(struct rpc_task *); 216 217 void rpc_exit(struct rpc_task *, int); 217 218 void rpc_release_calldata(const struct rpc_call_ops *, void *);
+1
kernel/sched.c
··· 4213 4213 { 4214 4214 __wake_up_common(q, mode, 1, 0, key); 4215 4215 } 4216 + EXPORT_SYMBOL_GPL(__wake_up_locked_key); 4216 4217 4217 4218 /** 4218 4219 * __wake_up_sync_key - wake up threads blocked on a waitqueue.
+61 -14
net/sunrpc/sched.c
··· 252 252 253 253 /* 254 254 * Mark an RPC call as having completed by clearing the 'active' bit 255 + * and then waking up all tasks that were sleeping. 255 256 */ 256 - static void rpc_mark_complete_task(struct rpc_task *task) 257 + static int rpc_complete_task(struct rpc_task *task) 257 258 { 258 - smp_mb__before_clear_bit(); 259 + void *m = &task->tk_runstate; 260 + wait_queue_head_t *wq = bit_waitqueue(m, RPC_TASK_ACTIVE); 261 + struct wait_bit_key k = __WAIT_BIT_KEY_INITIALIZER(m, RPC_TASK_ACTIVE); 262 + unsigned long flags; 263 + int ret; 264 + 265 + spin_lock_irqsave(&wq->lock, flags); 259 266 clear_bit(RPC_TASK_ACTIVE, &task->tk_runstate); 260 - smp_mb__after_clear_bit(); 261 - wake_up_bit(&task->tk_runstate, RPC_TASK_ACTIVE); 267 + ret = atomic_dec_and_test(&task->tk_count); 268 + if (waitqueue_active(wq)) 269 + __wake_up_locked_key(wq, TASK_NORMAL, &k); 270 + spin_unlock_irqrestore(&wq->lock, flags); 271 + return ret; 262 272 } 263 273 264 274 /* 265 275 * Allow callers to wait for completion of an RPC call 276 + * 277 + * Note the use of out_of_line_wait_on_bit() rather than wait_on_bit() 278 + * to enforce taking of the wq->lock and hence avoid races with 279 + * rpc_complete_task(). 266 280 */ 267 281 int __rpc_wait_for_completion_task(struct rpc_task *task, int (*action)(void *)) 268 282 { 269 283 if (action == NULL) 270 284 action = rpc_wait_bit_killable; 271 - return wait_on_bit(&task->tk_runstate, RPC_TASK_ACTIVE, 285 + return out_of_line_wait_on_bit(&task->tk_runstate, RPC_TASK_ACTIVE, 272 286 action, TASK_KILLABLE); 273 287 } 274 288 EXPORT_SYMBOL_GPL(__rpc_wait_for_completion_task); ··· 871 857 rpc_free_task(container_of(work, struct rpc_task, u.tk_work)); 872 858 } 873 859 874 - void rpc_put_task(struct rpc_task *task) 860 + static void rpc_release_resources_task(struct rpc_task *task) 875 861 { 876 - if (!atomic_dec_and_test(&task->tk_count)) 877 - return; 878 - /* Release resources */ 879 862 if (task->tk_rqstp) 880 863 xprt_release(task); 881 864 if (task->tk_msg.rpc_cred) 882 865 put_rpccred(task->tk_msg.rpc_cred); 883 866 rpc_task_release_client(task); 884 - if (task->tk_workqueue != NULL) { 867 + } 868 + 869 + static void rpc_final_put_task(struct rpc_task *task, 870 + struct workqueue_struct *q) 871 + { 872 + if (q != NULL) { 885 873 INIT_WORK(&task->u.tk_work, rpc_async_release); 886 - queue_work(task->tk_workqueue, &task->u.tk_work); 874 + queue_work(q, &task->u.tk_work); 887 875 } else 888 876 rpc_free_task(task); 889 877 } 878 + 879 + static void rpc_do_put_task(struct rpc_task *task, struct workqueue_struct *q) 880 + { 881 + if (atomic_dec_and_test(&task->tk_count)) { 882 + rpc_release_resources_task(task); 883 + rpc_final_put_task(task, q); 884 + } 885 + } 886 + 887 + void rpc_put_task(struct rpc_task *task) 888 + { 889 + rpc_do_put_task(task, NULL); 890 + } 890 891 EXPORT_SYMBOL_GPL(rpc_put_task); 892 + 893 + void rpc_put_task_async(struct rpc_task *task) 894 + { 895 + rpc_do_put_task(task, task->tk_workqueue); 896 + } 897 + EXPORT_SYMBOL_GPL(rpc_put_task_async); 891 898 892 899 static void rpc_release_task(struct rpc_task *task) 893 900 { ··· 916 881 917 882 BUG_ON (RPC_IS_QUEUED(task)); 918 883 919 - /* Wake up anyone who is waiting for task completion */ 920 - rpc_mark_complete_task(task); 884 + rpc_release_resources_task(task); 921 885 922 - rpc_put_task(task); 886 + /* 887 + * Note: at this point we have been removed from rpc_clnt->cl_tasks, 888 + * so it should be safe to use task->tk_count as a test for whether 889 + * or not any other processes still hold references to our rpc_task. 890 + */ 891 + if (atomic_read(&task->tk_count) != 1 + !RPC_IS_ASYNC(task)) { 892 + /* Wake up anyone who may be waiting for task completion */ 893 + if (!rpc_complete_task(task)) 894 + return; 895 + } else { 896 + if (!atomic_dec_and_test(&task->tk_count)) 897 + return; 898 + } 899 + rpc_final_put_task(task, task->tk_workqueue); 923 900 } 924 901 925 902 int rpciod_up(void)
+1
net/sunrpc/xprtrdma/svc_rdma_transport.c
··· 1335 1335 p, 0, length, DMA_FROM_DEVICE); 1336 1336 if (ib_dma_mapping_error(xprt->sc_cm_id->device, ctxt->sge[0].addr)) { 1337 1337 put_page(p); 1338 + svc_rdma_put_context(ctxt, 1); 1338 1339 return; 1339 1340 } 1340 1341 atomic_inc(&xprt->sc_dma_used);
+2 -1
net/sunrpc/xprtsock.c
··· 1631 1631 } 1632 1632 xs_reclassify_socket(family, sock); 1633 1633 1634 - if (xs_bind(transport, sock)) { 1634 + err = xs_bind(transport, sock); 1635 + if (err) { 1635 1636 sock_release(sock); 1636 1637 goto out; 1637 1638 }