]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
homectl: expose new rebalanceWeight JSON use record field
authorLennart Poettering <lennart@poettering.net>
Thu, 4 Nov 2021 17:12:13 +0000 (18:12 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 25 Nov 2021 17:28:44 +0000 (18:28 +0100)
man/homectl.xml
src/home/homectl.c

index 5ba93bbe1363228eaa01d3a360aa52b203ed566a..ca9225a1e0d6a5a3ff1ed8dafe74e177fad20c93 100644 (file)
         <para>Note that FIDO2 devices suitable for this option must implement the
         <literal>hmac-secret</literal> extension. Most current devices (such as the YubiKey 5 series) do. If
         the extension is not implemented the device cannot be used for unlocking home directories.</para>
-          
-        <para>The FIDO2 device may be subsequently removed by setting the device path to an empty string 
+
+        <para>The FIDO2 device may be subsequently removed by setting the device path to an empty string
         (e.g. <command>homectl update $USER --fido2-device=""</command>).</para>
 
         <para>Note that many hardware security tokens implement both FIDO2 and PKCS#11/PIV (and thus may be
         again.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--rebalance-weight=</option></term>
+
+        <listitem><para>Configures the weight parameter for the free disk space rebalancing logic. Only
+        applies to the LUKS2 backend (since for the LUKS2 backend disk space is allocated from a per-user
+        loopback file system instead of immediately from a common pool like the other backends do it). In
+        regular intervals free disk space in the active home areas and their backing storage is redistributed
+        among them, taking the weight value configured here into account. Expects an integer in the range
+        1…10000, or the special string <literal>off</literal>. If not specified defaults to 100. The weight
+        is used to scale free space made available to the home areas: a home area with a weight of 200 will
+        get twice the free space as one with a weight of 100; a home area with a weight of 50 will get half
+        of that. The backing file system will be assigned space for a weight of 20. If set to
+        <literal>off</literal> no automatic free space distribution is done for this home area. Note that
+        resizing the home area explicitly (with <command>homectl resize</command> see below) will implicitly
+        turn off the automatic rebalancing. To reenable the automatic rebalancing use
+        <option>--rebalance-weight=</option> with an empty parameter.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><option>--nosuid=</option><replaceable>BOOL</replaceable></term>
         <term><option>--nodev=</option><replaceable>BOOL</replaceable></term>
index 706ce75dfb0c3313cc8e2b4842ea8194b38f4224..0c69299c84f2e31c50657068f3434808258bfd82 100644 (file)
@@ -2270,6 +2270,7 @@ static int help(int argc, char *argv[], void *userdata) {
                "     --luks-extra-mount-options=OPTIONS\n"
                "                               LUKS extra mount options\n"
                "     --auto-resize-mode=MODE   Automatically grow/shrink home on login/logout\n"
+               "     --rebalance-weight=WEIGHT Weight while rebalancing\n"
                "\n%4$sMounting User Record Properties:%5$s\n"
                "     --nosuid=BOOL             Control the 'nosuid' flag of the home mount\n"
                "     --nodev=BOOL              Control the 'nodev' flag of the home mount\n"
@@ -2370,6 +2371,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_DROP_CACHES,
                 ARG_LUKS_EXTRA_MOUNT_OPTIONS,
                 ARG_AUTO_RESIZE_MODE,
+                ARG_REBALANCE_WEIGHT,
         };
 
         static const struct option options[] = {
@@ -2456,6 +2458,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "drop-caches",                 required_argument, NULL, ARG_DROP_CACHES                 },
                 { "luks-extra-mount-options",    required_argument, NULL, ARG_LUKS_EXTRA_MOUNT_OPTIONS    },
                 { "auto-resize-mode",            required_argument, NULL, ARG_AUTO_RESIZE_MODE            },
+                { "rebalance-weight",            required_argument, NULL, ARG_REBALANCE_WEIGHT            },
                 {}
         };
 
@@ -2931,13 +2934,13 @@ static int parse_argv(int argc, char *argv[]) {
 
                 case ARG_DISK_SIZE:
                         if (isempty(optarg)) {
-                                r = drop_from_identity("diskSize");
-                                if (r < 0)
-                                        return r;
+                                const char *prop;
 
-                                r = drop_from_identity("diskSizeRelative");
-                                if (r < 0)
-                                        return r;
+                                FOREACH_STRING(prop, "diskSize", "diskSizeRelative", "rebalanceWeight") {
+                                        r = drop_from_identity(prop);
+                                        if (r < 0)
+                                                return r;
+                                }
 
                                 arg_disk_size = arg_disk_size_relative = UINT64_MAX;
                                 break;
@@ -2973,6 +2976,11 @@ static int parse_argv(int argc, char *argv[]) {
                                 arg_disk_size = UINT64_MAX;
                         }
 
+                        /* Automatically turn off the rebalance logic if user configured a size explicitly */
+                        r = json_variant_set_field_unsigned(&arg_identity_extra_this_machine, "rebalanceWeight", REBALANCE_WEIGHT_OFF);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to set rebalanceWeight field: %m");
+
                         break;
 
                 case ARG_ACCESS_MODE: {
@@ -3571,6 +3579,40 @@ static int parse_argv(int argc, char *argv[]) {
 
                         break;
 
+                case ARG_REBALANCE_WEIGHT: {
+                        uint64_t u;
+
+                        if (isempty(optarg)) {
+                                r = drop_from_identity("rebalanceWeight");
+                                if (r < 0)
+                                        return r;
+                        }
+
+                        if (streq(optarg, "off"))
+                                u = REBALANCE_WEIGHT_OFF;
+                        else {
+                                r = safe_atou64(optarg, &u);
+                                if (r < 0)
+                                        return log_error_errno(r, "Failed to parse --rebalance-weight= argument: %s", optarg);
+
+                                if (u < REBALANCE_WEIGHT_MIN || u > REBALANCE_WEIGHT_MAX)
+                                        return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Rebalancing weight out of valid range %" PRIu64 "…%" PRIu64 ": %s",
+                                                               REBALANCE_WEIGHT_MIN, REBALANCE_WEIGHT_MAX, optarg);
+                        }
+
+                        /* Drop from per machine stuff and everywhere */
+                        r = drop_from_identity("rebalanceWeight");
+                        if (r < 0)
+                                return r;
+
+                        /* Add to main identity */
+                        r = json_variant_set_field_unsigned(&arg_identity_extra, "rebalanceWeight", u);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to set rebalanceWeight field: %m");
+
+                        break;
+                }
+
                 case 'j':
                         arg_json_format_flags = JSON_FORMAT_PRETTY_AUTO|JSON_FORMAT_COLOR_AUTO;
                         break;