From nobody Mon Jul 27 17:33:32 2026 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4h85Kn1gXqz6nHj0 for ; Mon, 27 Jul 2026 17:33:33 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4h85Km6WBJz3KrR for ; Mon, 27 Jul 2026 17:33:32 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1785173613; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=3wHmqrIHFzbIRTNOokw+AJLPAN3yoQOaezTIJA/tfdE=; b=Rbl2o67zBTn4K9EDzaWLisre+d7pKQppdrZxHFpmD14SCnJ0PTIqgkDZZNPmySJ8gyAOgB 1CWt+siUv9bhV1ZG9Cw13794sugFSI9xBajA9yPHGqo+dTQ0BlWzeCPzp7G1xQesngatge LL7v5+zJR2HYF30F5jxLzGXs9oKslIWkyFdziUYaMJ3L0zvtpZBcVXjwxYQbDET33YG2KX lYAqrV0lZLlpQ5h8aF5FQD/Qjvvz19ZbChRUMkpIIAqh5naYOG4K4nudRrCScmOpoKfNmE gTpoVAU0LUEpaptW7gChX0GV6kBolwRasFRWazdzQHHLAFRGEVZP66aWEKlGdQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1785173612; a=rsa-sha256; cv=none; b=O6jQ7H3Nywppgukcb/dHhs9LZI+W4tqgZ9UHdFVFws6jdKY5vTXOEe9juAMC/LR3D2MQd5 Rrj5H+YXVb/q0XS0ekEvFxILiWaUing396UDok/dHme/uFGofVY6jLc3d/0wlLsIo7PIVC f+XFa3B1/2Jg4/6Mw9+ZjVVyDyT/bmWS3e3cGKH3tyfNWukXNeF8cTaKdUm1WR662OL8iA TpA5tOj2LrEGWhgZrLHGYDOkjSzxk2moQoivlYMsy/hbMvF6FSBGQGwfSU9KlrjEfyf5D7 DcbdUZ30TGp0/bpVjxMcOKoMBQky7O8qEi8nPzo1HUSGnqZ9cu9ZMxNwNMMA3A== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1785173612; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=3wHmqrIHFzbIRTNOokw+AJLPAN3yoQOaezTIJA/tfdE=; b=ogH8NrbvL+dOG7+M6Ggg5fPkJ/KJQmf4w1USwMwfErYavyZWsQr9iqhAR0CxNeXm3Mqyrt LOl4n9YlMNrx/Mn2P4PuJLeAHyk6+aE1PJ/Nyuv8A2drpr5bJk/SG4P9GFiv+u0pEM0sHZ SHr7riPFbUuRUIZW3PJI8zJBTths/9bSQClyTDdLlAvu+qX0eBiGnimqVP7E6DWQCZREKM J0507RhCcJfxcUMNLRTRxpyPyZDn5RuF+6hfEwT/xKU6UmtocJ3zwIMD0WEO5n6quA2bDZ 46RkReKnOltRg5uqfpY0Mo7MhCXlgAIHHmvi//Yj8UYeXrmRt9gVOkJSmCf+cA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4h85Km4vZ9z1HTv for ; Mon, 27 Jul 2026 17:33:32 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 24563 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 27 Jul 2026 17:33:32 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Mark Johnston Subject: git: f6745503ded7 - stable/15 - Make zvol_set_common() block until the operation has completed List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: markj X-Git-Repository: src X-Git-Refname: refs/heads/stable/15 X-Git-Reftype: branch X-Git-Commit: f6745503ded7cc938a52d6916277da12c5b31d4f Auto-Submitted: auto-generated Date: Mon, 27 Jul 2026 17:33:32 +0000 Message-Id: <6a67966c.24563.34d4c5c7@gitrepo.freebsd.org> The branch stable/15 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=f6745503ded7cc938a52d6916277da12c5b31d4f commit f6745503ded7cc938a52d6916277da12c5b31d4f Author: Mark Johnston AuthorDate: 2026-02-02 01:55:04 +0000 Commit: Mark Johnston CommitDate: 2026-07-27 17:29:03 +0000 Make zvol_set_common() block until the operation has completed This is motivated by a FreeBSD AIO test case which create a zvol with -o volmode=dev, then immediately tries to open the zvol device file. The open occasionally fails with ENOENT. When a zvol is created without the volmode setting, zvol_create_minors() blocks until the task is finished, at which point OS-dependent code will have created a device file. However, zvol_set_common() may cause the device file to be destroyed and re-created, at least on FreeBSD, if the voltype switches from GEOM to DEV. In this case, we do not block waiting for the operation to finish, causing the test failure. Fix the problem by making zvol_set_common() block until the operation has finished. In FreeBSD zvol code, use g_waitidle() to block until asynchronous GEOM operations are done. This fixes a secondary race where zvol_os_remove_minor() does not block until the zvol device file is removed, and the subsequent zvol_os_create_minor() fails because the (to-be-destroyed) device file already exists. Reviewed-by: Brian Behlendorf Reviewed-by: Alexander Motin Signed-off-by: Mark Johnston Closes #18191 (cherry picked from commit d736868672cb3df197d2ddcfef29ac14edf4ee20) --- .../openzfs/module/os/freebsd/zfs/zvol_os.c | 4 +- sys/contrib/openzfs/module/zfs/zvol.c | 46 ++++++++++++++++++++-- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zvol_os.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zvol_os.c index fca99c42f73c..2bc85e9bd972 100644 --- a/sys/contrib/openzfs/module/os/freebsd/zfs/zvol_os.c +++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zvol_os.c @@ -919,7 +919,7 @@ retry: return (SET_ERROR(ENXIO)); mutex_enter(&zv->zv_state_lock); - if (zv->zv_zso->zso_dying || zv->zv_flags & ZVOL_REMOVING) { + if (zv->zv_flags & ZVOL_REMOVING || zv->zv_zso->zso_dying) { err = SET_ERROR(ENXIO); goto out_locked; } @@ -1426,6 +1426,7 @@ zvol_os_remove_minor(zvol_state_t *zv) pp->private = NULL; g_wither_geom(pp->geom, ENXIO); g_topology_unlock(); + g_waitidle(curthread); } else if (zv->zv_volmode == ZFS_VOLMODE_DEV) { struct zvol_state_dev *zsd = &zso->zso_dev; struct cdev *dev = zsd->zsd_cdev; @@ -1555,6 +1556,7 @@ out_dmu_objset_disown: g_error_provider(zv->zv_zso->zso_geom.zsg_provider, 0); /* geom was locked inside zvol_alloc() function */ g_topology_unlock(); + g_waitidle(curthread); } out_doi: kmem_free(doi, sizeof (dmu_object_info_t)); diff --git a/sys/contrib/openzfs/module/zfs/zvol.c b/sys/contrib/openzfs/module/zfs/zvol.c index 15ee62ca5249..185672672a2f 100644 --- a/sys/contrib/openzfs/module/zfs/zvol.c +++ b/sys/contrib/openzfs/module/zfs/zvol.c @@ -1952,6 +1952,10 @@ typedef struct zvol_set_prop_int_arg { uint64_t zsda_value; zprop_source_t zsda_source; zfs_prop_t zsda_prop; + taskqid_t zsda_taskqid; + boolean_t zsda_dispatched; + kmutex_t zsda_lock; + kcondvar_t zsda_cv; } zvol_set_prop_int_arg_t; /* @@ -1982,6 +1986,7 @@ zvol_set_common_sync_cb(dsl_pool_t *dp, dsl_dataset_t *ds, void *arg) char dsname[ZFS_MAX_DATASET_NAME_LEN]; zvol_task_t *task; uint64_t prop; + taskqid_t id; const char *prop_name = zfs_prop_to_name(zsda->zsda_prop); dsl_dataset_name(ds, dsname); @@ -2000,8 +2005,12 @@ zvol_set_common_sync_cb(dsl_pool_t *dp, dsl_dataset_t *ds, void *arg) } task->zt_value = prop; strlcpy(task->zt_name1, dsname, sizeof (task->zt_name1)); - (void) taskq_dispatch(dp->dp_spa->spa_zvol_taskq, zvol_task_cb, - task, TQ_SLEEP); + id = taskq_dispatch(dp->dp_spa->spa_zvol_taskq, zvol_task_cb, task, + TQ_SLEEP); + mutex_enter(&zsda->zsda_lock); + if (id != TASKQID_INVALID && id > zsda->zsda_taskqid) + zsda->zsda_taskqid = id; + mutex_exit(&zsda->zsda_lock); return (0); } @@ -2034,6 +2043,11 @@ zvol_set_common_sync(void *arg, dmu_tx_t *tx) dmu_objset_find_dp(dp, dd->dd_object, zvol_set_common_sync_cb, zsda, DS_FIND_CHILDREN); + mutex_enter(&zsda->zsda_lock); + zsda->zsda_dispatched = TRUE; + cv_broadcast(&zsda->zsda_cv); + mutex_exit(&zsda->zsda_lock); + dsl_dir_rele(dd, FTAG); } @@ -2042,14 +2056,38 @@ zvol_set_common(const char *ddname, zfs_prop_t prop, zprop_source_t source, uint64_t val) { zvol_set_prop_int_arg_t zsda; + spa_t *spa; + int error; zsda.zsda_name = ddname; zsda.zsda_source = source; zsda.zsda_value = val; zsda.zsda_prop = prop; + zsda.zsda_taskqid = TASKQID_INVALID; + zsda.zsda_dispatched = FALSE; + mutex_init(&zsda.zsda_lock, NULL, MUTEX_DEFAULT, NULL); + cv_init(&zsda.zsda_cv, NULL, CV_DEFAULT, NULL); - return (dsl_sync_task(ddname, zvol_set_common_check, - zvol_set_common_sync, &zsda, 0, ZFS_SPACE_CHECK_NONE)); + error = spa_open(ddname, &spa, FTAG); + if (error != 0) + goto out; + error = dsl_sync_task(ddname, zvol_set_common_check, + zvol_set_common_sync, &zsda, 0, ZFS_SPACE_CHECK_NONE); + if (error == 0) { + mutex_enter(&zsda.zsda_lock); + while (!zsda.zsda_dispatched) + cv_wait(&zsda.zsda_cv, &zsda.zsda_lock); + mutex_exit(&zsda.zsda_lock); + + if (zsda.zsda_taskqid != TASKQID_INVALID) + taskq_wait_outstanding(spa->spa_zvol_taskq, + zsda.zsda_taskqid); + } + spa_close(spa, FTAG); +out: + cv_destroy(&zsda.zsda_cv); + mutex_destroy(&zsda.zsda_lock); + return (error); } void