aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/callback_proc.c22
-rw-r--r--fs/nfs/flexfilelayout/flexfilelayout.c21
-rw-r--r--fs/nfs/flexfilelayout/flexfilelayout.h4
-rw-r--r--fs/nfs/flexfilelayout/flexfilelayoutdev.c19
-rw-r--r--fs/nfs/nfs42proc.c19
-rw-r--r--fs/nfs/nfs4_fs.h2
-rw-r--r--fs/nfs/nfs4state.c16
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(&copy->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,
707out: 711out:
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(&copy->stateid, &args->coa_stateid, NFS4_STATEID_SIZE); 714 memcpy(&copy->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(&copy->copies, &cps->clp->pending_cb_stateids); 716 list_add_tail(&copy->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
1372static void ff_layout_read_call_done(struct rpc_task *task, void *data) 1367static 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
1553static void ff_layout_write_call_done(struct rpc_task *task, void *data) 1543static 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);
216struct nfs_fh * 216struct nfs_fh *
217nfs4_ff_layout_select_ds_fh(struct pnfs_layout_segment *lseg, u32 mirror_idx); 217nfs4_ff_layout_select_ds_fh(struct pnfs_layout_segment *lseg, u32 mirror_idx);
218int
219nfs4_ff_layout_select_ds_stateid(struct pnfs_layout_segment *lseg,
220 u32 mirror_idx,
221 nfs4_stateid *stateid);
218 222
219struct nfs4_pnfs_ds * 223struct nfs4_pnfs_ds *
220nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx, 224nfs4_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
373int
374nfs4_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;
388out:
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, &copy->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(&copy->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(&copy->stateid, &res->write_res.stateid, NFS4_STATEID_SIZE); 166 memcpy(&copy->stateid, &res->write_res.stateid, NFS4_STATEID_SIZE);
166 init_completion(&copy->completion); 167 init_completion(&copy->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;