]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
user-record: add rebalanceWeight field
authorLennart Poettering <lennart@poettering.net>
Tue, 2 Nov 2021 22:09:31 +0000 (23:09 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 25 Nov 2021 17:28:44 +0000 (18:28 +0100)
docs/USER_RECORD.md
src/shared/user-record-show.c
src/shared/user-record.c
src/shared/user-record.h

index 9634f32b70bfa161379a126e797090b49d18a450..ea800c9928b5a0ebc581a34b90abf0312b5ae3b2 100644 (file)
@@ -507,6 +507,12 @@ the size configured in `diskSize` automatically at login time. If set to
 `shrink-and-grown` the home area is also shrunk to the minimal size possible
 (as dictated by used disk space and file system constraints) on logout.
 
+`rebalanceWeight` → An unsigned integer, `null` or a boolean. Configures the
+free disk space rebalancing weight for the home area. The integer must be in
+the range 1…10000 to configure an explicit weight. If unset, or set to `null`
+or `true` the default weight of 100 is implied. If set to 0 or `false`
+rebalancing is turned off for this home area.
+
 `service` → A string declaring the service that defines or manages this user
 record. It is recommended to use reverse domain name notation for this. For
 example, if `systemd-homed` manages a user a string of `io.systemd.Home` is
@@ -729,9 +735,10 @@ that may be used in this section are identical to the equally named ones in the
 `fileSystemUuid`, `luksDiscard`, `luksOfflineDiscard`, `luksCipher`,
 `luksCipherMode`, `luksVolumeKeySize`, `luksPbkdfHashAlgorithm`,
 `luksPbkdfType`, `luksPbkdfTimeCostUSec`, `luksPbkdfMemoryCost`,
-`luksPbkdfParallelThreads`, `rateLimitIntervalUSec`, `rateLimitBurst`,
-`enforcePasswordPolicy`, `autoLogin`, `stopDelayUSec`, `killProcesses`,
-`passwordChangeMinUSec`, `passwordChangeMaxUSec`, `passwordChangeWarnUSec`,
+`luksPbkdfParallelThreads`, `autoResizeMode`, `rebalanceWeight`,
+`rateLimitIntervalUSec`, `rateLimitBurst`, `enforcePasswordPolicy`,
+`autoLogin`, `stopDelayUSec`, `killProcesses`, `passwordChangeMinUSec`,
+`passwordChangeMaxUSec`, `passwordChangeWarnUSec`,
 `passwordChangeInactiveUSec`, `passwordChangeNow`, `pkcs11TokenUri`,
 `fido2HmacCredential`.
 
index 17502845af951a77a0dffbbb457b2a97575ecdfa..5335e64070101a2f65a120b07d78003bbbb97c2a 100644 (file)
@@ -447,6 +447,16 @@ void user_record_show(UserRecord *hr, bool show_full_group_info) {
         if (hr->auto_resize_mode >= 0)
                 printf(" Auto Resize: %s\n", auto_resize_mode_to_string(user_record_auto_resize_mode(hr)));
 
+        if (hr->rebalance_weight != REBALANCE_WEIGHT_UNSET) {
+                uint64_t rb;
+
+                rb = user_record_rebalance_weight(hr);
+                if (rb == REBALANCE_WEIGHT_OFF)
+                        printf("   Rebalance: off\n");
+                else
+                        printf("   Rebalance: weight %" PRIu64 "\n", rb);
+        }
+
         if (!strv_isempty(hr->ssh_authorized_keys))
                 printf("SSH Pub. Key: %zu\n", strv_length(hr->ssh_authorized_keys));
 
index fa677adb2c413f806c43e156c239cb4c9d4865dd..5b406d1f42ca8deba27fc508d44ba2d29d8fccba 100644 (file)
@@ -85,6 +85,7 @@ UserRecord* user_record_new(void) {
                 .fido2_user_verification_permitted = -1,
                 .drop_caches = -1,
                 .auto_resize_mode = _AUTO_RESIZE_MODE_INVALID,
+                .rebalance_weight = REBALANCE_WEIGHT_UNSET,
         };
 
         return h;
@@ -984,6 +985,36 @@ static int dispatch_auto_resize_mode(const char *name, JsonVariant *variant, Jso
         return 0;
 }
 
+static int dispatch_rebalance_weight(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
+        uint64_t *rebalance_weight = userdata;
+        uintmax_t u;
+
+        assert_se(rebalance_weight);
+
+        if (json_variant_is_null(variant)) {
+                *rebalance_weight = REBALANCE_WEIGHT_UNSET;
+                return 0;
+        }
+
+        if (json_variant_is_boolean(variant)) {
+                *rebalance_weight = json_variant_boolean(variant) ? REBALANCE_WEIGHT_DEFAULT : REBALANCE_WEIGHT_OFF;
+                return 0;
+        }
+
+        if (!json_variant_is_unsigned(variant))
+                return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an unsigned integer, boolean or null.", strna(name));
+
+        u = json_variant_unsigned(variant);
+        if (u >= REBALANCE_WEIGHT_MIN && u <= REBALANCE_WEIGHT_MAX)
+                *rebalance_weight = (uint64_t) u;
+        else if (u == 0)
+                *rebalance_weight = REBALANCE_WEIGHT_OFF;
+        else
+                return json_log(variant, flags, SYNTHETIC_ERRNO(ERANGE), "Rebalance weight is out of valid range %" PRIu64 "…%" PRIu64 ".", REBALANCE_WEIGHT_MIN, REBALANCE_WEIGHT_MAX);
+
+        return 0;
+}
+
 static int dispatch_privileged(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
 
         static const JsonDispatch privileged_dispatch_table[] = {
@@ -1177,6 +1208,7 @@ static int dispatch_per_machine(const char *name, JsonVariant *variant, JsonDisp
                 { "luksExtraMountOptions",      JSON_VARIANT_STRING,        json_dispatch_string,                 offsetof(UserRecord, luks_extra_mount_options),      0         },
                 { "dropCaches",                 JSON_VARIANT_BOOLEAN,       json_dispatch_tristate,               offsetof(UserRecord, drop_caches),                   0         },
                 { "autoResizeMode",             _JSON_VARIANT_TYPE_INVALID, dispatch_auto_resize_mode,            offsetof(UserRecord, auto_resize_mode),              0         },
+                { "rebalanceWeight",            _JSON_VARIANT_TYPE_INVALID, dispatch_rebalance_weight,            offsetof(UserRecord, rebalance_weight),              0         },
                 { "rateLimitIntervalUSec",      JSON_VARIANT_UNSIGNED,      json_dispatch_uint64,                 offsetof(UserRecord, ratelimit_interval_usec),       0         },
                 { "rateLimitBurst",             JSON_VARIANT_UNSIGNED,      json_dispatch_uint64,                 offsetof(UserRecord, ratelimit_burst),               0         },
                 { "enforcePasswordPolicy",      JSON_VARIANT_BOOLEAN,       json_dispatch_tristate,               offsetof(UserRecord, enforce_password_policy),       0         },
@@ -1528,6 +1560,7 @@ int user_record_load(UserRecord *h, JsonVariant *v, UserRecordLoadFlags load_fla
                 { "luksExtraMountOptions",      JSON_VARIANT_STRING,        json_dispatch_string,                 offsetof(UserRecord, luks_extra_mount_options),      0         },
                 { "dropCaches",                 JSON_VARIANT_BOOLEAN,       json_dispatch_tristate,               offsetof(UserRecord, drop_caches),                   0         },
                 { "autoResizeMode",             _JSON_VARIANT_TYPE_INVALID, dispatch_auto_resize_mode,            offsetof(UserRecord, auto_resize_mode),              0         },
+                { "rebalanceWeight",            _JSON_VARIANT_TYPE_INVALID, dispatch_rebalance_weight,            offsetof(UserRecord, rebalance_weight),              0         },
                 { "service",                    JSON_VARIANT_STRING,        json_dispatch_string,                 offsetof(UserRecord, service),                       JSON_SAFE },
                 { "rateLimitIntervalUSec",      JSON_VARIANT_UNSIGNED,      json_dispatch_uint64,                 offsetof(UserRecord, ratelimit_interval_usec),       0         },
                 { "rateLimitBurst",             JSON_VARIANT_UNSIGNED,      json_dispatch_uint64,                 offsetof(UserRecord, ratelimit_burst),               0         },
@@ -1939,6 +1972,15 @@ AutoResizeMode user_record_auto_resize_mode(UserRecord *h) {
         return user_record_storage(h) == USER_LUKS ? AUTO_RESIZE_SHRINK_AND_GROW : AUTO_RESIZE_OFF;
 }
 
+uint64_t user_record_rebalance_weight(UserRecord *h) {
+        assert(h);
+
+        if (h->rebalance_weight == REBALANCE_WEIGHT_UNSET)
+                return REBALANCE_WEIGHT_DEFAULT;
+
+        return h->rebalance_weight;
+}
+
 uint64_t user_record_ratelimit_next_try(UserRecord *h) {
         assert(h);
 
index c5424eef82ce5cb3ba0134d41c07ee8678c6b6dc..276b9150678407de2c6500d498972610bf133ddb 100644 (file)
@@ -221,6 +221,12 @@ typedef enum AutoResizeMode {
         _AUTO_RESIZE_MODE_INVALID = -EINVAL,
 } AutoResizeMode;
 
+#define REBALANCE_WEIGHT_OFF UINT64_C(0)
+#define REBALANCE_WEIGHT_DEFAULT UINT64_C(100)
+#define REBALANCE_WEIGHT_MIN UINT64_C(1)
+#define REBALANCE_WEIGHT_MAX UINT64_C(10000)
+#define REBALANCE_WEIGHT_UNSET UINT64_MAX
+
 typedef struct UserRecord {
         /* The following three fields are not part of the JSON record */
         unsigned n_ref;
@@ -258,6 +264,7 @@ typedef struct UserRecord {
         char *skeleton_directory;
         mode_t access_mode;
         AutoResizeMode auto_resize_mode;
+        uint64_t rebalance_weight;
 
         uint64_t tasks_max;
         uint64_t memory_high;
@@ -397,6 +404,7 @@ uint64_t user_record_ratelimit_burst(UserRecord *h);
 bool user_record_can_authenticate(UserRecord *h);
 bool user_record_drop_caches(UserRecord *h);
 AutoResizeMode user_record_auto_resize_mode(UserRecord *h);
+uint64_t user_record_rebalance_weight(UserRecord *h);
 
 int user_record_build_image_path(UserStorage storage, const char *user_name_and_realm, char **ret);