mirror of
https://github.com/systemd/systemd.git
synced 2024-12-23 21:35:11 +03:00
homed: add explicit API for requesting rebalancing too
This commit is contained in:
parent
d357b80d33
commit
4950591627
@ -96,6 +96,7 @@ node /org/freedesktop/home1 {
|
||||
ReleaseHome(in s user_name);
|
||||
LockAllHomes();
|
||||
DeactivateAllHomes();
|
||||
Rebalance();
|
||||
properties:
|
||||
readonly a(sso) AutoLogin = [...];
|
||||
};
|
||||
@ -159,6 +160,8 @@ node /org/freedesktop/home1 {
|
||||
|
||||
<variablelist class="dbus-method" generated="True" extra-ref="DeactivateAllHomes()"/>
|
||||
|
||||
<variablelist class="dbus-method" generated="True" extra-ref="Rebalance()"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="AutoLogin"/>
|
||||
|
||||
<!--End of Autogenerated section-->
|
||||
@ -346,6 +349,10 @@ node /org/freedesktop/home1 {
|
||||
|
||||
<para><function>DeactivateAllHomes()</function> deactivates all home areas that are currently
|
||||
active. This is usually invoked automatically shortly before system shutdown.</para>
|
||||
|
||||
<para><function>Rebalance()</function> synchronously rebalances free disk space between home
|
||||
areas. This only executes an operation if at least one home area using the LUKS2 backend is active and
|
||||
has rebalancing enabled, and is otherwise a NOP.</para>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
|
@ -635,6 +635,27 @@ static int method_deactivate_all_homes(sd_bus_message *message, void *userdata,
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
}
|
||||
|
||||
static int method_rebalance(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
Manager *m = userdata;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
r = manager_schedule_rebalance(m, /* immediately= */ true);
|
||||
if (r == 0)
|
||||
return sd_bus_reply_method_errorf(message, BUS_ERROR_REBALANCE_NOT_NEEDED, "No home directories need rebalancing.");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Keep a reference to this message, so that we can reply to it once we are done */
|
||||
r = set_ensure_put(&m->rebalance_queued_method_calls, &bus_message_hash_ops, message);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to track rebalance bus message: %m");
|
||||
|
||||
sd_bus_message_ref(message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const sd_bus_vtable manager_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
|
||||
@ -843,6 +864,7 @@ static const sd_bus_vtable manager_vtable[] = {
|
||||
/* An operation that acts on all homes that allow it */
|
||||
SD_BUS_METHOD("LockAllHomes", NULL, NULL, method_lock_all_homes, 0),
|
||||
SD_BUS_METHOD("DeactivateAllHomes", NULL, NULL, method_deactivate_all_homes, 0),
|
||||
SD_BUS_METHOD("Rebalance", NULL, NULL, method_rebalance, 0),
|
||||
|
||||
SD_BUS_VTABLE_END
|
||||
};
|
||||
|
@ -1985,6 +1985,24 @@ static int manager_rebalance_apply(Manager *m) {
|
||||
return c;
|
||||
}
|
||||
|
||||
static void manager_rebalance_reply_messages(Manager *m) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
for (;;) {
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *msg =
|
||||
set_steal_first(m->rebalance_pending_method_calls);
|
||||
|
||||
if (!msg)
|
||||
break;
|
||||
|
||||
r = sd_bus_reply_method_return(msg, NULL);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to reply to rebalance method call, ignoring: %m");
|
||||
}
|
||||
}
|
||||
|
||||
static int manager_rebalance_now(Manager *m) {
|
||||
RebalanceState busy_state; /* the state to revert to when operation fails if busy */
|
||||
int r;
|
||||
@ -2006,6 +2024,13 @@ static int manager_rebalance_now(Manager *m) {
|
||||
/* First shrink large home dirs */
|
||||
m->rebalance_state = REBALANCE_SHRINKING;
|
||||
busy_state = REBALANCE_PENDING;
|
||||
|
||||
/* We are initiating the next rebalancing cycle now, let's make the queued methods
|
||||
* calls the pending ones, and flush out any pending ones (which shouldn't exist at
|
||||
* this time anyway) */
|
||||
set_clear(m->rebalance_pending_method_calls);
|
||||
SWAP_TWO(m->rebalance_pending_method_calls, m->rebalance_queued_method_calls);
|
||||
|
||||
log_debug("Shrinking phase..");
|
||||
break;
|
||||
|
||||
@ -2055,6 +2080,7 @@ static int manager_rebalance_now(Manager *m) {
|
||||
finish:
|
||||
/* Reset state and schedule next rebalance */
|
||||
m->rebalance_state = REBALANCE_IDLE;
|
||||
manager_rebalance_reply_messages(m);
|
||||
(void) manager_schedule_rebalance(m, /* immediately= */ false);
|
||||
return r;
|
||||
}
|
||||
@ -2078,6 +2104,7 @@ int manager_schedule_rebalance(Manager *m, bool immediately) {
|
||||
/* Check if there are any records where rebalancing is requested */
|
||||
if (!manager_shall_rebalance(m)) {
|
||||
log_debug("Not scheduling rebalancing, not needed.");
|
||||
r = 0; /* report that we didn't schedule anything because nothing needed it */
|
||||
goto turn_off;
|
||||
}
|
||||
|
||||
@ -2118,13 +2145,13 @@ int manager_schedule_rebalance(Manager *m, bool immediately) {
|
||||
m->rebalance_state = REBALANCE_PENDING;
|
||||
|
||||
log_debug("Scheduled immediate rebalancing...");
|
||||
return 0;
|
||||
return 1; /* report that we scheduled something */
|
||||
}
|
||||
|
||||
/* If we are told to schedule a rebalancing eventually, then do so only if we are not executing
|
||||
* anything yet. Also if we have something scheduled already, leave it in place */
|
||||
if (!IN_SET(m->rebalance_state, REBALANCE_OFF, REBALANCE_IDLE))
|
||||
return 0;
|
||||
return 1; /* report that there's already something scheduled */
|
||||
|
||||
if (m->rebalance_event_source) {
|
||||
r = sd_event_source_set_time_relative(m->rebalance_event_source, m->rebalance_interval_usec);
|
||||
@ -2156,11 +2183,12 @@ int manager_schedule_rebalance(Manager *m, bool immediately) {
|
||||
|
||||
m->rebalance_state = REBALANCE_WAITING; /* We managed to enqueue a timer event, we now wait until it fires */
|
||||
log_debug("Scheduled rebalancing in %s...", FORMAT_TIMESPAN(m->rebalance_interval_usec, 0));
|
||||
return 0;
|
||||
return 1; /* report that we scheduled something */
|
||||
|
||||
turn_off:
|
||||
m->rebalance_event_source = sd_event_source_disable_unref(m->rebalance_event_source);
|
||||
m->rebalance_state = REBALANCE_OFF;
|
||||
manager_rebalance_reply_messages(m);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -63,6 +63,12 @@ struct Manager {
|
||||
|
||||
RebalanceState rebalance_state;
|
||||
usec_t rebalance_interval_usec;
|
||||
|
||||
/* In order to allow synchronous rebalance requests via bus calls we maintain two pools of bus
|
||||
* messages: 'rebalance_pending_methods' are the method calls we are currently operating on and
|
||||
* running a rebalancing operation for. 'rebalance_queued_method_calls' are the method calls that
|
||||
* have been queued since then and that we'll operate on once we complete the current run. */
|
||||
Set *rebalance_pending_method_calls, *rebalance_queued_method_calls;
|
||||
};
|
||||
|
||||
int manager_new(Manager **ret);
|
||||
|
@ -125,6 +125,10 @@
|
||||
send_interface="org.freedesktop.home1.Manager"
|
||||
send_member="LockAllHomes"/>
|
||||
|
||||
<allow send_destination="org.freedesktop.home1"
|
||||
send_interface="org.freedesktop.home1.Manager"
|
||||
send_member="Rebalance"/>
|
||||
|
||||
<!-- Home object -->
|
||||
|
||||
<allow send_destination="org.freedesktop.home1"
|
||||
|
@ -143,6 +143,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_AUTHENTICATION_LIMIT_HIT, ETOOMANYREFS),
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_HOME_CANT_AUTHENTICATE, EKEYREVOKED),
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_HOME_IN_USE, EADDRINUSE),
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_REBALANCE_NOT_NEEDED, EALREADY),
|
||||
|
||||
SD_BUS_ERROR_MAP_END
|
||||
};
|
||||
|
@ -127,5 +127,6 @@
|
||||
#define BUS_ERROR_AUTHENTICATION_LIMIT_HIT "org.freedesktop.home1.AuthenticationLimitHit"
|
||||
#define BUS_ERROR_HOME_CANT_AUTHENTICATE "org.freedesktop.home1.HomeCantAuthenticate"
|
||||
#define BUS_ERROR_HOME_IN_USE "org.freedesktop.home1.HomeInUse"
|
||||
#define BUS_ERROR_REBALANCE_NOT_NEEDED "org.freedesktop.home1.RebalanceNotNeeded"
|
||||
|
||||
BUS_ERROR_MAP_ELF_USE(bus_common_errors);
|
||||
|
Loading…
Reference in New Issue
Block a user