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 tag 'nfs-for-4.20-4' of git://git.linux-nfs.org/projects/trondmy/linux-nfs

Pull NFS client bugfixes from Trond Myklebust:

- Fix a NFSv4 state manager deadlock when returning a delegation

- NFSv4.2 copy do not allocate memory under the lock

- flexfiles: Use the correct stateid for IO in the tightly coupled case

* tag 'nfs-for-4.20-4' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
flexfiles: use per-mirror specified stateid for IO
NFSv4.2 copy do not allocate memory under the lock
NFSv4: Fix a NFSv4 state manager deadlock

+66 -37
+11 -11
fs/nfs/callback_proc.c
··· 686 686 { 687 687 struct cb_offloadargs *args = data; 688 688 struct nfs_server *server; 689 - struct nfs4_copy_state *copy; 689 + struct nfs4_copy_state *copy, *tmp_copy; 690 690 bool found = false; 691 + 692 + copy = kzalloc(sizeof(struct nfs4_copy_state), GFP_NOFS); 693 + if (!copy) 694 + return htonl(NFS4ERR_SERVERFAULT); 691 695 692 696 spin_lock(&cps->clp->cl_lock); 693 697 rcu_read_lock(); 694 698 list_for_each_entry_rcu(server, &cps->clp->cl_superblocks, 695 699 client_link) { 696 - list_for_each_entry(copy, &server->ss_copies, copies) { 700 + list_for_each_entry(tmp_copy, &server->ss_copies, copies) { 697 701 if (memcmp(args->coa_stateid.other, 698 - copy->stateid.other, 702 + tmp_copy->stateid.other, 699 703 sizeof(args->coa_stateid.other))) 700 704 continue; 701 - nfs4_copy_cb_args(copy, args); 702 - complete(&copy->completion); 705 + nfs4_copy_cb_args(tmp_copy, args); 706 + complete(&tmp_copy->completion); 703 707 found = true; 704 708 goto out; 705 709 } ··· 711 707 out: 712 708 rcu_read_unlock(); 713 709 if (!found) { 714 - copy = kzalloc(sizeof(struct nfs4_copy_state), GFP_NOFS); 715 - if (!copy) { 716 - spin_unlock(&cps->clp->cl_lock); 717 - return htonl(NFS4ERR_SERVERFAULT); 718 - } 719 710 memcpy(&copy->stateid, &args->coa_stateid, NFS4_STATEID_SIZE); 720 711 nfs4_copy_cb_args(copy, args); 721 712 list_add_tail(&copy->copies, &cps->clp->pending_cb_stateids); 722 - } 713 + } else 714 + kfree(copy); 723 715 spin_unlock(&cps->clp->cl_lock); 724 716 725 717 return 0;
+9 -12
fs/nfs/flexfilelayout/flexfilelayout.c
··· 1361 1361 task)) 1362 1362 return; 1363 1363 1364 - if (ff_layout_read_prepare_common(task, hdr)) 1365 - return; 1366 - 1367 - if (nfs4_set_rw_stateid(&hdr->args.stateid, hdr->args.context, 1368 - hdr->args.lock_context, FMODE_READ) == -EIO) 1369 - rpc_exit(task, -EIO); /* lost lock, terminate I/O */ 1364 + ff_layout_read_prepare_common(task, hdr); 1370 1365 } 1371 1366 1372 1367 static void ff_layout_read_call_done(struct rpc_task *task, void *data) ··· 1537 1542 task)) 1538 1543 return; 1539 1544 1540 - if (ff_layout_write_prepare_common(task, hdr)) 1541 - return; 1542 - 1543 - if (nfs4_set_rw_stateid(&hdr->args.stateid, hdr->args.context, 1544 - hdr->args.lock_context, FMODE_WRITE) == -EIO) 1545 - rpc_exit(task, -EIO); /* lost lock, terminate I/O */ 1545 + ff_layout_write_prepare_common(task, hdr); 1546 1546 } 1547 1547 1548 1548 static void ff_layout_write_call_done(struct rpc_task *task, void *data) ··· 1732 1742 fh = nfs4_ff_layout_select_ds_fh(lseg, idx); 1733 1743 if (fh) 1734 1744 hdr->args.fh = fh; 1745 + 1746 + if (!nfs4_ff_layout_select_ds_stateid(lseg, idx, &hdr->args.stateid)) 1747 + goto out_failed; 1748 + 1735 1749 /* 1736 1750 * Note that if we ever decide to split across DSes, 1737 1751 * then we may need to handle dense-like offsets. ··· 1797 1803 fh = nfs4_ff_layout_select_ds_fh(lseg, idx); 1798 1804 if (fh) 1799 1805 hdr->args.fh = fh; 1806 + 1807 + if (!nfs4_ff_layout_select_ds_stateid(lseg, idx, &hdr->args.stateid)) 1808 + goto out_failed; 1800 1809 1801 1810 /* 1802 1811 * Note that if we ever decide to split across DSes,
+4
fs/nfs/flexfilelayout/flexfilelayout.h
··· 215 215 unsigned int maxnum); 216 216 struct nfs_fh * 217 217 nfs4_ff_layout_select_ds_fh(struct pnfs_layout_segment *lseg, u32 mirror_idx); 218 + int 219 + nfs4_ff_layout_select_ds_stateid(struct pnfs_layout_segment *lseg, 220 + u32 mirror_idx, 221 + nfs4_stateid *stateid); 218 222 219 223 struct nfs4_pnfs_ds * 220 224 nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx,
+19
fs/nfs/flexfilelayout/flexfilelayoutdev.c
··· 370 370 return fh; 371 371 } 372 372 373 + int 374 + nfs4_ff_layout_select_ds_stateid(struct pnfs_layout_segment *lseg, 375 + u32 mirror_idx, 376 + nfs4_stateid *stateid) 377 + { 378 + struct nfs4_ff_layout_mirror *mirror = FF_LAYOUT_COMP(lseg, mirror_idx); 379 + 380 + if (!ff_layout_mirror_valid(lseg, mirror, false)) { 381 + pr_err_ratelimited("NFS: %s: No data server for mirror offset index %d\n", 382 + __func__, mirror_idx); 383 + goto out; 384 + } 385 + 386 + nfs4_stateid_copy(stateid, &mirror->stateid); 387 + return 1; 388 + out: 389 + return 0; 390 + } 391 + 373 392 /** 374 393 * nfs4_ff_layout_prepare_ds - prepare a DS connection for an RPC call 375 394 * @lseg: the layout segment we're operating on
+10 -9
fs/nfs/nfs42proc.c
··· 137 137 struct file *dst, 138 138 nfs4_stateid *src_stateid) 139 139 { 140 - struct nfs4_copy_state *copy; 140 + struct nfs4_copy_state *copy, *tmp_copy; 141 141 int status = NFS4_OK; 142 142 bool found_pending = false; 143 143 struct nfs_open_context *ctx = nfs_file_open_context(dst); 144 144 145 + copy = kzalloc(sizeof(struct nfs4_copy_state), GFP_NOFS); 146 + if (!copy) 147 + return -ENOMEM; 148 + 145 149 spin_lock(&server->nfs_client->cl_lock); 146 - list_for_each_entry(copy, &server->nfs_client->pending_cb_stateids, 150 + list_for_each_entry(tmp_copy, &server->nfs_client->pending_cb_stateids, 147 151 copies) { 148 - if (memcmp(&res->write_res.stateid, &copy->stateid, 152 + if (memcmp(&res->write_res.stateid, &tmp_copy->stateid, 149 153 NFS4_STATEID_SIZE)) 150 154 continue; 151 155 found_pending = true; 152 - list_del(&copy->copies); 156 + list_del(&tmp_copy->copies); 153 157 break; 154 158 } 155 159 if (found_pending) { 156 160 spin_unlock(&server->nfs_client->cl_lock); 161 + kfree(copy); 162 + copy = tmp_copy; 157 163 goto out; 158 164 } 159 165 160 - copy = kzalloc(sizeof(struct nfs4_copy_state), GFP_NOFS); 161 - if (!copy) { 162 - spin_unlock(&server->nfs_client->cl_lock); 163 - return -ENOMEM; 164 - } 165 166 memcpy(&copy->stateid, &res->write_res.stateid, NFS4_STATEID_SIZE); 166 167 init_completion(&copy->completion); 167 168 copy->parent_state = ctx->state;
+2
fs/nfs/nfs4_fs.h
··· 41 41 NFS4CLNT_MOVED, 42 42 NFS4CLNT_LEASE_MOVED, 43 43 NFS4CLNT_DELEGATION_EXPIRED, 44 + NFS4CLNT_RUN_MANAGER, 45 + NFS4CLNT_DELEGRETURN_RUNNING, 44 46 }; 45 47 46 48 #define NFS4_RENEW_TIMEOUT 0x01
+11 -5
fs/nfs/nfs4state.c
··· 1210 1210 struct task_struct *task; 1211 1211 char buf[INET6_ADDRSTRLEN + sizeof("-manager") + 1]; 1212 1212 1213 + set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state); 1213 1214 if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0) 1214 1215 return; 1215 1216 __module_get(THIS_MODULE); ··· 2504 2503 2505 2504 /* Ensure exclusive access to NFSv4 state */ 2506 2505 do { 2506 + clear_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state); 2507 2507 if (test_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state)) { 2508 2508 section = "purge state"; 2509 2509 status = nfs4_purge_lease(clp); ··· 2595 2593 } 2596 2594 2597 2595 nfs4_end_drain_session(clp); 2598 - if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) { 2599 - nfs_client_return_marked_delegations(clp); 2600 - continue; 2596 + nfs4_clear_state_manager_bit(clp); 2597 + 2598 + if (!test_and_set_bit(NFS4CLNT_DELEGRETURN_RUNNING, &clp->cl_state)) { 2599 + if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) { 2600 + nfs_client_return_marked_delegations(clp); 2601 + set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state); 2602 + } 2603 + clear_bit(NFS4CLNT_DELEGRETURN_RUNNING, &clp->cl_state); 2601 2604 } 2602 2605 2603 - nfs4_clear_state_manager_bit(clp); 2604 2606 /* Did we race with an attempt to give us more work? */ 2605 - if (clp->cl_state == 0) 2607 + if (!test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state)) 2606 2608 return; 2607 2609 if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0) 2608 2610 return;