* [PATCH RFC 0/3] mke2fs: small doc and features
@ 2025-09-09 15:40 Ralph Siemsen
2025-09-09 15:40 ` [PATCH RFC 1/3] mke2fs: document the hash_seed option Ralph Siemsen
` (2 more replies)
0 siblings, 3 replies; 12+ messages in thread
From: Ralph Siemsen @ 2025-09-09 15:40 UTC (permalink / raw)
To: linux-ext4; +Cc: Ralph Siemsen
Three independent fixes for mke2fs:
1) document the hash_seed option
2) prohibit multiple '-E' arguments
3) add extended option for setting root inode security context
The first fix is straightforward.
For the second one, some alternatives would be:
- only print a warning, not a fatal error (but that is easy to miss)
- allow multiple '-E' options, and join them automatically
For the third one, the main use case is when generating empty
filesystems for use when SELinux is enabled.
Signed-off-by: Ralph Siemsen <ralph.siemsen@linaro.org>
---
Ralph Siemsen (3):
mke2fs: document the hash_seed option
mke2fs.c: fail on multiple '-E' options
mke2fs: add root_selinux option for root inode label
misc/mke2fs.8.in | 14 +++++++++++
misc/mke2fs.c | 53 ++++++++++++++++++++++++++++++++++++++++
tests/m_root_selinux/expect.1 | 57 +++++++++++++++++++++++++++++++++++++++++++
tests/m_root_selinux/script | 4 +++
4 files changed, 128 insertions(+)
---
base-commit: 4b02eb164221c079b428566499343af2766c2ec3
change-id: 20250909-mke2fs-small-fixes-6d4a0c3a8781
Best regards,
--
Ralph Siemsen <ralph.siemsen@linaro.org>
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH RFC 1/3] mke2fs: document the hash_seed option
2025-09-09 15:40 [PATCH RFC 0/3] mke2fs: small doc and features Ralph Siemsen
@ 2025-09-09 15:40 ` Ralph Siemsen
2025-09-09 15:40 ` [PATCH RFC 2/3] mke2fs.c: fail on multiple '-E' options Ralph Siemsen
2025-09-09 15:40 ` [PATCH RFC 3/3] mke2fs: add root_selinux option for root inode label Ralph Siemsen
2 siblings, 0 replies; 12+ messages in thread
From: Ralph Siemsen @ 2025-09-09 15:40 UTC (permalink / raw)
To: linux-ext4; +Cc: Ralph Siemsen
For reproducible builds, it is necessary to control the random seed used
for hashing. Document the extended option for this feature.
Fixes: e1f71006 ("AOSP: mke2fs, libext2fs: make filesystem image reproducible")
Signed-off-by: Ralph Siemsen <ralph.siemsen@linaro.org>
---
misc/mke2fs.8.in | 4 ++++
misc/mke2fs.c | 1 +
2 files changed, 5 insertions(+)
diff --git a/misc/mke2fs.8.in b/misc/mke2fs.8.in
index 13ddef47..14bae326 100644
--- a/misc/mke2fs.8.in
+++ b/misc/mke2fs.8.in
@@ -320,6 +320,10 @@ In the default configuration, the
.I strict
flag is disabled.
.TP
+.BI hash_seed= UUID
+Use the specified UUID as the seed for hashing, rather than generating a
+random seed each time. Intended for use with reproducible builds.
+.TP
.B lazy_itable_init\fR[\fB= \fI<0 to disable, 1 to enable>\fR]
If enabled and the uninit_bg feature is enabled, the inode table will
not be fully initialized by
diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index 7f81a513..3a8ff5b1 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -1180,6 +1180,7 @@ static void parse_extended_opts(struct ext2_super_block *param,
"\trevision=<revision>\n"
"\tencoding=<encoding>\n"
"\tencoding_flags=<flags>\n"
+ "\thash_seed=<UUID for hash seed>\n"
"\tquotatype=<quota type(s) to be enabled>\n"
"\tassume_storage_prezeroed=<0 to disable, 1 to enable>\n\n"),
badopt ? badopt : "");
--
2.45.2.121.gc2b3f2b3cd
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH RFC 2/3] mke2fs.c: fail on multiple '-E' options
2025-09-09 15:40 [PATCH RFC 0/3] mke2fs: small doc and features Ralph Siemsen
2025-09-09 15:40 ` [PATCH RFC 1/3] mke2fs: document the hash_seed option Ralph Siemsen
@ 2025-09-09 15:40 ` Ralph Siemsen
2025-09-10 0:32 ` Andreas Dilger
2025-09-09 15:40 ` [PATCH RFC 3/3] mke2fs: add root_selinux option for root inode label Ralph Siemsen
2 siblings, 1 reply; 12+ messages in thread
From: Ralph Siemsen @ 2025-09-09 15:40 UTC (permalink / raw)
To: linux-ext4; +Cc: Ralph Siemsen
Make it an error to pass multiple -E options. As per the man page,
multiple extended options must be specified as a comma-separated list,
instead of multiple -E options.
This helps avoid surprises, as the existing behaviour is to process
only the last -E option, and to silently ignore any earlier ones.
Signed-off-by: Ralph Siemsen <ralph.siemsen@linaro.org>
---
misc/mke2fs.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index 3a8ff5b1..59c7be17 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -1796,6 +1796,12 @@ profile_error:
_("'-R' is deprecated, use '-E' instead"));
/* fallthrough */
case 'E':
+ if (extended_opts) {
+ com_err(program_name, 0, "%s",
+ _("Multiple '-E' options are not supported, "
+ "use one comma-separated value instead"));
+ exit(1);
+ }
extended_opts = optarg;
break;
case 'e':
--
2.45.2.121.gc2b3f2b3cd
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH RFC 3/3] mke2fs: add root_selinux option for root inode label
2025-09-09 15:40 [PATCH RFC 0/3] mke2fs: small doc and features Ralph Siemsen
2025-09-09 15:40 ` [PATCH RFC 1/3] mke2fs: document the hash_seed option Ralph Siemsen
2025-09-09 15:40 ` [PATCH RFC 2/3] mke2fs.c: fail on multiple '-E' options Ralph Siemsen
@ 2025-09-09 15:40 ` Ralph Siemsen
2 siblings, 0 replies; 12+ messages in thread
From: Ralph Siemsen @ 2025-09-09 15:40 UTC (permalink / raw)
To: linux-ext4; +Cc: Ralph Siemsen
This option allows setting the SELinux security context (label) for the
root directory. A common value would be system_u:object_r:root_t
possibly with a level/range such as :s0 suffix (for MCS/MLS policy).
Signed-off-by: Ralph Siemsen <ralph.siemsen@linaro.org>
---
misc/mke2fs.8.in | 10 ++++++++
misc/mke2fs.c | 46 ++++++++++++++++++++++++++++++++++
tests/m_root_selinux/expect.1 | 57 +++++++++++++++++++++++++++++++++++++++++++
tests/m_root_selinux/script | 4 +++
4 files changed, 117 insertions(+)
diff --git a/misc/mke2fs.8.in b/misc/mke2fs.8.in
index 14bae326..6af71fd5 100644
--- a/misc/mke2fs.8.in
+++ b/misc/mke2fs.8.in
@@ -426,6 +426,16 @@ Specify the root directory permissions in octal format. If no permissions
are specified then the root directory permissions would be set in accordance with
the default filesystem umask.
.TP
+.BI root_selinux= label
+Specify the root directory SELinux security context as
+.IR label ,
+typically
+.nh
+.B system_u:object_r:root_t
+with an optional level/range suffix such as
+.B :s0
+for MCS/MLS policy types.
+.TP
.BI stride= stride-size
Configure the file system for a RAID array with
.I stride-size
diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index 59c7be17..a16a808a 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -95,6 +95,7 @@ static int num_backups = 2; /* number of backup bg's for sparse_super2 */
static uid_t root_uid;
static mode_t root_perms = (mode_t)-1;
static gid_t root_gid;
+static char *root_selinux = NULL;
int journal_size;
int journal_flags;
int journal_fc_size;
@@ -515,6 +516,35 @@ static void create_root_dir(ext2_filsys fs)
exit(1);
}
}
+
+ if (root_selinux) {
+ struct ext2_xattr_handle *handle;
+ retval = ext2fs_xattrs_open(fs, EXT2_ROOT_INO, &handle);
+ if (retval) {
+ com_err("ext2fs_xattrs_open", retval,
+ _("while setting root inode label"));
+ exit(1);
+ }
+ retval = ext2fs_xattrs_read(handle);
+ if (retval) {
+ com_err("ext2fs_xattrs_read", retval,
+ _("while setting root inode label"));
+ exit(1);
+ }
+ retval = ext2fs_xattr_set(handle, "security.selinux",
+ root_selinux, strlen(root_selinux));
+ if (retval) {
+ com_err("ext2fs_xattr_set", retval,
+ _("while setting root inode label"));
+ exit(1);
+ }
+ retval = ext2fs_xattrs_close(&handle);
+ if (retval) {
+ com_err("ext2fs_xattrs_close", retval,
+ _("while setting root inode label"));
+ exit(1);
+ }
+ }
}
static void create_lost_and_found(ext2_filsys fs)
@@ -1089,6 +1119,21 @@ static void parse_extended_opts(struct ext2_super_block *param,
if (arg) {
root_perms = strtoul(arg, &p, 8);
}
+ } else if (!strcmp(token, "root_selinux")) {
+ if (arg) {
+ root_selinux = realloc(root_selinux,
+ strlen(arg) + 1);
+ if (!root_selinux) {
+ com_err(program_name, ENOMEM, "%s",
+ _("in malloc for root_selinux"));
+ exit(1);
+ }
+ strcpy(root_selinux, arg);
+ } else {
+ r_usage++;
+ badopt = token;
+ continue;
+ }
} else if (!strcmp(token, "discard")) {
discard = 1;
} else if (!strcmp(token, "nodiscard")) {
@@ -1174,6 +1219,7 @@ static void parse_extended_opts(struct ext2_super_block *param,
"\tlazy_journal_init=<0 to disable, 1 to enable>\n"
"\troot_owner=<uid of root dir>:<gid of root dir>\n"
"\troot_perms=<octal root directory permissions>\n"
+ "\troot_selinux=<selinux root directory label>\n"
"\ttest_fs\n"
"\tdiscard\n"
"\tnodiscard\n"
diff --git a/tests/m_root_selinux/expect.1 b/tests/m_root_selinux/expect.1
new file mode 100644
index 00000000..19a3d6ee
--- /dev/null
+++ b/tests/m_root_selinux/expect.1
@@ -0,0 +1,57 @@
+Creating filesystem with 1024 1k blocks and 128 inodes
+
+Allocating group tables: \b\b\bdone
+Writing inode tables: \b\b\bdone
+Writing superblocks and filesystem accounting information: \b\b\bdone
+
+Filesystem features: ext_attr resize_inode dir_index filetype sparse_super
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 11/128 files (0.0% non-contiguous), 54/1024 blocks
+Exit status is 0
+Filesystem volume name: <none>
+Last mounted on: <not available>
+Filesystem magic number: 0xEF53
+Filesystem revision #: 1 (dynamic)
+Filesystem features: ext_attr resize_inode dir_index filetype sparse_super
+Default mount options: (none)
+Filesystem state: clean
+Errors behavior: Continue
+Filesystem OS type: Linux
+Inode count: 128
+Block count: 1024
+Reserved block count: 51
+Overhead clusters: 40
+Free blocks: 970
+Free inodes: 117
+First block: 1
+Block size: 1024
+Fragment size: 1024
+Reserved GDT blocks: 3
+Blocks per group: 8192
+Fragments per group: 8192
+Inodes per group: 128
+Inode blocks per group: 32
+Mount count: 0
+Check interval: 15552000 (6 months)
+Reserved blocks uid: 0
+Reserved blocks gid: 0
+First inode: 11
+Inode size: 256
+Required extra isize: 32
+Desired extra isize: 32
+Default directory hash: half_md4
+
+
+Group 0: (Blocks 1-1023)
+ Primary superblock at 1, Group descriptors at 2-2
+ Reserved GDT blocks at 3-5
+ Block bitmap at 6 (+5)
+ Inode bitmap at 7 (+6)
+ Inode table at 8-39 (+7)
+ 970 free blocks, 117 free inodes, 2 directories
+ Free blocks: 54-1023
+ Free inodes: 12-128
diff --git a/tests/m_root_selinux/script b/tests/m_root_selinux/script
new file mode 100644
index 00000000..4ac82918
--- /dev/null
+++ b/tests/m_root_selinux/script
@@ -0,0 +1,4 @@
+DESCRIPTION="root directory SELinux security context"
+FS_SIZE=1024
+MKE2FS_OPTS="-E root_selinux=system_u:object_r:root_t"
+. $cmd_dir/run_mke2fs
--
2.45.2.121.gc2b3f2b3cd
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH RFC 2/3] mke2fs.c: fail on multiple '-E' options
2025-09-09 15:40 ` [PATCH RFC 2/3] mke2fs.c: fail on multiple '-E' options Ralph Siemsen
@ 2025-09-10 0:32 ` Andreas Dilger
2025-09-10 0:49 ` Ralph Siemsen
0 siblings, 1 reply; 12+ messages in thread
From: Andreas Dilger @ 2025-09-10 0:32 UTC (permalink / raw)
To: Ralph Siemsen; +Cc: linux-ext4, Ralph Siemsen
Ralph,
I think it would be much better to allow and merge multiple "-E" options.
Cheers, Andreas
> On Sep 9, 2025, at 09:43, Ralph Siemsen <ralph.siemsen@linaro.org> wrote:
>
> Make it an error to pass multiple -E options. As per the man page,
> multiple extended options must be specified as a comma-separated list,
> instead of multiple -E options.
>
> This helps avoid surprises, as the existing behaviour is to process
> only the last -E option, and to silently ignore any earlier ones.
>
> Signed-off-by: Ralph Siemsen <ralph.siemsen@linaro.org>
> ---
> misc/mke2fs.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/misc/mke2fs.c b/misc/mke2fs.c
> index 3a8ff5b1..59c7be17 100644
> --- a/misc/mke2fs.c
> +++ b/misc/mke2fs.c
> @@ -1796,6 +1796,12 @@ profile_error:
> _("'-R' is deprecated, use '-E' instead"));
> /* fallthrough */
> case 'E':
> + if (extended_opts) {
> + com_err(program_name, 0, "%s",
> + _("Multiple '-E' options are not supported, "
> + "use one comma-separated value instead"));
> + exit(1);
> + }
> extended_opts = optarg;
> break;
> case 'e':
>
> --
> 2.45.2.121.gc2b3f2b3cd
>
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH RFC 2/3] mke2fs.c: fail on multiple '-E' options
2025-09-10 0:32 ` Andreas Dilger
@ 2025-09-10 0:49 ` Ralph Siemsen
2025-09-10 14:52 ` Theodore Ts'o
0 siblings, 1 reply; 12+ messages in thread
From: Ralph Siemsen @ 2025-09-10 0:49 UTC (permalink / raw)
To: Andreas Dilger; +Cc: linux-ext4
Hi Andreas,
On Tue, Sep 9, 2025 at 8:32 PM Andreas Dilger <adilger@dilger.ca> wrote:
>
> I think it would be much better to allow and merge multiple "-E" options.
Agreed. I'll work on it and post a v2 patch.
Thanks for your feedback,
Ralph
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH RFC 2/3] mke2fs.c: fail on multiple '-E' options
2025-09-10 0:49 ` Ralph Siemsen
@ 2025-09-10 14:52 ` Theodore Ts'o
2025-09-10 15:00 ` Theodore Ts'o
2025-09-10 16:29 ` Ralph Siemsen
0 siblings, 2 replies; 12+ messages in thread
From: Theodore Ts'o @ 2025-09-10 14:52 UTC (permalink / raw)
To: Ralph Siemsen; +Cc: Andreas Dilger, linux-ext4
On Tue, Sep 09, 2025 at 08:49:37PM -0400, Ralph Siemsen wrote:
> Hi Andreas,
>
> On Tue, Sep 9, 2025 at 8:32 PM Andreas Dilger <adilger@dilger.ca> wrote:
> >
> > I think it would be much better to allow and merge multiple "-E" options.
>
> Agreed. I'll work on it and post a v2 patch.
What I would suggest that you do is to move code which mutates the
file system from parse_extended_opts() so it is only interpreting the
options, and move that code to tuine2fs_main().
That way we can call parse_extended_opts() multiple times. In fact,
that had been on my todo list, since I need to do this to support
changing the superblock using ioctl's while it is mounted, so we can
deny read/write access to the block device while the file system is
mounted. See [1].
[1] https://lore.kernel.org/all/20250908-tune2fs-v1-0-e3a6929f3355@mit.edu/
Cheers,
- Ted
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH RFC 2/3] mke2fs.c: fail on multiple '-E' options
2025-09-10 14:52 ` Theodore Ts'o
@ 2025-09-10 15:00 ` Theodore Ts'o
2025-09-10 16:29 ` Ralph Siemsen
1 sibling, 0 replies; 12+ messages in thread
From: Theodore Ts'o @ 2025-09-10 15:00 UTC (permalink / raw)
To: Ralph Siemsen; +Cc: Andreas Dilger, linux-ext4
[-- Attachment #1: Type: text/plain, Size: 1096 bytes --]
On Wed, Sep 10, 2025 at 10:52:41AM -0400, Theodore Ts'o wrote:
> What I would suggest that you do is to move code which mutates the
> file system from parse_extended_opts() so it is only interpreting the
> options, and move that code to tuine2fs_main().
>
> That way we can call parse_extended_opts() multiple times. In fact,
> that had been on my todo list, since I need to do this to support
> changing the superblock using ioctl's while it is mounted, so we can
> deny read/write access to the block device while the file system is
> mounted. See [1].
>
> [1] https://lore.kernel.org/all/20250908-tune2fs-v1-0-e3a6929f3355@mit.edu/
In fact, if you want to see the direction which I'm headed, here is a
purely in-progress patch set for tune2fs. The first patch is
incomplete because it doesn't handle parse_extended_opts() yet.
Since I want to have two code paths for setting the file system
parameters (one when the file system is mounted, one when it is
unmounted), it's why I want to separate out the functionality in
parse_extended_opts().
- Ted
[-- Attachment #2: 0001-tune2fs-reorganize-command-line-flag-handling.patch --]
[-- Type: text/x-diff, Size: 16794 bytes --]
From 198cba8bec884bbd51901ceae45fc4384acb113c Mon Sep 17 00:00:00 2001
From: Theodore Ts'o <tytso@mit.edu>
Date: Mon, 8 Sep 2025 14:16:32 -0400
Subject: [PATCH 1/2] tune2fs: reorganize command-line flag handling
Instead of using individual ad-hoc variables indicating whether a
particular superblock value has been requested to be changed (e.g.,
c_flag, C_flag, et.al) use an array of booleans with indexes that are
defined with more human-readable #define's (e.g., OPT_MAX_MOUNTCOUNT).
There should be no behavioral changes from this code restructuring.
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
---
misc/tune2fs.c | 206 +++++++++++++++++++++++++++----------------------
1 file changed, 114 insertions(+), 92 deletions(-)
diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index 3db57632..b4c63da4 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -103,13 +103,34 @@ struct fsuuid {
extern int ask_yn(const char *string, int def);
+#define OPT_MAX_MOUNTCOUNT 1
+#define OPT_MOUNTCOUNT 2
+#define OPT_CHECKINTERVAL 3
+#define OPT_CHECKTIME 4
+#define OPT_ERROR_BEHAVIOR 5
+#define OPT_RESUID 6
+#define OPT_RESGID 7
+#define OPT_RESERVED_BLOCKS 8
+#define OPT_RESERVED_RATIO 9
+#define OPT_INODE_SIZE 10
+#define OPT_LABEL 11
+#define OPT_UUID 12
+#define OPT_LAST_MOUNTED 13
+#define OPT_SPARSE_SUPER 14
+#define OPT_QUOTA 15
+#define OPT_JOURNAL_SIZE 16
+#define OPT_JOURNAL_OPTS 17
+#define OPT_MNTOPTS 18
+#define OPT_FEATURES 19
+#define OPT_EXTENDED_CMD 20
+#define MAX_OPTS 21
+static bool opts[MAX_OPTS];
+
const char *program_name = "tune2fs";
char *device_name;
char *new_label, *new_last_mounted, *requested_uuid;
char *io_options;
-static int c_flag, C_flag, e_flag, f_flag, g_flag, i_flag, l_flag, L_flag;
-static int m_flag, M_flag, Q_flag, r_flag, s_flag = -1, u_flag, U_flag, T_flag;
-static int I_flag;
+static int force, do_list_super, sparse_value = -1;
static int clear_mmp;
static time_t last_check_time;
static int print_label;
@@ -237,6 +258,19 @@ static __u32 clear_ok_features[3] = {
EXT4_FEATURE_RO_COMPAT_READONLY
};
+/**
+ * Return true if there is at least one superblock change requested
+ */
+static bool tune_opts_requested()
+{
+ int i;
+
+ for (i = 0; i < MAX_OPTS; i++)
+ if (opts[i])
+ return true;
+ return false;
+}
+
/**
* Try to get journal super block if any
*/
@@ -293,7 +327,7 @@ static int remove_journal_device(ext2_filsys fs)
int commit_remove_journal = 0;
io_manager io_ptr;
- if (f_flag)
+ if (force)
commit_remove_journal = 1; /* force removal even if error */
uuid_unparse(fs->super->s_journal_uuid, buf);
@@ -1204,7 +1238,7 @@ static int update_feature_set(ext2_filsys fs, char *features)
return 1;
}
if (ext2fs_has_feature_journal_needs_recovery(sb) &&
- f_flag < 2) {
+ force < 2) {
fputs(_("The needs_recovery flag is set. "
"Please run e2fsck before clearing\n"
"the has_journal flag.\n"), stderr);
@@ -1228,7 +1262,7 @@ static int update_feature_set(ext2_filsys fs, char *features)
"when the filesystem is unmounted.\n"), stderr);
return 1;
}
- if (ext2fs_has_feature_orphan_present(sb) && f_flag < 2) {
+ if (ext2fs_has_feature_orphan_present(sb) && force < 2) {
fputs(_("The orphan_present feature is set. Please "
"run e2fsck before clearing orphan_file "
"feature.\n"),
@@ -1551,8 +1585,8 @@ mmp_error:
* Set the Q_flag here and handle the quota options in the code
* below.
*/
- if (!Q_flag) {
- Q_flag = 1;
+ if (!opts[OPT_QUOTA]) {
+ opts[OPT_QUOTA] = 1;
/* Enable usr/grp quota by default */
for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
if (qtype != PRJQUOTA)
@@ -1571,26 +1605,26 @@ mmp_error:
"inode size too small.\n"));
return 1;
}
- Q_flag = 1;
+ opts[OPT_QUOTA] = true;
quota_enable[PRJQUOTA] = QOPT_ENABLE;
}
if (FEATURE_OFF(E2P_FEATURE_RO_INCOMPAT,
EXT4_FEATURE_RO_COMPAT_PROJECT)) {
- Q_flag = 1;
+ opts[OPT_QUOTA] = true;
quota_enable[PRJQUOTA] = QOPT_DISABLE;
}
if (FEATURE_OFF(E2P_FEATURE_RO_INCOMPAT,
EXT4_FEATURE_RO_COMPAT_QUOTA)) {
/*
- * Set the Q_flag here and handle the quota options in the code
- * below.
+ * Set the quota flag here and handle the quota
+ * options in the code below.
*/
- if (Q_flag)
+ if (opts[OPT_QUOTA])
fputs(_("\nWarning: '^quota' option overrides '-Q'"
"arguments.\n"), stderr);
- Q_flag = 1;
+ opts[OPT_QUOTA] = true;
/* Disable all quota by default */
for (qtype = 0; qtype < MAXQUOTAS; qtype++)
quota_enable[qtype] = QOPT_DISABLE;
@@ -1940,7 +1974,7 @@ static void parse_e2label_options(int argc, char ** argv)
open_flag = EXT2_FLAG_JOURNAL_DEV_OK | EXT2_FLAG_SUPER_ONLY;
if (argc == 3) {
open_flag |= EXT2_FLAG_RW;
- L_flag = 1;
+ opts[OPT_LABEL] = true;
new_label = argv[2];
} else
print_label++;
@@ -1990,8 +2024,7 @@ static void parse_tune2fs_options(int argc, char **argv)
while ((c = getopt(argc, argv, optstring)) != EOF)
switch (c) {
case 'c':
- open_flag = EXT2_FLAG_RW;
- c_flag = 1;
+ opts[OPT_MAX_MOUNTCOUNT] = true;
if (strcmp(optarg, "random") == 0) {
max_mount_count = 65536;
break;
@@ -2008,6 +2041,7 @@ static void parse_tune2fs_options(int argc, char **argv)
max_mount_count = -1;
break;
case 'C':
+ opts[OPT_MOUNTCOUNT] = true;
mount_count = strtoul(optarg, &tmp, 0);
if (*tmp || mount_count > 16000) {
com_err(program_name, 0,
@@ -2015,10 +2049,9 @@ static void parse_tune2fs_options(int argc, char **argv)
optarg);
usage();
}
- C_flag = 1;
- open_flag = EXT2_FLAG_RW;
break;
case 'e':
+ opts[OPT_ERROR_BEHAVIOR] = true;
if (strcmp(optarg, "continue") == 0)
errors = EXT2_ERRORS_CONTINUE;
else if (strcmp(optarg, "remount-ro") == 0)
@@ -2031,17 +2064,16 @@ static void parse_tune2fs_options(int argc, char **argv)
optarg);
usage();
}
- e_flag = 1;
- open_flag = EXT2_FLAG_RW;
break;
case 'E':
+ opts[OPT_EXTENDED_CMD] = true;
extended_cmd = optarg;
- open_flag |= EXT2_FLAG_RW;
break;
case 'f': /* Force */
- f_flag++;
+ force++;
break;
case 'g':
+ opts[OPT_RESGID] = true;
resgid = strtoul(optarg, &tmp, 0);
if (*tmp) {
gr = getgrnam(optarg);
@@ -2058,10 +2090,9 @@ static void parse_tune2fs_options(int argc, char **argv)
optarg);
usage();
}
- g_flag = 1;
- open_flag = EXT2_FLAG_RW;
break;
case 'i':
+ opts[OPT_CHECKINTERVAL] = 1;
interval = strtoul(optarg, &tmp, 0);
switch (*tmp) {
case 's':
@@ -2090,28 +2121,25 @@ static void parse_tune2fs_options(int argc, char **argv)
_("bad interval - %s"), optarg);
usage();
}
- i_flag = 1;
- open_flag = EXT2_FLAG_RW;
break;
case 'j':
+ opts[OPT_JOURNAL_SIZE] = true;
if (!journal_size)
journal_size = -1;
- open_flag = EXT2_FLAG_RW;
break;
case 'J':
+ opts[OPT_JOURNAL_OPTS] = true;
parse_journal_opts(optarg);
- open_flag = EXT2_FLAG_RW;
break;
case 'l':
- l_flag = 1;
+ do_list_super = 1;
break;
case 'L':
+ opts[OPT_LABEL] = true;
new_label = optarg;
- L_flag = 1;
- open_flag |= EXT2_FLAG_RW |
- EXT2_FLAG_JOURNAL_DEV_OK;
break;
case 'm':
+ opts[OPT_RESERVED_RATIO] = true;
reserved_ratio = strtod(optarg, &tmp);
if (*tmp || reserved_ratio > 50 ||
reserved_ratio < 0) {
@@ -2120,40 +2148,37 @@ static void parse_tune2fs_options(int argc, char **argv)
optarg);
usage();
}
- m_flag = 1;
- open_flag = EXT2_FLAG_RW;
break;
case 'M':
+ opts[OPT_LAST_MOUNTED] = true;
new_last_mounted = optarg;
- M_flag = 1;
- open_flag = EXT2_FLAG_RW;
break;
case 'o':
+ opts[OPT_MNTOPTS] = true;
if (mntopts_cmd) {
com_err(program_name, 0, "%s",
_("-o may only be specified once"));
usage();
}
mntopts_cmd = optarg;
- open_flag = EXT2_FLAG_RW;
break;
case 'O':
+ opts[OPT_FEATURES] = true;
if (features_cmd) {
com_err(program_name, 0, "%s",
_("-O may only be specified once"));
usage();
}
features_cmd = optarg;
- open_flag = EXT2_FLAG_RW;
break;
case 'Q':
- Q_flag = 1;
+ opts[OPT_QUOTA] = true;
ret = parse_quota_opts(optarg, option_handle_function);
if (ret)
exit(1);
- open_flag = EXT2_FLAG_RW;
break;
case 'r':
+ opts[OPT_RESERVED_BLOCKS] = true;
reserved_blocks = strtoul(optarg, &tmp, 0);
if (*tmp) {
com_err(program_name, 0,
@@ -2161,45 +2186,39 @@ static void parse_tune2fs_options(int argc, char **argv)
optarg);
usage();
}
- r_flag = 1;
- open_flag = EXT2_FLAG_RW;
break;
case 's': /* Deprecated */
- s_flag = atoi(optarg);
- open_flag = EXT2_FLAG_RW;
+ opts[OPT_SPARSE_SUPER] = true;
+ sparse_value = atoi(optarg);
break;
case 'T':
- T_flag = 1;
+ opts[OPT_CHECKTIME] = true;
last_check_time = parse_time(optarg);
- open_flag = EXT2_FLAG_RW;
break;
case 'u':
- resuid = strtoul(optarg, &tmp, 0);
- if (*tmp) {
- pw = getpwnam(optarg);
- if (pw == NULL)
- tmp = optarg;
- else {
- resuid = pw->pw_uid;
- *tmp = 0;
- }
+ opts[OPT_RESUID] = true;
+ resuid = strtoul(optarg, &tmp, 0);
+ if (*tmp) {
+ pw = getpwnam(optarg);
+ if (pw == NULL)
+ tmp = optarg;
+ else {
+ resuid = pw->pw_uid;
+ *tmp = 0;
}
- if (*tmp) {
- com_err(program_name, 0,
- _("bad uid/user name - %s"),
- optarg);
+ }
+ if (*tmp) {
+ com_err(program_name, 0,
+ _("bad uid/user name - %s"), optarg);
usage();
- }
- u_flag = 1;
- open_flag = EXT2_FLAG_RW;
- break;
+ }
+ break;
case 'U':
+ opts[OPT_UUID] = true;
requested_uuid = optarg;
- U_flag = 1;
- open_flag = EXT2_FLAG_RW |
- EXT2_FLAG_JOURNAL_DEV_OK;
break;
case 'I':
+ opts[OPT_INODE_SIZE] = true;
new_inode_size = strtoul(optarg, &tmp, 0);
if (*tmp) {
com_err(program_name, 0,
@@ -2215,8 +2234,6 @@ static void parse_tune2fs_options(int argc, char **argv)
optarg);
usage();
}
- open_flag = EXT2_FLAG_RW;
- I_flag = 1;
break;
case 'z':
undo_file = optarg;
@@ -2226,8 +2243,13 @@ static void parse_tune2fs_options(int argc, char **argv)
}
if (optind < argc - 1 || optind == argc)
usage();
- if (!open_flag && !l_flag)
+ if (tune_opts_requested()) {
+ open_flag = EXT2_FLAG_RW;
+ if (opts[OPT_LABEL] || opts[OPT_UUID])
+ open_flag |= EXT2_FLAG_JOURNAL_DEV_OK;
+ } else {
usage();
+ }
io_options = strchr(argv[optind], '?');
if (io_options)
*io_options++ = 0;
@@ -3221,8 +3243,8 @@ int tune2fs_main(int argc, char **argv)
* Try the get/set fs label using ioctls before we even attempt
* to open the file system.
*/
- if (L_flag || print_label) {
- rc = handle_fslabel(L_flag);
+ if (opts[OPT_LABEL] || print_label) {
+ rc = handle_fslabel(opts[OPT_LABEL]);
if (rc != -1) {
#ifndef BUILD_AS_LIB
exit(rc);
@@ -3233,7 +3255,7 @@ int tune2fs_main(int argc, char **argv)
}
retry_open:
- if ((open_flag & EXT2_FLAG_RW) == 0 || f_flag)
+ if ((open_flag & EXT2_FLAG_RW) == 0 || force)
open_flag |= EXT2_FLAG_SKIP_MMP;
open_flag |= EXT2_FLAG_64BITS | EXT2_FLAG_THREADS |
@@ -3276,7 +3298,7 @@ retry_open:
}
fs->default_bitmap_type = EXT2FS_BMAP64_RBTREE;
- if (I_flag) {
+ if (opts[OPT_INODE_SIZE]) {
/*
* Check the inode size is right so we can issue an
* error message and bail before setting up the tdb
@@ -3378,7 +3400,7 @@ _("Warning: The journal is dirty. You may wish to replay the journal like:\n\n"
/* Normally we only need to write out the superblock */
fs->flags |= EXT2_FLAG_SUPER_ONLY;
- if (c_flag) {
+ if (opts[OPT_MAX_MOUNTCOUNT]) {
if (max_mount_count == 65536)
max_mount_count = EXT2_DFL_MAX_MNT_COUNT +
(random() % EXT2_DFL_MAX_MNT_COUNT);
@@ -3387,17 +3409,17 @@ _("Warning: The journal is dirty. You may wish to replay the journal like:\n\n"
printf(_("Setting maximal mount count to %d\n"),
max_mount_count);
}
- if (C_flag) {
+ if (opts[OPT_MOUNTCOUNT]) {
sb->s_mnt_count = mount_count;
ext2fs_mark_super_dirty(fs);
printf(_("Setting current mount count to %d\n"), mount_count);
}
- if (e_flag) {
+ if (opts[OPT_ERROR_BEHAVIOR]) {
sb->s_errors = errors;
ext2fs_mark_super_dirty(fs);
printf(_("Setting error behavior to %d\n"), errors);
}
- if (g_flag) {
+ if (opts[OPT_RESGID]) {
if (sb->s_def_resgid != resgid) {
sb->s_def_resgid = resgid;
ext2fs_mark_super_dirty(fs);
@@ -3406,7 +3428,7 @@ _("Warning: The journal is dirty. You may wish to replay the journal like:\n\n"
printf(_("Reserved blocks gid already set to %lu\n"), resgid);
}
}
- if (i_flag) {
+ if (opts[OPT_CHECKINTERVAL]) {
if ((unsigned long long)interval >= (1ULL << 32)) {
com_err(program_name, 0,
_("interval between checks is too big (%lu)"),
@@ -3419,7 +3441,7 @@ _("Warning: The journal is dirty. You may wish to replay the journal like:\n\n"
printf(_("Setting interval between checks to %lu seconds\n"),
interval);
}
- if (m_flag) {
+ if (opts[OPT_RESERVED_RATIO]) {
ext2fs_r_blocks_count_set(sb, reserved_ratio *
ext2fs_blocks_count(sb) / 100.0);
ext2fs_mark_super_dirty(fs);
@@ -3427,7 +3449,7 @@ _("Warning: The journal is dirty. You may wish to replay the journal like:\n\n"
reserved_ratio,
(unsigned long long) ext2fs_r_blocks_count(sb));
}
- if (r_flag) {
+ if (opts[OPT_RESERVED_BLOCKS]) {
if (reserved_blocks > ext2fs_blocks_count(sb)/2) {
com_err(program_name, 0,
_("reserved blocks count is too big (%llu)"),
@@ -3440,7 +3462,7 @@ _("Warning: The journal is dirty. You may wish to replay the journal like:\n\n"
printf(_("Setting reserved blocks count to %llu\n"),
(unsigned long long) reserved_blocks);
}
- if (s_flag == 1) {
+ if (sparse_value == 1) {
if (ext2fs_has_feature_sparse_super(sb)) {
fputs(_("\nThe filesystem already has sparse "
"superblocks.\n"), stderr);
@@ -3459,24 +3481,24 @@ _("Warning: The journal is dirty. You may wish to replay the journal like:\n\n"
_(please_fsck));
}
}
- if (s_flag == 0) {
+ if (sparse_value == 0) {
fputs(_("\nClearing the sparse superblock flag not supported.\n"),
stderr);
rc = 1;
goto closefs;
}
- if (T_flag) {
+ if (opts[OPT_CHECKTIME]) {
ext2fs_set_tstamp(sb, s_lastcheck, last_check_time);
ext2fs_mark_super_dirty(fs);
printf(_("Setting time filesystem last checked to %s\n"),
ctime(&last_check_time));
}
- if (u_flag) {
+ if (opts[OPT_RESUID]) {
sb->s_def_resuid = resuid;
ext2fs_mark_super_dirty(fs);
printf(_("Setting reserved blocks uid to %lu\n"), resuid);
}
- if (L_flag) {
+ if (opts[OPT_LABEL]) {
if (strlen(new_label) > sizeof(sb->s_volume_name))
fputs(_("Warning: label too long, truncating.\n"),
stderr);
@@ -3485,7 +3507,7 @@ _("Warning: The journal is dirty. You may wish to replay the journal like:\n\n"
sizeof(sb->s_volume_name));
ext2fs_mark_super_dirty(fs);
}
- if (M_flag) {
+ if (opts[OPT_LAST_MOUNTED]) {
memset(sb->s_last_mounted, 0, sizeof(sb->s_last_mounted));
strncpy((char *)sb->s_last_mounted, new_last_mounted,
sizeof(sb->s_last_mounted));
@@ -3505,7 +3527,7 @@ _("Warning: The journal is dirty. You may wish to replay the journal like:\n\n"
rc = parse_extended_opts(fs, extended_cmd);
if (rc)
goto closefs;
- if (clear_mmp && !f_flag) {
+ if (clear_mmp && !force) {
fputs(_("Error in using clear_mmp. "
"It must be used with -f\n"),
stderr);
@@ -3541,7 +3563,7 @@ _("Warning: The journal is dirty. You may wish to replay the journal like:\n\n"
}
}
- if (Q_flag) {
+ if (opts[OPT_QUOTA]) {
if (mount_flags & (EXT2_MF_BUSY | EXT2_MF_MOUNTED)) {
fputs(_("The quota feature may only be changed when "
"the filesystem is unmounted and not in use.\n"), stderr);
@@ -3553,7 +3575,7 @@ _("Warning: The journal is dirty. You may wish to replay the journal like:\n\n"
goto closefs;
}
- if (U_flag) {
+ if (opts[OPT_UUID]) {
int set_csum = 0;
dgrp_t i;
char buf[SUPERBLOCK_SIZE] __attribute__ ((aligned(8)));
@@ -3694,7 +3716,7 @@ _("Warning: The journal is dirty. You may wish to replay the journal like:\n\n"
}
}
- if (I_flag) {
+ if (opts[OPT_INODE_SIZE]) {
if (mount_flags & (EXT2_MF_BUSY | EXT2_MF_MOUNTED)) {
fputs(_("The inode size may only be "
"changed when the filesystem is "
@@ -3740,7 +3762,7 @@ _("Warning: The journal is dirty. You may wish to replay the journal like:\n\n"
}
}
- if (l_flag)
+ if (do_list_super)
list_super(sb);
if (stride_set) {
sb->s_raid_stride = stride;
--
2.51.0
[-- Attachment #3: 0002-DO-NOT-SUBMIT-tune2fs-initial-support-for-EXT4_IOC_G.patch --]
[-- Type: text/x-diff, Size: 8042 bytes --]
From b3ad517ba41f8dc2129564ecfefcac45062076d5 Mon Sep 17 00:00:00 2001
From: Theodore Ts'o <tytso@mit.edu>
Date: Wed, 10 Sep 2025 10:56:37 -0400
Subject: [PATCH 2/2] DO NOT SUBMIT: tune2fs: initial support for
EXT4_IOC_GET_TUNE_SB_PARAM
Not-Signed-off-by: Theodore Ts'o <tytso@mit.edu>
---
misc/tune2fs.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 188 insertions(+), 10 deletions(-)
diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index b4c63da4..b76fba8c 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -101,6 +101,59 @@ struct fsuuid {
#define EXT4_IOC_SETFSUUID _IOW('f', 44, struct fsuuid)
#endif
+#if (!defined(EXT4_IOC_GET_TUNE_SB_PARAM) && defined(__linux__))
+
+struct ext4_tune_sb_params {
+ __u32 set_flags;
+ __u32 checkinterval;
+ __u16 errors_behavior;
+ __u16 mnt_count;
+ __u16 max_mnt_count;
+ __u16 raid_stride;
+ __u64 last_check_time;
+ __u64 reserved_blocks;
+ __u64 blocks_count;
+ __u32 default_mnt_opts;
+ __u32 reserved_uid;
+ __u32 reserved_gid;
+ __u32 raid_stripe_width;
+ __u8 def_hash_alg;
+ __u8 pad_1;
+ __u16 pad_2;
+ __u32 feature_compat;
+ __u32 feature_incompat;
+ __u32 feature_ro_compat;
+ __u32 set_feature_compat_mask;
+ __u32 set_feature_incompat_mask;
+ __u32 set_feature_ro_compat_mask;
+ __u32 clear_feature_compat_mask;
+ __u32 clear_feature_incompat_mask;
+ __u32 clear_feature_ro_compat_mask;
+ __u8 mount_opts[64];
+ __u8 pad[64];
+};
+
+#define EXT4_TUNE_FL_ERRORS_BEHAVIOR 0x00000001
+#define EXT4_TUNE_FL_MNT_COUNT 0x00000002
+#define EXT4_TUNE_FL_MAX_MNT_COUNT 0x00000004
+#define EXT4_TUNE_FL_CHECKINTRVAL 0x00000008
+#define EXT4_TUNE_FL_LAST_CHECK_TIME 0x00000010
+#define EXT4_TUNE_FL_RESERVED_BLOCKS 0x00000020
+#define EXT4_TUNE_FL_RESERVED_UID 0x00000040
+#define EXT4_TUNE_FL_RESERVED_GID 0x00000080
+#define EXT4_TUNE_FL_DEFAULT_MNT_OPTS 0x00000100
+#define EXT4_TUNE_FL_DEF_HASH_ALG 0x00000200
+#define EXT4_TUNE_FL_RAID_STRIDE 0x00000400
+#define EXT4_TUNE_FL_RAID_STRIPE_WIDTH 0x00000800
+#define EXT4_TUNE_FL_MOUNT_OPTS 0x00001000
+#define EXT4_TUNE_FL_FEATURES 0x00002000
+#define EXT4_TUNE_FL_EDIT_FEATURES 0x00002000
+
+#define EXT4_IOC_GET_TUNE_SB_PARAM _IOR('f', 45, struct ext4_tune_sb_params)
+#define EXT4_IOC_SET_TUNE_SB_PARAM _IOW('f', 46, struct ext4_tune_sb_params)
+
+#endif
+
extern int ask_yn(const char *string, int def);
#define OPT_MAX_MOUNTCOUNT 1
@@ -160,6 +213,10 @@ char *journal_device;
static blk64_t journal_location = ~0LL;
static e2_blkcnt_t orphan_file_blocks;
+static int fs_fd = -1;
+static int fs_mnt_flags = 0;
+static int fs_set_ops = 0;
+
static struct list_head blk_move_list;
struct blk_move {
@@ -2039,6 +2096,10 @@ static void parse_tune2fs_options(int argc, char **argv)
}
if (max_mount_count == 0)
max_mount_count = -1;
+ else if (max_mount_count == 65536) {
+ max_mount_count = EXT2_DFL_MAX_MNT_COUNT +
+ (random() % EXT2_DFL_MAX_MNT_COUNT);
+ }
break;
case 'C':
opts[OPT_MOUNTCOUNT] = true;
@@ -2121,6 +2182,12 @@ static void parse_tune2fs_options(int argc, char **argv)
_("bad interval - %s"), optarg);
usage();
}
+ if ((unsigned long long)interval >= (1ULL << 32)) {
+ com_err(program_name, 0,
+ _("interval between checks is too big (%lu)"),
+ interval);
+ exit(1);
+ }
break;
case 'j':
opts[OPT_JOURNAL_SIZE] = true;
@@ -3124,6 +3191,121 @@ fs_update_journal_user(struct ext2_super_block *sb, __u8 old_uuid[UUID_SIZE])
return 0;
}
+static void try_mounted_access()
+{
+#ifdef __linux__
+ errcode_t ret;
+ char mntpt[PATH_MAX + 1];
+ struct ext4_tune_sb_params params;
+ __u64 fs_blocks_count;
+ __u32 fs_feature_array[3];
+ int opts_success = 0;
+
+ fs_fd = -1;
+ fs_mnt_flags = 0;
+ ret = ext2fs_check_mount_point(device_name, &fs_mnt_flags,
+ mntpt, sizeof(
+ mntpt));
+ if (ret)
+ return;
+
+ if (!(fs_mnt_flags & EXT2_MF_MOUNTED))
+ return;
+
+ if (!mntpt[0])
+ return;
+
+ fs_fd = open(mntpt, O_RDONLY);
+ if (fs_fd < 0)
+ return;
+
+ if (ioctl(fs_fd, EXT4_IOC_GET_TUNE_SB_PARAM, ¶ms))
+ return;
+
+ fs_set_ops = params.set_flags;
+ fs_blocks_count = params.blocks_count;
+ fs_feature_array[0] = params.feature_compat;
+ fs_feature_array[1] = params.feature_incompat;
+ fs_feature_array[2] = params.feature_ro_compat;
+
+ memset(¶ms, 0, sizeof(params));
+
+ if (opts[OPT_ERROR_BEHAVIOR] &&
+ (fs_set_ops & EXT4_TUNE_FL_ERRORS_BEHAVIOR)) {
+ params.set_flags |= EXT4_TUNE_FL_ERRORS_BEHAVIOR;
+ params.errors_behavior = errors;
+ }
+ if (opts[OPT_MOUNTCOUNT] &&
+ (fs_set_ops & EXT4_TUNE_FL_MNT_COUNT)) {
+ params.set_flags |= EXT4_TUNE_FL_MNT_COUNT;
+ params.mnt_count = mount_count;
+ }
+ if (opts[OPT_MAX_MOUNTCOUNT] &&
+ (fs_set_ops & EXT4_TUNE_FL_MAX_MNT_COUNT)) {
+ params.set_flags |= EXT4_TUNE_FL_MAX_MNT_COUNT;
+ params.max_mnt_count = max_mount_count;
+ }
+ if (opts[OPT_CHECKINTERVAL] &&
+ (fs_set_ops & EXT4_TUNE_FL_CHECKINTRVAL)) {
+ params.set_flags |= EXT4_TUNE_FL_CHECKINTRVAL;
+ params.checkinterval = interval;
+ }
+ if (opts[OPT_CHECKTIME] &&
+ (fs_set_ops & EXT4_TUNE_FL_LAST_CHECK_TIME)) {
+ params.set_flags |= EXT4_TUNE_FL_LAST_CHECK_TIME;
+ params.last_check_time = last_check_time;
+ }
+ if (opts[OPT_RESUID] &&
+ (fs_set_ops & EXT4_TUNE_FL_RESERVED_UID)) {
+ params.set_flags |= EXT4_TUNE_FL_RESERVED_UID;
+ params.reserved_uid = resuid;
+ }
+ if (opts[OPT_RESGID] &&
+ (fs_set_ops & EXT4_TUNE_FL_RESERVED_GID)) {
+ params.set_flags |= EXT4_TUNE_FL_RESERVED_GID;
+ params.reserved_uid = resgid;
+ }
+ if (opts[OPT_RESERVED_RATIO) && !opts[OPT_RESERVED_BLOCKS]) {
+ reserved_blocks = reserved_ratio * fs_blocks_count / 100.0;
+ opts[OPT_RESERVED_BLOCKS] = true;
+ }
+ if (opts[OPT_RESERVED_BLOCKS] &&
+ (fs_set_ops & EXT4_TUNE_FL_RESERVED_BLOCKS)) {
+ params.set_flags |= EXT4_TUNE_FL_RESERVED_BLOCKS;
+ params.reserved_blocks = reserved_blocks;
+ }
+
+/* TODO:
+ * EXT4_TUNE_FL_DEFAULT_MNT_OPTS
+ * EXT4_TUNE_FL_DEF_HASH_ALG
+ * EXT4_TUNE_FL_RAID_STRIDE
+ * EXT4_TUNE_FL_RAID_STRIPE_WIDTH
+ * EXT4_TUNE_FL_MOUNT_OPTS
+ * EXT4_TUNE_FL_FEATURES
+ */
+
+ if (ioctl(fs_fd, EXT4_IOC_SET_TUNE_SB_PARAM, ¶ms) == 0) {
+ opts[OPT_ERROR_BEHAVIOR] = opts[OPT_MOUNTCOUNT] =
+ opts[OPT_MAX_MOUNTCOUNT] = opts[OPT_CHECKINTERVAL] =
+ opts[OPT_CHECKTIME] = opts[OPT_RESUID] =
+ opts[OPT_RESGID] = opts[OPT_RESERVED_RATIO] =
+ opts[OPT_RESERVED_BLOCKS] = false;
+ printf("ioctl EXT4_IOC_SET_TUNE_SB_PARAM succeeded\n");
+ } else {
+ perror("ioctl EXT4_IOC_SET_TUNE_SB_PARAM");
+ exit(1);
+ }
+ close(fs_fd);
+
+#else
+ fs_fd = -1;
+ fs_mnt_flags = 0;
+#endif
+ printf("fs_fd %d, mnt_flags %08x, set_ops %08x\n", fs_fd,
+ fs_mnt_flags, fs_set_ops);
+}
+
+
/*
* Use FS_IOC_SETFSLABEL or FS_IOC_GETFSLABEL to set/get file system label
* Return: 0 on success
@@ -3239,6 +3421,12 @@ int tune2fs_main(int argc, char **argv)
#endif
io_ptr = unix_io_manager;
+ try_mounted_access();
+ if (!tune_opts_requested()) {
+ printf("No further tune opts left\n");
+ exit(0);
+ }
+
/*
* Try the get/set fs label using ioctls before we even attempt
* to open the file system.
@@ -3401,9 +3589,6 @@ _("Warning: The journal is dirty. You may wish to replay the journal like:\n\n"
fs->flags |= EXT2_FLAG_SUPER_ONLY;
if (opts[OPT_MAX_MOUNTCOUNT]) {
- if (max_mount_count == 65536)
- max_mount_count = EXT2_DFL_MAX_MNT_COUNT +
- (random() % EXT2_DFL_MAX_MNT_COUNT);
sb->s_max_mnt_count = max_mount_count;
ext2fs_mark_super_dirty(fs);
printf(_("Setting maximal mount count to %d\n"),
@@ -3429,13 +3614,6 @@ _("Warning: The journal is dirty. You may wish to replay the journal like:\n\n"
}
}
if (opts[OPT_CHECKINTERVAL]) {
- if ((unsigned long long)interval >= (1ULL << 32)) {
- com_err(program_name, 0,
- _("interval between checks is too big (%lu)"),
- interval);
- rc = 1;
- goto closefs;
- }
sb->s_checkinterval = interval;
ext2fs_mark_super_dirty(fs);
printf(_("Setting interval between checks to %lu seconds\n"),
--
2.51.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH RFC 2/3] mke2fs.c: fail on multiple '-E' options
2025-09-10 14:52 ` Theodore Ts'o
2025-09-10 15:00 ` Theodore Ts'o
@ 2025-09-10 16:29 ` Ralph Siemsen
2025-09-10 20:45 ` Theodore Ts'o
1 sibling, 1 reply; 12+ messages in thread
From: Ralph Siemsen @ 2025-09-10 16:29 UTC (permalink / raw)
To: Theodore Ts'o; +Cc: Andreas Dilger, linux-ext4
Hi Ted,
On Wed, Sep 10, 2025 at 10:52 AM Theodore Ts'o <tytso@mit.edu> wrote:
> What I would suggest that you do is to move code which mutates the
> file system from parse_extended_opts() so it is only interpreting the
> options, and move that code to tuine2fs_main().
Yes, I see where you are going. Being able to deny read/write to a
block device that is mounted is a good goal.
But I am talking about mke2fs rather than tune2fs. I can't really see
a need for two code paths when creating a filesystem?
It would still make sense to separate the option parsing from the
mutation logic of course.
> That way we can call parse_extended_opts() multiple times.
Note this is already occurs in mke2fs: one call to process options
from profile/config file, and another call for command-line args.
So in v2 patch, I just made further calls, one for each -E argument.
So far it seems to work without problems.
Regards
-Ralph
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH RFC 2/3] mke2fs.c: fail on multiple '-E' options
2025-09-10 16:29 ` Ralph Siemsen
@ 2025-09-10 20:45 ` Theodore Ts'o
2025-09-10 21:31 ` Ralph Siemsen
0 siblings, 1 reply; 12+ messages in thread
From: Theodore Ts'o @ 2025-09-10 20:45 UTC (permalink / raw)
To: Ralph Siemsen; +Cc: Andreas Dilger, linux-ext4
On Wed, Sep 10, 2025 at 12:29:21PM -0400, Ralph Siemsen wrote:
> > That way we can call parse_extended_opts() multiple times.
>
> Note this is already occurs in mke2fs: one call to process options
> from profile/config file, and another call for command-line args.
Sorry, I've had tune2fs on the brain. Mke2fs is different from
tune2fs because there's only one path for configuring the newly create
file system --- and we have to process the command-line extended
options *after* processing the profile/config file options.
So in PRS, we need to save each of the -E arguments --- or concatenate
them together into a single set of extended options, and keep the call
site for parse_extended_options() them where it currently is located
- Ted
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH RFC 2/3] mke2fs.c: fail on multiple '-E' options
2025-09-10 20:45 ` Theodore Ts'o
@ 2025-09-10 21:31 ` Ralph Siemsen
2025-09-19 15:44 ` Ralph Siemsen
0 siblings, 1 reply; 12+ messages in thread
From: Ralph Siemsen @ 2025-09-10 21:31 UTC (permalink / raw)
To: Theodore Ts'o; +Cc: Andreas Dilger, linux-ext4
On Wed, Sep 10, 2025 at 4:45 PM Theodore Ts'o <tytso@mit.edu> wrote:
> So in PRS, we need to save each of the -E arguments --- or concatenate
> them together into a single set of extended options, and keep the call
> site for parse_extended_options() them where it currently is located
That what I am doing in patch v2:
https://lore.kernel.org/linux-ext4/20250910-mke2fs-small-fixes-v2-2-55c9842494e0@linaro.org/T/#u
It makes use of the already existing push_string() helper, to make
copies of each argument.
-Ralph
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH RFC 2/3] mke2fs.c: fail on multiple '-E' options
2025-09-10 21:31 ` Ralph Siemsen
@ 2025-09-19 15:44 ` Ralph Siemsen
0 siblings, 0 replies; 12+ messages in thread
From: Ralph Siemsen @ 2025-09-19 15:44 UTC (permalink / raw)
To: Theodore Ts'o; +Cc: Andreas Dilger, linux-ext4
Hi Andreas and Ted,
On Wed, Sep 10, 2025 at 5:31 PM Ralph Siemsen <ralph.siemsen@linaro.org> wrote:
> On Wed, Sep 10, 2025 at 4:45 PM Theodore Ts'o <tytso@mit.edu> wrote:
>
> > So in PRS, we need to save each of the -E arguments --- or concatenate
> > them together into a single set of extended options, and keep the call
> > site for parse_extended_options() them where it currently is located
>
> That what I am doing in patch v2:
> https://lore.kernel.org/linux-ext4/20250910-mke2fs-small-fixes-v2-2-55c9842494e0@linaro.org/T/#u
> It makes use of the already existing push_string() helper, to make
> copies of each argument.
Any feedback on the v2 patch series [1]? If you prefer another
approach (such as concatenating extended options) please let me know.
Also any comments regarding the other changes, particularly the
addition of root_selinux extended option?
[1] https://lore.kernel.org/linux-ext4/20250910-mke2fs-small-fixes-v2-0-55c9842494e0@linaro.org/
Thanks,
-Ralph
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2025-09-19 15:44 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-09 15:40 [PATCH RFC 0/3] mke2fs: small doc and features Ralph Siemsen
2025-09-09 15:40 ` [PATCH RFC 1/3] mke2fs: document the hash_seed option Ralph Siemsen
2025-09-09 15:40 ` [PATCH RFC 2/3] mke2fs.c: fail on multiple '-E' options Ralph Siemsen
2025-09-10 0:32 ` Andreas Dilger
2025-09-10 0:49 ` Ralph Siemsen
2025-09-10 14:52 ` Theodore Ts'o
2025-09-10 15:00 ` Theodore Ts'o
2025-09-10 16:29 ` Ralph Siemsen
2025-09-10 20:45 ` Theodore Ts'o
2025-09-10 21:31 ` Ralph Siemsen
2025-09-19 15:44 ` Ralph Siemsen
2025-09-09 15:40 ` [PATCH RFC 3/3] mke2fs: add root_selinux option for root inode label Ralph Siemsen
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.