Skip to content

Commit

Permalink
DOSE-768 zoa panicked at assertion failed: (left < right) during die_…
Browse files Browse the repository at this point in the history
…mtbf stress test (openzfs#28)
  • Loading branch information
grwilson committed Nov 25, 2021
1 parent 5929d24 commit 7890c98
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 10 deletions.
13 changes: 13 additions & 0 deletions include/sys/zil.h
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,19 @@ typedef struct zil_stats {
*/
kstat_named_t zil_itx_metaslab_slog_count;
kstat_named_t zil_itx_metaslab_slog_bytes;

/*
* Number of allocation failures to slog device when
* using object-based pools.
*/
kstat_named_t zil_slog_alloc_failures;

/*
* Object-based pools don't support sync write semantics unless
* a slog exits. If a slog does not exist, then we skip the
* zil_commit call. Keep a count of how often that occurs.
*/
kstat_named_t zil_skip_zil_commit;
} zil_stats_t;

extern zil_stats_t zil_stats;
Expand Down
15 changes: 15 additions & 0 deletions lib/libzfs/libzfs_dataset.c
Original file line number Diff line number Diff line change
Expand Up @@ -1492,6 +1492,21 @@ zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl,
chosen_normal = (int)intval;
break;

case ZFS_PROP_LOGBIAS:
if (zpool_hdl != NULL &&
zpool_is_object_based(zpool_hdl) &&
intval == ZFS_LOGBIAS_THROUGHPUT) {
const char *valname;
verify(zfs_prop_index_to_string(prop,
intval, &valname) == 0);
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"object based pools cannot set '%s' to "
"'%s'"), propname, valname);
(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
goto error;
}
break;

default:
break;
}
Expand Down
6 changes: 4 additions & 2 deletions module/zfs/zfs_log.c
Original file line number Diff line number Diff line change
Expand Up @@ -551,10 +551,12 @@ zfs_log_write(zilog_t *zilog, dmu_tx_t *tx, int txtype,
return;
}

if (zilog->zl_logbias == ZFS_LOGBIAS_THROUGHPUT)
boolean_t object_based = spa_is_object_based(zilog->zl_spa);

if (zilog->zl_logbias == ZFS_LOGBIAS_THROUGHPUT && !object_based)
write_state = WR_INDIRECT;
else if (!spa_has_slogs(zilog->zl_spa) &&
resid >= zfs_immediate_write_sz)
resid >= zfs_immediate_write_sz && !object_based)
write_state = WR_INDIRECT;
else if (ioflag & (O_SYNC | O_DSYNC))
write_state = WR_COPIED;
Expand Down
17 changes: 14 additions & 3 deletions module/zfs/zil.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ zil_stats_t zil_stats = {
{ "zil_itx_metaslab_normal_bytes", KSTAT_DATA_UINT64 },
{ "zil_itx_metaslab_slog_count", KSTAT_DATA_UINT64 },
{ "zil_itx_metaslab_slog_bytes", KSTAT_DATA_UINT64 },
{ "zil_slog_alloc_failures", KSTAT_DATA_UINT64 },
{ "zil_skip_zil_commit", KSTAT_DATA_UINT64 },
};

static kstat_t *zil_ksp;
Expand Down Expand Up @@ -709,6 +711,8 @@ zil_create(zilog_t *zilog)

if (error == 0)
zil_init_log_chain(zilog, &blk);
else if (slog)
ZIL_STAT_BUMP(zil_slog_alloc_failures);
}

