iflib: drain enqueued tasks before detaching from taskqgroup
The taskqgroup_detach function does not check if task is already enqueued when detaching it. This may lead to kernel panic if enqueued task starts after context state lock is destroyed. Ensure that the already enqueued admin tasks are executed before detaching them. The issue was discovered during validation of D16429. Unloading of if_ixlv followed by immediate removal of VFs with iovctl -D may lead to panic on NODEBUG kernel. As well, check if iflib is in detach before enqueueing new admin or iov tasks, to prevent new tasks from executing while the taskqgroup tasks are being drained. Submitted by: Krzysztof Galazka <krzysztof.galazka@intel.com> Reviewed by: shurd@, erj@ Sponsored by: Intel Corporation Differential Revision: https://reviews.freebsd.org/D17404
This commit is contained in:
parent
3c22d78997
commit
940f62d616
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=339634
@ -812,6 +812,7 @@ taskqgroup_detach(struct taskqgroup *qgroup, struct grouptask *gtask)
|
||||
qgroup->tqg_queue[i].tgc_cnt--;
|
||||
LIST_REMOVE(gtask, gt_list);
|
||||
mtx_unlock(&qgroup->tqg_lock);
|
||||
gtaskqueue_drain(gtask->gt_taskqueue, >ask->gt_task);
|
||||
gtask->gt_taskqueue = NULL;
|
||||
}
|
||||
|
||||
|
@ -2279,8 +2279,8 @@ iflib_timer(void *arg)
|
||||
STATE_LOCK(ctx);
|
||||
if_setdrvflagbits(ctx->ifc_ifp, IFF_DRV_OACTIVE, IFF_DRV_RUNNING);
|
||||
ctx->ifc_flags |= (IFC_DO_WATCHDOG|IFC_DO_RESET);
|
||||
iflib_admin_intr_deferred(ctx);
|
||||
STATE_UNLOCK(ctx);
|
||||
iflib_admin_intr_deferred(ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2802,8 +2802,8 @@ iflib_rxeof(iflib_rxq_t rxq, qidx_t budget)
|
||||
err:
|
||||
STATE_LOCK(ctx);
|
||||
ctx->ifc_flags |= IFC_DO_RESET;
|
||||
iflib_admin_intr_deferred(ctx);
|
||||
STATE_UNLOCK(ctx);
|
||||
iflib_admin_intr_deferred(ctx);
|
||||
return (false);
|
||||
}
|
||||
|
||||
@ -5973,7 +5973,10 @@ iflib_admin_intr_deferred(if_ctx_t ctx)
|
||||
{
|
||||
#ifdef INVARIANTS
|
||||
struct grouptask *gtask;
|
||||
|
||||
#endif
|
||||
if (iflib_in_detach(ctx))
|
||||
return;
|
||||
#ifdef INVARIANTS
|
||||
gtask = &ctx->ifc_admin_task;
|
||||
MPASS(gtask != NULL && gtask->gt_taskqueue != NULL);
|
||||
#endif
|
||||
@ -5984,6 +5987,8 @@ iflib_admin_intr_deferred(if_ctx_t ctx)
|
||||
void
|
||||
iflib_iov_intr_deferred(if_ctx_t ctx)
|
||||
{
|
||||
if (iflib_in_detach(ctx))
|
||||
return;
|
||||
|
||||
GROUPTASK_ENQUEUE(&ctx->ifc_vflr_task);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user