summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2020-04-01 15:18:10 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2020-07-10 10:19:09 +0200
commit74ccda8a713f707fe09f218b737865db6579f955 (patch)
treefc08bc13833e60630b6c8b503a09970002fcc2cf
parent6fcb077a98a4681af15d2431977d367256f8e667 (diff)
downloadNetworkManager-74ccda8a713f707fe09f218b737865db6579f955.tar.gz
device: allow queuing SR-IOV operation from a callback
Keep priv->sriov.pending set during the callback set so that it becomes possible to insert a new operation from the callback itself.
-rw-r--r--src/devices/nm-device.c35
1 files changed, 17 insertions, 18 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index b320d6b4f5..3bc0f47245 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -614,6 +614,7 @@ typedef struct _NMDevicePrivate {
SriovOp *pending; /* SR-IOV operation currently running */
SriovOp *next; /* next SR-IOV operation scheduled */
} sriov;
+ guint sriov_reset_pending;
struct {
guint timeout_id;
@@ -4765,15 +4766,12 @@ sriov_op_cb (GError *error, gpointer user_data)
nm_assert (op == priv->sriov.pending);
- priv->sriov.pending = NULL;
-
g_clear_object (&op->cancellable);
if (op->callback)
op->callback (error, op->callback_data);
- nm_assert (!priv->sriov.pending);
-
+ priv->sriov.pending = NULL;
nm_g_slice_free (op);
if (priv->sriov.next) {
@@ -4791,6 +4789,8 @@ sriov_op_queue_op (NMDevice *self,
if (priv->sriov.next) {
SriovOp *op_next = g_steal_pointer (&priv->sriov.next);
+ priv->sriov.next = op;
+
/* Cancel the next operation immediately */
if (op_next->callback) {
gs_free_error GError *error = NULL;
@@ -4800,17 +4800,10 @@ sriov_op_queue_op (NMDevice *self,
}
nm_g_slice_free (op_next);
+ return;
+ }
- if (!priv->sriov.pending) {
- /* This (having "next" set but "pending" not) can only happen if we are
- * called from inside the callback again.
- *
- * That means we append the new request as "next" and return. Once
- * the callback returns, it will schedule the request. */
- priv->sriov.next = op;
- return;
- }
- } else if (priv->sriov.pending) {
+ if (priv->sriov.pending) {
priv->sriov.next = op;
g_cancellable_cancel (priv->sriov.pending->cancellable);
return;
@@ -15927,23 +15920,28 @@ deactivate_ready (NMDevice *self, NMDeviceStateReason reason)
if (priv->dispatcher.call_id)
return;
- if ( priv->sriov.pending
- || priv->sriov.next)
+ if (priv->sriov_reset_pending > 0)
return;
- nm_device_queue_state (self, NM_DEVICE_STATE_DISCONNECTED, reason);
+ if (priv->state == NM_DEVICE_STATE_DEACTIVATING)
+ nm_device_queue_state (self, NM_DEVICE_STATE_DISCONNECTED, reason);
}
static void
sriov_deactivate_cb (GError *error, gpointer user_data)
{
NMDevice *self;
+ NMDevicePrivate *priv;
gpointer reason;
+ nm_utils_user_data_unpack (user_data, &self, &reason);
+ priv = NM_DEVICE_GET_PRIVATE (self);
+ nm_assert (priv->sriov_reset_pending > 0);
+ priv->sriov_reset_pending--;
+
if (nm_utils_error_is_cancelled_or_disposing (error))
return;
- nm_utils_user_data_unpack (user_data, &self, &reason);
deactivate_ready (self, (NMDeviceStateReason) reason);
}
@@ -16273,6 +16271,7 @@ _set_state_full (NMDevice *self,
if ( priv->ifindex > 0
&& (s_sriov = nm_device_get_applied_setting (self, NM_TYPE_SETTING_SRIOV))) {
+ priv->sriov_reset_pending++;
sriov_op_queue (self,
0,
NM_TERNARY_TRUE,