@@ -1398,6 +1398,26 @@ static bool pnfs_within_mdsthreshold(struct nfs_open_context *ctx,
1398
1398
return ret ;
1399
1399
}
1400
1400
1401
+ /* stop waiting if someone clears NFS_LAYOUT_RETRY_LAYOUTGET bit. */
1402
+ static int pnfs_layoutget_retry_bit_wait (struct wait_bit_key * key )
1403
+ {
1404
+ if (!test_bit (NFS_LAYOUT_RETRY_LAYOUTGET , key -> flags ))
1405
+ return 1 ;
1406
+ return nfs_wait_bit_killable (key );
1407
+ }
1408
+
1409
+ static bool pnfs_prepare_to_retry_layoutget (struct pnfs_layout_hdr * lo )
1410
+ {
1411
+ /*
1412
+ * send layoutcommit as it can hold up layoutreturn due to lseg
1413
+ * reference
1414
+ */
1415
+ pnfs_layoutcommit_inode (lo -> plh_inode , false);
1416
+ return !wait_on_bit_action (& lo -> plh_flags , NFS_LAYOUT_RETURN ,
1417
+ pnfs_layoutget_retry_bit_wait ,
1418
+ TASK_UNINTERRUPTIBLE );
1419
+ }
1420
+
1401
1421
/*
1402
1422
* Layout segment is retreived from the server if not cached.
1403
1423
* The appropriate layout segment is referenced and returned to the caller.
@@ -1444,7 +1464,8 @@ pnfs_update_layout(struct inode *ino,
1444
1464
}
1445
1465
1446
1466
/* if LAYOUTGET already failed once we don't try again */
1447
- if (pnfs_layout_io_test_failed (lo , iomode ))
1467
+ if (pnfs_layout_io_test_failed (lo , iomode ) &&
1468
+ !pnfs_should_retry_layoutget (lo ))
1448
1469
goto out_unlock ;
1449
1470
1450
1471
first = list_empty (& lo -> plh_segs );
@@ -1469,6 +1490,22 @@ pnfs_update_layout(struct inode *ino,
1469
1490
goto out_unlock ;
1470
1491
}
1471
1492
1493
+ /*
1494
+ * Because we free lsegs before sending LAYOUTRETURN, we need to wait
1495
+ * for LAYOUTRETURN even if first is true.
1496
+ */
1497
+ if (!lseg && pnfs_should_retry_layoutget (lo ) &&
1498
+ test_bit (NFS_LAYOUT_RETURN , & lo -> plh_flags )) {
1499
+ spin_unlock (& ino -> i_lock );
1500
+ dprintk ("%s wait for layoutreturn\n" , __func__ );
1501
+ if (pnfs_prepare_to_retry_layoutget (lo )) {
1502
+ pnfs_put_layout_hdr (lo );
1503
+ dprintk ("%s retrying\n" , __func__ );
1504
+ goto lookup_again ;
1505
+ }
1506
+ goto out_put_layout_hdr ;
1507
+ }
1508
+
1472
1509
if (pnfs_layoutgets_blocked (lo , & arg , 0 ))
1473
1510
goto out_unlock ;
1474
1511
atomic_inc (& lo -> plh_outstanding );
0 commit comments