提交 27b6f539 编写于 作者: P Peng Tao 提交者: Tom Haynes

nfs/flexfiles: send layoutreturn before freeing lseg

Otherwise we'll lose error tracking information when
encoding layoutreturn.

pnfs_put_lseg may be called from rpc callbacks. So we should not
call pnfs_send_layoutreturn directly because it can deadlock in
the rpc layer.
Signed-off-by: NPeng Tao <tao.peng@primarydata.com>
Signed-off-by: NTom Haynes <loghyr@primarydata.com>
上级 193e3aa2
master alk-4.19.24 alk-4.19.30 alk-4.19.34 alk-4.19.36 alk-4.19.43 alk-4.19.48 alk-4.19.57 ck-4.19.67 ck-4.19.81 ck-4.19.91 github/fork/deepanshu1422/fix-typo-in-comment github/fork/haosdent/fix-typo linux-next v4.19.91 v4.19.90 v4.19.89 v4.19.88 v4.19.87 v4.19.86 v4.19.85 v4.19.84 v4.19.83 v4.19.82 v4.19.81 v4.19.80 v4.19.79 v4.19.78 v4.19.77 v4.19.76 v4.19.75 v4.19.74 v4.19.73 v4.19.72 v4.19.71 v4.19.70 v4.19.69 v4.19.68 v4.19.67 v4.19.66 v4.19.65 v4.19.64 v4.19.63 v4.19.62 v4.19.61 v4.19.60 v4.19.59 v4.19.58 v4.19.57 v4.19.56 v4.19.55 v4.19.54 v4.19.53 v4.19.52 v4.19.51 v4.19.50 v4.19.49 v4.19.48 v4.19.47 v4.19.46 v4.19.45 v4.19.44 v4.19.43 v4.19.42 v4.19.41 v4.19.40 v4.19.39 v4.19.38 v4.19.37 v4.19.36 v4.19.35 v4.19.34 v4.19.33 v4.19.32 v4.19.31 v4.19.30 v4.19.29 v4.19.28 v4.19.27 v4.19.26 v4.19.25 v4.19.24 v4.19.23 v4.19.22 v4.19.21 v4.19.20 v4.19.19 v4.19.18 v4.19.17 v4.19.16 v4.19.15 v4.19.14 v4.19.13 v4.19.12 v4.19.11 v4.19.10 v4.19.9 v4.19.8 v4.19.7 v4.19.6 v4.19.5 v4.19.4 v4.19.3 v4.19.2 v4.19.1 v4.19 v4.19-rc8 v4.19-rc7 v4.19-rc6 v4.19-rc5 v4.19-rc4 v4.19-rc3 v4.19-rc2 v4.19-rc1 ck-release-21 ck-release-20 ck-release-19.2 ck-release-19.1 ck-release-19 ck-release-18 ck-release-17.2 ck-release-17.1 ck-release-17 ck-release-16 ck-release-15.1 ck-release-15 ck-release-14 ck-release-13.2 ck-release-13 ck-release-12 ck-release-11 ck-release-10 ck-release-9 ck-release-7 alk-release-15 alk-release-14 alk-release-13.2 alk-release-13 alk-release-12 alk-release-11 alk-release-10 alk-release-9 alk-release-7
无相关合并请求
......@@ -346,8 +346,7 @@ pnfs_layout_remove_lseg(struct pnfs_layout_hdr *lo,
/* Return true if layoutreturn is needed */
static bool
pnfs_layout_need_return(struct pnfs_layout_hdr *lo,
struct pnfs_layout_segment *lseg,
nfs4_stateid *stateid, enum pnfs_iomode *iomode)
struct pnfs_layout_segment *lseg)
{
struct pnfs_layout_segment *s;
......@@ -355,17 +354,54 @@ pnfs_layout_need_return(struct pnfs_layout_hdr *lo,
return false;
list_for_each_entry(s, &lo->plh_segs, pls_list)
if (test_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags))
if (s != lseg && test_bit(NFS_LSEG_LAYOUTRETURN, &s->pls_flags))
return false;
*stateid = lo->plh_stateid;
*iomode = lo->plh_return_iomode;
/* decreased in pnfs_send_layoutreturn() */
lo->plh_block_lgets++;
lo->plh_return_iomode = 0;
return true;
}
static void pnfs_layoutreturn_free_lseg(struct work_struct *work)
{
struct pnfs_layout_segment *lseg;
struct pnfs_layout_hdr *lo;
struct inode *inode;
lseg = container_of(work, struct pnfs_layout_segment, pls_work);
WARN_ON(atomic_read(&lseg->pls_refcount));
lo = lseg->pls_layout;
inode = lo->plh_inode;
spin_lock(&inode->i_lock);
if (pnfs_layout_need_return(lo, lseg)) {
nfs4_stateid stateid;
enum pnfs_iomode iomode;
stateid = lo->plh_stateid;
iomode = lo->plh_return_iomode;
/* decreased in pnfs_send_layoutreturn() */
lo->plh_block_lgets++;
lo->plh_return_iomode = 0;
spin_unlock(&inode->i_lock);
pnfs_send_layoutreturn(lo, stateid, iomode, true);
spin_lock(&inode->i_lock);
} else
/* match pnfs_get_layout_hdr #2 in pnfs_put_lseg */
pnfs_put_layout_hdr(lo);
pnfs_layout_remove_lseg(lo, lseg);
spin_unlock(&inode->i_lock);
pnfs_free_lseg(lseg);
/* match pnfs_get_layout_hdr #1 in pnfs_put_lseg */
pnfs_put_layout_hdr(lo);
}
static void
pnfs_layoutreturn_free_lseg_async(struct pnfs_layout_segment *lseg)
{
INIT_WORK(&lseg->pls_work, pnfs_layoutreturn_free_lseg);
queue_work(nfsiod_workqueue, &lseg->pls_work);
}
void
pnfs_put_lseg(struct pnfs_layout_segment *lseg)
{
......@@ -381,21 +417,18 @@ pnfs_put_lseg(struct pnfs_layout_segment *lseg)
lo = lseg->pls_layout;
inode = lo->plh_inode;
if (atomic_dec_and_lock(&lseg->pls_refcount, &inode->i_lock)) {
bool need_return;
nfs4_stateid stateid;
enum pnfs_iomode iomode;
pnfs_get_layout_hdr(lo);
pnfs_layout_remove_lseg(lo, lseg);
need_return = pnfs_layout_need_return(lo, lseg,
&stateid, &iomode);
spin_unlock(&inode->i_lock);
pnfs_free_lseg(lseg);
if (need_return)
pnfs_send_layoutreturn(lo, stateid, iomode,
true);
else
if (pnfs_layout_need_return(lo, lseg)) {
spin_unlock(&inode->i_lock);
/* hdr reference dropped in nfs4_layoutreturn_release */
pnfs_get_layout_hdr(lo);
pnfs_layoutreturn_free_lseg_async(lseg);
} else {
pnfs_layout_remove_lseg(lo, lseg);
spin_unlock(&inode->i_lock);
pnfs_free_lseg(lseg);
pnfs_put_layout_hdr(lo);
}
}
}
EXPORT_SYMBOL_GPL(pnfs_put_lseg);
......@@ -1059,8 +1092,7 @@ bool pnfs_roc(struct inode *ino)
}
spin_unlock(&ino->i_lock);
if (layoutreturn)
pnfs_send_layoutreturn(lo, stateid, IOMODE_ANY, 0,
NFS4_MAX_UINT64, true);
pnfs_send_layoutreturn(lo, stateid, IOMODE_ANY, true);
return false;
}
......@@ -1127,8 +1159,7 @@ bool pnfs_roc_drain(struct inode *ino, u32 *barrier, struct rpc_task *task)
spin_unlock(&ino->i_lock);
if (layoutreturn) {
rpc_sleep_on(&NFS_SERVER(ino)->roc_rpcwaitq, task, NULL);
pnfs_send_layoutreturn(lo, stateid, IOMODE_ANY, 0,
NFS4_MAX_UINT64, false);
pnfs_send_layoutreturn(lo, stateid, IOMODE_ANY, false);
}
return found;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部