xfs: hoist refcount record merge predicates

[ Upstream commit 9d720a5a65 ]

Hoist these multiline conditionals into separate static inline helpers
to improve readability and set the stage for corruption fixes that will
be introduced in the next patch.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Xiao Yang <yangx.jy@fujitsu.com>
Signed-off-by: Leah Rumancik <leah.rumancik@gmail.com>
Acked-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Darrick J. Wong 2024-05-01 11:41:06 -07:00 committed by Greg Kroah-Hartman
parent 0d889ae85f
commit 131a854c09

View File

@ -815,11 +815,119 @@ out_error:
/* Is this extent valid? */
static inline bool
xfs_refc_valid(
struct xfs_refcount_irec *rc)
const struct xfs_refcount_irec *rc)
{
return rc->rc_startblock != NULLAGBLOCK;
}
static inline bool
xfs_refc_want_merge_center(
const struct xfs_refcount_irec *left,
const struct xfs_refcount_irec *cleft,
const struct xfs_refcount_irec *cright,
const struct xfs_refcount_irec *right,
bool cleft_is_cright,
enum xfs_refc_adjust_op adjust,
unsigned long long *ulenp)
{
unsigned long long ulen = left->rc_blockcount;
/*
* To merge with a center record, both shoulder records must be
* adjacent to the record we want to adjust. This is only true if
* find_left and find_right made all four records valid.
*/
if (!xfs_refc_valid(left) || !xfs_refc_valid(right) ||
!xfs_refc_valid(cleft) || !xfs_refc_valid(cright))
return false;
/* There must only be one record for the entire range. */
if (!cleft_is_cright)
return false;
/* The shoulder record refcounts must match the new refcount. */
if (left->rc_refcount != cleft->rc_refcount + adjust)
return false;
if (right->rc_refcount != cleft->rc_refcount + adjust)
return false;
/*
* The new record cannot exceed the max length. ulen is a ULL as the
* individual record block counts can be up to (u32 - 1) in length
* hence we need to catch u32 addition overflows here.
*/
ulen += cleft->rc_blockcount + right->rc_blockcount;
if (ulen >= MAXREFCEXTLEN)
return false;
*ulenp = ulen;
return true;
}
static inline bool
xfs_refc_want_merge_left(
const struct xfs_refcount_irec *left,
const struct xfs_refcount_irec *cleft,
enum xfs_refc_adjust_op adjust)
{
unsigned long long ulen = left->rc_blockcount;
/*
* For a left merge, the left shoulder record must be adjacent to the
* start of the range. If this is true, find_left made left and cleft
* contain valid contents.
*/
if (!xfs_refc_valid(left) || !xfs_refc_valid(cleft))
return false;
/* Left shoulder record refcount must match the new refcount. */
if (left->rc_refcount != cleft->rc_refcount + adjust)
return false;
/*
* The new record cannot exceed the max length. ulen is a ULL as the
* individual record block counts can be up to (u32 - 1) in length
* hence we need to catch u32 addition overflows here.
*/
ulen += cleft->rc_blockcount;
if (ulen >= MAXREFCEXTLEN)
return false;
return true;
}
static inline bool
xfs_refc_want_merge_right(
const struct xfs_refcount_irec *cright,
const struct xfs_refcount_irec *right,
enum xfs_refc_adjust_op adjust)
{
unsigned long long ulen = right->rc_blockcount;
/*
* For a right merge, the right shoulder record must be adjacent to the
* end of the range. If this is true, find_right made cright and right
* contain valid contents.
*/
if (!xfs_refc_valid(right) || !xfs_refc_valid(cright))
return false;
/* Right shoulder record refcount must match the new refcount. */
if (right->rc_refcount != cright->rc_refcount + adjust)
return false;
/*
* The new record cannot exceed the max length. ulen is a ULL as the
* individual record block counts can be up to (u32 - 1) in length
* hence we need to catch u32 addition overflows here.
*/
ulen += cright->rc_blockcount;
if (ulen >= MAXREFCEXTLEN)
return false;
return true;
}
/*
* Try to merge with any extents on the boundaries of the adjustment range.
*/
@ -861,23 +969,15 @@ xfs_refcount_merge_extents(
(cleft.rc_blockcount == cright.rc_blockcount);
/* Try to merge left, cleft, and right. cleft must == cright. */
ulen = (unsigned long long)left.rc_blockcount + cleft.rc_blockcount +
right.rc_blockcount;
if (xfs_refc_valid(&left) && xfs_refc_valid(&right) &&
xfs_refc_valid(&cleft) && xfs_refc_valid(&cright) && cequal &&
left.rc_refcount == cleft.rc_refcount + adjust &&
right.rc_refcount == cleft.rc_refcount + adjust &&
ulen < MAXREFCEXTLEN) {
if (xfs_refc_want_merge_center(&left, &cleft, &cright, &right, cequal,
adjust, &ulen)) {
*shape_changed = true;
return xfs_refcount_merge_center_extents(cur, &left, &cleft,
&right, ulen, aglen);
}
/* Try to merge left and cleft. */
ulen = (unsigned long long)left.rc_blockcount + cleft.rc_blockcount;
if (xfs_refc_valid(&left) && xfs_refc_valid(&cleft) &&
left.rc_refcount == cleft.rc_refcount + adjust &&
ulen < MAXREFCEXTLEN) {
if (xfs_refc_want_merge_left(&left, &cleft, adjust)) {
*shape_changed = true;
error = xfs_refcount_merge_left_extent(cur, &left, &cleft,
agbno, aglen);
@ -893,10 +993,7 @@ xfs_refcount_merge_extents(
}
/* Try to merge cright and right. */
ulen = (unsigned long long)right.rc_blockcount + cright.rc_blockcount;
if (xfs_refc_valid(&right) && xfs_refc_valid(&cright) &&
right.rc_refcount == cright.rc_refcount + adjust &&
ulen < MAXREFCEXTLEN) {
if (xfs_refc_want_merge_right(&cright, &right, adjust)) {
*shape_changed = true;
return xfs_refcount_merge_right_extent(cur, &right, &cright,
aglen);