You need to sign in or sign up before continuing.
提交 0833e447 编写于 作者: D Darrick J. Wong 提交者: Yang Yingliang

xfs: fix brainos in the refcount scrubber's rmap fragment processor

stable inclusion
from linux-4.19.158
commit 964e25377fab8e9071c07d8cdf1c9a4fb079285e

--------------------------------

[ Upstream commit 54e9b09e ]

Fix some serious WTF in the reference count scrubber's rmap fragment
processing.  The code comment says that this loop is supposed to move
all fragment records starting at or before bno onto the worklist, but
there's no obvious reason why nr (the number of items added) should
increment starting from 1, and breaking the loop when we've added the
target number seems dubious since we could have more rmap fragments that
should have been added to the worklist.

This seems to manifest in xfs/411 when adding one to the refcount field.

Fixes: dbde19da ("xfs: cross-reference the rmapbt data with the refcountbt")
Signed-off-by: NDarrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: NChristoph Hellwig <hch@lst.de>
Signed-off-by: NSasha Levin <sashal@kernel.org>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
Signed-off-by: NCheng Jian <cj.chengjian@huawei.com>
上级 ae5ea479
...@@ -180,7 +180,6 @@ xchk_refcountbt_process_rmap_fragments( ...@@ -180,7 +180,6 @@ xchk_refcountbt_process_rmap_fragments(
*/ */
INIT_LIST_HEAD(&worklist); INIT_LIST_HEAD(&worklist);
rbno = NULLAGBLOCK; rbno = NULLAGBLOCK;
nr = 1;
/* Make sure the fragments actually /are/ in agbno order. */ /* Make sure the fragments actually /are/ in agbno order. */
bno = 0; bno = 0;
...@@ -194,15 +193,14 @@ xchk_refcountbt_process_rmap_fragments( ...@@ -194,15 +193,14 @@ xchk_refcountbt_process_rmap_fragments(
* Find all the rmaps that start at or before the refc extent, * Find all the rmaps that start at or before the refc extent,
* and put them on the worklist. * and put them on the worklist.
*/ */
nr = 0;
list_for_each_entry_safe(frag, n, &refchk->fragments, list) { list_for_each_entry_safe(frag, n, &refchk->fragments, list) {
if (frag->rm.rm_startblock > refchk->bno) if (frag->rm.rm_startblock > refchk->bno || nr > target_nr)
goto done; break;
bno = frag->rm.rm_startblock + frag->rm.rm_blockcount; bno = frag->rm.rm_startblock + frag->rm.rm_blockcount;
if (bno < rbno) if (bno < rbno)
rbno = bno; rbno = bno;
list_move_tail(&frag->list, &worklist); list_move_tail(&frag->list, &worklist);
if (nr == target_nr)
break;
nr++; nr++;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册