mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-01-14 17:22:05 +03:00
ZIL: add zil_commit_flags() to make honouring failmode= optional
The vast majority of calls to zil_commit() follow VFS ops, and should honour the failmode= setting - either wait for sync, or return error. Some calls however are part of a larger syncing op, and shouldn't ever block if something goes wrong. To allow this, we introduce zil_commit_flags(), with a flag ZIL_COMMIT_FAILMODE to indicate whether or not the pool failmode should be honoured. zil_commit() is now a wrapper that always sets this flag, but any caller wanting a different behaviour can request ZIL_COMMIT_NOW instead to have the call return failure if the pool suspends, regardless of the failmode= setting. Sponsored-by: Klara, Inc. Sponsored-by: Wasabi Technology, Inc. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Alexander Motin <alexander.motin@TrueNAS.com> Signed-off-by: Rob Norris <rob.norris@klarasystems.com> Closes #17398
This commit is contained in:
parent
72602f6ad9
commit
391e85f519
@ -581,6 +581,25 @@ typedef struct zil_sums {
|
||||
#define ZIL_STAT_BUMP(zil, stat) \
|
||||
ZIL_STAT_INCR(zil, stat, 1);
|
||||
|
||||
/*
|
||||
* Flags for zil_commit_flags(). zil_commit() is a shortcut for
|
||||
* zil_commit_flags(ZIL_COMMIT_FAILMODE), which is the most common use.
|
||||
*/
|
||||
typedef enum {
|
||||
/*
|
||||
* Try to commit the ZIL. If it fails, fall back to txg_wait_synced().
|
||||
* If that fails, return EIO.
|
||||
*/
|
||||
ZIL_COMMIT_NOW = 0,
|
||||
|
||||
/*
|
||||
* Like ZIL_COMMIT_NOW, but if the ZIL commit fails because the pool
|
||||
* suspended, act according to the pool's failmode= setting (wait for
|
||||
* the pool to resume, or return EIO).
|
||||
*/
|
||||
ZIL_COMMIT_FAILMODE = (1 << 1),
|
||||
} zil_commit_flag_t;
|
||||
|
||||
typedef int zil_parse_blk_func_t(zilog_t *zilog, const blkptr_t *bp, void *arg,
|
||||
uint64_t txg);
|
||||
typedef int zil_parse_lr_func_t(zilog_t *zilog, const lr_t *lr, void *arg,
|
||||
@ -614,9 +633,12 @@ extern void zil_itx_destroy(itx_t *itx, int err);
|
||||
extern void zil_itx_assign(zilog_t *zilog, itx_t *itx, dmu_tx_t *tx);
|
||||
|
||||
extern void zil_async_to_sync(zilog_t *zilog, uint64_t oid);
|
||||
extern int __must_check zil_commit(zilog_t *zilog, uint64_t oid);
|
||||
extern void zil_remove_async(zilog_t *zilog, uint64_t oid);
|
||||
|
||||
extern int zil_commit_flags(zilog_t *zilog, uint64_t oid,
|
||||
zil_commit_flag_t flags);
|
||||
extern int __must_check zil_commit(zilog_t *zilog, uint64_t oid);
|
||||
|
||||
extern int zil_reset(const char *osname, void *txarg);
|
||||
extern int zil_claim(struct dsl_pool *dp,
|
||||
struct dsl_dataset *ds, void *txarg);
|
||||
|
||||
@ -3878,6 +3878,12 @@ static int zil_commit_impl(zilog_t *zilog, uint64_t foid);
|
||||
|
||||
int
|
||||
zil_commit(zilog_t *zilog, uint64_t foid)
|
||||
{
|
||||
return (zil_commit_flags(zilog, foid, ZIL_COMMIT_FAILMODE));
|
||||
}
|
||||
|
||||
int
|
||||
zil_commit_flags(zilog_t *zilog, uint64_t foid, zil_commit_flag_t flags)
|
||||
{
|
||||
/*
|
||||
* We should never attempt to call zil_commit on a snapshot for
|
||||
@ -3955,7 +3961,11 @@ out:
|
||||
*/
|
||||
ASSERT3U(err, ==, ESHUTDOWN);
|
||||
|
||||
if (spa_get_failmode(zilog->zl_spa) == ZIO_FAILURE_MODE_CONTINUE)
|
||||
/*
|
||||
* Return error if failmode=continue or caller will handle directly.
|
||||
*/
|
||||
if (!(flags & ZIL_COMMIT_FAILMODE) ||
|
||||
spa_get_failmode(zilog->zl_spa) == ZIO_FAILURE_MODE_CONTINUE)
|
||||
return (SET_ERROR(EIO));
|
||||
|
||||
/*
|
||||
@ -4321,7 +4331,7 @@ zil_close(zilog_t *zilog)
|
||||
uint64_t txg;
|
||||
|
||||
if (!dmu_objset_is_snapshot(zilog->zl_os)) {
|
||||
if (zil_commit(zilog, 0) != 0)
|
||||
if (zil_commit_flags(zilog, 0, ZIL_COMMIT_NOW) != 0)
|
||||
txg_wait_synced(zilog->zl_dmu_pool, 0);
|
||||
} else {
|
||||
ASSERT(list_is_empty(&zilog->zl_lwb_list));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user