Skip to content

ZIL: "crash" the ZIL if the pool suspends during fallback #17398

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/zilstat.in
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ cols = {
"cec": [5, 1000, "zil_commit_error_count"],
"csc": [5, 1000, "zil_commit_stall_count"],
"cSc": [5, 1000, "zil_commit_suspend_count"],
"cCc": [5, 1000, "zil_commit_crash_count"],
"ic": [5, 1000, "zil_itx_count"],
"iic": [5, 1000, "zil_itx_indirect_count"],
"iib": [5, 1024, "zil_itx_indirect_bytes"],
Expand Down
8 changes: 4 additions & 4 deletions cmd/ztest.c
Original file line number Diff line number Diff line change
Expand Up @@ -1995,7 +1995,7 @@ ztest_log_write(ztest_ds_t *zd, dmu_tx_t *tx, lr_write_t *lr)
dmu_read(zd->zd_os, lr->lr_foid, lr->lr_offset, lr->lr_length,
((lr_write_t *)&itx->itx_lr) + 1, DMU_READ_NO_PREFETCH |
DMU_KEEP_CACHING) != 0) {
zil_itx_destroy(itx);
zil_itx_destroy(itx, 0);
itx = zil_itx_create(TX_WRITE, sizeof (*lr));
write_state = WR_NEED_COPY;
}
Expand Down Expand Up @@ -2965,7 +2965,7 @@ ztest_zil_commit(ztest_ds_t *zd, uint64_t id)

(void) pthread_rwlock_rdlock(&zd->zd_zilog_lock);

zil_commit(zilog, ztest_random(ZTEST_OBJECTS));
VERIFY0(zil_commit(zilog, ztest_random(ZTEST_OBJECTS)));

/*
* Remember the committed values in zd, which is in parent/child
Expand Down Expand Up @@ -7933,7 +7933,7 @@ ztest_freeze(void)
*/
while (BP_IS_HOLE(&zd->zd_zilog->zl_header->zh_log)) {
ztest_dmu_object_alloc_free(zd, 0);
zil_commit(zd->zd_zilog, 0);
VERIFY0(zil_commit(zd->zd_zilog, 0));
}

txg_wait_synced(spa_get_dsl(spa), 0);
Expand Down Expand Up @@ -7975,7 +7975,7 @@ ztest_freeze(void)
/*
* Commit all of the changes we just generated.
*/
zil_commit(zd->zd_zilog, 0);
VERIFY0(zil_commit(zd->zd_zilog, 0));
txg_wait_synced(spa_get_dsl(spa), 0);

/*
Expand Down
27 changes: 27 additions & 0 deletions config/kernel-sb-wb-err.m4
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# dnl
# dnl 5.8 (735e4ae5ba28) introduced a superblock scoped errseq_t to use to
# dnl record writeback errors for syncfs() to return. Up until 5.17, when
# dnl sync_fs errors were returned directly, this is the only way for us to
# dnl report an error from syncfs().
# dnl
AC_DEFUN([ZFS_AC_KERNEL_SRC_SUPER_BLOCK_S_WB_ERR], [
ZFS_LINUX_TEST_SRC([super_block_s_wb_err], [
#include <linux/fs.h>

static const struct super_block
sb __attribute__ ((unused)) = {
.s_wb_err = 0,
};
],[])
])

AC_DEFUN([ZFS_AC_KERNEL_SUPER_BLOCK_S_WB_ERR], [
AC_MSG_CHECKING([whether super_block has s_wb_err])
ZFS_LINUX_TEST_RESULT([super_block_s_wb_err], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_SUPER_BLOCK_S_WB_ERR, 1,
[have super_block s_wb_err])
],[
AC_MSG_RESULT(no)
])
])
2 changes: 2 additions & 0 deletions config/kernel.m4
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
ZFS_AC_KERNEL_SRC_FILE
ZFS_AC_KERNEL_SRC_PIN_USER_PAGES
ZFS_AC_KERNEL_SRC_TIMER
ZFS_AC_KERNEL_SRC_SUPER_BLOCK_S_WB_ERR
case "$host_cpu" in
powerpc*)
ZFS_AC_KERNEL_SRC_CPU_HAS_FEATURE
Expand Down Expand Up @@ -246,6 +247,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
ZFS_AC_KERNEL_FILE
ZFS_AC_KERNEL_PIN_USER_PAGES
ZFS_AC_KERNEL_TIMER
ZFS_AC_KERNEL_SUPER_BLOCK_S_WB_ERR
case "$host_cpu" in
powerpc*)
ZFS_AC_KERNEL_CPU_HAS_FEATURE
Expand Down
4 changes: 4 additions & 0 deletions include/os/freebsd/spl/sys/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@
#define __maybe_unused __attribute__((unused))
#endif

#ifndef __must_check
#define __must_check __attribute__((__warn_unused_result__))
#endif

/*
* Without this, we see warnings from objtool during normal Linux builds when
* the kernel is built with CONFIG_STACK_VALIDATION=y:
Expand Down
2 changes: 2 additions & 0 deletions include/os/freebsd/spl/sys/vm.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
extern const int zfs_vm_pagerret_bad;
extern const int zfs_vm_pagerret_error;
extern const int zfs_vm_pagerret_ok;
extern const int zfs_vm_pagerret_pend;
extern const int zfs_vm_pagerret_again;
extern const int zfs_vm_pagerput_sync;
extern const int zfs_vm_pagerput_inval;

Expand Down
4 changes: 4 additions & 0 deletions include/os/linux/spl/sys/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@
#define __maybe_unused __attribute__((unused))
#endif

#ifndef __must_check
#define __must_check __attribute__((__warn_unused_result__))
#endif

/*
* Without this, we see warnings from objtool during normal Linux builds when
* the kernel is built with CONFIG_STACK_VALIDATION=y:
Expand Down
11 changes: 7 additions & 4 deletions include/sys/zil.h
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ typedef enum {
WR_NUM_STATES /* number of states */
} itx_wr_state_t;

