Skip to content

Commit 32cc132

Browse files
author
CKI KWF Bot
committed
Merge: ext4: fix FS_IOC_GETFSMAP handling
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/7389 JIRA: https://issues.redhat.com/browse/RHEL-109218 Fixes to allow ext4 to pass fstests generic/365. Signed-off-by: Brian Foster <bfoster@redhat.com> Approved-by: Pavel Reichl <preichl@redhat.com> Approved-by: Carlos Maiolino <cmaiolino@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: CKI GitLab Kmaint Pipeline Bot <26919896-cki-kmaint-pipeline-bot@users.noreply.gitlab.com>
2 parents 59c30cf + 1befbcf commit 32cc132

File tree

3 files changed

+87
-9
lines changed

3 files changed

+87
-9
lines changed

fs/ext4/fsmap.c

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,56 @@ static inline ext4_fsblk_t ext4_fsmap_next_pblk(struct ext4_fsmap *fmr)
185185
return fmr->fmr_physical + fmr->fmr_length;
186186
}
187187

188+
static int ext4_getfsmap_meta_helper(struct super_block *sb,
189+
ext4_group_t agno, ext4_grpblk_t start,
190+
ext4_grpblk_t len, void *priv)
191+
{
192+
struct ext4_getfsmap_info *info = priv;
193+
struct ext4_fsmap *p;
194+
struct ext4_fsmap *tmp;
195+
struct ext4_sb_info *sbi = EXT4_SB(sb);
196+
ext4_fsblk_t fsb, fs_start, fs_end;
197+
int error;
198+
199+
fs_start = fsb = (EXT4_C2B(sbi, start) +
200+
ext4_group_first_block_no(sb, agno));
201+
fs_end = fs_start + EXT4_C2B(sbi, len);
202+
203+
/* Return relevant extents from the meta_list */
204+
list_for_each_entry_safe(p, tmp, &info->gfi_meta_list, fmr_list) {
205+
if (p->fmr_physical < info->gfi_next_fsblk) {
206+
list_del(&p->fmr_list);
207+
kfree(p);
208+
continue;
209+
}
210+
if (p->fmr_physical <= fs_start ||
211+
p->fmr_physical + p->fmr_length <= fs_end) {
212+
/* Emit the retained free extent record if present */
213+
if (info->gfi_lastfree.fmr_owner) {
214+
error = ext4_getfsmap_helper(sb, info,
215+
&info->gfi_lastfree);
216+
if (error)
217+
return error;
218+
info->gfi_lastfree.fmr_owner = 0;
219+
}
220+
error = ext4_getfsmap_helper(sb, info, p);
221+
if (error)
222+
return error;
223+
fsb = p->fmr_physical + p->fmr_length;
224+
if (info->gfi_next_fsblk < fsb)
225+
info->gfi_next_fsblk = fsb;
226+
list_del(&p->fmr_list);
227+
kfree(p);
228+
continue;
229+
}
230+
}
231+
if (info->gfi_next_fsblk < fsb)
232+
info->gfi_next_fsblk = fsb;
233+
234+
return 0;
235+
}
236+
237+
188238
/* Transform a blockgroup's free record into a fsmap */
189239
static int ext4_getfsmap_datadev_helper(struct super_block *sb,
190240
ext4_group_t agno, ext4_grpblk_t start,
@@ -343,6 +393,14 @@ static unsigned int ext4_getfsmap_find_sb(struct super_block *sb,
343393
/* Reserved GDT blocks */
344394
if (!ext4_has_feature_meta_bg(sb) || metagroup < first_meta_bg) {
345395
len = le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks);
396+
397+
/*
398+
* mkfs.ext4 can set s_reserved_gdt_blocks as 0 in some cases,
399+
* check for that.
400+
*/
401+
if (!len)
402+
return 0;
403+
346404
error = ext4_getfsmap_fill(meta_list, fsb, len,
347405
EXT4_FMR_OWN_RESV_GDT);
348406
if (error)
@@ -476,6 +534,7 @@ static int ext4_getfsmap_datadev(struct super_block *sb,
476534
ext4_group_t end_ag;
477535
ext4_grpblk_t first_cluster;
478536
ext4_grpblk_t last_cluster;
537+
struct ext4_fsmap irec;
479538
int error = 0;
480539

481540
bofs = le32_to_cpu(sbi->s_es->s_first_data_block);
@@ -539,6 +598,7 @@ static int ext4_getfsmap_datadev(struct super_block *sb,
539598
error = ext4_mballoc_query_range(sb, info->gfi_agno,
540599
EXT4_B2C(sbi, info->gfi_low.fmr_physical),
541600
EXT4_B2C(sbi, info->gfi_high.fmr_physical),
601+
ext4_getfsmap_meta_helper,
542602
ext4_getfsmap_datadev_helper, info);
543603
if (error)
544604
goto err;
@@ -558,9 +618,18 @@ static int ext4_getfsmap_datadev(struct super_block *sb,
558618
goto err;
559619
}
560620

561-
/* Report any gaps at the end of the bg */
621+
/*
622+
* The dummy record below will cause ext4_getfsmap_helper() to report
623+
* any allocated blocks at the end of the range.
624+
*/
625+
irec.fmr_device = 0;
626+
irec.fmr_physical = end_fsb + 1;
627+
irec.fmr_length = 0;
628+
irec.fmr_owner = EXT4_FMR_OWN_FREE;
629+
irec.fmr_flags = 0;
630+
562631
info->gfi_last = true;
563-
error = ext4_getfsmap_datadev_helper(sb, end_ag, last_cluster, 0, info);
632+
error = ext4_getfsmap_helper(sb, info, &irec);
564633
if (error)
565634
goto err;
566635

fs/ext4/mballoc.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6769,8 +6769,7 @@ __releases(ext4_group_lock_ptr(sb, e4b->bd_group))
67696769
return 0;
67706770

67716771
bitmap = e4b->bd_bitmap;
6772-
start = (e4b->bd_info->bb_first_free > start) ?
6773-
e4b->bd_info->bb_first_free : start;
6772+
start = max(e4b->bd_info->bb_first_free, start);
67746773
count = 0;
67756774
free_count = 0;
67766775

@@ -6970,13 +6969,14 @@ int
69706969
ext4_mballoc_query_range(
69716970
struct super_block *sb,
69726971
ext4_group_t group,
6973-
ext4_grpblk_t start,
6972+
ext4_grpblk_t first,
69746973
ext4_grpblk_t end,
6974+
ext4_mballoc_query_range_fn meta_formatter,
69756975
ext4_mballoc_query_range_fn formatter,
69766976
void *priv)
69776977
{
69786978
void *bitmap;
6979-
ext4_grpblk_t next;
6979+
ext4_grpblk_t start, next;
69806980
struct ext4_buddy e4b;
69816981
int error;
69826982

@@ -6987,11 +6987,19 @@ ext4_mballoc_query_range(
69876987

69886988
ext4_lock_group(sb, group);
69896989

6990-
start = (e4b.bd_info->bb_first_free > start) ?
6991-
e4b.bd_info->bb_first_free : start;
6990+
start = max(e4b.bd_info->bb_first_free, first);
69926991
if (end >= EXT4_CLUSTERS_PER_GROUP(sb))
69936992
end = EXT4_CLUSTERS_PER_GROUP(sb) - 1;
6994-
6993+
if (meta_formatter && start != first) {
6994+
if (start > end)
6995+
start = end;
6996+
ext4_unlock_group(sb, group);
6997+
error = meta_formatter(sb, group, first, start - first,
6998+
priv);
6999+
if (error)
7000+
goto out_unload;
7001+
ext4_lock_group(sb, group);
7002+
}
69957003
while (start <= end) {
69967004
start = mb_find_next_zero_bit(bitmap, end + 1, start);
69977005
if (start > end)

fs/ext4/mballoc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ ext4_mballoc_query_range(
246246
ext4_group_t agno,
247247
ext4_grpblk_t start,
248248
ext4_grpblk_t end,
249+
ext4_mballoc_query_range_fn meta_formatter,
249250
ext4_mballoc_query_range_fn formatter,
250251
void *priv);
251252

0 commit comments

Comments
 (0)