Merge tag 'xfs-fixes-6.18-rc5' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
Pull xfs fixes from Carlos Maiolino: "This contain fixes for the RT and zoned allocator, and a few fixes for atomic writes" * tag 'xfs-fixes-6.18-rc5' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: xfs: free xfs_busy_extents structure when no RT extents are queued xfs: fix zone selection in xfs_select_open_zone_mru xfs: fix a rtgroup leak when xfs_init_zone fails xfs: fix various problems in xfs_atomic_write_cow_iomap_begin xfs: fix delalloc write failures in software-provided atomic writes
This commit is contained in:
@@ -726,8 +726,10 @@ xfs_trim_rtgroup_extents(
|
||||
break;
|
||||
}
|
||||
|
||||
if (!tr.queued)
|
||||
if (!tr.queued) {
|
||||
kfree(tr.extents);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We hand the extent list to the discard function here so the
|
||||
|
||||
@@ -1091,6 +1091,29 @@ const struct iomap_ops xfs_zoned_direct_write_iomap_ops = {
|
||||
};
|
||||
#endif /* CONFIG_XFS_RT */
|
||||
|
||||
#ifdef DEBUG
|
||||
static void
|
||||
xfs_check_atomic_cow_conversion(
|
||||
struct xfs_inode *ip,
|
||||
xfs_fileoff_t offset_fsb,
|
||||
xfs_filblks_t count_fsb,
|
||||
const struct xfs_bmbt_irec *cmap)
|
||||
{
|
||||
struct xfs_iext_cursor icur;
|
||||
struct xfs_bmbt_irec cmap2 = { };
|
||||
|
||||
if (xfs_iext_lookup_extent(ip, ip->i_cowfp, offset_fsb, &icur, &cmap2))
|
||||
xfs_trim_extent(&cmap2, offset_fsb, count_fsb);
|
||||
|
||||
ASSERT(cmap2.br_startoff == cmap->br_startoff);
|
||||
ASSERT(cmap2.br_blockcount == cmap->br_blockcount);
|
||||
ASSERT(cmap2.br_startblock == cmap->br_startblock);
|
||||
ASSERT(cmap2.br_state == cmap->br_state);
|
||||
}
|
||||
#else
|
||||
# define xfs_check_atomic_cow_conversion(...) ((void)0)
|
||||
#endif
|
||||
|
||||
static int
|
||||
xfs_atomic_write_cow_iomap_begin(
|
||||
struct inode *inode,
|
||||
@@ -1102,9 +1125,10 @@ xfs_atomic_write_cow_iomap_begin(
|
||||
{
|
||||
struct xfs_inode *ip = XFS_I(inode);
|
||||
struct xfs_mount *mp = ip->i_mount;
|
||||
const xfs_fileoff_t offset_fsb = XFS_B_TO_FSBT(mp, offset);
|
||||
xfs_fileoff_t end_fsb = xfs_iomap_end_fsb(mp, offset, length);
|
||||
xfs_filblks_t count_fsb = end_fsb - offset_fsb;
|
||||
const xfs_fileoff_t offset_fsb = XFS_B_TO_FSBT(mp, offset);
|
||||
const xfs_fileoff_t end_fsb = XFS_B_TO_FSB(mp, offset + length);
|
||||
const xfs_filblks_t count_fsb = end_fsb - offset_fsb;
|
||||
xfs_filblks_t hole_count_fsb;
|
||||
int nmaps = 1;
|
||||
xfs_filblks_t resaligned;
|
||||
struct xfs_bmbt_irec cmap;
|
||||
@@ -1130,7 +1154,7 @@ xfs_atomic_write_cow_iomap_begin(
|
||||
return -EAGAIN;
|
||||
|
||||
trace_xfs_iomap_atomic_write_cow(ip, offset, length);
|
||||
|
||||
retry:
|
||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||
|
||||
if (!ip->i_cowfp) {
|
||||
@@ -1141,14 +1165,22 @@ xfs_atomic_write_cow_iomap_begin(
|
||||
if (!xfs_iext_lookup_extent(ip, ip->i_cowfp, offset_fsb, &icur, &cmap))
|
||||
cmap.br_startoff = end_fsb;
|
||||
if (cmap.br_startoff <= offset_fsb) {
|
||||
if (isnullstartblock(cmap.br_startblock))
|
||||
goto convert_delay;
|
||||
|
||||
/*
|
||||
* cmap could extend outside the write range due to previous
|
||||
* speculative preallocations. We must trim cmap to the write
|
||||
* range because the cow fork treats written mappings to mean
|
||||
* "write in progress".
|
||||
*/
|
||||
xfs_trim_extent(&cmap, offset_fsb, count_fsb);
|
||||
goto found;
|
||||
}
|
||||
|
||||
end_fsb = cmap.br_startoff;
|
||||
count_fsb = end_fsb - offset_fsb;
|
||||
hole_count_fsb = cmap.br_startoff - offset_fsb;
|
||||
|
||||
resaligned = xfs_aligned_fsb_count(offset_fsb, count_fsb,
|
||||
resaligned = xfs_aligned_fsb_count(offset_fsb, hole_count_fsb,
|
||||
xfs_get_cowextsz_hint(ip));
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
|
||||
@@ -1169,8 +1201,10 @@ xfs_atomic_write_cow_iomap_begin(
|
||||
if (!xfs_iext_lookup_extent(ip, ip->i_cowfp, offset_fsb, &icur, &cmap))
|
||||
cmap.br_startoff = end_fsb;
|
||||
if (cmap.br_startoff <= offset_fsb) {
|
||||
xfs_trim_extent(&cmap, offset_fsb, count_fsb);
|
||||
xfs_trans_cancel(tp);
|
||||
if (isnullstartblock(cmap.br_startblock))
|
||||
goto convert_delay;
|
||||
xfs_trim_extent(&cmap, offset_fsb, count_fsb);
|
||||
goto found;
|
||||
}
|
||||
|
||||
@@ -1182,7 +1216,7 @@ xfs_atomic_write_cow_iomap_begin(
|
||||
* atomic writes to that same range will be aligned (and don't require
|
||||
* this COW-based method).
|
||||
*/
|
||||
error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb,
|
||||
error = xfs_bmapi_write(tp, ip, offset_fsb, hole_count_fsb,
|
||||
XFS_BMAPI_COWFORK | XFS_BMAPI_PREALLOC |
|
||||
XFS_BMAPI_EXTSZALIGN, 0, &cmap, &nmaps);
|
||||
if (error) {
|
||||
@@ -1195,21 +1229,43 @@ xfs_atomic_write_cow_iomap_begin(
|
||||
if (error)
|
||||
goto out_unlock;
|
||||
|
||||
/*
|
||||
* cmap could map more blocks than the range we passed into bmapi_write
|
||||
* because of EXTSZALIGN or adjacent pre-existing unwritten mappings
|
||||
* that were merged. Trim cmap to the original write range so that we
|
||||
* don't convert more than we were asked to do for this write.
|
||||
*/
|
||||
xfs_trim_extent(&cmap, offset_fsb, count_fsb);
|
||||
|
||||
found:
|
||||
if (cmap.br_state != XFS_EXT_NORM) {
|
||||
error = xfs_reflink_convert_cow_locked(ip, offset_fsb,
|
||||
count_fsb);
|
||||
error = xfs_reflink_convert_cow_locked(ip, cmap.br_startoff,
|
||||
cmap.br_blockcount);
|
||||
if (error)
|
||||
goto out_unlock;
|
||||
cmap.br_state = XFS_EXT_NORM;
|
||||
xfs_check_atomic_cow_conversion(ip, offset_fsb, count_fsb,
|
||||
&cmap);
|
||||
}
|
||||
|
||||
length = XFS_FSB_TO_B(mp, cmap.br_startoff + cmap.br_blockcount);
|
||||
trace_xfs_iomap_found(ip, offset, length - offset, XFS_COW_FORK, &cmap);
|
||||
trace_xfs_iomap_found(ip, offset, length, XFS_COW_FORK, &cmap);
|
||||
seq = xfs_iomap_inode_sequence(ip, IOMAP_F_SHARED);
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
return xfs_bmbt_to_iomap(ip, iomap, &cmap, flags, IOMAP_F_SHARED, seq);
|
||||
|
||||
convert_delay:
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
error = xfs_bmapi_convert_delalloc(ip, XFS_COW_FORK, offset, iomap,
|
||||
NULL);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/*
|
||||
* Try the lookup again, because the delalloc conversion might have
|
||||
* turned the COW mapping into unwritten, but we need it to be in
|
||||
* written state.
|
||||
*/
|
||||
goto retry;
|
||||
out_unlock:
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
return error;
|
||||
|
||||
@@ -615,7 +615,7 @@ xfs_select_open_zone_mru(
|
||||
lockdep_assert_held(&zi->zi_open_zones_lock);
|
||||
|
||||
list_for_each_entry_reverse(oz, &zi->zi_open_zones, oz_entry)
|
||||
if (xfs_try_use_zone(zi, file_hint, oz, false))
|
||||
if (xfs_try_use_zone(zi, file_hint, oz, XFS_ZONE_ALLOC_OK))
|
||||
return oz;
|
||||
|
||||
cond_resched_lock(&zi->zi_open_zones_lock);
|
||||
@@ -1249,8 +1249,10 @@ xfs_mount_zones(
|
||||
|
||||
while ((rtg = xfs_rtgroup_next(mp, rtg))) {
|
||||
error = xfs_init_zone(&iz, rtg, NULL);
|
||||
if (error)
|
||||
if (error) {
|
||||
xfs_rtgroup_rele(rtg);
|
||||
goto out_free_zone_info;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user