There is a race here.

> static int
> +dpaa2_mtr_meter_create(struct rte_eth_dev *dev,
> +     uint32_t mtr_id, struct rte_mtr_params *params,
> +     int shared, struct rte_mtr_error *error)
> +{
> +     struct dpaa2_dev_priv *priv = dev->data->dev_private;
> +     struct dpaa2_dev_meter_profile *profile;
> +     struct dpaa2_dev_meter_policy *policy;
> +     struct dpaa2_dev_meter *meter, *curr;
> +     uint32_t profile_id, policy_id;
> +     enum rte_mtr_error_type err_type = RTE_MTR_ERROR_TYPE_NONE;
> +     bool found = false;
> +     int ret = 0;
> +

...

> +     rte_spinlock_lock(&priv->meter_lock);
> +     profile = LIST_FIRST(&priv->profiles);
> +     while (profile != NULL) {
> +             if (profile->profile_id == profile_id) {
> +                     found = true;
> +                     break;
> +             }
> +             profile = LIST_NEXT(profile, next);
> +     }
> +     if (!found) {
> +             snprintf(s_err_msg, sizeof(s_err_msg),
> +                     "Meter profile ID(%d) not exist!", profile_id);
> +             ret = ENOENT;
> +             err_type = RTE_MTR_ERROR_TYPE_METER_PROFILE_ID;
> +             goto quit;
> +     }
> +
> +     found = false;
> +     policy = LIST_FIRST(&priv->policies);
> +     while (policy != NULL) {
> +             if (policy->policy_id == policy_id) {
> +                     found = true;
> +                     break;
> +             }
> +             policy = LIST_NEXT(policy, next);
> +     }
> +     if (!found) {
> +             snprintf(s_err_msg, sizeof(s_err_msg),
> +                     "Meter policy ID(%d) not exist!", policy_id);
> +             ret = ENOENT;
> +             err_type = RTE_MTR_ERROR_TYPE_METER_POLICY_ID;
> +             goto quit;
> +     }
> +     meter = LIST_FIRST(&priv->meters);
> +     while (meter != NULL) {
> +             if (meter->meter_id == mtr_id) {
> +                     snprintf(s_err_msg, sizeof(s_err_msg),
> +                             "Meter ID(%d) exist!", mtr_id);
> +                     ret = EEXIST;
> +                     err_type = RTE_MTR_ERROR_TYPE_MTR_ID;
> +                     goto quit;
> +             }
> +             meter = LIST_NEXT(meter, next);
> +     }
> +     meter = rte_zmalloc(NULL, sizeof(struct dpaa2_dev_meter), 0);
> +     if (meter == NULL) {
> +             snprintf(s_err_msg, sizeof(s_err_msg),
> +                     "Meter memory alloc failed!");
> +             ret = ENOMEM;
> +             err_type = RTE_MTR_ERROR_TYPE_UNSPECIFIED;
> +             goto quit;
> +     }
> +     meter->meter_id = mtr_id;
> +     meter->profile_id = profile_id;
> +     meter->policy_id = policy_id;
> +
> +     rte_spinlock_unlock(&priv->meter_lock);

At this point meter is created but not put into any list.

> +
> +     /* Program the hardware policing configuration for this TC. */
> +     ret = dpaa2_mtr_hw_program(dev, mtr_id, profile, policy);
> +     if (ret) {
> +             rte_free(meter);
> +             snprintf(s_err_msg, sizeof(s_err_msg),
> +                     "TC[%u] HW policing set failed (%d)!", mtr_id, ret);
> +             return rte_mtr_error_set(error, -ret,
> +                     RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL, s_err_msg);
> +     }
> +
> +     rte_spinlock_lock(&priv->meter_lock);

While HW was being programmed, in theory the policy and mtr_id could have
gone away. Either refcount the mtr_id or do a quick rescan to make sure
it hasn't disappeared.

> +     curr = LIST_FIRST(&priv->meters);
> +     if (curr == NULL) {
> +             LIST_INSERT_HEAD(&priv->meters, meter, next);
> +     } else {
> +             while (LIST_NEXT(curr, next) != NULL)
> +                     curr = LIST_NEXT(curr, next);
> +             LIST_INSERT_AFTER(curr, meter, next);
> +     }
> +
> +quit:
> +     rte_spinlock_unlock(&priv->meter_lock);
> +     if (ret != 0) {
> +             if (meter != NULL && ret == ENOMEM)
> +                     rte_free(meter);
> +             return rte_mtr_error_set(error, ret, err_type, NULL, s_err_msg);
> +     }
> +
> +     return 0;
> +}

The code would also be easier to read with helper functions that
looked up in list rather lots of open coded list walks.

Reply via email to