Skip to content

Commit 411ae72

Browse files
author
Trond Myklebust
committed
pNFS: Wait for stale layoutget calls to complete in pnfs_update_layout()
If the old layout was recalled, and we returned NFS4ERR_NOMATCHINGLAYOUT then we need to wait for all outstanding layoutget calls to complete before we can send a new one. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
1 parent 056f9ad commit 411ae72

File tree

1 file changed

+31
-5
lines changed

1 file changed

+31
-5
lines changed

fs/nfs/pnfs.c

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1740,6 +1740,17 @@ static bool pnfs_prepare_to_retry_layoutget(struct pnfs_layout_hdr *lo)
17401740
TASK_UNINTERRUPTIBLE);
17411741
}
17421742

1743+
static void nfs_layoutget_begin(struct pnfs_layout_hdr *lo)
1744+
{
1745+
atomic_inc(&lo->plh_outstanding);
1746+
}
1747+
1748+
static void nfs_layoutget_end(struct pnfs_layout_hdr *lo)
1749+
{
1750+
if (atomic_dec_and_test(&lo->plh_outstanding))
1751+
wake_up_var(&lo->plh_outstanding);
1752+
}
1753+
17431754
static void pnfs_clear_first_layoutget(struct pnfs_layout_hdr *lo)
17441755
{
17451756
unsigned long *bitlock = &lo->plh_flags;
@@ -1839,6 +1850,21 @@ pnfs_update_layout(struct inode *ino,
18391850
goto out_unlock;
18401851
}
18411852

1853+
/*
1854+
* If the layout segment list is empty, but there are outstanding
1855+
* layoutget calls, then they might be subject to a layoutrecall.
1856+
*/
1857+
if (list_empty(&lo->plh_segs) &&
1858+
atomic_read(&lo->plh_outstanding) != 0) {
1859+
spin_unlock(&ino->i_lock);
1860+
if (wait_var_event_killable(&lo->plh_outstanding,
1861+
atomic_read(&lo->plh_outstanding) == 0
1862+
|| !list_empty(&lo->plh_segs)))
1863+
goto out_put_layout_hdr;
1864+
pnfs_put_layout_hdr(lo);
1865+
goto lookup_again;
1866+
}
1867+
18421868
lseg = pnfs_find_lseg(lo, &arg, strict_iomode);
18431869
if (lseg) {
18441870
trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
@@ -1912,7 +1938,7 @@ pnfs_update_layout(struct inode *ino,
19121938
PNFS_UPDATE_LAYOUT_BLOCKED);
19131939
goto out_unlock;
19141940
}
1915-
atomic_inc(&lo->plh_outstanding);
1941+
nfs_layoutget_begin(lo);
19161942
spin_unlock(&ino->i_lock);
19171943

19181944
_add_to_server_list(lo, server);
@@ -1929,14 +1955,14 @@ pnfs_update_layout(struct inode *ino,
19291955
if (!lgp) {
19301956
trace_pnfs_update_layout(ino, pos, count, iomode, lo, NULL,
19311957
PNFS_UPDATE_LAYOUT_NOMEM);
1932-
atomic_dec(&lo->plh_outstanding);
1958+
nfs_layoutget_end(lo);
19331959
goto out_put_layout_hdr;
19341960
}
19351961

19361962
lseg = nfs4_proc_layoutget(lgp, &timeout);
19371963
trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
19381964
PNFS_UPDATE_LAYOUT_SEND_LAYOUTGET);
1939-
atomic_dec(&lo->plh_outstanding);
1965+
nfs_layoutget_end(lo);
19401966
if (IS_ERR(lseg)) {
19411967
switch(PTR_ERR(lseg)) {
19421968
case -EBUSY:
@@ -2031,7 +2057,7 @@ _pnfs_grab_empty_layout(struct inode *ino, struct nfs_open_context *ctx)
20312057
goto out_unlock;
20322058
if (test_and_set_bit(NFS_LAYOUT_FIRST_LAYOUTGET, &lo->plh_flags))
20332059
goto out_unlock;
2034-
atomic_inc(&lo->plh_outstanding);
2060+
nfs_layoutget_begin(lo);
20352061
spin_unlock(&ino->i_lock);
20362062
_add_to_server_list(lo, NFS_SERVER(ino));
20372063
return lo;
@@ -2172,8 +2198,8 @@ void nfs4_lgopen_release(struct nfs4_layoutget *lgp)
21722198
struct inode *inode = lgp->args.inode;
21732199
if (inode) {
21742200
struct pnfs_layout_hdr *lo = NFS_I(inode)->layout;
2175-
atomic_dec(&lo->plh_outstanding);
21762201
pnfs_clear_first_layoutget(lo);
2202+
nfs_layoutget_end(lo);
21772203
}
21782204
pnfs_layoutget_free(lgp);
21792205
}

0 commit comments

Comments
 (0)