Linux XFS filesystem development
 help / color / mirror / Atom feed
From: Lukas Herbolt <lukas@herbolt.com>
To: djwong@kernel.org, sandeen@sandeen.net, aalbersh@kernel.org
Cc: linux-xfs@vger.kernel.org, Lukas Herbolt <lukas@herbolt.com>
Subject: [RFC PATCH 1/1] xfsprogs: mkfs.xfs add default configuration file.
Date: Thu, 14 May 2026 16:37:17 +0200	[thread overview]
Message-ID: <20260514143716.893814-3-lukas@herbolt.com> (raw)
In-Reply-To: <20260514143716.893814-2-lukas@herbolt.com>

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


  reply	other threads:[~2026-05-14 14:38 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
2026-05-14 15:21   ` [RFC PATCH 1/1] xfsprogs: mkfs.xfs add default configuration file Carlos Maiolino
2026-05-14 16:05     ` Eric Sandeen
2026-05-14 16:29       ` Darrick J. Wong
2026-05-14 22:27       ` Dave Chinner
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260514143716.893814-3-lukas@herbolt.com \
    --to=lukas@herbolt.com \
    --cc=aalbersh@kernel.org \
    --cc=djwong@kernel.org \
    --cc=linux-xfs@vger.kernel.org \
    --cc=sandeen@sandeen.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox