Skip to content
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

NAS-125539 / None / [stable/dragonfish] Block Cloning Fixes and ZVOL Patch Backports #200

Merged
merged 6 commits into from
Dec 13, 2023
Merged
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
13 changes: 13 additions & 0 deletions include/os/freebsd/spl/sys/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,14 @@
* ASSERT3U() - Assert unsigned X OP Y is true, if not panic.
* ASSERT3P() - Assert pointer X OP Y is true, if not panic.
* ASSERT0() - Assert value is zero, if not panic.
* ASSERT0P() - Assert pointer is null, if not panic.
* VERIFY() - Verify X is true, if not panic.
* VERIFY3B() - Verify boolean X OP Y is true, if not panic.
* VERIFY3S() - Verify signed X OP Y is true, if not panic.
* VERIFY3U() - Verify unsigned X OP Y is true, if not panic.
* VERIFY3P() - Verify pointer X OP Y is true, if not panic.
* VERIFY0() - Verify value is zero, if not panic.
* VERIFY0P() - Verify pointer is null, if not panic.
*/

#ifndef _SPL_DEBUG_H
Expand Down Expand Up @@ -136,6 +138,15 @@ spl_assert(const char *buf, const char *file, const char *func, int line)
(long long) (_verify3_right)); \
} while (0)

#define VERIFY0P(RIGHT) do { \
const uintptr_t _verify0_right = (uintptr_t)(RIGHT); \
if (unlikely(!(0 == _verify0_right))) \
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"VERIFY0P(" #RIGHT ") " \
"failed (NULL == %p)\n", \
(void *)_verify0_right); \
} while (0)

/*
* Debugging disabled (--disable-debug)
*/
Expand All @@ -151,6 +162,7 @@ spl_assert(const char *buf, const char *file, const char *func, int line)
#define ASSERT3P(x, y, z) \
((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z)))
#define ASSERT0(x) ((void) sizeof ((uintptr_t)(x)))
#define ASSERT0P(x) ((void) sizeof ((uintptr_t)(x)))
#define IMPLY(A, B) \
((void) sizeof ((uintptr_t)(A)), (void) sizeof ((uintptr_t)(B)))
#define EQUIV(A, B) \
Expand All @@ -166,6 +178,7 @@ spl_assert(const char *buf, const char *file, const char *func, int line)
#define ASSERT3U VERIFY3U
#define ASSERT3P VERIFY3P
#define ASSERT0 VERIFY0
#define ASSERT0P VERIFY0P
#define ASSERT VERIFY
#define IMPLY(A, B) \
((void)(likely((!(A)) || (B)) || \
Expand Down
13 changes: 13 additions & 0 deletions include/os/linux/spl/sys/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,14 @@
* ASSERT3U() - Assert unsigned X OP Y is true, if not panic.
* ASSERT3P() - Assert pointer X OP Y is true, if not panic.
* ASSERT0() - Assert value is zero, if not panic.
* ASSERT0P() - Assert pointer is null, if not panic.
* VERIFY() - Verify X is true, if not panic.
* VERIFY3B() - Verify boolean X OP Y is true, if not panic.
* VERIFY3S() - Verify signed X OP Y is true, if not panic.
* VERIFY3U() - Verify unsigned X OP Y is true, if not panic.
* VERIFY3P() - Verify pointer X OP Y is true, if not panic.
* VERIFY0() - Verify value is zero, if not panic.
* VERIFY0P() - Verify pointer is null, if not panic.
*/

#ifndef _SPL_DEBUG_H
Expand Down Expand Up @@ -140,6 +142,15 @@ spl_assert(const char *buf, const char *file, const char *func, int line)
(long long) (_verify3_right)); \
} while (0)

#define VERIFY0P(RIGHT) do { \
const uintptr_t _verify0_right = (uintptr_t)(RIGHT); \
if (unlikely(!(0 == _verify0_right))) \
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"VERIFY0P(" #RIGHT ") " \
"failed (NULL == %px)\n", \
(void *)_verify0_right); \
} while (0)

#define VERIFY_IMPLY(A, B) \
((void)(likely((!(A)) || (B)) || \
spl_assert("(" #A ") implies (" #B ")", \
Expand All @@ -165,6 +176,7 @@ spl_assert(const char *buf, const char *file, const char *func, int line)
#define ASSERT3P(x, y, z) \
((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z)))
#define ASSERT0(x) ((void) sizeof ((uintptr_t)(x)))
#define ASSERT0P(x) ((void) sizeof ((uintptr_t)(x)))
#define IMPLY(A, B) \
((void) sizeof ((uintptr_t)(A)), (void) sizeof ((uintptr_t)(B)))
#define EQUIV(A, B) \
Expand All @@ -180,6 +192,7 @@ spl_assert(const char *buf, const char *file, const char *func, int line)
#define ASSERT3U VERIFY3U
#define ASSERT3P VERIFY3P
#define ASSERT0 VERIFY0
#define ASSERT0P VERIFY0P
#define ASSERT VERIFY
#define IMPLY VERIFY_IMPLY
#define EQUIV VERIFY_EQUIV
Expand Down
1 change: 1 addition & 0 deletions include/sys/fs/zfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ typedef enum {
ZFS_PROP_REDACTED,
ZFS_PROP_REDACT_SNAPS,
ZFS_PROP_SNAPSHOTS_CHANGED,
ZFS_PROP_VOLTHREADING,
ZFS_NUM_PROPS
} zfs_prop_t;

Expand Down
5 changes: 3 additions & 2 deletions include/sys/zvol.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@ extern int zvol_get_stats(objset_t *, nvlist_t *);
extern boolean_t zvol_is_zvol(const char *);
extern void zvol_create_cb(objset_t *, void *, cred_t *, dmu_tx_t *);
extern int zvol_set_volsize(const char *, uint64_t);
extern int zvol_set_snapdev(const char *, zprop_source_t, uint64_t);
extern int zvol_set_volmode(const char *, zprop_source_t, uint64_t);
extern int zvol_set_volthreading(const char *, boolean_t);
extern int zvol_set_common(const char *, zfs_prop_t, zprop_source_t, uint64_t);
extern int zvol_set_ro(const char *, boolean_t);
extern zvol_state_handle_t *zvol_suspend(const char *);
extern int zvol_resume(zvol_state_handle_t *);
extern void *zvol_tag(zvol_state_handle_t *);
Expand Down
1 change: 1 addition & 0 deletions include/sys/zvol_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ typedef struct zvol_state {
atomic_t zv_suspend_ref; /* refcount for suspend */
krwlock_t zv_suspend_lock; /* suspend lock */
struct zvol_state_os *zv_zso; /* private platform state */
boolean_t zv_threading; /* volthreading property */
} zvol_state_t;


Expand Down
11 changes: 11 additions & 0 deletions lib/libspl/include/assert.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,15 @@ do { \
(u_longlong_t)__left); \
} while (0)

#define VERIFY0P(LEFT) \
do { \
const uintptr_t __left = (uintptr_t)(LEFT); \
if (!(__left == 0)) \
libspl_assertf(__FILE__, __FUNCTION__, __LINE__, \
"%s == 0 (%p == 0)", #LEFT, \
(void *)__left); \
} while (0)

#ifdef assert
#undef assert
#endif
Expand All @@ -134,6 +143,7 @@ do { \
#define ASSERT3P(x, y, z) \
((void) sizeof ((uintptr_t)(x)), (void) sizeof ((uintptr_t)(z)))
#define ASSERT0(x) ((void) sizeof ((uintptr_t)(x)))
#define ASSERT0P(x) ((void) sizeof ((uintptr_t)(x)))
#define ASSERT(x) ((void) sizeof ((uintptr_t)(x)))
#define assert(x) ((void) sizeof ((uintptr_t)(x)))
#define IMPLY(A, B) \
Expand All @@ -146,6 +156,7 @@ do { \
#define ASSERT3U VERIFY3U
#define ASSERT3P VERIFY3P
#define ASSERT0 VERIFY0
#define ASSERT0P VERIFY0P
#define ASSERT VERIFY
#define assert VERIFY
#define IMPLY(A, B) \
Expand Down
3 changes: 2 additions & 1 deletion lib/libzfs/libzfs.abi
Original file line number Diff line number Diff line change
Expand Up @@ -1867,7 +1867,8 @@
<enumerator name='ZFS_PROP_REDACTED' value='93'/>
<enumerator name='ZFS_PROP_REDACT_SNAPS' value='94'/>
<enumerator name='ZFS_PROP_SNAPSHOTS_CHANGED' value='95'/>
<enumerator name='ZFS_NUM_PROPS' value='96'/>
<enumerator name='ZFS_PROP_VOLTHREADING' value='96'/>
<enumerator name='ZFS_NUM_PROPS' value='97'/>
</enum-decl>
<typedef-decl name='zfs_prop_t' type-id='4b000d60' id='58603c44'/>
<enum-decl name='zprop_source_t' naming-typedef-id='a2256d42' id='5903f80e'>
Expand Down
12 changes: 12 additions & 0 deletions man/man7/zfsprops.7
Original file line number Diff line number Diff line change
Expand Up @@ -1192,6 +1192,18 @@ are equivalent to the
and
.Sy noexec
mount options.
.It Sy volthreading Ns = Ns Sy on Ns | Ns Sy off
Controls internal zvol threading.
The value
.Sy off
disables zvol threading, and zvol relies on application threads.
The default value is
.Sy on ,
which enables threading within a zvol.
Please note that this property will be overridden by
.Sy zvol_request_sync
module parameter.
This property is only applicable to Linux.
.It Sy filesystem_limit Ns = Ns Ar count Ns | Ns Sy none
Limits the number of filesystems and volumes that can exist under this point in
the dataset tree.
Expand Down
9 changes: 8 additions & 1 deletion module/os/linux/zfs/zvol_os.c
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ zvol_request_impl(zvol_state_t *zv, struct bio *bio, struct request *rq,
uint64_t size = io_size(bio, rq);
int rw = io_data_dir(bio, rq);

if (zvol_request_sync)
if (zvol_request_sync || zv->zv_threading == B_FALSE)
force_sync = 1;

zv_request_t zvr = {
Expand Down Expand Up @@ -1304,6 +1304,7 @@ zvol_os_create_minor(const char *name)
int error = 0;
int idx;
uint64_t hash = zvol_name_hash(name);
uint64_t volthreading;
bool replayed_zil = B_FALSE;

if (zvol_inhibit_dev)
Expand Down Expand Up @@ -1350,6 +1351,12 @@ zvol_os_create_minor(const char *name)
zv->zv_volsize = volsize;
zv->zv_objset = os;

/* Default */
zv->zv_threading = B_TRUE;
if (dsl_prop_get_integer(name, "volthreading", &volthreading, NULL)
== 0)
zv->zv_threading = volthreading;

set_capacity(zv->zv_zso->zvo_disk, zv->zv_volsize >> 9);

blk_queue_max_hw_sectors(zv->zv_zso->zvo_queue,
Expand Down
3 changes: 3 additions & 0 deletions module/zcommon/zfs_prop.c
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,9 @@ zfs_prop_init(void)
ZVOL_DEFAULT_BLOCKSIZE, PROP_ONETIME,
ZFS_TYPE_VOLUME, "512 to 128k, power of 2", "VOLBLOCK", B_FALSE,
sfeatures);
zprop_register_index(ZFS_PROP_VOLTHREADING, "volthreading",
1, PROP_DEFAULT, ZFS_TYPE_VOLUME, "on | off", "zvol threading",
boolean_table, sfeatures);
zprop_register_number(ZFS_PROP_USEDSNAP, "usedbysnapshots", 0,
PROP_READONLY, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "<size>",
"USEDSNAP", B_FALSE, sfeatures);
Expand Down
20 changes: 16 additions & 4 deletions module/zfs/dbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1904,7 +1904,6 @@ dbuf_unoverride(dbuf_dirty_record_t *dr)
dmu_buf_impl_t *db = dr->dr_dbuf;
blkptr_t *bp = &dr->dt.dl.dr_overridden_by;
uint64_t txg = dr->dr_txg;
boolean_t release;

ASSERT(MUTEX_HELD(&db->db_mtx));
/*
Expand All @@ -1925,7 +1924,10 @@ dbuf_unoverride(dbuf_dirty_record_t *dr)
if (!BP_IS_HOLE(bp) && !dr->dt.dl.dr_nopwrite)
zio_free(db->db_objset->os_spa, txg, bp);

release = !dr->dt.dl.dr_brtwrite;
if (dr->dt.dl.dr_brtwrite) {
ASSERT0P(dr->dt.dl.dr_data);
dr->dt.dl.dr_data = db->db_buf;
}
dr->dt.dl.dr_override_state = DR_NOT_OVERRIDDEN;
dr->dt.dl.dr_nopwrite = B_FALSE;
dr->dt.dl.dr_brtwrite = B_FALSE;
Expand All @@ -1939,7 +1941,7 @@ dbuf_unoverride(dbuf_dirty_record_t *dr)
* the buf thawed to save the effort of freezing &
* immediately re-thawing it.
*/
if (release)
if (dr->dt.dl.dr_data)
arc_release(dr->dt.dl.dr_data, db);
}

Expand Down Expand Up @@ -2930,7 +2932,8 @@ dbuf_assign_arcbuf(dmu_buf_impl_t *db, arc_buf_t *buf, dmu_tx_t *tx)
while (db->db_state == DB_READ || db->db_state == DB_FILL)
cv_wait(&db->db_changed, &db->db_mtx);

ASSERT(db->db_state == DB_CACHED || db->db_state == DB_UNCACHED);
ASSERT(db->db_state == DB_CACHED || db->db_state == DB_UNCACHED ||
db->db_state == DB_NOFILL);

if (db->db_state == DB_CACHED &&
zfs_refcount_count(&db->db_holds) - 1 > db->db_dirtycnt) {
Expand Down Expand Up @@ -2967,6 +2970,15 @@ dbuf_assign_arcbuf(dmu_buf_impl_t *db, arc_buf_t *buf, dmu_tx_t *tx)
arc_buf_destroy(db->db_buf, db);
}
db->db_buf = NULL;
} else if (db->db_state == DB_NOFILL) {
/*
* We will be completely replacing the cloned block. In case
* it was cloned in this transaction group, let's undirty the
* pending clone and mark the block as uncached. This will be
* as if the clone was never done.
*/
VERIFY(!dbuf_undirty(db, tx));
db->db_state = DB_UNCACHED;
}
ASSERT(db->db_buf == NULL);
dbuf_set_data(db, buf);
Expand Down
22 changes: 19 additions & 3 deletions module/zfs/zfs_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2523,11 +2523,27 @@ zfs_prop_set_special(const char *dsname, zprop_source_t source,
case ZFS_PROP_VOLSIZE:
err = zvol_set_volsize(dsname, intval);
break;
case ZFS_PROP_SNAPDEV:
err = zvol_set_snapdev(dsname, source, intval);
case ZFS_PROP_VOLTHREADING:
err = zvol_set_volthreading(dsname, intval);
/*
* Set err to -1 to force the zfs_set_prop_nvlist code down the
* default path to set the value in the nvlist.
*/
if (err == 0)
err = -1;
break;
case ZFS_PROP_SNAPDEV:
case ZFS_PROP_VOLMODE:
err = zvol_set_volmode(dsname, source, intval);
err = zvol_set_common(dsname, prop, source, intval);
break;
case ZFS_PROP_READONLY:
err = zvol_set_ro(dsname, intval);
/*
* Set err to -1 to force the zfs_set_prop_nvlist code down the
* default path to set the value in the nvlist.
*/
if (err == 0)
err = -1;
break;
case ZFS_PROP_VERSION:
{
Expand Down
Loading
Loading