diff --git a/include/sys/zil.h b/include/sys/zil.h index fb4c3aee1..da0859988 100644 --- a/include/sys/zil.h +++ b/include/sys/zil.h @@ -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); diff --git a/module/zfs/zil.c b/module/zfs/zil.c index 36ca475df..31b59c55f 100644 --- a/module/zfs/zil.c +++ b/module/zfs/zil.c @@ -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));