useradd: Support config for creating home dirs as Btrfs subvolumes

Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
This commit is contained in:
Iker Pedrosa 2026-01-12 11:42:00 +01:00
commit f47e36e72a
2 changed files with 155 additions and 1 deletions

View file

@ -0,0 +1,149 @@
From 3e8c105f0703264e947d8c034b90419794955d49 Mon Sep 17 00:00:00 2001
From: Hadi Chokr <hadichokr@icloud.com>
Date: Fri, 12 Dec 2025 11:18:06 +0100
Subject: [PATCH] src/useradd: Support config for creating home dirs as Btrfs
subvolumes
Closes: #1162
Co-authored-by: Neal Gompa <ngompa@velocitylimitless.com>
Signed-off-by: Hadi Chokr <hadichokr@icloud.com>
Signed-off-by: Neal Gompa <ngompa@velocitylimitless.com>
Reviewed-by: Alejandro Colomar <alx@kernel.org>
---
man/useradd.8.xml | 27 +++++++++++++++++++++++++++
src/useradd.c | 24 ++++++++++++++++++++++++
2 files changed, 51 insertions(+)
diff --git a/man/useradd.8.xml b/man/useradd.8.xml
index e6db7f6d..c745a620 100644
--- a/man/useradd.8.xml
+++ b/man/useradd.8.xml
@@ -134,6 +134,33 @@
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>
+ <option>--btrfs-subvolume-home</option>
+ </term>
+ <listitem>
+ <para>
+ Create the user's home directory as a Btrfs subvolume.
+ </para>
+ <para>
+ If this option is not specified,
+ <command>useradd</command> will follow the default behavior
+ defined by the <option>BTRFS_SUBVOLUME_HOME</option> variable
+ in <filename>/etc/default/useradd</filename>.
+ If this variable is not set, the default value is no.
+ </para>
+ <para>
+ When the <option>--btrfs-subvolume-home</option> command-line option
+ is specified,
+ a Btrfs subvolume is created
+ regardless of any configuration file settings.
+ </para>
+ <para>
+ Note: this feature works only if the underlying filesystem supports
+ Btrfs subvolumes.
+ </para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term>
<option>-c</option>, <option>--comment</option>&nbsp;<replaceable>COMMENT</replaceable>
diff --git a/src/useradd.c b/src/useradd.c
index 899efe3c..8433ed8a 100644
--- a/src/useradd.c
+++ b/src/useradd.c
@@ -114,6 +114,7 @@ static const char *def_shell = "/bin/bash";
static const char *def_template = SKEL_DIR;
static const char *def_usrtemplate = USRSKELDIR;
static const char *def_create_mail_spool = "yes";
+static const char *def_btrfs_subvolume_home = "no";
static const char *def_log_init = "yes";
static long def_inactive = -1;
@@ -222,6 +223,7 @@ static bool home_added = false;
#define DSKEL "SKEL"
#define DUSRSKEL "USRSKEL"
#define DCREATE_MAIL_SPOOL "CREATE_MAIL_SPOOL"
+#define DBTRFS_SUBVOLUME_HOME "BTRFS_SUBVOLUME_HOME"
#define DLOG_INIT "LOG_INIT"
/* local function prototypes */
@@ -456,6 +458,7 @@ get_defaults(const struct option_flags *flags)
def_usrtemplate = xstrdup(ccp);
}
}
+
/*
* Create by default user mail spool or not ?
*/
@@ -466,6 +469,15 @@ get_defaults(const struct option_flags *flags)
def_create_mail_spool = xstrdup(ccp);
}
+ /*
+ * Create home directories as Btrfs subvolumes by default?
+ */
+ else if (streq(buf, DBTRFS_SUBVOLUME_HOME)) {
+ if (streq(ccp, ""))
+ ccp = "no";
+ def_btrfs_subvolume_home = xstrdup(ccp);
+ }
+
/*
* By default do we add the user to the lastlog and faillog databases ?
*/
@@ -500,6 +512,7 @@ static void show_defaults (void)
printf ("SKEL=%s\n", def_template);
printf ("USRSKEL=%s\n", def_usrtemplate);
printf ("CREATE_MAIL_SPOOL=%s\n", def_create_mail_spool);
+ printf ("BTRFS_SUBVOLUME_HOME=%s\n", def_btrfs_subvolume_home);
printf ("LOG_INIT=%s\n", def_log_init);
}
@@ -523,6 +536,7 @@ set_defaults(void)
bool out_skel = false;
bool out_usrskel = false;
bool out_create_mail_spool = false;
+ bool out_btrfs_subvolume_home = false;
bool out_log_init = false;
char buf[1024];
char *new_file = NULL;
@@ -639,6 +653,11 @@ set_defaults(void)
DCREATE_MAIL_SPOOL "=%s\n",
def_create_mail_spool);
out_create_mail_spool = true;
+ } else if (!out_btrfs_subvolume_home && streq(buf, DBTRFS_SUBVOLUME_HOME)) {
+ fprintf(ofp,
+ DBTRFS_SUBVOLUME_HOME "=%s\n",
+ def_btrfs_subvolume_home);
+ out_btrfs_subvolume_home = true;
} else if (!out_log_init && streq(buf, DLOG_INIT)) {
fprintf(ofp, DLOG_INIT "=%s\n", def_log_init);
out_log_init = true;
@@ -673,6 +692,8 @@ set_defaults(void)
if (!out_create_mail_spool)
fprintf (ofp, DCREATE_MAIL_SPOOL "=%s\n", def_create_mail_spool);
+ if (!out_btrfs_subvolume_home)
+ fprintf (ofp, DBTRFS_SUBVOLUME_HOME "=%s\n", def_btrfs_subvolume_home);
if (!out_log_init)
fprintf (ofp, DLOG_INIT "=%s\n", def_log_init);
/*
@@ -1431,6 +1452,9 @@ static void process_flags (int argc, char **argv, struct option_flags *flags)
}
}
+ if (!subvolflg && strcaseeq(def_btrfs_subvolume_home, "yes"))
+ subvolflg = true;
+
if (!gflg && !Nflg && !Uflg) {
/* Get the settings from login.defs */
Uflg = getdef_bool ("USERGROUPS_ENAB");
--
2.52.0

View file

@ -1,7 +1,7 @@
Summary: Utilities for managing accounts and shadow password files
Name: shadow-utils
Version: 4.19.0
Release: 2%{?dist}
Release: 3%{?dist}
Epoch: 2
License: BSD-3-Clause AND GPL-2.0-or-later
URL: https://github.com/shadow-maint/shadow
@ -24,6 +24,8 @@ Source7: passwd.pamd
Patch0: shadow-4.15.0-manfix.patch
# Probably non-upstreamable
Patch1: shadow-4.19.0-account-tools-setuid.patch
# https://github.com/shadow-maint/shadow/commit/3e8c105f0703264e947d8c034b90419794955d49
Patch2: shadow-4-19-useradd-support-btrfs.patch
### Dependencies ###
Requires: audit-libs >= 1.6.5
@ -273,6 +275,9 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.a
%{_libdir}/libsubid.so
%changelog
* Mon Jan 12 2026 Iker Pedrosa <ipedrosa@redhat.com> - 2:4.19.0-3
- useradd: Support config for creating home dirs as Btrfs subvolumes
* Fri Jan 9 2026 Iker Pedrosa <ipedrosa@redhat.com> - 2:4.19.0-2
- Enable unit-tests