diff --git a/include/sys/zfs_refcount.h b/include/sys/zfs_refcount.h index 1e6449472e..2f59ebb32b 100644 --- a/include/sys/zfs_refcount.h +++ b/include/sys/zfs_refcount.h @@ -72,6 +72,14 @@ int zfs_refcount_is_zero(zfs_refcount_t *); int64_t zfs_refcount_count(zfs_refcount_t *); int64_t zfs_refcount_add(zfs_refcount_t *, const void *); int64_t zfs_refcount_remove(zfs_refcount_t *, const void *); +/* + * Note that (add|remove)_many add/remove one reference with "number" N, + * _not_ make N references with "number" 1, which is what vanilla + * zfs_refcount_(add|remove) would do if called N times. + * + * Attempting to remove a reference with number N when none exists is a + * panic on debug kernels with reference_tracking enabled. + */ int64_t zfs_refcount_add_many(zfs_refcount_t *, uint64_t, const void *); int64_t zfs_refcount_remove_many(zfs_refcount_t *, uint64_t, const void *); void zfs_refcount_transfer(zfs_refcount_t *, zfs_refcount_t *); diff --git a/module/zfs/dmu_zfetch.c b/module/zfs/dmu_zfetch.c index a26b0d7399..043344a137 100644 --- a/module/zfs/dmu_zfetch.c +++ b/module/zfs/dmu_zfetch.c @@ -488,7 +488,8 @@ dmu_zfetch_run(zstream_t *zs, boolean_t missed, boolean_t have_lock) issued = pf_end - pf_start + ipf_end - ipf_start; if (issued > 1) { /* More references on top of taken in dmu_zfetch_prepare(). */ - zfs_refcount_add_many(&zs->zs_refs, issued - 1, NULL); + for (int i = 0; i < issued - 1; i++) + zfs_refcount_add(&zs->zs_refs, NULL); } else if (issued == 0) { /* Some other thread has done our work, so drop the ref. */ if (zfs_refcount_remove(&zs->zs_refs, NULL) == 0)