diff options
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/callback_proc.c | 22 | ||||
-rw-r--r-- | fs/nfs/flexfilelayout/flexfilelayout.c | 21 | ||||
-rw-r--r-- | fs/nfs/flexfilelayout/flexfilelayout.h | 4 | ||||
-rw-r--r-- | fs/nfs/flexfilelayout/flexfilelayoutdev.c | 19 | ||||
-rw-r--r-- | fs/nfs/nfs42proc.c | 19 | ||||
-rw-r--r-- | fs/nfs/nfs4_fs.h | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 16 |
7 files changed, 66 insertions, 37 deletions
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index 7b861bbc0b43..315967354954 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c | |||
@@ -686,20 +686,24 @@ __be32 nfs4_callback_offload(void *data, void *dummy, | |||
686 | { | 686 | { |
687 | struct cb_offloadargs *args = data; | 687 | struct cb_offloadargs *args = data; |
688 | struct nfs_server *server; | 688 | struct nfs_server *server; |
689 | struct nfs4_copy_state *copy; | 689 | struct nfs4_copy_state *copy, *tmp_copy; |
690 | bool found = false; | 690 | bool found = false; |
691 | 691 | ||
692 | copy = kzalloc(sizeof(struct nfs4_copy_state), GFP_NOFS); | ||
693 | if (!copy) | ||
694 | return htonl(NFS4ERR_SERVERFAULT); | ||
695 | |||
692 | spin_lock(&cps->clp->cl_lock); | 696 | spin_lock(&cps->clp->cl_lock); |
693 | rcu_read_lock(); | 697 | rcu_read_lock(); |
694 | list_for_each_entry_rcu(server, &cps->clp->cl_superblocks, | 698 | list_for_each_entry_rcu(server, &cps->clp->cl_superblocks, |
695 | client_link) { | 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 | if (memcmp(args->coa_stateid.other, | 701 | if (memcmp(args->coa_stateid.other, |
698 | copy->stateid.other, | 702 | tmp_copy->stateid.other, |
699 | sizeof(args->coa_stateid.other))) | 703 | sizeof(args->coa_stateid.other))) |
700 | continue; | 704 | continue; |
701 | nfs4_copy_cb_args(copy, args); | 705 | nfs4_copy_cb_args(tmp_copy, args); |
702 | complete(©->completion); | 706 | complete(&tmp_copy->completion); |
703 | found = true; | 707 | found = true; |
704 | goto out; | 708 | goto out; |
705 | } | 709 | } |
@@ -707,15 +711,11 @@ __be32 nfs4_callback_offload(void *data, void *dummy, | |||
707 | out: | 711 | out: |
708 | rcu_read_unlock(); | 712 | rcu_read_unlock(); |
709 | if (!found) { | 713 | if (!found) { |
710 | copy = kzalloc(sizeof(struct nfs4_copy_state), GFP_NOFS); | ||
711 | if (!copy) { | ||
712 | spin_unlock(&cps->clp->cl_lock); | ||
713 | return htonl(NFS4ERR_SERVERFAULT); | ||
714 | } | ||
715 | memcpy(©->stateid, &args->coa_stateid, NFS4_STATEID_SIZE); | 714 | memcpy(©->stateid, &args->coa_stateid, NFS4_STATEID_SIZE); |
716 | nfs4_copy_cb_args(copy, args); | 715 | nfs4_copy_cb_args(copy, args); |
717 | list_add_tail(©->copies, &cps->clp->pending_cb_stateids); | 716 | list_add_tail(©->copies, &cps->clp->pending_cb_stateids); |
718 | } | 717 | } else |
718 | kfree(copy); | ||
719 | spin_unlock(&cps->clp->cl_lock); | 719 | spin_unlock(&cps->clp->cl_lock); |
720 | 720 | ||
721 | return 0; | 721 | return 0; |
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c index 86bcba40ca61..74b36ed883ca 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.c +++ b/fs/nfs/flexfilelayout/flexfilelayout.c | |||
@@ -1361,12 +1361,7 @@ static void ff_layout_read_prepare_v4(struct rpc_task *task, void *data) | |||
1361 | task)) | 1361 | task)) |
1362 | return; | 1362 | return; |
1363 | 1363 | ||
1364 | if (ff_layout_read_prepare_common(task, hdr)) | 1364 | 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 */ | ||
1370 | } | 1365 | } |
1371 | 1366 | ||
1372 | static void ff_layout_read_call_done(struct rpc_task *task, void *data) | 1367 | static void ff_layout_read_call_done(struct rpc_task *task, void *data) |
@@ -1542,12 +1537,7 @@ static void ff_layout_write_prepare_v4(struct rpc_task *task, void *data) | |||
1542 | task)) | 1537 | task)) |
1543 | return; | 1538 | return; |
1544 | 1539 | ||
1545 | if (ff_layout_write_prepare_common(task, hdr)) | 1540 | ff_layout_write_prepare_common(task, hdr); |
1546 | return; | ||
1547 | |||
1548 | if (nfs4_set_rw_stateid(&hdr->args.stateid, hdr->args.context, | ||
1549 | hdr->args.lock_context, FMODE_WRITE) == -EIO) | ||
1550 | rpc_exit(task, -EIO); /* lost lock, terminate I/O */ | ||
1551 | } | 1541 | } |
1552 | 1542 | ||
1553 | static void ff_layout_write_call_done(struct rpc_task *task, void *data) | 1543 | static void ff_layout_write_call_done(struct rpc_task *task, void *data) |
@@ -1742,6 +1732,10 @@ ff_layout_read_pagelist(struct nfs_pgio_header *hdr) | |||
1742 | fh = nfs4_ff_layout_select_ds_fh(lseg, idx); | 1732 | fh = nfs4_ff_layout_select_ds_fh(lseg, idx); |
1743 | if (fh) | 1733 | if (fh) |
1744 | hdr->args.fh = fh; | 1734 | hdr->args.fh = fh; |
1735 | |||
1736 | if (!nfs4_ff_layout_select_ds_stateid(lseg, idx, &hdr->args.stateid)) | ||
1737 | goto out_failed; | ||
1738 | |||
1745 | /* | 1739 | /* |
1746 | * Note that if we ever decide to split across DSes, | 1740 | * Note that if we ever decide to split across DSes, |
1747 | * then we may need to handle dense-like offsets. | 1741 | * then we may need to handle dense-like offsets. |
@@ -1804,6 +1798,9 @@ ff_layout_write_pagelist(struct nfs_pgio_header *hdr, int sync) | |||
1804 | if (fh) | 1798 | if (fh) |
1805 | hdr->args.fh = fh; | 1799 | hdr->args.fh = fh; |
1806 | 1800 | ||
1801 | if (!nfs4_ff_layout_select_ds_stateid(lseg, idx, &hdr->args.stateid)) | ||
1802 | goto out_failed; | ||
1803 | |||
1807 | /* | 1804 | /* |
1808 | * Note that if we ever decide to split across DSes, | 1805 | * Note that if we ever decide to split across DSes, |
1809 | * then we may need to handle dense-like offsets. | 1806 | * then we may need to handle dense-like offsets. |
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.h b/fs/nfs/flexfilelayout/flexfilelayout.h index 411798346e48..de50a342d5a5 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.h +++ b/fs/nfs/flexfilelayout/flexfilelayout.h | |||
@@ -215,6 +215,10 @@ unsigned int ff_layout_fetch_ds_ioerr(struct pnfs_layout_hdr *lo, | |||
215 | unsigned int maxnum); | 215 | unsigned int maxnum); |
216 | struct nfs_fh * | 216 | struct nfs_fh * |
217 | nfs4_ff_layout_select_ds_fh(struct pnfs_layout_segment *lseg, u32 mirror_idx); | 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 | struct nfs4_pnfs_ds * | 223 | struct nfs4_pnfs_ds * |
220 | nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx, | 224 | nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx, |
diff --git a/fs/nfs/flexfilelayout/flexfilelayoutdev.c b/fs/nfs/flexfilelayout/flexfilelayoutdev.c index 74d8d5352438..d23347389626 100644 --- a/fs/nfs/flexfilelayout/flexfilelayoutdev.c +++ b/fs/nfs/flexfilelayout/flexfilelayoutdev.c | |||
@@ -370,6 +370,25 @@ out: | |||
370 | return fh; | 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 | * nfs4_ff_layout_prepare_ds - prepare a DS connection for an RPC call | 393 | * nfs4_ff_layout_prepare_ds - prepare a DS connection for an RPC call |
375 | * @lseg: the layout segment we're operating on | 394 | * @lseg: the layout segment we're operating on |
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c index ac5b784a1de0..fed06fd9998d 100644 --- a/fs/nfs/nfs42proc.c +++ b/fs/nfs/nfs42proc.c | |||
@@ -137,31 +137,32 @@ static int handle_async_copy(struct nfs42_copy_res *res, | |||
137 | struct file *dst, | 137 | struct file *dst, |
138 | nfs4_stateid *src_stateid) | 138 | nfs4_stateid *src_stateid) |
139 | { | 139 | { |
140 | struct nfs4_copy_state *copy; | 140 | struct nfs4_copy_state *copy, *tmp_copy; |
141 | int status = NFS4_OK; | 141 | int status = NFS4_OK; |
142 | bool found_pending = false; | 142 | bool found_pending = false; |
143 | struct nfs_open_context *ctx = nfs_file_open_context(dst); | 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 | spin_lock(&server->nfs_client->cl_lock); | 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 | copies) { | 151 | copies) { |
148 | if (memcmp(&res->write_res.stateid, ©->stateid, | 152 | if (memcmp(&res->write_res.stateid, &tmp_copy->stateid, |
149 | NFS4_STATEID_SIZE)) | 153 | NFS4_STATEID_SIZE)) |
150 | continue; | 154 | continue; |
151 | found_pending = true; | 155 | found_pending = true; |
152 | list_del(©->copies); | 156 | list_del(&tmp_copy->copies); |
153 | break; | 157 | break; |
154 | } | 158 | } |
155 | if (found_pending) { | 159 | if (found_pending) { |
156 | spin_unlock(&server->nfs_client->cl_lock); | 160 | spin_unlock(&server->nfs_client->cl_lock); |
161 | kfree(copy); | ||
162 | copy = tmp_copy; | ||
157 | goto out; | 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 | memcpy(©->stateid, &res->write_res.stateid, NFS4_STATEID_SIZE); | 166 | memcpy(©->stateid, &res->write_res.stateid, NFS4_STATEID_SIZE); |
166 | init_completion(©->completion); | 167 | init_completion(©->completion); |
167 | copy->parent_state = ctx->state; | 168 | copy->parent_state = ctx->state; |
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 8d59c9655ec4..1b994b527518 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -41,6 +41,8 @@ enum nfs4_client_state { | |||
41 | NFS4CLNT_MOVED, | 41 | NFS4CLNT_MOVED, |
42 | NFS4CLNT_LEASE_MOVED, | 42 | NFS4CLNT_LEASE_MOVED, |
43 | NFS4CLNT_DELEGATION_EXPIRED, | 43 | NFS4CLNT_DELEGATION_EXPIRED, |
44 | NFS4CLNT_RUN_MANAGER, | ||
45 | NFS4CLNT_DELEGRETURN_RUNNING, | ||
44 | }; | 46 | }; |
45 | 47 | ||
46 | #define NFS4_RENEW_TIMEOUT 0x01 | 48 | #define NFS4_RENEW_TIMEOUT 0x01 |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index ffea57885394..d8decf2ec48f 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -1210,6 +1210,7 @@ void nfs4_schedule_state_manager(struct nfs_client *clp) | |||
1210 | struct task_struct *task; | 1210 | struct task_struct *task; |
1211 | char buf[INET6_ADDRSTRLEN + sizeof("-manager") + 1]; | 1211 | char buf[INET6_ADDRSTRLEN + sizeof("-manager") + 1]; |
1212 | 1212 | ||
1213 | set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state); | ||
1213 | if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0) | 1214 | if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0) |
1214 | return; | 1215 | return; |
1215 | __module_get(THIS_MODULE); | 1216 | __module_get(THIS_MODULE); |
@@ -2503,6 +2504,7 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
2503 | 2504 | ||
2504 | /* Ensure exclusive access to NFSv4 state */ | 2505 | /* Ensure exclusive access to NFSv4 state */ |
2505 | do { | 2506 | do { |
2507 | clear_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state); | ||
2506 | if (test_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state)) { | 2508 | if (test_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state)) { |
2507 | section = "purge state"; | 2509 | section = "purge state"; |
2508 | status = nfs4_purge_lease(clp); | 2510 | status = nfs4_purge_lease(clp); |
@@ -2593,14 +2595,18 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
2593 | } | 2595 | } |
2594 | 2596 | ||
2595 | nfs4_end_drain_session(clp); | 2597 | nfs4_end_drain_session(clp); |
2596 | if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) { | 2598 | nfs4_clear_state_manager_bit(clp); |
2597 | nfs_client_return_marked_delegations(clp); | 2599 | |
2598 | continue; | 2600 | if (!test_and_set_bit(NFS4CLNT_DELEGRETURN_RUNNING, &clp->cl_state)) { |
2601 | if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) { | ||
2602 | nfs_client_return_marked_delegations(clp); | ||
2603 | set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state); | ||
2604 | } | ||
2605 | clear_bit(NFS4CLNT_DELEGRETURN_RUNNING, &clp->cl_state); | ||
2599 | } | 2606 | } |
2600 | 2607 | ||
2601 | nfs4_clear_state_manager_bit(clp); | ||
2602 | /* Did we race with an attempt to give us more work? */ | 2608 | /* Did we race with an attempt to give us more work? */ |
2603 | if (clp->cl_state == 0) | 2609 | if (!test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state)) |
2604 | return; | 2610 | return; |
2605 | if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0) | 2611 | if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0) |
2606 | return; | 2612 | return; |