aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/flexfilelayout/flexfilelayoutdev.c
diff options
context:
space:
mode:
authorFred Isaman <fred.isaman@gmail.com>2016-09-30 14:37:41 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2016-12-08 21:49:57 -0500
commit65990d1afbd2d6fc23c6ecbd6f1899aa760a024f (patch)
tree3a18ac67020a08d0e7aec06158902b10f0644c4f /fs/nfs/flexfilelayout/flexfilelayoutdev.c
parent2f065ddb64193ebf9cd600395d4782287cd0f58e (diff)
pNFS/flexfiles: Fix a deadlock on LAYOUTGET
We encountered a deadlock where the SEQUENCE that accompanied the LAYOUTGET triggered a session drain, while ff_layout_alloc_lseg triggered a GETDEVICEINFO. The GETDEVICEINFO hung waiting for the session drain, while the LAYOUTGET held the slot waiting for alloc_lseg to finish. Avoid this by moving the call to nfs4_find_get_deviceid out of ff_layout_alloc_lseg and into nfs4_ff_layout_prepare_ds. Signed-off-by: Fred Isaman <fred.isaman@gmail.com> [dros@primarydata.com: pNFS/flexfiles: fix races in ff_layout_mirror_valid] Signed-off-by: Weston Andros Adamson <dros@primarydata.com> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs/flexfilelayout/flexfilelayoutdev.c')
-rw-r--r--fs/nfs/flexfilelayout/flexfilelayoutdev.c50
1 files changed, 39 insertions, 11 deletions
diff --git a/fs/nfs/flexfilelayout/flexfilelayoutdev.c b/fs/nfs/flexfilelayout/flexfilelayoutdev.c
index 142bfd0b1663..3cc39d1c1206 100644
--- a/fs/nfs/flexfilelayout/flexfilelayoutdev.c
+++ b/fs/nfs/flexfilelayout/flexfilelayoutdev.c
@@ -20,9 +20,11 @@
20static unsigned int dataserver_timeo = NFS_DEF_TCP_RETRANS; 20static unsigned int dataserver_timeo = NFS_DEF_TCP_RETRANS;
21static unsigned int dataserver_retrans; 21static unsigned int dataserver_retrans;
22 22
23static bool ff_layout_has_available_ds(struct pnfs_layout_segment *lseg);
24
23void nfs4_ff_layout_put_deviceid(struct nfs4_ff_layout_ds *mirror_ds) 25void nfs4_ff_layout_put_deviceid(struct nfs4_ff_layout_ds *mirror_ds)
24{ 26{
25 if (mirror_ds) 27 if (!IS_ERR_OR_NULL(mirror_ds))
26 nfs4_put_deviceid_node(&mirror_ds->id_node); 28 nfs4_put_deviceid_node(&mirror_ds->id_node);
27} 29}
28 30
@@ -182,12 +184,29 @@ static void ff_layout_mark_devid_invalid(struct pnfs_layout_segment *lseg,
182} 184}
183 185
184static bool ff_layout_mirror_valid(struct pnfs_layout_segment *lseg, 186static bool ff_layout_mirror_valid(struct pnfs_layout_segment *lseg,
185 struct nfs4_ff_layout_mirror *mirror) 187 struct nfs4_ff_layout_mirror *mirror,
188 bool create)
186{ 189{
187 if (mirror == NULL || mirror->mirror_ds == NULL) { 190 if (mirror == NULL || IS_ERR(mirror->mirror_ds))
188 pnfs_error_mark_layout_for_return(lseg->pls_layout->plh_inode, 191 goto outerr;
189 lseg); 192 if (mirror->mirror_ds == NULL) {
190 return false; 193 if (create) {
194 struct nfs4_deviceid_node *node;
195 struct pnfs_layout_hdr *lh = lseg->pls_layout;
196 struct nfs4_ff_layout_ds *mirror_ds = ERR_PTR(-ENODEV);
197
198 node = nfs4_find_get_deviceid(NFS_SERVER(lh->plh_inode),
199 &mirror->devid, lh->plh_lc_cred,
200 GFP_KERNEL);
201 if (node)
202 mirror_ds = FF_LAYOUT_MIRROR_DS(node);
203
204 /* check for race with another call to this function */
205 if (cmpxchg(&mirror->mirror_ds, NULL, mirror_ds) &&
206 mirror_ds != ERR_PTR(-ENODEV))
207 nfs4_put_deviceid_node(node);
208 } else
209 goto outerr;
191 } 210 }
192 if (mirror->mirror_ds->ds == NULL) { 211 if (mirror->mirror_ds->ds == NULL) {
193 struct nfs4_deviceid_node *devid; 212 struct nfs4_deviceid_node *devid;
@@ -196,6 +215,9 @@ static bool ff_layout_mirror_valid(struct pnfs_layout_segment *lseg,
196 return false; 215 return false;
197 } 216 }
198 return true; 217 return true;
218outerr:
219 pnfs_error_mark_layout_for_return(lseg->pls_layout->plh_inode, lseg);
220 return false;
199} 221}
200 222
201static void extend_ds_error(struct nfs4_ff_layout_ds_err *err, 223static void extend_ds_error(struct nfs4_ff_layout_ds_err *err,
@@ -323,7 +345,7 @@ nfs4_ff_layout_select_ds_fh(struct pnfs_layout_segment *lseg, u32 mirror_idx)
323 struct nfs4_ff_layout_mirror *mirror = FF_LAYOUT_COMP(lseg, mirror_idx); 345 struct nfs4_ff_layout_mirror *mirror = FF_LAYOUT_COMP(lseg, mirror_idx);
324 struct nfs_fh *fh = NULL; 346 struct nfs_fh *fh = NULL;
325 347
326 if (!ff_layout_mirror_valid(lseg, mirror)) { 348 if (!ff_layout_mirror_valid(lseg, mirror, false)) {
327 pr_err_ratelimited("NFS: %s: No data server for mirror offset index %d\n", 349 pr_err_ratelimited("NFS: %s: No data server for mirror offset index %d\n",
328 __func__, mirror_idx); 350 __func__, mirror_idx);
329 goto out; 351 goto out;
@@ -363,7 +385,7 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx,
363 struct nfs_server *s = NFS_SERVER(ino); 385 struct nfs_server *s = NFS_SERVER(ino);
364 unsigned int max_payload; 386 unsigned int max_payload;
365 387
366 if (!ff_layout_mirror_valid(lseg, mirror)) { 388 if (!ff_layout_mirror_valid(lseg, mirror, true)) {
367 pr_err_ratelimited("NFS: %s: No data server for offset index %d\n", 389 pr_err_ratelimited("NFS: %s: No data server for offset index %d\n",
368 __func__, ds_idx); 390 __func__, ds_idx);
369 goto out; 391 goto out;
@@ -547,7 +569,11 @@ static bool ff_read_layout_has_available_ds(struct pnfs_layout_segment *lseg)
547 569
548 for (idx = 0; idx < FF_LAYOUT_MIRROR_COUNT(lseg); idx++) { 570 for (idx = 0; idx < FF_LAYOUT_MIRROR_COUNT(lseg); idx++) {
549 mirror = FF_LAYOUT_COMP(lseg, idx); 571 mirror = FF_LAYOUT_COMP(lseg, idx);
550 if (mirror && mirror->mirror_ds) { 572 if (mirror) {
573 if (!mirror->mirror_ds)
574 return true;
575 if (IS_ERR(mirror->mirror_ds))
576 continue;
551 devid = &mirror->mirror_ds->id_node; 577 devid = &mirror->mirror_ds->id_node;
552 if (!ff_layout_test_devid_unavailable(devid)) 578 if (!ff_layout_test_devid_unavailable(devid))
553 return true; 579 return true;
@@ -565,8 +591,10 @@ static bool ff_rw_layout_has_available_ds(struct pnfs_layout_segment *lseg)
565 591
566 for (idx = 0; idx < FF_LAYOUT_MIRROR_COUNT(lseg); idx++) { 592 for (idx = 0; idx < FF_LAYOUT_MIRROR_COUNT(lseg); idx++) {
567 mirror = FF_LAYOUT_COMP(lseg, idx); 593 mirror = FF_LAYOUT_COMP(lseg, idx);
568 if (!mirror || !mirror->mirror_ds) 594 if (!mirror || IS_ERR(mirror->mirror_ds))
569 return false; 595 return false;
596 if (!mirror->mirror_ds)
597 continue;
570 devid = &mirror->mirror_ds->id_node; 598 devid = &mirror->mirror_ds->id_node;
571 if (ff_layout_test_devid_unavailable(devid)) 599 if (ff_layout_test_devid_unavailable(devid))
572 return false; 600 return false;
@@ -575,7 +603,7 @@ static bool ff_rw_layout_has_available_ds(struct pnfs_layout_segment *lseg)
575 return FF_LAYOUT_MIRROR_COUNT(lseg) != 0; 603 return FF_LAYOUT_MIRROR_COUNT(lseg) != 0;
576} 604}
577 605
578bool ff_layout_has_available_ds(struct pnfs_layout_segment *lseg) 606static bool ff_layout_has_available_ds(struct pnfs_layout_segment *lseg)
579{ 607{
580 if (lseg->pls_range.iomode == IOMODE_READ) 608 if (lseg->pls_range.iomode == IOMODE_READ)
581 return ff_read_layout_has_available_ds(lseg); 609 return ff_read_layout_has_available_ds(lseg);