Skip to content

Fix deadlock on dmu_tx_assign() from vdev_rebuild()#18258

Merged
behlendorf merged 1 commit intoopenzfs:masterfrom
andriytk:spaconfdeadlock
Feb 26, 2026
Merged

Fix deadlock on dmu_tx_assign() from vdev_rebuild()#18258
behlendorf merged 1 commit intoopenzfs:masterfrom
andriytk:spaconfdeadlock

Conversation

@andriytk
Copy link
Contributor

@andriytk andriytk commented Feb 24, 2026

Motivation and Context

Deadlock on spa_vdev_attach(), see #18210.

Description

vdev_rebuild() is always called with spa_config_lock held in RW_WRITER mode. However, when it tries to call dmu_tx_assign() the latter may hang on dmu_tx_wait() waiting for available txg. But that available txg may not happen because txg_sync takes spa_config_lock in order to process the current txg. So we have a deadlock case here:

  • dmu_tx_assign() waits for txg holding spa_config_lock;
  • txg_sync waits for spa_config_lock not progressing with txg.

Here are the stacks:

__schedule+0x24e/0x590
schedule+0x69/0x110
cv_wait_common+0xf8/0x130 [spl]
__cv_wait+0x15/0x20 [spl]
dmu_tx_wait+0x8e/0x1e0 [zfs]
dmu_tx_assign+0x49/0x80 [zfs]
vdev_rebuild_initiate+0x39/0xc0 [zfs]
vdev_rebuild+0x84/0x90 [zfs]
spa_vdev_attach+0x305/0x680 [zfs]
zfs_ioc_vdev_attach+0xc7/0xe0 [zfs]

cv_wait_common+0xf8/0x130 [spl]
__cv_wait+0x15/0x20 [spl]
spa_config_enter+0xf9/0x120 [zfs]
spa_sync+0x6d/0x5b0 [zfs]
txg_sync_thread+0x266/0x2f0 [zfs]

The solution is to pass txg returned by spa_vdev_enter(spa) at the top of spa_vdev_attach() to vdev_rebuild() and call dmu_tx_create_assigned(txg) which doesn't wait for txg.

How Has This Been Tested?

zfs-tests.sh -T redundancy tests have passed.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Performance enhancement (non-breaking change which improves efficiency)
  • Code cleanup (non-breaking change which makes code smaller or more readable)
  • Quality assurance (non-breaking change which makes the code more robust against bugs)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Library ABI change (libzfs, libzfs_core, libnvpair, libuutil and libzfsbootenv)
  • Documentation (a change to man pages or other documentation)

Checklist:

Closes #18210.

@behlendorf behlendorf added the Status: Code Review Needed Ready for review and testing label Feb 24, 2026
@andriytk andriytk force-pushed the spaconfdeadlock branch 3 times, most recently from 9733e1c to fd3622f Compare February 24, 2026 22:04
@behlendorf behlendorf requested a review from alek-p February 25, 2026 19:16
@behlendorf behlendorf added Status: Accepted Ready to integrate (reviewed, tested) and removed Status: Code Review Needed Ready for review and testing labels Feb 25, 2026
vdev_rebuild() is always called with spa_config_lock held in
RW_WRITER mode. However, when it tries to call dmu_tx_assign()
the latter may hang on dmu_tx_wait() waiting for available txg.
But that available txg may not happen because txg_sync takes
spa_config_lock in order to process the current txg. So we have
a deadlock case here:

 - dmu_tx_assign() waits for txg holding spa_config_lock;
 - txg_sync waits for spa_config_lock not progressing with txg.

Here are the stacks:

    __schedule+0x24e/0x590
    schedule+0x69/0x110
    cv_wait_common+0xf8/0x130 [spl]
    __cv_wait+0x15/0x20 [spl]
    dmu_tx_wait+0x8e/0x1e0 [zfs]
    dmu_tx_assign+0x49/0x80 [zfs]
    vdev_rebuild_initiate+0x39/0xc0 [zfs]
    vdev_rebuild+0x84/0x90 [zfs]
    spa_vdev_attach+0x305/0x680 [zfs]
    zfs_ioc_vdev_attach+0xc7/0xe0 [zfs]

    cv_wait_common+0xf8/0x130 [spl]
    __cv_wait+0x15/0x20 [spl]
    spa_config_enter+0xf9/0x120 [zfs]
    spa_sync+0x6d/0x5b0 [zfs]
    txg_sync_thread+0x266/0x2f0 [zfs]

The solution is to pass txg returned by spa_vdev_enter(spa)
at the top of spa_vdev_attach() to vdev_rebuild() and call
dmu_tx_create_assigned(txg) which doesn't wait for txg.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Andriy Tkachuk <andriy.tkachuk@seagate.com>
Closes openzfs#18210.
@github-actions github-actions bot removed the Status: Accepted Ready to integrate (reviewed, tested) label Feb 25, 2026
@andriytk
Copy link
Contributor Author

I've just rebased it on the latest master.

@behlendorf behlendorf added the Status: Accepted Ready to integrate (reviewed, tested) label Feb 26, 2026
Copy link
Contributor

@akashb-22 akashb-22 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@behlendorf behlendorf merged commit f8457fb into openzfs:master Feb 26, 2026
22 of 26 checks passed
@andriytk andriytk deleted the spaconfdeadlock branch February 26, 2026 19:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Status: Accepted Ready to integrate (reviewed, tested)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deadlock between spa_vdev_attach and txg_sync

4 participants