platform: refactor completing netlink responses in event_handler_read_netlink()
- refactor the loop in event_handler_read_netlink() to mark pending requests as answered by adding a new helper function delayed_action_wait_for_nl_response_complete_check() - delayed_action_wait_for_nl_response_complete_all() can be implemented in terms of delayed_action_wait_for_nl_response_complete_check() - if nm_platform_netns_push() fails, also complete all pending requests with a new error code WAIT_FOR_NL_RESPONSE_RESULT_FAILED_SETNS.
This commit is contained in:
@@ -294,6 +294,7 @@ typedef enum {
|
|||||||
WAIT_FOR_NL_RESPONSE_RESULT_FAILED_POLL,
|
WAIT_FOR_NL_RESPONSE_RESULT_FAILED_POLL,
|
||||||
WAIT_FOR_NL_RESPONSE_RESULT_FAILED_TIMEOUT,
|
WAIT_FOR_NL_RESPONSE_RESULT_FAILED_TIMEOUT,
|
||||||
WAIT_FOR_NL_RESPONSE_RESULT_FAILED_DISPOSING,
|
WAIT_FOR_NL_RESPONSE_RESULT_FAILED_DISPOSING,
|
||||||
|
WAIT_FOR_NL_RESPONSE_RESULT_FAILED_SETNS,
|
||||||
} WaitForNlResponseResult;
|
} WaitForNlResponseResult;
|
||||||
|
|
||||||
typedef void (*WaitForNlResponseCallback) (NMPlatform *platform,
|
typedef void (*WaitForNlResponseCallback) (NMPlatform *platform,
|
||||||
@@ -3441,28 +3442,59 @@ delayed_action_wait_for_nl_response_complete (NMPlatform *platform,
|
|||||||
g_array_remove_index_fast (priv->delayed_action.list_wait_for_nl_response, idx);
|
g_array_remove_index_fast (priv->delayed_action.list_wait_for_nl_response, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
delayed_action_wait_for_nl_response_complete_check (NMPlatform *platform,
|
||||||
|
WaitForNlResponseResult force_result,
|
||||||
|
guint32 *out_next_seq_number,
|
||||||
|
gint64 *out_next_timeout_abs_ns,
|
||||||
|
gint64 *p_now_ns)
|
||||||
|
{
|
||||||
|
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||||
|
guint i;
|
||||||
|
guint32 next_seq_number = 0;
|
||||||
|
gint64 next_timeout_abs_ns = 0;
|
||||||
|
gint now_ns = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < priv->delayed_action.list_wait_for_nl_response->len; ) {
|
||||||
|
const DelayedActionWaitForNlResponseData *data = &g_array_index (priv->delayed_action.list_wait_for_nl_response, DelayedActionWaitForNlResponseData, i);
|
||||||
|
|
||||||
|
if (data->seq_result)
|
||||||
|
delayed_action_wait_for_nl_response_complete (platform, i, data->seq_result);
|
||||||
|
else if ( p_now_ns
|
||||||
|
&& ((now_ns ?: (now_ns = nm_utils_get_monotonic_timestamp_ns ())) >= data->timeout_abs_ns)) {
|
||||||
|
/* the caller can optionally check for timeout by providing a p_now_ns argument. */
|
||||||
|
delayed_action_wait_for_nl_response_complete (platform, i, WAIT_FOR_NL_RESPONSE_RESULT_FAILED_TIMEOUT);
|
||||||
|
} else if (force_result != WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN)
|
||||||
|
delayed_action_wait_for_nl_response_complete (platform, i, force_result);
|
||||||
|
else {
|
||||||
|
if ( next_seq_number == 0
|
||||||
|
|| next_timeout_abs_ns > data->timeout_abs_ns) {
|
||||||
|
next_seq_number = data->seq_number;
|
||||||
|
next_timeout_abs_ns = data->timeout_abs_ns;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (force_result != WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN) {
|
||||||
|
nm_assert (!NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE));
|
||||||
|
nm_assert (priv->delayed_action.list_wait_for_nl_response->len == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
NM_SET_OUT (out_next_seq_number, next_seq_number);
|
||||||
|
NM_SET_OUT (out_next_timeout_abs_ns, next_timeout_abs_ns);
|
||||||
|
NM_SET_OUT (p_now_ns, now_ns);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
delayed_action_wait_for_nl_response_complete_all (NMPlatform *platform,
|
delayed_action_wait_for_nl_response_complete_all (NMPlatform *platform,
|
||||||
WaitForNlResponseResult fallback_result)
|
WaitForNlResponseResult fallback_result)
|
||||||
{
|
{
|
||||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
delayed_action_wait_for_nl_response_complete_check (platform,
|
||||||
|
fallback_result,
|
||||||
if (NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) {
|
NULL,
|
||||||
while (priv->delayed_action.list_wait_for_nl_response->len > 0) {
|
NULL,
|
||||||
const DelayedActionWaitForNlResponseData *data;
|
NULL);
|
||||||
guint idx = priv->delayed_action.list_wait_for_nl_response->len - 1;
|
|
||||||
WaitForNlResponseResult r;
|
|
||||||
|
|
||||||
data = &g_array_index (priv->delayed_action.list_wait_for_nl_response, DelayedActionWaitForNlResponseData, idx);
|
|
||||||
|
|
||||||
/* prefer the result that we already have. */
|
|
||||||
r = data->seq_result ? : fallback_result;
|
|
||||||
|
|
||||||
delayed_action_wait_for_nl_response_complete (platform, idx, r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nm_assert (!NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE));
|
|
||||||
nm_assert (priv->delayed_action.list_wait_for_nl_response->len == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -6627,23 +6659,25 @@ event_handler_read_netlink (NMPlatform *platform, gboolean wait_for_acks)
|
|||||||
{
|
{
|
||||||
nm_auto_pop_netns NMPNetns *netns = NULL;
|
nm_auto_pop_netns NMPNetns *netns = NULL;
|
||||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||||
int r, nle;
|
int r;
|
||||||
struct pollfd pfd;
|
struct pollfd pfd;
|
||||||
gboolean any = FALSE;
|
gboolean any = FALSE;
|
||||||
gint64 now_ns;
|
|
||||||
int timeout_ms;
|
int timeout_ms;
|
||||||
guint i;
|
|
||||||
struct {
|
struct {
|
||||||
guint32 seq_number;
|
guint32 seq_number;
|
||||||
gint64 timeout_abs_ns;
|
gint64 timeout_abs_ns;
|
||||||
} data_next;
|
gint64 now_ns;
|
||||||
|
} next;
|
||||||
|
|
||||||
if (!nm_platform_netns_push (platform, &netns))
|
if (!nm_platform_netns_push (platform, &netns)) {
|
||||||
|
delayed_action_wait_for_nl_response_complete_all (platform,
|
||||||
|
WAIT_FOR_NL_RESPONSE_RESULT_FAILED_SETNS);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
while (TRUE) {
|
for (;;) {
|
||||||
|
for (;;) {
|
||||||
while (TRUE) {
|
int nle;
|
||||||
|
|
||||||
nle = event_handler_recvmsgs (platform, TRUE);
|
nle = event_handler_recvmsgs (platform, TRUE);
|
||||||
|
|
||||||
@@ -6666,7 +6700,9 @@ event_handler_read_netlink (NMPlatform *platform, gboolean wait_for_acks)
|
|||||||
_reason;
|
_reason;
|
||||||
}));
|
}));
|
||||||
event_handler_recvmsgs (platform, FALSE);
|
event_handler_recvmsgs (platform, FALSE);
|
||||||
delayed_action_wait_for_nl_response_complete_all (platform, WAIT_FOR_NL_RESPONSE_RESULT_FAILED_RESYNC);
|
delayed_action_wait_for_nl_response_complete_all (platform,
|
||||||
|
WAIT_FOR_NL_RESPONSE_RESULT_FAILED_RESYNC);
|
||||||
|
|
||||||
delayed_action_schedule (platform,
|
delayed_action_schedule (platform,
|
||||||
DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS |
|
DELAYED_ACTION_TYPE_REFRESH_ALL_LINKS |
|
||||||
DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES |
|
DELAYED_ACTION_TYPE_REFRESH_ALL_IP4_ADDRESSES |
|
||||||
@@ -6690,39 +6726,23 @@ after_read:
|
|||||||
if (!NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE))
|
if (!NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE))
|
||||||
return any;
|
return any;
|
||||||
|
|
||||||
now_ns = 0;
|
delayed_action_wait_for_nl_response_complete_check (platform,
|
||||||
data_next.seq_number = 0;
|
WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN,
|
||||||
data_next.timeout_abs_ns = 0;
|
&next.seq_number,
|
||||||
|
&next.timeout_abs_ns,
|
||||||
for (i = 0; i < priv->delayed_action.list_wait_for_nl_response->len; ) {
|
&next.now_ns);
|
||||||
DelayedActionWaitForNlResponseData *data = &g_array_index (priv->delayed_action.list_wait_for_nl_response, DelayedActionWaitForNlResponseData, i);
|
|
||||||
|
|
||||||
if (data->seq_result)
|
|
||||||
delayed_action_wait_for_nl_response_complete (platform, i, data->seq_result);
|
|
||||||
else if ((now_ns ?: (now_ns = nm_utils_get_monotonic_timestamp_ns ())) > data->timeout_abs_ns)
|
|
||||||
delayed_action_wait_for_nl_response_complete (platform, i, WAIT_FOR_NL_RESPONSE_RESULT_FAILED_TIMEOUT);
|
|
||||||
else {
|
|
||||||
i++;
|
|
||||||
|
|
||||||
if ( data_next.seq_number == 0
|
|
||||||
|| data_next.timeout_abs_ns > data->timeout_abs_ns) {
|
|
||||||
data_next.seq_number = data->seq_number;
|
|
||||||
data_next.timeout_abs_ns = data->timeout_abs_ns;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !wait_for_acks
|
if ( !wait_for_acks
|
||||||
|| !NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE))
|
|| !NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE))
|
||||||
return any;
|
return any;
|
||||||
|
|
||||||
nm_assert (data_next.seq_number);
|
nm_assert (next.seq_number);
|
||||||
nm_assert (data_next.timeout_abs_ns > 0);
|
nm_assert (next.now_ns > 0);
|
||||||
nm_assert (now_ns > 0);
|
nm_assert (next.timeout_abs_ns > next.now_ns);
|
||||||
|
|
||||||
_LOGT ("netlink: read: wait for ACK for sequence number %u...", data_next.seq_number);
|
_LOGT ("netlink: read: wait for ACK for sequence number %u...", next.seq_number);
|
||||||
|
|
||||||
timeout_ms = (data_next.timeout_abs_ns - now_ns) / (NM_UTILS_NS_PER_SECOND / 1000);
|
timeout_ms = (next.timeout_abs_ns - next.now_ns) / (NM_UTILS_NS_PER_SECOND / 1000);
|
||||||
|
|
||||||
memset (&pfd, 0, sizeof (pfd));
|
memset (&pfd, 0, sizeof (pfd));
|
||||||
pfd.fd = nl_socket_get_fd (priv->nlh);
|
pfd.fd = nl_socket_get_fd (priv->nlh);
|
||||||
@@ -6733,6 +6753,7 @@ after_read:
|
|||||||
/* timeout and there is nothing to read. */
|
/* timeout and there is nothing to read. */
|
||||||
goto after_read;
|
goto after_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
int errsv = errno;
|
int errsv = errno;
|
||||||
|
|
||||||
@@ -7003,7 +7024,8 @@ dispose (GObject *object)
|
|||||||
|
|
||||||
_LOGD ("dispose");
|
_LOGD ("dispose");
|
||||||
|
|
||||||
delayed_action_wait_for_nl_response_complete_all (platform, WAIT_FOR_NL_RESPONSE_RESULT_FAILED_DISPOSING);
|
delayed_action_wait_for_nl_response_complete_all (platform,
|
||||||
|
WAIT_FOR_NL_RESPONSE_RESULT_FAILED_DISPOSING);
|
||||||
|
|
||||||
priv->delayed_action.flags = DELAYED_ACTION_TYPE_NONE;
|
priv->delayed_action.flags = DELAYED_ACTION_TYPE_NONE;
|
||||||
g_ptr_array_set_size (priv->delayed_action.list_master_connected, 0);
|
g_ptr_array_set_size (priv->delayed_action.list_master_connected, 0);
|
||||||
|
Reference in New Issue
Block a user