Skip to content

Commit e284d51

Browse files
committed
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
2 parents e811c33 + d8a823c commit e284d51

3 files changed

Lines changed: 76 additions & 16 deletions

File tree

fs/xfs/xfs_discard.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -726,8 +726,10 @@ xfs_trim_rtgroup_extents(
726726
break;
727727
}
728728

729-
if (!tr.queued)
729+
if (!tr.queued) {
730+
kfree(tr.extents);
730731
break;
732+
}
731733

732734
/*
733735
* We hand the extent list to the discard function here so the

fs/xfs/xfs_iomap.c

Lines changed: 69 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,6 +1091,29 @@ const struct iomap_ops xfs_zoned_direct_write_iomap_ops = {
10911091
};
10921092
#endif /* CONFIG_XFS_RT */
10931093

1094+
#ifdef DEBUG
1095+
static void
1096+
xfs_check_atomic_cow_conversion(
1097+
struct xfs_inode *ip,
1098+
xfs_fileoff_t offset_fsb,
1099+
xfs_filblks_t count_fsb,
1100+
const struct xfs_bmbt_irec *cmap)
1101+
{
1102+
struct xfs_iext_cursor icur;
1103+
struct xfs_bmbt_irec cmap2 = { };
1104+
1105+
if (xfs_iext_lookup_extent(ip, ip->i_cowfp, offset_fsb, &icur, &cmap2))
1106+
xfs_trim_extent(&cmap2, offset_fsb, count_fsb);
1107+
1108+
ASSERT(cmap2.br_startoff == cmap->br_startoff);
1109+
ASSERT(cmap2.br_blockcount == cmap->br_blockcount);
1110+
ASSERT(cmap2.br_startblock == cmap->br_startblock);
1111+
ASSERT(cmap2.br_state == cmap->br_state);
1112+
}
1113+
#else
1114+
# define xfs_check_atomic_cow_conversion(...) ((void)0)
1115+
#endif
1116+
10941117
static int
10951118
xfs_atomic_write_cow_iomap_begin(
10961119
struct inode *inode,
@@ -1102,9 +1125,10 @@ xfs_atomic_write_cow_iomap_begin(
11021125
{
11031126
struct xfs_inode *ip = XFS_I(inode);
11041127
struct xfs_mount *mp = ip->i_mount;
1105-
const xfs_fileoff_t offset_fsb = XFS_B_TO_FSBT(mp, offset);
1106-
xfs_fileoff_t end_fsb = xfs_iomap_end_fsb(mp, offset, length);
1107-
xfs_filblks_t count_fsb = end_fsb - offset_fsb;
1128+
const xfs_fileoff_t offset_fsb = XFS_B_TO_FSBT(mp, offset);
1129+
const xfs_fileoff_t end_fsb = XFS_B_TO_FSB(mp, offset + length);
1130+
const xfs_filblks_t count_fsb = end_fsb - offset_fsb;
1131+
xfs_filblks_t hole_count_fsb;
11081132
int nmaps = 1;
11091133
xfs_filblks_t resaligned;
11101134
struct xfs_bmbt_irec cmap;
@@ -1130,7 +1154,7 @@ xfs_atomic_write_cow_iomap_begin(
11301154
return -EAGAIN;
11311155

11321156
trace_xfs_iomap_atomic_write_cow(ip, offset, length);
1133-
1157+
retry:
11341158
xfs_ilock(ip, XFS_ILOCK_EXCL);
11351159

11361160
if (!ip->i_cowfp) {
@@ -1141,14 +1165,22 @@ xfs_atomic_write_cow_iomap_begin(
11411165
if (!xfs_iext_lookup_extent(ip, ip->i_cowfp, offset_fsb, &icur, &cmap))
11421166
cmap.br_startoff = end_fsb;
11431167
if (cmap.br_startoff <= offset_fsb) {
1168+
if (isnullstartblock(cmap.br_startblock))
1169+
goto convert_delay;
1170+
1171+
/*
1172+
* cmap could extend outside the write range due to previous
1173+
* speculative preallocations. We must trim cmap to the write
1174+
* range because the cow fork treats written mappings to mean
1175+
* "write in progress".
1176+
*/
11441177
xfs_trim_extent(&cmap, offset_fsb, count_fsb);
11451178
goto found;
11461179
}
11471180

1148-
end_fsb = cmap.br_startoff;
1149-
count_fsb = end_fsb - offset_fsb;
1181+
hole_count_fsb = cmap.br_startoff - offset_fsb;
11501182

1151-
resaligned = xfs_aligned_fsb_count(offset_fsb, count_fsb,
1183+
resaligned = xfs_aligned_fsb_count(offset_fsb, hole_count_fsb,
11521184
xfs_get_cowextsz_hint(ip));
11531185
xfs_iunlock(ip, XFS_ILOCK_EXCL);
11541186

@@ -1169,8 +1201,10 @@ xfs_atomic_write_cow_iomap_begin(
11691201
if (!xfs_iext_lookup_extent(ip, ip->i_cowfp, offset_fsb, &icur, &cmap))
11701202
cmap.br_startoff = end_fsb;
11711203
if (cmap.br_startoff <= offset_fsb) {
1172-
xfs_trim_extent(&cmap, offset_fsb, count_fsb);
11731204
xfs_trans_cancel(tp);
1205+
if (isnullstartblock(cmap.br_startblock))
1206+
goto convert_delay;
1207+
xfs_trim_extent(&cmap, offset_fsb, count_fsb);
11741208
goto found;
11751209
}
11761210

@@ -1182,7 +1216,7 @@ xfs_atomic_write_cow_iomap_begin(
11821216
* atomic writes to that same range will be aligned (and don't require
11831217
* this COW-based method).
11841218
*/
1185-
error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb,
1219+
error = xfs_bmapi_write(tp, ip, offset_fsb, hole_count_fsb,
11861220
XFS_BMAPI_COWFORK | XFS_BMAPI_PREALLOC |
11871221
XFS_BMAPI_EXTSZALIGN, 0, &cmap, &nmaps);
11881222
if (error) {
@@ -1195,21 +1229,43 @@ xfs_atomic_write_cow_iomap_begin(
11951229
if (error)
11961230
goto out_unlock;
11971231

1232+
/*
1233+
* cmap could map more blocks than the range we passed into bmapi_write
1234+
* because of EXTSZALIGN or adjacent pre-existing unwritten mappings
1235+
* that were merged. Trim cmap to the original write range so that we
1236+
* don't convert more than we were asked to do for this write.
1237+
*/
1238+
xfs_trim_extent(&cmap, offset_fsb, count_fsb);
1239+
11981240
found:
11991241
if (cmap.br_state != XFS_EXT_NORM) {
1200-
error = xfs_reflink_convert_cow_locked(ip, offset_fsb,
1201-
count_fsb);
1242+
error = xfs_reflink_convert_cow_locked(ip, cmap.br_startoff,
1243+
cmap.br_blockcount);
12021244
if (error)
12031245
goto out_unlock;
12041246
cmap.br_state = XFS_EXT_NORM;
1247+
xfs_check_atomic_cow_conversion(ip, offset_fsb, count_fsb,
1248+
&cmap);
12051249
}
12061250

1207-
length = XFS_FSB_TO_B(mp, cmap.br_startoff + cmap.br_blockcount);
1208-
trace_xfs_iomap_found(ip, offset, length - offset, XFS_COW_FORK, &cmap);
1251+
trace_xfs_iomap_found(ip, offset, length, XFS_COW_FORK, &cmap);
12091252
seq = xfs_iomap_inode_sequence(ip, IOMAP_F_SHARED);
12101253
xfs_iunlock(ip, XFS_ILOCK_EXCL);
12111254
return xfs_bmbt_to_iomap(ip, iomap, &cmap, flags, IOMAP_F_SHARED, seq);
12121255

1256+
convert_delay:
1257+
xfs_iunlock(ip, XFS_ILOCK_EXCL);
1258+
error = xfs_bmapi_convert_delalloc(ip, XFS_COW_FORK, offset, iomap,
1259+
NULL);
1260+
if (error)
1261+
return error;
1262+
1263+
/*
1264+
* Try the lookup again, because the delalloc conversion might have
1265+
* turned the COW mapping into unwritten, but we need it to be in
1266+
* written state.
1267+
*/
1268+
goto retry;
12131269
out_unlock:
12141270
xfs_iunlock(ip, XFS_ILOCK_EXCL);
12151271
return error;

fs/xfs/xfs_zone_alloc.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,7 @@ xfs_select_open_zone_mru(
615615
lockdep_assert_held(&zi->zi_open_zones_lock);
616616

617617
list_for_each_entry_reverse(oz, &zi->zi_open_zones, oz_entry)
618-
if (xfs_try_use_zone(zi, file_hint, oz, false))
618+
if (xfs_try_use_zone(zi, file_hint, oz, XFS_ZONE_ALLOC_OK))
619619
return oz;
620620

621621
cond_resched_lock(&zi->zi_open_zones_lock);
@@ -1249,8 +1249,10 @@ xfs_mount_zones(
12491249

12501250
while ((rtg = xfs_rtgroup_next(mp, rtg))) {
12511251
error = xfs_init_zone(&iz, rtg, NULL);
1252-
if (error)
1252+
if (error) {
1253+
xfs_rtgroup_rele(rtg);
12531254
goto out_free_zone_info;
1255+
}
12541256
}
12551257
}
12561258

0 commit comments

Comments
 (0)