References: Debian bug#1103454, GNU bug#77887
Dear maintainers,
libparted wrongly detects ext4 without journal as ext2 instead of ext4.
Steps to reproduce:
truncate -s 1G blob
mkfs.ext4 -O ^has_journal blob
blkid blob -> ext4
parted blob print -> ext2
mount -t ext2 blob /mnt -> "couldn't mount as ext2 due to feature
incompatibilities"
mount -t ext4 blob /mnt -> ok
In libparted/fs/ext2/interface.c, _ext2_generic_probe() considers ext4
as a subset of ext3 which is ext2 with journal. IMO this is wrong
because ext4 without journal may have other incompatible features.
I did very basic testing with the attached patch applied on Debian [1],
now parted detects ext* filesystems as expected:
mkfs.ext2 -> ext2
mkfs.ext3 -> ext3
mkfs.ext4 -> ext4
mkfs.ext4 -O ^has_journal -> ext4
However I am neither a developer nor an ext4 expert so not sure I did
things properly.
[1]
<https://salsa.debian.org/pham/parted/-/commit/a27db8d317c71dbaacd51475721361bfb404152b>From a27db8d317c71dbaacd51475721361bfb404152b Mon Sep 17 00:00:00 2001
From: Pascal Hambourg <[email protected]>
Date: Thu, 17 Apr 2025 18:42:33 +0200
Subject: [PATCH] libparted: Do not detect ext4 without journal as ext2
ext4 may have other incompatible features than journal and cannot be
mounted as ext2 by linux, so detect it as ext4 even without journal
if it has other incompatible features.
---
libparted/fs/ext2/interface.c | 33 +++++++++++++++------------------
1 file changed, 15 insertions(+), 18 deletions(-)
diff --git a/libparted/fs/ext2/interface.c b/libparted/fs/ext2/interface.c
index 7e0b1974..5f64ab37 100644
--- a/libparted/fs/ext2/interface.c
+++ b/libparted/fs/ext2/interface.c
@@ -52,24 +52,21 @@ _ext2_generic_probe (PedGeometry* geom, int expect_ext_ver)
int is_ext3 = 0;
int is_ext4 = 0;
- is_ext3 = (EXT2_SUPER_FEATURE_COMPAT (*sb)
- & EXT3_FEATURE_COMPAT_HAS_JOURNAL) != 0;
- if (is_ext3) {
- is_ext4 = ((EXT2_SUPER_FEATURE_RO_COMPAT (*sb)
- & EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
- || (EXT2_SUPER_FEATURE_RO_COMPAT (*sb)
- & EXT4_FEATURE_RO_COMPAT_GDT_CSUM)
- || (EXT2_SUPER_FEATURE_RO_COMPAT (*sb)
- & EXT4_FEATURE_RO_COMPAT_DIR_NLINK)
- || (EXT2_SUPER_FEATURE_INCOMPAT (*sb)
- & EXT4_FEATURE_INCOMPAT_EXTENTS)
- || (EXT2_SUPER_FEATURE_INCOMPAT (*sb)
- & EXT4_FEATURE_INCOMPAT_64BIT)
- || (EXT2_SUPER_FEATURE_INCOMPAT (*sb)
- & EXT4_FEATURE_INCOMPAT_FLEX_BG));
- if (is_ext4)
- is_ext3 = 0;
- }
+ is_ext4 = ((EXT2_SUPER_FEATURE_RO_COMPAT (*sb)
+ & EXT4_FEATURE_RO_COMPAT_HUGE_FILE)
+ || (EXT2_SUPER_FEATURE_RO_COMPAT (*sb)
+ & EXT4_FEATURE_RO_COMPAT_GDT_CSUM)
+ || (EXT2_SUPER_FEATURE_RO_COMPAT (*sb)
+ & EXT4_FEATURE_RO_COMPAT_DIR_NLINK)
+ || (EXT2_SUPER_FEATURE_INCOMPAT (*sb)
+ & EXT4_FEATURE_INCOMPAT_EXTENTS)
+ || (EXT2_SUPER_FEATURE_INCOMPAT (*sb)
+ & EXT4_FEATURE_INCOMPAT_64BIT)
+ || (EXT2_SUPER_FEATURE_INCOMPAT (*sb)
+ & EXT4_FEATURE_INCOMPAT_FLEX_BG));
+ if (!is_ext4)
+ is_ext3 = (EXT2_SUPER_FEATURE_COMPAT (*sb)
+ & EXT3_FEATURE_COMPAT_HAS_JOURNAL) != 0;
if (expect_ext_ver == 2 && (is_ext3 || is_ext4))
return NULL;
if (expect_ext_ver == 3 && !is_ext3)
--
2.39.5