zpl: handle suspend from two remaining calls to txg_wait_synced()

* zfs_link: allow tempfile sync to fail if pool suspends

4653e2f7d3 (#17355) allows dmu_tx_assign() to fail if the pool suspends
when failmode=continue, but zfs_link() can fall back to
txg_wait_synced() if it has to wait for a tempfile to be fully created
before continuing, which will block if the pool suspends.

Handle this by requesting an error return if the pool suspends when
failmode=continue, and if that happens, return EIO.

* zfs_clone_range: allow dirty wait to fail if pool suspends

4653e2f7d3 (#17355) allows dmu_tx_assign() to fail if the pool suspends
when failmode=continue, but zfs_clone_range() can fall back to
txg_wait_synced() if it has to wait for a dirty block to be written out,
which will block if the pool suspends.

Handle this by requesting an error return if the pool suspends when
failmode=continue, and if that happens, return EIO.

Sponsored-by: Klara, Inc.
Sponsored-by: Wasabi Technology, Inc.
Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: Alexander Motin <[email protected]>
Signed-off-by: Rob Norris <[email protected]>
Closes #17413
This commit is contained in:
Rob Norris authored and GitHub committed 2025-06-05 15:38:26 -04:00
1 parent b96f1a4b1f
commit af7d609592
2 files changed
+22 -5

No files matched your search

+11 -2
View File
@@ -3672,8 +3672,17 @@ top:
if (!is_tmpfile && zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
zil_commit(zilog, 0);
if (is_tmpfile && zfsvfs->z_os->os_sync != ZFS_SYNC_DISABLED)
txg_wait_synced(dmu_objset_pool(zfsvfs->z_os), txg);
if (is_tmpfile && zfsvfs->z_os->os_sync != ZFS_SYNC_DISABLED) {
txg_wait_flag_t wait_flags =
spa_get_failmode(dmu_objset_spa(zfsvfs->z_os)) ==
ZIO_FAILURE_MODE_CONTINUE ? TXG_WAIT_SUSPEND : 0;
error = txg_wait_synced_flags(dmu_objset_pool(zfsvfs->z_os),
txg, wait_flags);
if (error != 0) {
ASSERT3U(error, ==, ESHUTDOWN);
error = SET_ERROR(EIO);
}
}
zfs_znode_update_vfs(tdzp);
zfs_znode_update_vfs(szp);
+11 -3
View File
@@ -1813,9 +1813,17 @@ zfs_clone_range(znode_t *inzp, uint64_t *inoffp, znode_t *outzp,
* fallback, or wait for the next TXG and check again.
*/
if (error == EAGAIN && zfs_bclone_wait_dirty) {
txg_wait_synced(dmu_objset_pool(inos),
last_synced_txg + 1);
continue;
txg_wait_flag_t wait_flags =
spa_get_failmode(dmu_objset_spa(inos)) ==
ZIO_FAILURE_MODE_CONTINUE ?
TXG_WAIT_SUSPEND : 0;
error = txg_wait_synced_flags(
dmu_objset_pool(inos), last_synced_txg + 1,
wait_flags);
if (error == 0)
continue;
ASSERT3U(error, ==, ESHUTDOWN);
error = SET_ERROR(EIO);
}
break;