Skip to content

Commit aa8a45e

Browse files
Peng TaoTom Haynes
authored andcommitted
nfs41: wait for LAYOUTRETURN before retrying LAYOUTGET
Also take care to stop waiting if someone clears retry bit. Signed-off-by: Peng Tao <tao.peng@primarydata.com>
1 parent 012fa16 commit aa8a45e

File tree

3 files changed

+45
-3
lines changed

3 files changed

+45
-3
lines changed

fs/nfs/nfs4proc.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7796,7 +7796,9 @@ static void nfs4_layoutreturn_release(void *calldata)
77967796
spin_lock(&lo->plh_inode->i_lock);
77977797
if (lrp->res.lrs_present)
77987798
pnfs_set_layout_stateid(lo, &lrp->res.stateid, true);
7799-
clear_bit(NFS_LAYOUT_RETURN, &lo->plh_flags);
7799+
clear_bit_unlock(NFS_LAYOUT_RETURN, &lo->plh_flags);
7800+
smp_mb__after_atomic();
7801+
wake_up_bit(&lo->plh_flags, NFS_LAYOUT_RETURN);
78007802
clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, &lo->plh_flags);
78017803
rpc_wake_up(&NFS_SERVER(lo->plh_inode)->roc_rpcwaitq);
78027804
lo->plh_block_lgets--;

fs/nfs/pnfs.c

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1398,6 +1398,26 @@ static bool pnfs_within_mdsthreshold(struct nfs_open_context *ctx,
13981398
return ret;
13991399
}
14001400

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+
14011421
/*
14021422
* Layout segment is retreived from the server if not cached.
14031423
* The appropriate layout segment is referenced and returned to the caller.
@@ -1444,7 +1464,8 @@ pnfs_update_layout(struct inode *ino,
14441464
}
14451465

14461466
/* 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))
14481469
goto out_unlock;
14491470

14501471
first = list_empty(&lo->plh_segs);
@@ -1469,6 +1490,22 @@ pnfs_update_layout(struct inode *ino,
14691490
goto out_unlock;
14701491
}
14711492

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+
14721509
if (pnfs_layoutgets_blocked(lo, &arg, 0))
14731510
goto out_unlock;
14741511
atomic_inc(&lo->plh_outstanding);

fs/nfs/pnfs.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,8 +359,11 @@ static inline void pnfs_set_retry_layoutget(struct pnfs_layout_hdr *lo)
359359

360360
static inline void pnfs_clear_retry_layoutget(struct pnfs_layout_hdr *lo)
361361
{
362-
if (test_and_clear_bit(NFS_LAYOUT_RETRY_LAYOUTGET, &lo->plh_flags))
362+
if (test_and_clear_bit(NFS_LAYOUT_RETRY_LAYOUTGET, &lo->plh_flags)) {
363363
atomic_dec(&lo->plh_refcount);
364+
/* wake up waiters for LAYOUTRETURN as that is not needed */
365+
wake_up_bit(&lo->plh_flags, NFS_LAYOUT_RETURN);
366+
}
364367
}
365368

366369
static inline bool pnfs_should_retry_layoutget(struct pnfs_layout_hdr *lo)

0 commit comments

Comments
 (0)