typedef void (*zil_callback_t)(void *data);
typedef void (*zil_callback_t)(void *data, int err);

typedef struct itx {
list_node_t itx_node; /* linkage on zl_itx_list */
Expand Down Expand Up @@ -498,10 +498,13 @@ typedef struct zil_stats {
* (see zil_commit_writer_stall())
* - suspend: ZIL suspended
* (see zil_commit(), zil_get_commit_list())
* - crash: ZIL crashed
* (see zil_crash(), zil_commit(), ...)
*/
kstat_named_t zil_commit_error_count;
kstat_named_t zil_commit_stall_count;
kstat_named_t zil_commit_suspend_count;
kstat_named_t zil_commit_crash_count;

/*
* Number of transactions (reads, writes, renames, etc.)
Expand Down Expand Up @@ -549,6 +552,7 @@ typedef struct zil_sums {
wmsum_t zil_commit_error_count;
wmsum_t zil_commit_stall_count;
wmsum_t zil_commit_suspend_count;
wmsum_t zil_commit_crash_count;
wmsum_t zil_itx_count;
wmsum_t zil_itx_indirect_count;
wmsum_t zil_itx_indirect_bytes;
Expand Down Expand Up @@ -606,12 +610,11 @@ extern boolean_t zil_destroy(zilog_t *zilog, boolean_t keep_first);
extern void zil_destroy_sync(zilog_t *zilog, dmu_tx_t *tx);

extern itx_t *zil_itx_create(uint64_t txtype, size_t lrsize);
extern void zil_itx_destroy(itx_t *itx);
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 void zil_commit(zilog_t *zilog, uint64_t oid);
extern void zil_commit_impl(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_reset(const char *osname, void *txarg);
Expand Down
4 changes: 4 additions & 0 deletions include/sys/zil_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ struct zilog {
uint64_t zl_cur_left; /* current burst remaining size */
uint64_t zl_cur_max; /* biggest record in current burst */
list_t zl_lwb_list; /* in-flight log write list */
list_t zl_lwb_crash_list; /* log writes in-flight at crash */
avl_tree_t zl_bp_tree; /* track bps during log parse */
clock_t zl_replay_time; /* lbolt of when replay started */
uint64_t zl_replay_blks; /* number of log blocks replayed */
Expand All @@ -245,6 +246,9 @@ struct zilog {
*/
uint64_t zl_max_block_size;

/* After crash, txg to restart zil */
uint64_t zl_restart_txg;

/* Pointer for per dataset zil sums */
zil_sums_t *zl_sums;
};
Expand Down
4 changes: 4 additions & 0 deletions lib/libspl/include/sys/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,8 @@
#define __maybe_unused __attribute__((unused))
#endif

#ifndef __must_check
#define __must_check __attribute__((warn_unused_result))
#endif

#endif
2 changes: 2 additions & 0 deletions module/os/freebsd/spl/spl_vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
const int zfs_vm_pagerret_bad = VM_PAGER_BAD;
const int zfs_vm_pagerret_error = VM_PAGER_ERROR;
const int zfs_vm_pagerret_ok = VM_PAGER_OK;
const int zfs_vm_pagerret_pend = VM_PAGER_PEND;
const int zfs_vm_pagerret_again = VM_PAGER_AGAIN;
const int zfs_vm_pagerput_sync = VM_PAGER_PUT_SYNC;
const int zfs_vm_pagerput_inval = VM_PAGER_PUT_INVAL;

Expand Down
9 changes: 7 additions & 2 deletions module/os/freebsd/zfs/zfs_vfsops.c
Original file line number Diff line number Diff line change
Expand Up @@ -455,8 +455,13 @@ zfs_sync(vfs_t *vfsp, int waitfor)
return (0);
}

if (zfsvfs->z_log != NULL)
zil_commit(zfsvfs->z_log, 0);
if (zfsvfs->z_log != NULL) {
error = zil_commit(zfsvfs->z_log, 0);
if (error != 0) {
zfs_exit(zfsvfs, FTAG);
return (error);
}
}

zfs_exit(zfsvfs, FTAG);
} else {
Expand Down
Loading
Loading