@@ -161,6 +161,7 @@ int home_new(Manager *m, UserRecord *hr, const char *sysfs, Home **ret) {
161161
162162 (void ) bus_manager_emit_auto_login_changed (m );
163163 (void ) bus_home_emit_change (home );
164+ (void ) manager_schedule_rebalance (m , /* immediately= */ false);
164165
165166 if (ret )
166167 * ret = TAKE_PTR (home );
@@ -193,6 +194,8 @@ Home *home_free(Home *h) {
193194
194195 if (h -> manager -> gc_focus == h )
195196 h -> manager -> gc_focus = NULL ;
197+
198+ (void ) manager_schedule_rebalance (h -> manager , /* immediately= */ false);
196199 }
197200
198201 user_record_unref (h -> record );
@@ -489,6 +492,7 @@ static void home_set_state(Home *h, HomeState state) {
489492 * enqueue it for GC too. */
490493
491494 home_schedule_operation (h , NULL , NULL );
495+ manager_reschedule_rebalance (h -> manager );
492496 manager_enqueue_gc (h -> manager , h );
493497 }
494498}
@@ -727,6 +731,7 @@ static void home_fixate_finish(Home *h, int ret, UserRecord *hr) {
727731 /* Reset the state to "invalid", which makes home_get_state() test if the image exists and returns
728732 * HOME_ABSENT vs. HOME_INACTIVE as necessary. */
729733 home_set_state (h , _HOME_STATE_INVALID );
734+ (void ) manager_schedule_rebalance (h -> manager , /* immediately= */ false);
730735 return ;
731736
732737fail :
@@ -781,6 +786,9 @@ static void home_activate_finish(Home *h, int ret, UserRecord *hr) {
781786finish :
782787 h -> current_operation = operation_result_unref (h -> current_operation , r , & error );
783788 home_set_state (h , _HOME_STATE_INVALID );
789+
790+ if (r >= 0 )
791+ (void ) manager_schedule_rebalance (h -> manager , /* immediately= */ true);
784792}
785793
786794static void home_deactivate_finish (Home * h , int ret , UserRecord * hr ) {
@@ -803,6 +811,9 @@ static void home_deactivate_finish(Home *h, int ret, UserRecord *hr) {
803811finish :
804812 h -> current_operation = operation_result_unref (h -> current_operation , r , & error );
805813 home_set_state (h , _HOME_STATE_INVALID );
814+
815+ if (r >= 0 )
816+ (void ) manager_schedule_rebalance (h -> manager , /* immediately= */ true);
806817}
807818
808819static void home_remove_finish (Home * h , int ret , UserRecord * hr ) {
@@ -841,6 +852,8 @@ static void home_remove_finish(Home *h, int ret, UserRecord *hr) {
841852
842853 /* Unload this record from memory too now. */
843854 h = home_free (h );
855+
856+ (void ) manager_schedule_rebalance (m , /* immediately= */ true);
844857 return ;
845858
846859fail :
@@ -885,6 +898,8 @@ static void home_create_finish(Home *h, int ret, UserRecord *hr) {
885898
886899 h -> current_operation = operation_result_unref (h -> current_operation , 0 , NULL );
887900 home_set_state (h , _HOME_STATE_INVALID );
901+
902+ (void ) manager_schedule_rebalance (h -> manager , /* immediately= */ true);
888903}
889904
890905static void home_change_finish (Home * h , int ret , UserRecord * hr ) {
@@ -918,6 +933,7 @@ static void home_change_finish(Home *h, int ret, UserRecord *hr) {
918933 }
919934
920935 log_debug ("Change operation of %s completed." , h -> user_name );
936+ (void ) manager_schedule_rebalance (h -> manager , /* immediately= */ false);
921937 r = 0 ;
922938
923939finish :
@@ -1683,7 +1699,12 @@ int home_update(Home *h, UserRecord *hr, sd_bus_error *error) {
16831699 return 0 ;
16841700}
16851701
1686- int home_resize (Home * h , uint64_t disk_size , UserRecord * secret , sd_bus_error * error ) {
1702+ int home_resize (Home * h ,
1703+ uint64_t disk_size ,
1704+ UserRecord * secret ,
1705+ bool automatic ,
1706+ sd_bus_error * error ) {
1707+
16871708 _cleanup_ (user_record_unrefp ) UserRecord * c = NULL ;
16881709 HomeState state ;
16891710 int r ;
@@ -1711,6 +1732,12 @@ int home_resize(Home *h, uint64_t disk_size, UserRecord *secret, sd_bus_error *e
17111732 if (r < 0 )
17121733 return r ;
17131734
1735+ /* If the user didn't specify any size explicitly and rebalancing is on, then the disk size is
1736+ * determined by automatic rebalancing and hence not user configured but determined by us and thus
1737+ * applied anyway. */
1738+ if (disk_size == UINT64_MAX && h -> record -> rebalance_weight != REBALANCE_WEIGHT_OFF )
1739+ return sd_bus_error_set (error , SD_BUS_ERROR_INVALID_ARGS , "Disk size is being determined by automatic disk space rebalancing." );
1740+
17141741 if (disk_size == UINT64_MAX || disk_size == h -> record -> disk_size ) {
17151742 if (h -> record -> disk_size == UINT64_MAX )
17161743 return sd_bus_error_set (error , SD_BUS_ERROR_INVALID_ARGS , "No disk size to resize to specified." );
@@ -1732,6 +1759,11 @@ int home_resize(Home *h, uint64_t disk_size, UserRecord *secret, sd_bus_error *e
17321759 if (r < 0 )
17331760 return r ;
17341761
1762+ /* If user picked an explicit size, then turn off rebalancing, so that we don't undo what user chose */
1763+ r = user_record_set_rebalance_weight (c , REBALANCE_WEIGHT_OFF );
1764+ if (r < 0 )
1765+ return r ;
1766+
17351767 r = user_record_update_last_changed (c , false);
17361768 if (r == - ECHRNG )
17371769 return sd_bus_error_setf (error , BUS_ERROR_HOME_RECORD_MISMATCH , "Record last change time of %s is newer than current time, cannot update." , h -> user_name );
@@ -1746,7 +1778,7 @@ int home_resize(Home *h, uint64_t disk_size, UserRecord *secret, sd_bus_error *e
17461778 c = TAKE_PTR (signed_c );
17471779 }
17481780
1749- r = home_update_internal (h , "resize" , c , secret , error );
1781+ r = home_update_internal (h , automatic ? "resize-auto" : "resize" , c , secret , error );
17501782 if (r < 0 )
17511783 return r ;
17521784
@@ -2965,6 +2997,8 @@ static int on_pending(sd_event_source *s, void *userdata) {
29652997 if (r < 0 )
29662998 return log_error_errno (r , "Failed to disable event source: %m" );
29672999
3000+ /* No operations pending anymore, maybe this is a good time to trigger a rebalancing */
3001+ manager_reschedule_rebalance (h -> manager );
29683002 return 0 ;
29693003}
29703004
@@ -3121,6 +3155,35 @@ int home_wait_for_worker(Home *h) {
31213155 return 1 ;
31223156}
31233157
3158+ bool home_shall_rebalance (Home * h ) {
3159+ HomeState state ;
3160+
3161+ assert (h );
3162+
3163+ /* Determines if the home directory is a candidate for rebalancing */
3164+
3165+ if (!user_record_shall_rebalance (h -> record ))
3166+ return false;
3167+
3168+ state = home_get_state (h );
3169+ if (!HOME_STATE_SHALL_REBALANCE (state ))
3170+ return false;
3171+
3172+ return true;
3173+ }
3174+
3175+ bool home_is_busy (Home * h ) {
3176+ assert (h );
3177+
3178+ if (h -> current_operation )
3179+ return true;
3180+
3181+ if (!ordered_set_isempty (h -> pending_operations ))
3182+ return true;
3183+
3184+ return HOME_STATE_IS_EXECUTING_OPERATION (home_get_state (h ));
3185+ }
3186+
31243187static const char * const home_state_table [_HOME_STATE_MAX ] = {
31253188 [HOME_UNFIXATED ] = "unfixated" ,
31263189 [HOME_ABSENT ] = "absent" ,
0 commit comments