diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 0e029de97e..ef00a4b26f 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -131,11 +131,6 @@ typedef struct { bool configure; } SlaveInfo; -typedef struct { - NMDevice *device; - guint idle_add_id; -} DeleteOnDeactivateData; - typedef struct { NMDevice *device; GCancellable *cancellable; @@ -335,7 +330,6 @@ enum { IP6_PREFIX_DELEGATED, IP6_SUBNET_NEEDED, REMOVED, - RECHECK_AUTO_ACTIVATE, RECHECK_ASSUME, DNS_LOOKUP_DONE, PLATFORM_ADDRESS_CHANGED, @@ -513,8 +507,8 @@ typedef struct _NMDevicePrivate { NMUnmanagedFlags unmanaged_mask; NMUnmanagedFlags unmanaged_flags; - DeleteOnDeactivateData - *delete_on_deactivate_data; /* data for scheduled cleanup when deleting link (g_idle_add) */ + + GSource *delete_on_deactivate_idle_source; GCancellable *deactivating_cancellable; @@ -6444,7 +6438,7 @@ carrier_changed(NMDevice *self, gboolean carrier) * when the carrier appears, auto connections are rechecked for * the device. */ - nm_device_emit_recheck_auto_activate(self); + nm_device_recheck_auto_activate_schedule(self); } } else { if (priv->state == NM_DEVICE_STATE_UNAVAILABLE) { @@ -6768,7 +6762,7 @@ device_link_changed(gpointer user_data) /* Let any connections that use the new interface name have a chance * to auto-activate on the device. */ - nm_device_emit_recheck_auto_activate(self); + nm_device_recheck_auto_activate_schedule(self); } if (priv->ipac6_data.ndisc && pllink->inet6_token.id) { @@ -7703,7 +7697,7 @@ nm_device_unrealize(NMDevice *self, gboolean remove_resources, GError **error) /* In case the unrealized device is not going away, it may need to * autoactivate. Schedule also a check for that. */ - nm_device_emit_recheck_auto_activate(self); + nm_device_recheck_auto_activate_schedule(self); return TRUE; } @@ -7725,7 +7719,7 @@ nm_device_notify_availability_maybe_changed(NMDevice *self) * available. */ nm_device_recheck_available_connections(self); if (g_hash_table_size(priv->available_connections) > 0) - nm_device_emit_recheck_auto_activate(self); + nm_device_recheck_auto_activate_schedule(self); } /** @@ -8335,7 +8329,7 @@ nm_device_autoconnect_allowed(NMDevice *self) return FALSE; } - if (priv->delete_on_deactivate_data) + if (priv->delete_on_deactivate_idle_source) return FALSE; /* The 'autoconnect-allowed' signal is emitted on a device to allow @@ -9081,9 +9075,9 @@ nm_device_queue_recheck_available(NMDevice *self, } void -nm_device_emit_recheck_auto_activate(NMDevice *self) +nm_device_recheck_auto_activate_schedule(NMDevice *self) { - g_signal_emit(self, signals[RECHECK_AUTO_ACTIVATE], 0); + nm_manager_device_recheck_auto_activate_schedule(nm_device_get_manager(self), self); } void @@ -12614,24 +12608,24 @@ nm_device_is_nm_owned(NMDevice *self) static gboolean delete_on_deactivate_link_delete(gpointer user_data) { - DeleteOnDeactivateData *data = user_data; - nm_auto_unref_object NMDevice *self = data->device; + nm_auto_unref_object NMDevice *self = user_data; NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); gs_free_error GError *error = NULL; - _LOGD(LOGD_DEVICE, - "delete_on_deactivate: cleanup and delete virtual link (id=%u)", - data->idle_add_id); + _LOGD(LOGD_DEVICE, "delete_on_deactivate: cleanup and delete virtual link"); - priv->delete_on_deactivate_data = NULL; + nm_clear_g_source_inst(&priv->delete_on_deactivate_idle_source); if (!nm_device_unrealize(self, TRUE, &error)) _LOGD(LOGD_DEVICE, "delete_on_deactivate: unrealizing failed (%s)", error->message); - nm_device_emit_recheck_auto_activate(self); + if (nm_dbus_object_is_exported(NM_DBUS_OBJECT(self))) { + /* The device is still alive. We may need to autoactivate virtual + * devices again. */ + nm_device_recheck_auto_activate_schedule(self); + } - g_free(data); - return FALSE; + return G_SOURCE_CONTINUE; } static void @@ -12639,25 +12633,16 @@ delete_on_deactivate_unschedule(NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - if (priv->delete_on_deactivate_data) { - DeleteOnDeactivateData *data = priv->delete_on_deactivate_data; - - priv->delete_on_deactivate_data = NULL; - - g_source_remove(data->idle_add_id); - _LOGD(LOGD_DEVICE, - "delete_on_deactivate: cancel cleanup and delete virtual link (id=%u)", - data->idle_add_id); - g_object_unref(data->device); - g_free(data); + if (nm_clear_g_source_inst(&priv->delete_on_deactivate_idle_source)) { + _LOGD(LOGD_DEVICE, "delete_on_deactivate: cancel cleanup and delete virtual link"); + g_object_unref(self); } } static void delete_on_deactivate_check_and_schedule(NMDevice *self) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - DeleteOnDeactivateData *data; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); if (!priv->nm_owned) return; @@ -12671,14 +12656,11 @@ delete_on_deactivate_check_and_schedule(NMDevice *self) return; delete_on_deactivate_unschedule(self); /* always cancel and reschedule */ - data = g_new(DeleteOnDeactivateData, 1); - data->device = g_object_ref(self); - data->idle_add_id = g_idle_add(delete_on_deactivate_link_delete, data); - priv->delete_on_deactivate_data = data; + g_object_ref(self); + priv->delete_on_deactivate_idle_source = + nm_g_idle_add_source(delete_on_deactivate_link_delete, self); - _LOGD(LOGD_DEVICE, - "delete_on_deactivate: schedule cleanup and delete virtual link (id=%u)", - data->idle_add_id); + _LOGD(LOGD_DEVICE, "delete_on_deactivate: schedule cleanup and delete virtual link"); } static void @@ -17768,6 +17750,7 @@ nm_device_init(NMDevice *self) c_list_init(&priv->concheck_lst_head); c_list_init(&self->devices_lst); + c_list_init(&self->policy_auto_activate_lst); c_list_init(&priv->slaves); priv->ipdhcp_data_6.v6.mode = NM_NDISC_DHCP_LEVEL_NONE; @@ -17888,6 +17871,8 @@ dispose(GObject *object) _LOGD(LOGD_DEVICE, "disposing"); nm_assert(c_list_is_empty(&self->devices_lst)); + nm_assert(c_list_is_empty(&self->policy_auto_activate_lst)); + nm_assert(!self->policy_auto_activate_idle_source); while ((con_handle = c_list_first_entry(&priv->concheck_lst_head, NMDeviceConnectivityHandle, @@ -18550,16 +18535,6 @@ nm_device_class_init(NMDeviceClass *klass) G_TYPE_NONE, 0); - signals[RECHECK_AUTO_ACTIVATE] = g_signal_new(NM_DEVICE_RECHECK_AUTO_ACTIVATE, - G_OBJECT_CLASS_TYPE(object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, - NULL, - NULL, - G_TYPE_NONE, - 0); - signals[RECHECK_ASSUME] = g_signal_new(NM_DEVICE_RECHECK_ASSUME, G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_FIRST, diff --git a/src/core/devices/nm-device.h b/src/core/devices/nm-device.h index a9dc18b19d..ac843a39cb 100644 --- a/src/core/devices/nm-device.h +++ b/src/core/devices/nm-device.h @@ -75,7 +75,6 @@ #define NM_DEVICE_IP6_PREFIX_DELEGATED "ip6-prefix-delegated" #define NM_DEVICE_IP6_SUBNET_NEEDED "ip6-subnet-needed" #define NM_DEVICE_REMOVED "removed" -#define NM_DEVICE_RECHECK_AUTO_ACTIVATE "recheck-auto-activate" #define NM_DEVICE_RECHECK_ASSUME "recheck-assume" #define NM_DEVICE_STATE_CHANGED "state-changed" #define NM_DEVICE_LINK_INITIALIZED "link-initialized" @@ -144,6 +143,9 @@ struct _NMDevice { NMDBusObject parent; struct _NMDevicePrivate *_priv; CList devices_lst; + + CList policy_auto_activate_lst; + GSource *policy_auto_activate_idle_source; }; /* The flags have an relaxing meaning, that means, specifying more flags, can make @@ -294,7 +296,7 @@ typedef struct _NMDeviceClass { GPtrArray *(*get_extra_rules)(NMDevice *self); /* allow derived classes to override the result of nm_device_autoconnect_allowed(). - * If the value changes, the class should call nm_device_emit_recheck_auto_activate(), + * If the value changes, the class should call nm_device_recheck_auto_activate_schedule(), * which emits NM_DEVICE_RECHECK_AUTO_ACTIVATE signal. */ gboolean (*get_autoconnect_allowed)(NMDevice *self); @@ -705,7 +707,7 @@ nm_device_autoconnect_blocked_unset(NMDevice *device, NMDeviceAutoconnectBlocked nm_device_autoconnect_blocked_set_full(device, mask, NM_DEVICE_AUTOCONNECT_BLOCKED_NONE); } -void nm_device_emit_recheck_auto_activate(NMDevice *device); +void nm_device_recheck_auto_activate_schedule(NMDevice *device); NMDeviceSysIfaceState nm_device_sys_iface_state_get(NMDevice *device); diff --git a/src/core/devices/ovs/nm-device-ovs-interface.c b/src/core/devices/ovs/nm-device-ovs-interface.c index 711f65cb5b..8b0fc7f79c 100644 --- a/src/core/devices/ovs/nm-device-ovs-interface.c +++ b/src/core/devices/ovs/nm-device-ovs-interface.c @@ -479,7 +479,7 @@ ovsdb_ready(NMOvsdb *ovsdb, NMDeviceOvsInterface *self) NM_DEVICE_STATE_REASON_NONE, NM_DEVICE_STATE_REASON_NONE); nm_device_recheck_available_connections(device); - nm_device_emit_recheck_auto_activate(device); + nm_device_recheck_auto_activate_schedule(device); } static void diff --git a/src/core/devices/wifi/nm-device-iwd.c b/src/core/devices/wifi/nm-device-iwd.c index e03227cd03..6bb420354f 100644 --- a/src/core/devices/wifi/nm-device-iwd.c +++ b/src/core/devices/wifi/nm-device-iwd.c @@ -159,7 +159,7 @@ ap_add_remove(NMDeviceIwd *self, } if (priv->enabled && !priv->iwd_autoconnect) - nm_device_emit_recheck_auto_activate(NM_DEVICE(self)); + nm_device_recheck_auto_activate_schedule(NM_DEVICE(self)); if (recheck_available_connections) nm_device_recheck_available_connections(NM_DEVICE(self)); @@ -208,7 +208,7 @@ remove_all_aps(NMDeviceIwd *self) ap_add_remove(self, FALSE, ap, FALSE); if (!priv->iwd_autoconnect) - nm_device_emit_recheck_auto_activate(NM_DEVICE(self)); + nm_device_recheck_auto_activate_schedule(NM_DEVICE(self)); nm_device_recheck_available_connections(NM_DEVICE(self)); } @@ -401,7 +401,7 @@ get_ordered_networks_cb(GObject *source, GAsyncResult *res, gpointer user_data) if (changed) { if (!priv->iwd_autoconnect) - nm_device_emit_recheck_auto_activate(NM_DEVICE(self)); + nm_device_recheck_auto_activate_schedule(NM_DEVICE(self)); nm_device_recheck_available_connections(NM_DEVICE(self)); } @@ -1682,7 +1682,7 @@ failed: if (!priv->nm_autoconnect) { priv->nm_autoconnect = true; - nm_device_emit_recheck_auto_activate(device); + nm_device_recheck_auto_activate_schedule(device); } } g_variant_unref(value); @@ -2908,7 +2908,7 @@ state_changed(NMDeviceIwd *self, const char *new_state) if (!priv->iwd_autoconnect && NM_IN_STRSET(new_state, "disconnected")) { priv->nm_autoconnect = TRUE; if (!can_connect) - nm_device_emit_recheck_auto_activate(device); + nm_device_recheck_auto_activate_schedule(device); } } diff --git a/src/core/devices/wifi/nm-device-olpc-mesh.c b/src/core/devices/wifi/nm-device-olpc-mesh.c index 4705f75ce3..436c7847ab 100644 --- a/src/core/devices/wifi/nm-device-olpc-mesh.c +++ b/src/core/devices/wifi/nm-device-olpc-mesh.c @@ -270,7 +270,7 @@ companion_state_changed_cb(NMDeviceWifi *companion, NMDeviceState self_state = nm_device_get_state(NM_DEVICE(self)); if (old_state > NM_DEVICE_STATE_DISCONNECTED && state <= NM_DEVICE_STATE_DISCONNECTED) { - nm_device_emit_recheck_auto_activate(NM_DEVICE(self)); + nm_device_recheck_auto_activate_schedule(NM_DEVICE(self)); } if (self_state < NM_DEVICE_STATE_PREPARE || self_state > NM_DEVICE_STATE_ACTIVATED diff --git a/src/core/devices/wifi/nm-device-wifi.c b/src/core/devices/wifi/nm-device-wifi.c index 03625f8d6d..9012a59bef 100644 --- a/src/core/devices/wifi/nm-device-wifi.c +++ b/src/core/devices/wifi/nm-device-wifi.c @@ -483,7 +483,7 @@ _scan_notify_is_scanning(NMDeviceWifi *self) if (!_scan_is_scanning_eval(priv)) { if (state <= NM_DEVICE_STATE_DISCONNECTED || state > NM_DEVICE_STATE_ACTIVATED) - nm_device_emit_recheck_auto_activate(NM_DEVICE(self)); + nm_device_recheck_auto_activate_schedule(NM_DEVICE(self)); nm_device_remove_pending_action(NM_DEVICE(self), NM_PENDING_ACTION_WIFI_SCAN, FALSE); } @@ -843,7 +843,7 @@ ap_add_remove(NMDeviceWifi *self, nm_dbus_object_clear_and_unexport(&ap); } - nm_device_emit_recheck_auto_activate(NM_DEVICE(self)); + nm_device_recheck_auto_activate_schedule(NM_DEVICE(self)); if (recheck_available_connections) nm_device_recheck_available_connections(NM_DEVICE(self)); } diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c index 19ca1d1e9b..c0af846c1f 100644 --- a/src/core/nm-manager.c +++ b/src/core/nm-manager.c @@ -2666,6 +2666,16 @@ _rfkill_update_from_user(NMManager *self, NMRfkillType rtype, gboolean enabled) /*****************************************************************************/ +void +nm_manager_device_recheck_auto_activate_schedule(NMManager *self, NMDevice *device) +{ + g_return_if_fail(NM_IS_MANAGER(self)); + + nm_policy_device_recheck_auto_activate_schedule(NM_MANAGER_GET_PRIVATE(self)->policy, device); +} + +/*****************************************************************************/ + static void device_auth_done_cb(NMAuthChain *chain, GDBusMethodInvocation *context, gpointer user_data) { @@ -3449,7 +3459,7 @@ _device_realize_finish(NMManager *self, NMDevice *device, const NMPlatformLink * nm_device_state_changed(device, NM_DEVICE_STATE_UNAVAILABLE, NM_DEVICE_STATE_REASON_NOW_MANAGED); - nm_device_emit_recheck_auto_activate(device); + nm_manager_device_recheck_auto_activate_schedule(self, device); } /** @@ -7963,6 +7973,14 @@ nm_settings_get(void) return NM_MANAGER_GET_PRIVATE(singleton_instance)->settings; } +NMPolicy * +nm_manager_get_policy(NMManager *self) +{ + g_return_val_if_fail(NM_IS_MANAGER(self), NULL); + + return NM_MANAGER_GET_PRIVATE(self)->policy; +} + NMManager * nm_manager_setup(void) { diff --git a/src/core/nm-manager.h b/src/core/nm-manager.h index 0cbbcbf0ae..1bf8ded3af 100644 --- a/src/core/nm-manager.h +++ b/src/core/nm-manager.h @@ -69,6 +69,8 @@ NMManager *nm_manager_setup(void); NMManager *nm_manager_get(void); #define NM_MANAGER_GET (nm_manager_get()) +NMPolicy *nm_manager_get_policy(NMManager *self); + gboolean nm_manager_start(NMManager *manager, GError **error); void nm_manager_stop(NMManager *manager); NMState nm_manager_get_state(NMManager *manager); @@ -121,6 +123,8 @@ NMSettingsConnection **nm_manager_get_activatable_connections(NMManager *manager gboolean sort, guint *out_len); +void nm_manager_device_recheck_auto_activate_schedule(NMManager *self, NMDevice *device); + void nm_manager_write_device_state_all(NMManager *manager); gboolean nm_manager_write_device_state(NMManager *manager, NMDevice *device, int *out_ifindex); diff --git a/src/core/nm-policy.c b/src/core/nm-policy.c index d7e05b7b5b..6dcdeb4c66 100644 --- a/src/core/nm-policy.c +++ b/src/core/nm-policy.c @@ -51,7 +51,7 @@ typedef struct { NMManager *manager; NMNetns *netns; NMFirewalldManager *firewalld_manager; - CList pending_activation_checks; + CList policy_auto_activate_lst_head; NMAgentManager *agent_mgr; @@ -62,6 +62,10 @@ typedef struct { NMSettings *settings; + GSource *device_recheck_auto_activate_all_idle_source; + + GSource *reset_connections_retries_idle_source; + NMHostnameManager *hostname_manager; NMActiveConnection *default_ac4, *activating_ac4; @@ -70,10 +74,6 @@ typedef struct { NMDnsManager *dns_manager; gulong config_changed_id; - guint reset_retries_id; /* idle handler for resetting the retries count */ - - guint schedule_activate_all_id; /* idle handler for schedule_activate_all(). */ - NMPolicyHostnameMode hostname_mode; char *orig_hostname; /* hostname at NM start time */ char *cur_hostname; /* hostname we want to assign */ @@ -135,8 +135,7 @@ _PRIV_TO_SELF(NMPolicyPrivate *priv) /*****************************************************************************/ static void update_system_hostname(NMPolicy *self, const char *msg); -static void schedule_activate_all(NMPolicy *self); -static void schedule_activate_check(NMPolicy *self, NMDevice *device); +static void nm_policy_device_recheck_auto_activate_all_schedule(NMPolicy *self); static NMDevice *get_default_device(NMPolicy *self, int addr_family); /*****************************************************************************/ @@ -1283,23 +1282,6 @@ check_activating_active_connections(NMPolicy *self) g_object_thaw_notify(G_OBJECT(self)); } -typedef struct { - CList pending_lst; - NMPolicy *policy; - NMDevice *device; - guint autoactivate_id; -} ActivateData; - -static void -activate_data_free(ActivateData *data) -{ - nm_device_remove_pending_action(data->device, NM_PENDING_ACTION_AUTOACTIVATE, TRUE); - c_list_unlink_stale(&data->pending_lst); - nm_clear_g_source(&data->autoactivate_id); - g_object_unref(data->device); - g_slice_free(ActivateData, data); -} - static void pending_ac_gone(gpointer data, GObject *where_the_object_was) { @@ -1332,7 +1314,8 @@ pending_ac_state_changed(NMActiveConnection *ac, guint state, guint reason, NMPo con, NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED, TRUE); - schedule_activate_check(self, nm_active_connection_get_device(ac)); + nm_policy_device_recheck_auto_activate_schedule(self, + nm_active_connection_get_device(ac)); } /* Cleanup */ @@ -1345,7 +1328,7 @@ pending_ac_state_changed(NMActiveConnection *ac, guint state, guint reason, NMPo } static void -auto_activate_device(NMPolicy *self, NMDevice *device) +_auto_activate_device(NMPolicy *self, NMDevice *device) { NMPolicyPrivate *priv; NMSettingsConnection *best_connection; @@ -1439,7 +1422,7 @@ auto_activate_device(NMPolicy *self, NMDevice *device) best_connection, NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED, TRUE); - schedule_activate_check(self, device); + nm_policy_device_recheck_auto_activate_schedule(self, device); return; } @@ -1456,32 +1439,33 @@ auto_activate_device(NMPolicy *self, NMDevice *device) } } -static gboolean -auto_activate_device_cb(gpointer user_data) +static void +_auto_activate_device_clear(NMPolicy *self, NMDevice *device, gboolean do_activate) { - ActivateData *data = user_data; + nm_assert(NM_IS_DEVICE(device)); + nm_assert(NM_IS_POLICY(self)); + nm_assert(c_list_is_linked(&device->policy_auto_activate_lst)); + nm_assert(c_list_contains(&NM_POLICY_GET_PRIVATE(self)->policy_auto_activate_lst_head, + &device->policy_auto_activate_lst)); - g_assert(data); - g_assert(NM_IS_POLICY(data->policy)); - g_assert(NM_IS_DEVICE(data->device)); + c_list_unlink(&device->policy_auto_activate_lst); + nm_clear_g_source_inst(&device->policy_auto_activate_idle_source); - data->autoactivate_id = 0; - auto_activate_device(data->policy, data->device); - activate_data_free(data); - return G_SOURCE_REMOVE; + if (do_activate) + _auto_activate_device(self, device); + + nm_device_remove_pending_action(device, NM_PENDING_ACTION_AUTOACTIVATE, TRUE); } -static ActivateData * -find_pending_activation(NMPolicy *self, NMDevice *device) +static gboolean +_auto_activate_idle_cb(gpointer user_data) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self); - ActivateData *data; + NMDevice *device = user_data; - c_list_for_each_entry (data, &priv->pending_activation_checks, pending_lst) { - if (data->device == device) - return data; - } - return NULL; + nm_assert(NM_IS_DEVICE(device)); + + _auto_activate_device_clear(nm_manager_get_policy(nm_device_get_manager(device)), device, TRUE); + return G_SOURCE_CONTINUE; } /*****************************************************************************/ @@ -1683,23 +1667,37 @@ sleeping_changed(NMManager *manager, GParamSpec *pspec, gpointer user_data) reset_autoconnect_all(self, NULL, FALSE); } -static void -schedule_activate_check(NMPolicy *self, NMDevice *device) +void +nm_policy_device_recheck_auto_activate_schedule(NMPolicy *self, NMDevice *device) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self); - ActivateData *data; + NMPolicyPrivate *priv; NMActiveConnection *ac; const CList *tmp_list; + g_return_if_fail(NM_IS_POLICY(self)); + g_return_if_fail(NM_IS_DEVICE(device)); + nm_assert(g_signal_handler_find(device, + G_SIGNAL_MATCH_DATA, + 0, + 0, + NULL, + NULL, + NM_POLICY_GET_PRIVATE(self)) + != 0); + + if (!c_list_is_empty(&device->policy_auto_activate_lst)) { + /* already queued. Return. */ + return; + } + + priv = NM_POLICY_GET_PRIVATE(self); + if (nm_manager_get_state(priv->manager) == NM_STATE_ASLEEP) return; if (!nm_device_autoconnect_allowed(device)) return; - if (find_pending_activation(self, device)) - return; - nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) { if (nm_active_connection_get_device(ac) == device) { if (nm_device_sys_iface_state_is_external(device) @@ -1712,11 +1710,8 @@ schedule_activate_check(NMPolicy *self, NMDevice *device) nm_device_add_pending_action(device, NM_PENDING_ACTION_AUTOACTIVATE, TRUE); - data = g_slice_new0(ActivateData); - data->policy = self; - data->device = g_object_ref(device); - data->autoactivate_id = g_idle_add(auto_activate_device_cb, data); - c_list_link_tail(&priv->pending_activation_checks, &data->pending_lst); + c_list_link_tail(&priv->policy_auto_activate_lst_head, &device->policy_auto_activate_lst); + device->policy_auto_activate_idle_source = nm_g_idle_add_source(_auto_activate_idle_cb, device); } static gboolean @@ -1729,7 +1724,7 @@ reset_connections_retries(gpointer user_data) gint32 con_stamp, min_stamp, now; gboolean changed = FALSE; - priv->reset_retries_id = 0; + nm_clear_g_source_inst(&priv->reset_connections_retries_idle_source); min_stamp = 0; now = nm_utils_get_monotonic_timestamp_sec(); @@ -1749,15 +1744,16 @@ reset_connections_retries(gpointer user_data) } /* Schedule the handler again if there are some stamps left */ - if (min_stamp != 0) - priv->reset_retries_id = - g_timeout_add_seconds(min_stamp - now, reset_connections_retries, self); + if (min_stamp != 0) { + priv->reset_connections_retries_idle_source = + nm_g_timeout_add_seconds_source(min_stamp - now, reset_connections_retries, self); + } /* If anything changed, try to activate the newly re-enabled connections */ if (changed) - schedule_activate_all(self); + nm_policy_device_recheck_auto_activate_all_schedule(self); - return FALSE; + return G_SOURCE_CONTINUE; } static void @@ -1772,15 +1768,15 @@ _connection_autoconnect_retries_set(NMPolicy *self, NMSettingsConnection *connec if (tries == 0) { /* Schedule a handler to reset retries count */ - if (!priv->reset_retries_id) { + if (!priv->reset_connections_retries_idle_source) { gint32 retry_time = nm_settings_connection_autoconnect_retries_blocked_until(connection); g_warn_if_fail(retry_time != 0); - priv->reset_retries_id = - g_timeout_add_seconds(MAX(0, retry_time - nm_utils_get_monotonic_timestamp_sec()), - reset_connections_retries, - self); + priv->reset_connections_retries_idle_source = nm_g_timeout_add_seconds_source( + MAX(0, retry_time - nm_utils_get_monotonic_timestamp_sec()), + reset_connections_retries, + self); } } } @@ -1853,7 +1849,7 @@ activate_slave_connections(NMPolicy *self, NMDevice *device) } if (changed) - schedule_activate_all(self); + nm_policy_device_recheck_auto_activate_all_schedule(self); } static gboolean @@ -2126,7 +2122,7 @@ device_state_changed(NMDevice *device, update_routing_and_dns(self, FALSE, device); /* Device is now available for auto-activation */ - schedule_activate_check(self, device); + nm_policy_device_recheck_auto_activate_schedule(self, device); break; case NM_DEVICE_STATE_PREPARE: @@ -2248,16 +2244,7 @@ device_autoconnect_changed(NMDevice *device, GParamSpec *pspec, gpointer user_da NMPolicyPrivate *priv = user_data; NMPolicy *self = _PRIV_TO_SELF(priv); - schedule_activate_check(self, device); -} - -static void -device_recheck_auto_activate(NMDevice *device, gpointer user_data) -{ - NMPolicyPrivate *priv = user_data; - NMPolicy *self = _PRIV_TO_SELF(priv); - - schedule_activate_check(self, device); + nm_policy_device_recheck_auto_activate_schedule(self, device); } static void @@ -2292,10 +2279,6 @@ devices_list_register(NMPolicy *self, NMDevice *device) "notify::" NM_DEVICE_AUTOCONNECT, G_CALLBACK(device_autoconnect_changed), priv); - g_signal_connect(device, - NM_DEVICE_RECHECK_AUTO_ACTIVATE, - G_CALLBACK(device_recheck_auto_activate), - priv); } static void @@ -2319,16 +2302,13 @@ device_removed(NMManager *manager, NMDevice *device, gpointer user_data) { NMPolicyPrivate *priv = user_data; NMPolicy *self = _PRIV_TO_SELF(priv); - ActivateData *data; /* TODO: is this needed? The delegations are cleaned up * on transition to deactivated too. */ ip6_remove_device_prefix_delegations(self, device); - /* Clear any idle callbacks for this device */ - data = find_pending_activation(self, device); - if (data && data->autoactivate_id) - activate_data_free(data); + if (c_list_is_linked(&device->policy_auto_activate_lst)) + _auto_activate_device_clear(self, device, FALSE); if (g_hash_table_remove(priv->devices, device)) devices_list_unregister(self, device); @@ -2508,39 +2488,43 @@ active_connection_removed(NMManager *manager, NMActiveConnection *active, gpoint /*****************************************************************************/ static gboolean -schedule_activate_all_cb(gpointer user_data) +_device_recheck_auto_activate_all_cb(gpointer user_data) { NMPolicy *self = user_data; NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self); const CList *tmp_lst; NMDevice *device; - priv->schedule_activate_all_id = 0; + nm_clear_g_source_inst(&priv->device_recheck_auto_activate_all_idle_source); nm_manager_for_each_device (priv->manager, device, tmp_lst) - schedule_activate_check(self, device); + nm_policy_device_recheck_auto_activate_schedule(self, device); - return G_SOURCE_REMOVE; + return G_SOURCE_CONTINUE; } static void -schedule_activate_all(NMPolicy *self) +nm_policy_device_recheck_auto_activate_all_schedule(NMPolicy *self) { NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self); /* always restart the idle handler. That way, we settle * all other events before restarting to activate them. */ - nm_clear_g_source(&priv->schedule_activate_all_id); - priv->schedule_activate_all_id = g_idle_add(schedule_activate_all_cb, self); + nm_clear_g_source_inst(&priv->device_recheck_auto_activate_all_idle_source); + + priv->device_recheck_auto_activate_all_idle_source = + nm_g_idle_add_source(_device_recheck_auto_activate_all_cb, self); } +/*****************************************************************************/ + static void connection_added(NMSettings *settings, NMSettingsConnection *connection, gpointer user_data) { NMPolicyPrivate *priv = user_data; NMPolicy *self = _PRIV_TO_SELF(priv); - schedule_activate_all(self); + nm_policy_device_recheck_auto_activate_all_schedule(self); } static void @@ -2608,7 +2592,7 @@ connection_updated(NMSettings *settings, } } - schedule_activate_all(self); + nm_policy_device_recheck_auto_activate_all_schedule(self); } static void @@ -2657,7 +2641,7 @@ connection_flags_changed(NMSettings *settings, NMSettingsConnection *connection, if (NM_FLAGS_HAS(nm_settings_connection_get_flags(connection), NM_SETTINGS_CONNECTION_INT_FLAGS_VISIBLE)) { if (!nm_settings_connection_autoconnect_is_blocked(connection)) - schedule_activate_all(self); + nm_policy_device_recheck_auto_activate_all_schedule(self); } } @@ -2671,7 +2655,7 @@ secret_agent_registered(NMSettings *settings, NMSecretAgent *agent, gpointer use * connections failed due to missing secrets may re-try auto-connection. */ if (reset_autoconnect_all(self, NULL, TRUE)) - schedule_activate_all(self); + nm_policy_device_recheck_auto_activate_all_schedule(self); } NMActiveConnection * @@ -2765,7 +2749,7 @@ nm_policy_init(NMPolicy *self) NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self); gs_free char *hostname_mode = NULL; - c_list_init(&priv->pending_activation_checks); + c_list_init(&priv->policy_auto_activate_lst_head); priv->netns = g_object_ref(nm_netns_get()); @@ -2901,9 +2885,9 @@ dispose(GObject *object) { NMPolicy *self = NM_POLICY(object); NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self); - GHashTableIter h_iter; - NMDevice *device; - ActivateData *data, *data_safe; + + nm_assert(!c_list_is_empty(&priv->policy_auto_activate_lst_head)); + nm_assert(g_hash_table_size(priv->devices) == 0); nm_clear_g_object(&priv->default_ac4); nm_clear_g_object(&priv->default_ac6); @@ -2911,9 +2895,6 @@ dispose(GObject *object) nm_clear_g_object(&priv->activating_ac6); nm_clear_pointer(&priv->pending_active_connections, g_hash_table_unref); - c_list_for_each_entry_safe (data, data_safe, &priv->pending_activation_checks, pending_lst) - activate_data_free(data); - g_slist_free_full(priv->pending_secondaries, (GDestroyNotify) pending_secondary_data_free); priv->pending_secondaries = NULL; @@ -2932,20 +2913,14 @@ dispose(GObject *object) g_clear_object(&priv->dns_manager); } - g_hash_table_iter_init(&h_iter, priv->devices); - while (g_hash_table_iter_next(&h_iter, (gpointer *) &device, NULL)) { - g_hash_table_iter_remove(&h_iter); - devices_list_unregister(self, device); - } - /* The manager should have disposed of ActiveConnections already, which * will have called active_connection_removed() and thus we don't need * to clean anything up. Assert that this is TRUE. */ nm_assert(c_list_is_empty(nm_manager_get_active_connections(priv->manager))); - nm_clear_g_source(&priv->reset_retries_id); - nm_clear_g_source(&priv->schedule_activate_all_id); + nm_clear_g_source_inst(&priv->reset_connections_retries_idle_source); + nm_clear_g_source_inst(&priv->device_recheck_auto_activate_all_idle_source); nm_clear_g_free(&priv->orig_hostname); nm_clear_g_free(&priv->cur_hostname); diff --git a/src/core/nm-policy.h b/src/core/nm-policy.h index f2b98dbd34..9cfb0b2448 100644 --- a/src/core/nm-policy.h +++ b/src/core/nm-policy.h @@ -34,6 +34,8 @@ NMActiveConnection *nm_policy_get_activating_ip6_ac(NMPolicy *policy); void nm_policy_unblock_failed_ovs_interfaces(NMPolicy *self); +void nm_policy_device_recheck_auto_activate_schedule(NMPolicy *self, NMDevice *device); + /** * NMPolicyHostnameMode * @NM_POLICY_HOSTNAME_MODE_NONE: never update the transient hostname.