/*
Expand Down Expand Up @@ -1557,6 +1561,8 @@ zil_lwb_write_issue(zilog_t *zilog, lwb_t *lwb)
if (slog) {
ZIL_STAT_BUMP(zil_itx_metaslab_slog_count);
ZIL_STAT_INCR(zil_itx_metaslab_slog_bytes, lwb->lwb_nused);
if (error)
ZIL_STAT_BUMP(zil_slog_alloc_failures);
} else {
ZIL_STAT_BUMP(zil_itx_metaslab_normal_count);
ZIL_STAT_INCR(zil_itx_metaslab_normal_bytes, lwb->lwb_nused);
Expand Down Expand Up @@ -1753,6 +1759,7 @@ zil_lwb_commit(zilog_t *zilog, itx_t *itx, lwb_t *lwb)
ZIL_STAT_INCR(zil_itx_needcopy_bytes, dnow);
} else {
ASSERT3S(itx->itx_wr_state, ==, WR_INDIRECT);
ASSERT(!spa_is_object_based(zilog->zl_spa));
dbuf = NULL;
ZIL_STAT_BUMP(zil_itx_indirect_count);
ZIL_STAT_INCR(zil_itx_indirect_bytes,
Expand Down Expand Up @@ -2956,10 +2963,14 @@ zil_commit(zilog_t *zilog, uint64_t foid)
*/
ASSERT3B(dmu_objset_is_snapshot(zilog->zl_os), ==, B_FALSE);

if (zilog->zl_sync == ZFS_SYNC_DISABLED ||
(spa_is_object_based(zilog->zl_spa) &&
!spa_has_slogs(zilog->zl_spa)))
if (zilog->zl_sync == ZFS_SYNC_DISABLED)
return;

if (spa_is_object_based(zilog->zl_spa) &&
!spa_has_slogs(zilog->zl_spa)) {
ZIL_STAT_BUMP(zil_skip_zil_commit);
return;
}

if (!spa_writeable(zilog->zl_spa)) {
/*
Expand Down
14 changes: 11 additions & 3 deletions module/zfs/zio.c
Original file line number Diff line number Diff line change
Expand Up @@ -3741,15 +3741,23 @@ zio_alloc_zil(spa_t *spa, objset_t *os, uint64_t txg, blkptr_t *new_bp,
int flags = METASLAB_FASTWRITE | METASLAB_ZIL;
int allocator = (uint_t)cityhash4(0, 0, 0,
os->os_dsl_dataset->ds_object) % spa->spa_alloc_count;

/*
* Object-based pools can only allocate zil block on the slog,
* so if we failed to allocate from the slog we need to return
* an error and not fallback to the normal class.
*/
boolean_t object_based = spa_is_object_based(spa);
error = metaslab_alloc(spa, spa_log_class(spa), size, new_bp, 1,
txg, NULL, flags, &io_alloc_list, NULL, allocator);
*slog = (error == 0);
if (error != 0) {
*slog = (error == 0 || object_based);

if (error != 0 && !object_based) {
error = metaslab_alloc(spa, spa_embedded_log_class(spa), size,
new_bp, 1, txg, NULL, flags,
&io_alloc_list, NULL, allocator);
}
if (error != 0) {
if (error != 0 && !object_based) {
error = metaslab_alloc(spa, spa_normal_class(spa), size,
new_bp, 1, txg, NULL, flags,
&io_alloc_list, NULL, allocator);
Expand Down
7 changes: 5 additions & 2 deletions module/zfs/zvol.c
Original file line number Diff line number Diff line change
Expand Up @@ -580,10 +580,13 @@ zvol_log_write(zvol_state_t *zv, dmu_tx_t *tx, uint64_t offset,
if (zil_replaying(zilog, tx))
return;

if (zilog->zl_logbias == ZFS_LOGBIAS_THROUGHPUT)
boolean_t object_based = spa_is_object_based(zilog->zl_spa);

if (zilog->zl_logbias == ZFS_LOGBIAS_THROUGHPUT && !object_based)
write_state = WR_INDIRECT;
else if (!spa_has_slogs(zilog->zl_spa) &&
size >= blocksize && blocksize > zvol_immediate_write_sz)
size >= blocksize && blocksize > zvol_immediate_write_sz &&
!object_based)
write_state = WR_INDIRECT;
else if (sync)
write_state = WR_COPIED;
Expand Down

0 comments on commit 7890c98

Please sign in to comment.