mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-06 14:05:39 +00:00
xfs: add a helper to prevent bmap merges across rtgroup boundaries
Except for the rt superblock, realtime groups do not store any metadata at the start (or end) of the group. There is nothing to prevent the bmap code from merging allocations from multiple groups into a single bmap record. Add a helper to check for this case. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <djwong@kernel.org> [djwong: massage the commit message after pulling this into rtgroups] Signed-off-by: Darrick J. Wong <djwong@kernel.org>
This commit is contained in:
parent
9bb5127347
commit
8458c4944e
@ -40,6 +40,7 @@
|
||||
#include "xfs_bmap_item.h"
|
||||
#include "xfs_symlink_remote.h"
|
||||
#include "xfs_inode_util.h"
|
||||
#include "xfs_rtgroup.h"
|
||||
|
||||
struct kmem_cache *xfs_bmap_intent_cache;
|
||||
|
||||
@ -1426,6 +1427,24 @@ xfs_bmap_last_offset(
|
||||
* Extent tree manipulation functions used during allocation.
|
||||
*/
|
||||
|
||||
static inline bool
|
||||
xfs_bmap_same_rtgroup(
|
||||
struct xfs_inode *ip,
|
||||
int whichfork,
|
||||
struct xfs_bmbt_irec *left,
|
||||
struct xfs_bmbt_irec *right)
|
||||
{
|
||||
struct xfs_mount *mp = ip->i_mount;
|
||||
|
||||
if (xfs_ifork_is_realtime(ip, whichfork) && xfs_has_rtgroups(mp)) {
|
||||
if (xfs_rtb_to_rgno(mp, left->br_startblock) !=
|
||||
xfs_rtb_to_rgno(mp, right->br_startblock))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a delayed allocation to a real allocation.
|
||||
*/
|
||||
@ -1495,7 +1514,8 @@ xfs_bmap_add_extent_delay_real(
|
||||
LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff &&
|
||||
LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock &&
|
||||
LEFT.br_state == new->br_state &&
|
||||
LEFT.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN)
|
||||
LEFT.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN &&
|
||||
xfs_bmap_same_rtgroup(bma->ip, whichfork, &LEFT, new))
|
||||
state |= BMAP_LEFT_CONTIG;
|
||||
|
||||
/*
|
||||
@ -1519,7 +1539,8 @@ xfs_bmap_add_extent_delay_real(
|
||||
(BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING |
|
||||
BMAP_RIGHT_FILLING) ||
|
||||
LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount
|
||||
<= XFS_MAX_BMBT_EXTLEN))
|
||||
<= XFS_MAX_BMBT_EXTLEN) &&
|
||||
xfs_bmap_same_rtgroup(bma->ip, whichfork, new, &RIGHT))
|
||||
state |= BMAP_RIGHT_CONTIG;
|
||||
|
||||
error = 0;
|
||||
@ -2064,7 +2085,8 @@ xfs_bmap_add_extent_unwritten_real(
|
||||
LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff &&
|
||||
LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock &&
|
||||
LEFT.br_state == new->br_state &&
|
||||
LEFT.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN)
|
||||
LEFT.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN &&
|
||||
xfs_bmap_same_rtgroup(ip, whichfork, &LEFT, new))
|
||||
state |= BMAP_LEFT_CONTIG;
|
||||
|
||||
/*
|
||||
@ -2088,7 +2110,8 @@ xfs_bmap_add_extent_unwritten_real(
|
||||
(BMAP_LEFT_CONTIG | BMAP_LEFT_FILLING |
|
||||
BMAP_RIGHT_FILLING) ||
|
||||
LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount
|
||||
<= XFS_MAX_BMBT_EXTLEN))
|
||||
<= XFS_MAX_BMBT_EXTLEN) &&
|
||||
xfs_bmap_same_rtgroup(ip, whichfork, new, &RIGHT))
|
||||
state |= BMAP_RIGHT_CONTIG;
|
||||
|
||||
/*
|
||||
@ -2597,7 +2620,8 @@ xfs_bmap_add_extent_hole_delay(
|
||||
*/
|
||||
if ((state & BMAP_LEFT_VALID) && (state & BMAP_LEFT_DELAY) &&
|
||||
left.br_startoff + left.br_blockcount == new->br_startoff &&
|
||||
left.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN)
|
||||
left.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN &&
|
||||
xfs_bmap_same_rtgroup(ip, whichfork, &left, new))
|
||||
state |= BMAP_LEFT_CONTIG;
|
||||
|
||||
if ((state & BMAP_RIGHT_VALID) && (state & BMAP_RIGHT_DELAY) &&
|
||||
@ -2605,7 +2629,8 @@ xfs_bmap_add_extent_hole_delay(
|
||||
new->br_blockcount + right.br_blockcount <= XFS_MAX_BMBT_EXTLEN &&
|
||||
(!(state & BMAP_LEFT_CONTIG) ||
|
||||
(left.br_blockcount + new->br_blockcount +
|
||||
right.br_blockcount <= XFS_MAX_BMBT_EXTLEN)))
|
||||
right.br_blockcount <= XFS_MAX_BMBT_EXTLEN)) &&
|
||||
xfs_bmap_same_rtgroup(ip, whichfork, new, &right))
|
||||
state |= BMAP_RIGHT_CONTIG;
|
||||
|
||||
/*
|
||||
@ -2748,7 +2773,8 @@ xfs_bmap_add_extent_hole_real(
|
||||
left.br_startoff + left.br_blockcount == new->br_startoff &&
|
||||
left.br_startblock + left.br_blockcount == new->br_startblock &&
|
||||
left.br_state == new->br_state &&
|
||||
left.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN)
|
||||
left.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN &&
|
||||
xfs_bmap_same_rtgroup(ip, whichfork, &left, new))
|
||||
state |= BMAP_LEFT_CONTIG;
|
||||
|
||||
if ((state & BMAP_RIGHT_VALID) && !(state & BMAP_RIGHT_DELAY) &&
|
||||
@ -2758,7 +2784,8 @@ xfs_bmap_add_extent_hole_real(
|
||||
new->br_blockcount + right.br_blockcount <= XFS_MAX_BMBT_EXTLEN &&
|
||||
(!(state & BMAP_LEFT_CONTIG) ||
|
||||
left.br_blockcount + new->br_blockcount +
|
||||
right.br_blockcount <= XFS_MAX_BMBT_EXTLEN))
|
||||
right.br_blockcount <= XFS_MAX_BMBT_EXTLEN) &&
|
||||
xfs_bmap_same_rtgroup(ip, whichfork, new, &right))
|
||||
state |= BMAP_RIGHT_CONTIG;
|
||||
|
||||
error = 0;
|
||||
@ -5715,6 +5742,8 @@ xfs_bunmapi(
|
||||
*/
|
||||
STATIC bool
|
||||
xfs_bmse_can_merge(
|
||||
struct xfs_inode *ip,
|
||||
int whichfork,
|
||||
struct xfs_bmbt_irec *left, /* preceding extent */
|
||||
struct xfs_bmbt_irec *got, /* current extent to shift */
|
||||
xfs_fileoff_t shift) /* shift fsb */
|
||||
@ -5730,7 +5759,8 @@ xfs_bmse_can_merge(
|
||||
if ((left->br_startoff + left->br_blockcount != startoff) ||
|
||||
(left->br_startblock + left->br_blockcount != got->br_startblock) ||
|
||||
(left->br_state != got->br_state) ||
|
||||
(left->br_blockcount + got->br_blockcount > XFS_MAX_BMBT_EXTLEN))
|
||||
(left->br_blockcount + got->br_blockcount > XFS_MAX_BMBT_EXTLEN) ||
|
||||
!xfs_bmap_same_rtgroup(ip, whichfork, left, got))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -5766,7 +5796,7 @@ xfs_bmse_merge(
|
||||
blockcount = left->br_blockcount + got->br_blockcount;
|
||||
|
||||
xfs_assert_ilocked(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
|
||||
ASSERT(xfs_bmse_can_merge(left, got, shift));
|
||||
ASSERT(xfs_bmse_can_merge(ip, whichfork, left, got, shift));
|
||||
|
||||
new = *left;
|
||||
new.br_blockcount = blockcount;
|
||||
@ -5928,7 +5958,8 @@ xfs_bmap_collapse_extents(
|
||||
goto del_cursor;
|
||||
}
|
||||
|
||||
if (xfs_bmse_can_merge(&prev, &got, offset_shift_fsb)) {
|
||||
if (xfs_bmse_can_merge(ip, whichfork, &prev, &got,
|
||||
offset_shift_fsb)) {
|
||||
error = xfs_bmse_merge(tp, ip, whichfork,
|
||||
offset_shift_fsb, &icur, &got, &prev,
|
||||
cur, &logflags);
|
||||
@ -6064,7 +6095,8 @@ xfs_bmap_insert_extents(
|
||||
* never find mergeable extents in this scenario. Check anyways
|
||||
* and warn if we encounter two extents that could be one.
|
||||
*/
|
||||
if (xfs_bmse_can_merge(&got, &next, offset_shift_fsb))
|
||||
if (xfs_bmse_can_merge(ip, whichfork, &got, &next,
|
||||
offset_shift_fsb))
|
||||
WARN_ON_ONCE(1);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user