DF-3173 / fix.diff
--- a/sys/vfs/autofs/autofs.c 2026-06-29 12:51:19.000000000 +0000 +++ b/sys/vfs/autofs/autofs.c 2026-09-07 20:04:48.870811775 +0000 @@ -300,7 +300,6 @@ autofs_trigger_one(struct autofs_node *anp, const char *component, int componentlen) { -#define _taskqueue_thread (taskqueue_thread[mycpuid]) struct autofs_mount *amp = anp->an_mount; struct autofs_request *ar; char *key, *path; @@ -354,9 +353,18 @@ strlcpy(ar->ar_key, key, sizeof(ar->ar_key)); strlcpy(ar->ar_options, amp->am_options, sizeof(ar->ar_options)); - TIMEOUT_TASK_INIT(_taskqueue_thread, &ar->ar_task, 0, + /* + * Remember which per-cpu taskqueue the timeout task is + * armed on. The request is shared (dedup above), so the + * thread releasing the last reference may run on a + * different CPU than this one, and the teardown must + * cancel/drain against the queue the task actually lives + * on (tasks must not be shared between CPUs' taskqueues). + */ + ar->ar_taskqueue = taskqueue_thread[mycpuid]; + TIMEOUT_TASK_INIT(ar->ar_taskqueue, &ar->ar_task, 0, autofs_task, ar); - taskqueue_enqueue_timeout(_taskqueue_thread, &ar->ar_task, + taskqueue_enqueue_timeout(ar->ar_taskqueue, &ar->ar_task, autofs_timeout * hz); refcount_init(&ar->ar_refcount, 1); TAILQ_INSERT_TAIL(&autofs_softc->sc_requests, ar, ar_next); @@ -395,8 +403,9 @@ if (refcount_release(&ar->ar_refcount)) { TAILQ_REMOVE(&autofs_softc->sc_requests, ar, ar_next); mtx_unlock_ex(&autofs_softc->sc_lock); - taskqueue_cancel_timeout(_taskqueue_thread, &ar->ar_task, NULL); - taskqueue_drain_timeout(_taskqueue_thread, &ar->ar_task); + taskqueue_cancel_timeout(ar->ar_taskqueue, &ar->ar_task, + NULL); + taskqueue_drain_timeout(ar->ar_taskqueue, &ar->ar_task); objcache_put(autofs_request_objcache, ar); mtx_lock_ex_quick(&autofs_softc->sc_lock); } --- a/sys/vfs/autofs/autofs.h 2026-06-29 12:51:19.000000000 +0000 +++ b/sys/vfs/autofs/autofs.h 2026-09-07 20:04:48.878811675 +0000 @@ -134,6 +134,8 @@ char ar_key[MAXPATHLEN]; char ar_options[MAXPATHLEN]; struct timeout_task ar_task; + struct taskqueue *ar_taskqueue; /* queue ar_task + * is armed on */ volatile unsigned int ar_refcount; }; |