* [RFC PATCH 0/1] Add default config file for mkfs.xfs
@ 2026-05-14 14:37 Lukas Herbolt
2026-05-14 14:37 ` [RFC PATCH 1/1] xfsprogs: mkfs.xfs add default configuration file Lukas Herbolt
2026-05-14 15:05 ` [RFC PATCH 0/1] Add default config file for mkfs.xfs Darrick J. Wong
0 siblings, 2 replies; 7+ messages in thread
From: Lukas Herbolt @ 2026-05-14 14:37 UTC (permalink / raw)
To: djwong, sandeen, aalbersh; +Cc: linux-xfs, Lukas Herbolt
Hi all,
The default values cannot always satisfy everybody and users/packagers should
be able to override defaults without the need of specifying configuration file
on command line. It was previously discussed in here [1].
The proposed patch adds /etc/mkfs.xfs.conf where the default values can be set.
It also lightly changes the default behavior for -l/-d/-r concurrency allowing
now to be set to -1 to keep autodetection on SSDs.
[1]
https://lore.kernel.org/linux-xfs/84c8a5e5-938d-4745-996d-4237009c9cc5@sandeen.net/
Lukas Herbolt (1):
xfsprogs: mkfs.xfs add default configuration file.
include/builddefs.in | 1 +
mkfs/Makefile | 3 ++
mkfs/mkfs.xfs.conf | 50 ++++++++++++++++++++++++++++++
mkfs/xfs_mkfs.c | 72 +++++++++++++++++++++++++++++++++++++++-----
4 files changed, 119 insertions(+), 7 deletions(-)
create mode 100644 mkfs/mkfs.xfs.conf
--
2.54.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [RFC PATCH 1/1] xfsprogs: mkfs.xfs add default configuration file.
2026-05-14 14:37 [RFC PATCH 0/1] Add default config file for mkfs.xfs Lukas Herbolt
@ 2026-05-14 14:37 ` Lukas Herbolt
2026-05-14 15:21 ` Carlos Maiolino
2026-05-14 16:27 ` Darrick J. Wong
2026-05-14 15:05 ` [RFC PATCH 0/1] Add default config file for mkfs.xfs Darrick J. Wong
1 sibling, 2 replies; 7+ messages in thread
From: Lukas Herbolt @ 2026-05-14 14:37 UTC (permalink / raw)
To: djwong, sandeen, aalbersh; +Cc: linux-xfs, Lukas Herbolt
Various users may prefer different default values. Having a default config
file will allow them to utilize it without the need specifying configuration
file on command line.
Signed-off-by: Lukas Herbolt <lukas@herbolt.com>
---
include/builddefs.in | 1 +
mkfs/Makefile | 3 ++
mkfs/mkfs.xfs.conf | 50 ++++++++++++++++++++++++++++++
mkfs/xfs_mkfs.c | 72 +++++++++++++++++++++++++++++++++++++++-----
4 files changed, 119 insertions(+), 7 deletions(-)
create mode 100644 mkfs/mkfs.xfs.conf
diff --git a/include/builddefs.in b/include/builddefs.in
index 3b52d1afd703..b635a7cd08a6 100644
--- a/include/builddefs.in
+++ b/include/builddefs.in
@@ -59,6 +59,7 @@ PKG_DOC_DIR = @datadir@/doc/@pkg_name@
PKG_LOCALE_DIR = @datadir@/locale
PKG_DATA_DIR = @datadir@/@pkg_name@
MKFS_CFG_DIR = @datadir@/@pkg_name@/mkfs
+MKFS_SYSCONF_DIR = @sysconfdir@
PKG_STATE_DIR = @localstatedir@/lib/@pkg_name@
XFS_SCRUB_ALL_AUTO_MEDIA_SCAN_STAMP=$(PKG_STATE_DIR)/xfs_scrub_all_media.stamp
diff --git a/mkfs/Makefile b/mkfs/Makefile
index fb1473324cde..57cee687eb1e 100644
--- a/mkfs/Makefile
+++ b/mkfs/Makefile
@@ -21,6 +21,7 @@ CFGFILES = \
lts_6.12.conf \
lts_6.18.conf
+LCFLAGS += -DMKFS_CFG_DIR=\"$(MKFS_CFG_DIR)\" -DMKFS_SYSCONF_DIR=\"$(MKFS_SYSCONF_DIR)\"
LLDLIBS += $(LIBXFS) $(LIBXCMD) $(LIBFROG) $(LIBRT) $(LIBBLKID) \
$(LIBUUID) $(LIBINIH) $(LIBURCU) $(LIBPTHREAD)
LTDEPENDENCIES += $(LIBXFS) $(LIBXCMD) $(LIBFROG)
@@ -45,6 +46,8 @@ install: default
$(INSTALL) -m 755 $(XFS_PROTOFILE) $(PKG_SBIN_DIR)/xfs_protofile
$(INSTALL) -m 755 -d $(MKFS_CFG_DIR)
$(INSTALL) -m 644 $(CFGFILES) $(MKFS_CFG_DIR)
+ $(INSTALL) -m 755 -d $(MKFS_SYSCONF_DIR)
+ $(INSTALL) -m 644 mkfs.xfs.conf $(MKFS_SYSCONF_DIR)
install-dev:
diff --git a/mkfs/mkfs.xfs.conf b/mkfs/mkfs.xfs.conf
new file mode 100644
index 000000000000..76f5ab4d4d8e
--- /dev/null
+++ b/mkfs/mkfs.xfs.conf
@@ -0,0 +1,50 @@
+# mkfs.xfs default configuration file
+#
+# This file documents some of the options recognised by mkfs.xfs config file.
+# Adjust any value to override it system-wide.
+#
+# Command-line options always take precedence over values in this file.
+# A specific config file can be selected with: mkfs.xfs -c options=<path>
+
+[block]
+#size = 4096
+
+[metadata]
+#crc = 1
+#finobt = 1
+#inobtcount = 1
+#rmapbt = 1
+#reflink = 1
+#bigtime = 1
+#metadir = 0
+#autofsck = 0
+
+[inode]
+#align = 1
+# The default value is 25% for filesystems under 1TB,#5% for filesystems under
+# 50TB and 1% for filesystems over 50TB.
+#
+#maxpct = 25
+#size = 512
+#perblock = 8
+#attr = 2
+#projid32bit = 1
+#sparse = 1
+#nrext64 = 1
+#exchange = 1
+
+[data]
+# -1 = autodetect (use CPU count only on solid-state devices), 0 = disabled
+#concurrency = -1
+
+[log]
+#internal = 1
+#version = 2
+#lazy-count = 1
+# -1 = autodetect (use CPU count only on solid-state devices), 0 = disabled
+#concurrency = -1
+
+[realtime]
+# -1 = autodetect (use CPU count only on solid-state devices), 0 = disabled
+#concurrency = -1
+
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index dd8a48c3633e..dbf15eca3442 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -44,6 +44,11 @@
*/
#define WHACK_SIZE (128 * 1024)
+/*
+ * Default configuration file which can keep distro specific values.
+ */
+#define MKFS_DEFAULT_CFGFILE MKFS_SYSCONF_DIR "/mkfs.xfs.conf"
+
/*
* XXX: The configured block and sector sizes are defined as global variables so
* that they don't need to be passed to getnum/cvtnum().
@@ -51,6 +56,11 @@
static unsigned int blocksize;
static unsigned int sectorsize;
+/*
+ * Set to true while parsing the config file so option handlers know the source
+ */
+static bool parsing_cfgfile;
+
/*
* Enums for each CLI parameter type are declared first so we can calculate the
* maximum array size needed to hold them automatically.
@@ -264,6 +274,7 @@ struct opt_params {
bool str_seen;
bool convert;
bool is_power_2;
+ bool from_file;
struct _conflict {
struct opt_params *opts;
int subopt;
@@ -472,7 +483,7 @@ static struct opt_params dopts = {
.conflicts = { { &dopts, D_AGCOUNT },
{ &dopts, D_AGSIZE },
{ NULL, LAST_CONFLICT } },
- .minval = 0,
+ .minval = -1,
.maxval = INT_MAX,
.defaultval = 1,
},
@@ -672,7 +683,7 @@ static struct opt_params lopts = {
{ &lopts, L_FILE },
{ &lopts, L_DEV },
{ NULL, LAST_CONFLICT } },
- .minval = 0,
+ .minval = -1,
.maxval = INT_MAX,
.defaultval = 1,
},
@@ -827,7 +838,7 @@ static struct opt_params ropts = {
{ &ropts, R_RGSIZE },
{ NULL, LAST_CONFLICT } },
.convert = true,
- .minval = 0,
+ .minval = -1,
.maxval = INT_MAX,
.defaultval = 1,
},
@@ -1072,6 +1083,7 @@ struct cli_params {
int blocksize;
char *cfgfile;
+ bool cfgfile_had_options;
char *protofile;
enum fsprop_autofsck autofsck;
@@ -1654,10 +1666,12 @@ check_opt(
if (sp->seen)
respec(opts->name, opts->subopts, index);
sp->seen = true;
+ sp->from_file = parsing_cfgfile;
} else {
if (sp->str_seen)
respec(opts->name, opts->subopts, index);
sp->str_seen = true;
+ sp->from_file = parsing_cfgfile;
}
/* check for conflicts with the option */
@@ -1806,6 +1820,7 @@ set_data_concurrency(
/*
* "nr_cpus" or "1" means set the concurrency level to the CPU count.
* If this cannot be determined, fall back to the default AG geometry.
+ * -1 means autodetect (use CPU count only on solid-state devices).
*/
if (!value || !strcmp(value, "nr_cpus"))
optnum = 1;
@@ -1814,6 +1829,8 @@ set_data_concurrency(
if (optnum == 1)
cli->data_concurrency = nr_cpus();
+ else if (optnum == -1)
+ cli->data_concurrency = -1;
else
cli->data_concurrency = optnum;
}
@@ -1954,6 +1971,7 @@ set_log_concurrency(
/*
* "nr_cpus" or 1 means set the concurrency level to the CPU count. If
* this cannot be determined, fall back to the default computation.
+ * -1 means autodetect (use CPU count only on solid-state devices).
*/
if (!value || !strcmp(value, "nr_cpus"))
optnum = 1;
@@ -1962,6 +1980,8 @@ set_log_concurrency(
if (optnum == 1)
cli->log_concurrency = nr_cpus();
+ else if (optnum == -1)
+ cli->log_concurrency = -1;
else
cli->log_concurrency = optnum;
}
@@ -2175,6 +2195,7 @@ set_rtvol_concurrency(
* "nr_cpus" or "1" means set the concurrency level to the CPU count.
* If this cannot be determined, fall back to the default rtgroup
* geometry.
+ * -1 means autodetect (use CPU count only on solid-state devices).
*/
if (!value || !strcmp(value, "nr_cpus"))
optnum = 1;
@@ -2183,6 +2204,8 @@ set_rtvol_concurrency(
if (optnum == 1)
cli->rtvol_concurrency = nr_cpus();
+ else if (optnum == -1)
+ cli->rtvol_concurrency = -1;
else
cli->rtvol_concurrency = optnum;
}
@@ -2336,9 +2359,32 @@ parse_cfgopt(
if (!subopts[i])
break;
if (strcasecmp(name, subopts[i]) == 0) {
+ struct subopt_param *sp = &sop->opts->subopt_params[i];
+ int j;
+
+ /*
+ * Command line options take precedence over config file
+ * options. If this option or any option that conflicts
+ * with it was already set from the command line, skip
+ * the config file value silently.
+ */
+ if ((sp->seen || sp->str_seen) && !sp->from_file)
+ return true;
+ for (j = 0; j < MAX_CONFLICTS; j++) {
+ struct _conflict *con = &sp->conflicts[j];
+ struct subopt_param *csp;
+
+ if (con->subopt == LAST_CONFLICT)
+ break;
+ csp = &con->opts->subopt_params[con->subopt];
+ if ((csp->seen || csp->str_seen) && !csp->from_file)
+ return true;
+ }
+
ret = (sop->parser)(sop->opts, i, value, cli);
if (ret)
goto invalid_opt;
+ cli->cfgfile_had_options = true;
return true;
}
}
@@ -5749,10 +5795,21 @@ cfgfile_parse(
{
int error;
- if (!cli->cfgfile)
- return;
+ bool default_cfgfile = !cli->cfgfile;
+
+ if (!cli->cfgfile) {
+ /*
+ * No config file specified on the command line. Use the default
+ * system-wide config file if it exists, otherwise do nothing.
+ */
+ if (access(MKFS_DEFAULT_CFGFILE, F_OK) != 0)
+ return;
+ cli->cfgfile = MKFS_DEFAULT_CFGFILE;
+ }
+ parsing_cfgfile = true;
error = ini_parse(cli->cfgfile, cfgfile_parse_ini, cli);
+ parsing_cfgfile = false;
if (error) {
if (error > 0) {
fprintf(stderr,
@@ -5773,8 +5830,9 @@ cfgfile_parse(
}
exit(1);
}
- printf(_("Parameters parsed from config file %s successfully\n"),
- cli->cfgfile);
+ if (!default_cfgfile || cli->cfgfile_had_options)
+ printf(_("Parameters parsed from config file %s successfully\n"),
+ cli->cfgfile);
}
static void
--
2.54.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [RFC PATCH 0/1] Add default config file for mkfs.xfs
2026-05-14 14:37 [RFC PATCH 0/1] Add default config file for mkfs.xfs Lukas Herbolt
2026-05-14 14:37 ` [RFC PATCH 1/1] xfsprogs: mkfs.xfs add default configuration file Lukas Herbolt
@ 2026-05-14 15:05 ` Darrick J. Wong
1 sibling, 0 replies; 7+ messages in thread
From: Darrick J. Wong @ 2026-05-14 15:05 UTC (permalink / raw)
To: Lukas Herbolt; +Cc: sandeen, aalbersh, linux-xfs, Theodore Ts'o
[add ted to cc]
On Thu, May 14, 2026 at 04:37:16PM +0200, Lukas Herbolt wrote:
> Hi all,
> The default values cannot always satisfy everybody and users/packagers
> should be able to override defaults without the need of specifying
> configuration file on command line. It was previously discussed in
> here [1].
Hmm. A long time ago Ted asked for a slghtly different alteration to
help him make running fstests easier. What he wanted iirc was a way to
install a set of default mkfs settings from a config file, but still
allow the settings to be overridden by cli arguments.
Apparently I never sent the patch because it doesn't exist in lore, so I
suppose I should send it now. ;)
> The proposed patch adds /etc/mkfs.xfs.conf where the default values
> can be set. It also lightly changes the default behavior for -l/-d/-r
> concurrency allowing now to be set to -1 to keep autodetection on
> SSDs.
I don't think I like magic negative numbers, but I'll save that for my
reply to the actual patch.
--D
> https://lore.kernel.org/linux-xfs/84c8a5e5-938d-4745-996d-4237009c9cc5@sandeen.net/
>
> Lukas Herbolt (1):
> xfsprogs: mkfs.xfs add default configuration file.
>
> include/builddefs.in | 1 +
> mkfs/Makefile | 3 ++
> mkfs/mkfs.xfs.conf | 50 ++++++++++++++++++++++++++++++
> mkfs/xfs_mkfs.c | 72 +++++++++++++++++++++++++++++++++++++++-----
> 4 files changed, 119 insertions(+), 7 deletions(-)
> create mode 100644 mkfs/mkfs.xfs.conf
>
> --
> 2.54.0
>
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC PATCH 1/1] xfsprogs: mkfs.xfs add default configuration file.
2026-05-14 14:37 ` [RFC PATCH 1/1] xfsprogs: mkfs.xfs add default configuration file Lukas Herbolt
@ 2026-05-14 15:21 ` Carlos Maiolino
2026-05-14 16:05 ` Eric Sandeen
2026-05-14 16:27 ` Darrick J. Wong
1 sibling, 1 reply; 7+ messages in thread
From: Carlos Maiolino @ 2026-05-14 15:21 UTC (permalink / raw)
To: Lukas Herbolt; +Cc: djwong, sandeen, aalbersh, linux-xfs
On Thu, May 14, 2026 at 04:37:17PM +0200, Lukas Herbolt wrote:
> Various users may prefer different default values. Having a default config
> file will allow them to utilize it without the need specifying configuration
> file on command line.
>
The idea seems reasonable, to have a default file to load if it's found.
I just particularly don't like the idea of shipping/installing a 'default'
config file.
I think we could ship an "example" one, but leave to distributions to decide
what to do. If they would install a default config or not. And maintain
the default config file.
LTS configs are easy to maintain because we know no new features will be
ported to LTS. Providing a default config file from the mainline risks
getting a lot of user complains if we in the future decide to change the
'defaults' of the default config file.
> Signed-off-by: Lukas Herbolt <lukas@herbolt.com>
> ---
> include/builddefs.in | 1 +
> mkfs/Makefile | 3 ++
> mkfs/mkfs.xfs.conf | 50 ++++++++++++++++++++++++++++++
> mkfs/xfs_mkfs.c | 72 +++++++++++++++++++++++++++++++++++++++-----
> 4 files changed, 119 insertions(+), 7 deletions(-)
> create mode 100644 mkfs/mkfs.xfs.conf
>
> diff --git a/include/builddefs.in b/include/builddefs.in
> index 3b52d1afd703..b635a7cd08a6 100644
> --- a/include/builddefs.in
> +++ b/include/builddefs.in
> @@ -59,6 +59,7 @@ PKG_DOC_DIR = @datadir@/doc/@pkg_name@
> PKG_LOCALE_DIR = @datadir@/locale
> PKG_DATA_DIR = @datadir@/@pkg_name@
> MKFS_CFG_DIR = @datadir@/@pkg_name@/mkfs
> +MKFS_SYSCONF_DIR = @sysconfdir@
> PKG_STATE_DIR = @localstatedir@/lib/@pkg_name@
>
> XFS_SCRUB_ALL_AUTO_MEDIA_SCAN_STAMP=$(PKG_STATE_DIR)/xfs_scrub_all_media.stamp
> diff --git a/mkfs/Makefile b/mkfs/Makefile
> index fb1473324cde..57cee687eb1e 100644
> --- a/mkfs/Makefile
> +++ b/mkfs/Makefile
> @@ -21,6 +21,7 @@ CFGFILES = \
> lts_6.12.conf \
> lts_6.18.conf
>
> +LCFLAGS += -DMKFS_CFG_DIR=\"$(MKFS_CFG_DIR)\" -DMKFS_SYSCONF_DIR=\"$(MKFS_SYSCONF_DIR)\"
> LLDLIBS += $(LIBXFS) $(LIBXCMD) $(LIBFROG) $(LIBRT) $(LIBBLKID) \
> $(LIBUUID) $(LIBINIH) $(LIBURCU) $(LIBPTHREAD)
> LTDEPENDENCIES += $(LIBXFS) $(LIBXCMD) $(LIBFROG)
> @@ -45,6 +46,8 @@ install: default
> $(INSTALL) -m 755 $(XFS_PROTOFILE) $(PKG_SBIN_DIR)/xfs_protofile
> $(INSTALL) -m 755 -d $(MKFS_CFG_DIR)
> $(INSTALL) -m 644 $(CFGFILES) $(MKFS_CFG_DIR)
> + $(INSTALL) -m 755 -d $(MKFS_SYSCONF_DIR)
> + $(INSTALL) -m 644 mkfs.xfs.conf $(MKFS_SYSCONF_DIR)
>
> install-dev:
>
> diff --git a/mkfs/mkfs.xfs.conf b/mkfs/mkfs.xfs.conf
> new file mode 100644
> index 000000000000..76f5ab4d4d8e
> --- /dev/null
> +++ b/mkfs/mkfs.xfs.conf
> @@ -0,0 +1,50 @@
> +# mkfs.xfs default configuration file
> +#
> +# This file documents some of the options recognised by mkfs.xfs config file.
> +# Adjust any value to override it system-wide.
> +#
> +# Command-line options always take precedence over values in this file.
> +# A specific config file can be selected with: mkfs.xfs -c options=<path>
> +
> +[block]
> +#size = 4096
> +
> +[metadata]
> +#crc = 1
> +#finobt = 1
> +#inobtcount = 1
> +#rmapbt = 1
> +#reflink = 1
> +#bigtime = 1
> +#metadir = 0
> +#autofsck = 0
> +
> +[inode]
> +#align = 1
> +# The default value is 25% for filesystems under 1TB,#5% for filesystems under
> +# 50TB and 1% for filesystems over 50TB.
> +#
> +#maxpct = 25
> +#size = 512
> +#perblock = 8
> +#attr = 2
> +#projid32bit = 1
> +#sparse = 1
> +#nrext64 = 1
> +#exchange = 1
> +
> +[data]
> +# -1 = autodetect (use CPU count only on solid-state devices), 0 = disabled
> +#concurrency = -1
> +
> +[log]
> +#internal = 1
> +#version = 2
> +#lazy-count = 1
> +# -1 = autodetect (use CPU count only on solid-state devices), 0 = disabled
> +#concurrency = -1
> +
> +[realtime]
> +# -1 = autodetect (use CPU count only on solid-state devices), 0 = disabled
> +#concurrency = -1
> +
> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> index dd8a48c3633e..dbf15eca3442 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -44,6 +44,11 @@
> */
> #define WHACK_SIZE (128 * 1024)
>
> +/*
> + * Default configuration file which can keep distro specific values.
> + */
> +#define MKFS_DEFAULT_CFGFILE MKFS_SYSCONF_DIR "/mkfs.xfs.conf"
> +
> /*
> * XXX: The configured block and sector sizes are defined as global variables so
> * that they don't need to be passed to getnum/cvtnum().
> @@ -51,6 +56,11 @@
> static unsigned int blocksize;
> static unsigned int sectorsize;
>
> +/*
> + * Set to true while parsing the config file so option handlers know the source
> + */
> +static bool parsing_cfgfile;
> +
> /*
> * Enums for each CLI parameter type are declared first so we can calculate the
> * maximum array size needed to hold them automatically.
> @@ -264,6 +274,7 @@ struct opt_params {
> bool str_seen;
> bool convert;
> bool is_power_2;
> + bool from_file;
> struct _conflict {
> struct opt_params *opts;
> int subopt;
> @@ -472,7 +483,7 @@ static struct opt_params dopts = {
> .conflicts = { { &dopts, D_AGCOUNT },
> { &dopts, D_AGSIZE },
> { NULL, LAST_CONFLICT } },
> - .minval = 0,
> + .minval = -1,
> .maxval = INT_MAX,
> .defaultval = 1,
> },
> @@ -672,7 +683,7 @@ static struct opt_params lopts = {
> { &lopts, L_FILE },
> { &lopts, L_DEV },
> { NULL, LAST_CONFLICT } },
> - .minval = 0,
> + .minval = -1,
> .maxval = INT_MAX,
> .defaultval = 1,
> },
> @@ -827,7 +838,7 @@ static struct opt_params ropts = {
> { &ropts, R_RGSIZE },
> { NULL, LAST_CONFLICT } },
> .convert = true,
> - .minval = 0,
> + .minval = -1,
> .maxval = INT_MAX,
> .defaultval = 1,
> },
> @@ -1072,6 +1083,7 @@ struct cli_params {
> int blocksize;
>
> char *cfgfile;
> + bool cfgfile_had_options;
> char *protofile;
>
> enum fsprop_autofsck autofsck;
> @@ -1654,10 +1666,12 @@ check_opt(
> if (sp->seen)
> respec(opts->name, opts->subopts, index);
> sp->seen = true;
> + sp->from_file = parsing_cfgfile;
> } else {
> if (sp->str_seen)
> respec(opts->name, opts->subopts, index);
> sp->str_seen = true;
> + sp->from_file = parsing_cfgfile;
> }
>
> /* check for conflicts with the option */
> @@ -1806,6 +1820,7 @@ set_data_concurrency(
> /*
> * "nr_cpus" or "1" means set the concurrency level to the CPU count.
> * If this cannot be determined, fall back to the default AG geometry.
> + * -1 means autodetect (use CPU count only on solid-state devices).
> */
> if (!value || !strcmp(value, "nr_cpus"))
> optnum = 1;
> @@ -1814,6 +1829,8 @@ set_data_concurrency(
>
> if (optnum == 1)
> cli->data_concurrency = nr_cpus();
> + else if (optnum == -1)
> + cli->data_concurrency = -1;
> else
> cli->data_concurrency = optnum;
> }
> @@ -1954,6 +1971,7 @@ set_log_concurrency(
> /*
> * "nr_cpus" or 1 means set the concurrency level to the CPU count. If
> * this cannot be determined, fall back to the default computation.
> + * -1 means autodetect (use CPU count only on solid-state devices).
> */
> if (!value || !strcmp(value, "nr_cpus"))
> optnum = 1;
> @@ -1962,6 +1980,8 @@ set_log_concurrency(
>
> if (optnum == 1)
> cli->log_concurrency = nr_cpus();
> + else if (optnum == -1)
> + cli->log_concurrency = -1;
> else
> cli->log_concurrency = optnum;
> }
> @@ -2175,6 +2195,7 @@ set_rtvol_concurrency(
> * "nr_cpus" or "1" means set the concurrency level to the CPU count.
> * If this cannot be determined, fall back to the default rtgroup
> * geometry.
> + * -1 means autodetect (use CPU count only on solid-state devices).
> */
> if (!value || !strcmp(value, "nr_cpus"))
> optnum = 1;
> @@ -2183,6 +2204,8 @@ set_rtvol_concurrency(
>
> if (optnum == 1)
> cli->rtvol_concurrency = nr_cpus();
> + else if (optnum == -1)
> + cli->rtvol_concurrency = -1;
> else
> cli->rtvol_concurrency = optnum;
> }
> @@ -2336,9 +2359,32 @@ parse_cfgopt(
> if (!subopts[i])
> break;
> if (strcasecmp(name, subopts[i]) == 0) {
> + struct subopt_param *sp = &sop->opts->subopt_params[i];
> + int j;
> +
> + /*
> + * Command line options take precedence over config file
> + * options. If this option or any option that conflicts
> + * with it was already set from the command line, skip
> + * the config file value silently.
> + */
> + if ((sp->seen || sp->str_seen) && !sp->from_file)
> + return true;
> + for (j = 0; j < MAX_CONFLICTS; j++) {
> + struct _conflict *con = &sp->conflicts[j];
> + struct subopt_param *csp;
> +
> + if (con->subopt == LAST_CONFLICT)
> + break;
> + csp = &con->opts->subopt_params[con->subopt];
> + if ((csp->seen || csp->str_seen) && !csp->from_file)
> + return true;
> + }
> +
> ret = (sop->parser)(sop->opts, i, value, cli);
> if (ret)
> goto invalid_opt;
> + cli->cfgfile_had_options = true;
> return true;
> }
> }
> @@ -5749,10 +5795,21 @@ cfgfile_parse(
> {
> int error;
>
> - if (!cli->cfgfile)
> - return;
> + bool default_cfgfile = !cli->cfgfile;
> +
> + if (!cli->cfgfile) {
> + /*
> + * No config file specified on the command line. Use the default
> + * system-wide config file if it exists, otherwise do nothing.
> + */
> + if (access(MKFS_DEFAULT_CFGFILE, F_OK) != 0)
> + return;
> + cli->cfgfile = MKFS_DEFAULT_CFGFILE;
> + }
>
> + parsing_cfgfile = true;
> error = ini_parse(cli->cfgfile, cfgfile_parse_ini, cli);
> + parsing_cfgfile = false;
> if (error) {
> if (error > 0) {
> fprintf(stderr,
> @@ -5773,8 +5830,9 @@ cfgfile_parse(
> }
> exit(1);
> }
> - printf(_("Parameters parsed from config file %s successfully\n"),
> - cli->cfgfile);
> + if (!default_cfgfile || cli->cfgfile_had_options)
> + printf(_("Parameters parsed from config file %s successfully\n"),
> + cli->cfgfile);
> }
>
> static void
> --
> 2.54.0
>
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC PATCH 1/1] xfsprogs: mkfs.xfs add default configuration file.
2026-05-14 15:21 ` Carlos Maiolino
@ 2026-05-14 16:05 ` Eric Sandeen
2026-05-14 16:29 ` Darrick J. Wong
0 siblings, 1 reply; 7+ messages in thread
From: Eric Sandeen @ 2026-05-14 16:05 UTC (permalink / raw)
To: Carlos Maiolino, Lukas Herbolt; +Cc: djwong, aalbersh, linux-xfs
On 5/14/26 10:21 AM, Carlos Maiolino wrote:
> On Thu, May 14, 2026 at 04:37:17PM +0200, Lukas Herbolt wrote:
>> Various users may prefer different default values. Having a default config
>> file will allow them to utilize it without the need specifying configuration
>> file on command line.
>>
> The idea seems reasonable, to have a default file to load if it's found.
> I just particularly don't like the idea of shipping/installing a 'default'
> config file.
> I think we could ship an "example" one, but leave to distributions to decide
> what to do. If they would install a default config or not. And maintain
> the default config file.
> LTS configs are easy to maintain because we know no new features will be
> ported to LTS. Providing a default config file from the mainline risks
> getting a lot of user complains if we in the future decide to change the
> 'defaults' of the default config file.
Thanks for starting this discussion Lukas.
I'm sure others will have Deeper Thoughts but I more or less agree with
Carlos here - a default config file to be loaded /if it exists/ but maybe
not existing by default - because we already have defaults hardcoded into
the binary itself - might be a more maintainable path for upstream.
Otherwise I see new tests appearing which are like "make sure the dfault
config we ship matches the defaults built into the binary itself" which
seems like unneeded complexity.
(i.e. the os-specific config files could be renamed or symlinked to
that special default config file path, for example?)
I could maybe see generating an example defaults config file which matches
the built-in defaults at build time? Not sure if that would be useful
or helpful (or complex).
Thanks,
-Eric
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC PATCH 1/1] xfsprogs: mkfs.xfs add default configuration file.
2026-05-14 14:37 ` [RFC PATCH 1/1] xfsprogs: mkfs.xfs add default configuration file Lukas Herbolt
2026-05-14 15:21 ` Carlos Maiolino
@ 2026-05-14 16:27 ` Darrick J. Wong
1 sibling, 0 replies; 7+ messages in thread
From: Darrick J. Wong @ 2026-05-14 16:27 UTC (permalink / raw)
To: Lukas Herbolt; +Cc: sandeen, aalbersh, linux-xfs
On Thu, May 14, 2026 at 04:37:17PM +0200, Lukas Herbolt wrote:
> Various users may prefer different default values. Having a default config
> file will allow them to utilize it without the need specifying configuration
> file on command line.
>
> Signed-off-by: Lukas Herbolt <lukas@herbolt.com>
> ---
> include/builddefs.in | 1 +
> mkfs/Makefile | 3 ++
> mkfs/mkfs.xfs.conf | 50 ++++++++++++++++++++++++++++++
> mkfs/xfs_mkfs.c | 72 +++++++++++++++++++++++++++++++++++++++-----
> 4 files changed, 119 insertions(+), 7 deletions(-)
> create mode 100644 mkfs/mkfs.xfs.conf
>
> diff --git a/include/builddefs.in b/include/builddefs.in
> index 3b52d1afd703..b635a7cd08a6 100644
> --- a/include/builddefs.in
> +++ b/include/builddefs.in
> @@ -59,6 +59,7 @@ PKG_DOC_DIR = @datadir@/doc/@pkg_name@
> PKG_LOCALE_DIR = @datadir@/locale
> PKG_DATA_DIR = @datadir@/@pkg_name@
> MKFS_CFG_DIR = @datadir@/@pkg_name@/mkfs
> +MKFS_SYSCONF_DIR = @sysconfdir@
> PKG_STATE_DIR = @localstatedir@/lib/@pkg_name@
>
> XFS_SCRUB_ALL_AUTO_MEDIA_SCAN_STAMP=$(PKG_STATE_DIR)/xfs_scrub_all_media.stamp
> diff --git a/mkfs/Makefile b/mkfs/Makefile
> index fb1473324cde..57cee687eb1e 100644
> --- a/mkfs/Makefile
> +++ b/mkfs/Makefile
> @@ -21,6 +21,7 @@ CFGFILES = \
> lts_6.12.conf \
> lts_6.18.conf
>
> +LCFLAGS += -DMKFS_CFG_DIR=\"$(MKFS_CFG_DIR)\" -DMKFS_SYSCONF_DIR=\"$(MKFS_SYSCONF_DIR)\"
> LLDLIBS += $(LIBXFS) $(LIBXCMD) $(LIBFROG) $(LIBRT) $(LIBBLKID) \
> $(LIBUUID) $(LIBINIH) $(LIBURCU) $(LIBPTHREAD)
> LTDEPENDENCIES += $(LIBXFS) $(LIBXCMD) $(LIBFROG)
> @@ -45,6 +46,8 @@ install: default
> $(INSTALL) -m 755 $(XFS_PROTOFILE) $(PKG_SBIN_DIR)/xfs_protofile
> $(INSTALL) -m 755 -d $(MKFS_CFG_DIR)
> $(INSTALL) -m 644 $(CFGFILES) $(MKFS_CFG_DIR)
> + $(INSTALL) -m 755 -d $(MKFS_SYSCONF_DIR)
> + $(INSTALL) -m 644 mkfs.xfs.conf $(MKFS_SYSCONF_DIR)
At first I thought "gee, are we not supposed to dump config files into
/etc anymore?" but maybe that's a crazy ro-root/systemd thing. I guess
that at least it /is/ in the spirit of /etc/mke2fs.conf.
> install-dev:
>
> diff --git a/mkfs/mkfs.xfs.conf b/mkfs/mkfs.xfs.conf
> new file mode 100644
> index 000000000000..76f5ab4d4d8e
> --- /dev/null
> +++ b/mkfs/mkfs.xfs.conf
> @@ -0,0 +1,50 @@
> +# mkfs.xfs default configuration file
> +#
> +# This file documents some of the options recognised by mkfs.xfs config file.
> +# Adjust any value to override it system-wide.
> +#
> +# Command-line options always take precedence over values in this file.
> +# A specific config file can be selected with: mkfs.xfs -c options=<path>
> +
> +[block]
> +#size = 4096
> +
> +[metadata]
> +#crc = 1
> +#finobt = 1
> +#inobtcount = 1
> +#rmapbt = 1
> +#reflink = 1
> +#bigtime = 1
> +#metadir = 0
> +#autofsck = 0
> +
> +[inode]
> +#align = 1
> +# The default value is 25% for filesystems under 1TB,#5% for filesystems under
> +# 50TB and 1% for filesystems over 50TB.
> +#
> +#maxpct = 25
> +#size = 512
> +#perblock = 8
> +#attr = 2
> +#projid32bit = 1
> +#sparse = 1
> +#nrext64 = 1
> +#exchange = 1
> +
> +[data]
> +# -1 = autodetect (use CPU count only on solid-state devices), 0 = disabled
> +#concurrency = -1
> +
> +[log]
> +#internal = 1
> +#version = 2
> +#lazy-count = 1
> +# -1 = autodetect (use CPU count only on solid-state devices), 0 = disabled
> +#concurrency = -1
> +
> +[realtime]
> +# -1 = autodetect (use CPU count only on solid-state devices), 0 = disabled
> +#concurrency = -1
Oh, I see. The "-1" changes scattered throughout are to make it so that
you can specify that as a concurrency= option. I had mistakenly thought
pre-coffee that they were adding a new value.
However, I think "concurrency=auto" would be more ergonomic for users.
/*
* "nr_cpus" or "1" means set the concurrency level to the CPU count.
* If this cannot be determined, fall back to the default AG geometry.
* "auto" means use CPU count only solid-state devices
*/
if (!value || !strcmp(value, "nr_cpus"))
optnum = 1;
else if (!strcmp(value, "auto"))
optnum = -1;
else
optnum = getnum(value, opts, subopt);
if (optnum == 1)
cli->data_concurrency = nr_cpus();
else
cli->data_concurrency = optnum;
Also note that the explicit strcmp carveout for "auto" (and "nr_cpus")
means you don't have to tweak minval below.
Whatever we end up adding for a "just use the defaults" value, that
ought to be a separate patch from the one that adds the defaults config
file.
> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
> index dd8a48c3633e..dbf15eca3442 100644
> --- a/mkfs/xfs_mkfs.c
> +++ b/mkfs/xfs_mkfs.c
> @@ -44,6 +44,11 @@
> */
> #define WHACK_SIZE (128 * 1024)
>
> +/*
> + * Default configuration file which can keep distro specific values.
> + */
> +#define MKFS_DEFAULT_CFGFILE MKFS_SYSCONF_DIR "/mkfs.xfs.conf"
> +
> /*
> * XXX: The configured block and sector sizes are defined as global variables so
> * that they don't need to be passed to getnum/cvtnum().
> @@ -51,6 +56,11 @@
> static unsigned int blocksize;
> static unsigned int sectorsize;
>
> +/*
> + * Set to true while parsing the config file so option handlers know the source
> + */
> +static bool parsing_cfgfile;
> +
> /*
> * Enums for each CLI parameter type are declared first so we can calculate the
> * maximum array size needed to hold them automatically.
> @@ -264,6 +274,7 @@ struct opt_params {
> bool str_seen;
> bool convert;
> bool is_power_2;
> + bool from_file;
> struct _conflict {
> struct opt_params *opts;
> int subopt;
> @@ -472,7 +483,7 @@ static struct opt_params dopts = {
> .conflicts = { { &dopts, D_AGCOUNT },
> { &dopts, D_AGSIZE },
> { NULL, LAST_CONFLICT } },
> - .minval = 0,
> + .minval = -1,
> .maxval = INT_MAX,
> .defaultval = 1,
> },
> @@ -672,7 +683,7 @@ static struct opt_params lopts = {
> { &lopts, L_FILE },
> { &lopts, L_DEV },
> { NULL, LAST_CONFLICT } },
> - .minval = 0,
> + .minval = -1,
> .maxval = INT_MAX,
> .defaultval = 1,
> },
> @@ -827,7 +838,7 @@ static struct opt_params ropts = {
> { &ropts, R_RGSIZE },
> { NULL, LAST_CONFLICT } },
> .convert = true,
> - .minval = 0,
> + .minval = -1,
> .maxval = INT_MAX,
> .defaultval = 1,
> },
> @@ -1072,6 +1083,7 @@ struct cli_params {
> int blocksize;
>
> char *cfgfile;
> + bool cfgfile_had_options;
> char *protofile;
>
> enum fsprop_autofsck autofsck;
> @@ -1654,10 +1666,12 @@ check_opt(
> if (sp->seen)
> respec(opts->name, opts->subopts, index);
> sp->seen = true;
> + sp->from_file = parsing_cfgfile;
> } else {
> if (sp->str_seen)
> respec(opts->name, opts->subopts, index);
> sp->str_seen = true;
> + sp->from_file = parsing_cfgfile;
> }
>
> /* check for conflicts with the option */
> @@ -1806,6 +1820,7 @@ set_data_concurrency(
> /*
> * "nr_cpus" or "1" means set the concurrency level to the CPU count.
> * If this cannot be determined, fall back to the default AG geometry.
> + * -1 means autodetect (use CPU count only on solid-state devices).
> */
> if (!value || !strcmp(value, "nr_cpus"))
> optnum = 1;
> @@ -1814,6 +1829,8 @@ set_data_concurrency(
>
> if (optnum == 1)
> cli->data_concurrency = nr_cpus();
> + else if (optnum == -1)
> + cli->data_concurrency = -1;
> else
> cli->data_concurrency = optnum;
> }
> @@ -1954,6 +1971,7 @@ set_log_concurrency(
> /*
> * "nr_cpus" or 1 means set the concurrency level to the CPU count. If
> * this cannot be determined, fall back to the default computation.
> + * -1 means autodetect (use CPU count only on solid-state devices).
> */
> if (!value || !strcmp(value, "nr_cpus"))
> optnum = 1;
> @@ -1962,6 +1980,8 @@ set_log_concurrency(
>
> if (optnum == 1)
> cli->log_concurrency = nr_cpus();
> + else if (optnum == -1)
> + cli->log_concurrency = -1;
> else
> cli->log_concurrency = optnum;
> }
> @@ -2175,6 +2195,7 @@ set_rtvol_concurrency(
> * "nr_cpus" or "1" means set the concurrency level to the CPU count.
> * If this cannot be determined, fall back to the default rtgroup
> * geometry.
> + * -1 means autodetect (use CPU count only on solid-state devices).
> */
> if (!value || !strcmp(value, "nr_cpus"))
> optnum = 1;
> @@ -2183,6 +2204,8 @@ set_rtvol_concurrency(
>
> if (optnum == 1)
> cli->rtvol_concurrency = nr_cpus();
> + else if (optnum == -1)
> + cli->rtvol_concurrency = -1;
> else
> cli->rtvol_concurrency = optnum;
> }
> @@ -2336,9 +2359,32 @@ parse_cfgopt(
> if (!subopts[i])
> break;
> if (strcasecmp(name, subopts[i]) == 0) {
> + struct subopt_param *sp = &sop->opts->subopt_params[i];
> + int j;
> +
> + /*
> + * Command line options take precedence over config file
> + * options. If this option or any option that conflicts
> + * with it was already set from the command line, skip
> + * the config file value silently.
Currently, config file options take precedence over CLI options:
$ mkfs.xfs -c options=/usr/share/xfsprogs/mkfs/lts_6.6.conf -i nrext64=0 /tmp/a
-i nrext64 option respecified
So I guess this patch is changing that policy too?
--D
> + */
> + if ((sp->seen || sp->str_seen) && !sp->from_file)
> + return true;
> + for (j = 0; j < MAX_CONFLICTS; j++) {
> + struct _conflict *con = &sp->conflicts[j];
> + struct subopt_param *csp;
> +
> + if (con->subopt == LAST_CONFLICT)
> + break;
> + csp = &con->opts->subopt_params[con->subopt];
> + if ((csp->seen || csp->str_seen) && !csp->from_file)
> + return true;
> + }
> +
> ret = (sop->parser)(sop->opts, i, value, cli);
> if (ret)
> goto invalid_opt;
> + cli->cfgfile_had_options = true;
> return true;
> }
> }
> @@ -5749,10 +5795,21 @@ cfgfile_parse(
> {
> int error;
>
> - if (!cli->cfgfile)
> - return;
> + bool default_cfgfile = !cli->cfgfile;
> +
> + if (!cli->cfgfile) {
> + /*
> + * No config file specified on the command line. Use the default
> + * system-wide config file if it exists, otherwise do nothing.
> + */
> + if (access(MKFS_DEFAULT_CFGFILE, F_OK) != 0)
> + return;
> + cli->cfgfile = MKFS_DEFAULT_CFGFILE;
> + }
>
> + parsing_cfgfile = true;
> error = ini_parse(cli->cfgfile, cfgfile_parse_ini, cli);
> + parsing_cfgfile = false;
> if (error) {
> if (error > 0) {
> fprintf(stderr,
> @@ -5773,8 +5830,9 @@ cfgfile_parse(
> }
> exit(1);
> }
> - printf(_("Parameters parsed from config file %s successfully\n"),
> - cli->cfgfile);
> + if (!default_cfgfile || cli->cfgfile_had_options)
> + printf(_("Parameters parsed from config file %s successfully\n"),
> + cli->cfgfile);
> }
>
> static void
> --
> 2.54.0
>
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC PATCH 1/1] xfsprogs: mkfs.xfs add default configuration file.
2026-05-14 16:05 ` Eric Sandeen
@ 2026-05-14 16:29 ` Darrick J. Wong
0 siblings, 0 replies; 7+ messages in thread
From: Darrick J. Wong @ 2026-05-14 16:29 UTC (permalink / raw)
To: Eric Sandeen; +Cc: Carlos Maiolino, Lukas Herbolt, aalbersh, linux-xfs
On Thu, May 14, 2026 at 11:05:14AM -0500, Eric Sandeen wrote:
> On 5/14/26 10:21 AM, Carlos Maiolino wrote:
> > On Thu, May 14, 2026 at 04:37:17PM +0200, Lukas Herbolt wrote:
> >> Various users may prefer different default values. Having a default config
> >> file will allow them to utilize it without the need specifying configuration
> >> file on command line.
> >>
> > The idea seems reasonable, to have a default file to load if it's found.
> > I just particularly don't like the idea of shipping/installing a 'default'
> > config file.
> > I think we could ship an "example" one, but leave to distributions to decide
> > what to do. If they would install a default config or not. And maintain
> > the default config file.
> > LTS configs are easy to maintain because we know no new features will be
> > ported to LTS. Providing a default config file from the mainline risks
> > getting a lot of user complains if we in the future decide to change the
> > 'defaults' of the default config file.
>
> Thanks for starting this discussion Lukas.
>
> I'm sure others will have Deeper Thoughts but I more or less agree with
> Carlos here - a default config file to be loaded /if it exists/ but maybe
> not existing by default - because we already have defaults hardcoded into
> the binary itself - might be a more maintainable path for upstream.
> Otherwise I see new tests appearing which are like "make sure the dfault
> config we ship matches the defaults built into the binary itself" which
> seems like unneeded complexity.
>
> (i.e. the os-specific config files could be renamed or symlinked to
> that special default config file path, for example?)
>
> I could maybe see generating an example defaults config file which matches
> the built-in defaults at build time? Not sure if that would be useful
> or helpful (or complex).
I think that would be a lot easier than us trying to keep the default
config file in sync with xfs_mkfs.c by hand.
--D
>
> Thanks,
> -Eric
>
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-05-14 16:29 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-14 14:37 [RFC PATCH 0/1] Add default config file for mkfs.xfs Lukas Herbolt
2026-05-14 14:37 ` [RFC PATCH 1/1] xfsprogs: mkfs.xfs add default configuration file Lukas Herbolt
2026-05-14 15:21 ` Carlos Maiolino
2026-05-14 16:05 ` Eric Sandeen
2026-05-14 16:29 ` Darrick J. Wong
2026-05-14 16:27 ` Darrick J. Wong
2026-05-14 15:05 ` [RFC PATCH 0/1] Add default config file for mkfs.xfs Darrick J. Wong
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox