aboutsummaryrefslogtreecommitdiff
path: root/sys/contrib/openzfs/module
diff options
context:
space:
mode:
authorMartin Matuska <mm@FreeBSD.org>2021-03-14 01:23:51 +0000
committerMartin Matuska <mm@FreeBSD.org>2021-03-14 01:32:14 +0000
commit9db44a8e5da9bf1ce6dd1c0f1468ddafed6d6c91 (patch)
tree773094eb34c30390e902748ef1ca381665a2ae73 /sys/contrib/openzfs/module
parenta9275d996c229a30879baa42a6d02d24663ac43b (diff)
parent9162a1ce3ae9158ae75ab1835e30ac14d3b6899c (diff)
downloadsrc-9db44a8e5da9bf1ce6dd1c0f1468ddafed6d6c91.tar.gz
src-9db44a8e5da9bf1ce6dd1c0f1468ddafed6d6c91.zip
zfs: merge OpenZFS master-9305ff2ed
Notable upstream pull request merges: #11153 Scalable teardown lock for FreeBSD #11651 Don't bomb out when using keylocation=file:// #11667 zvol: call zil_replaying() during replay #11683 abd_get_offset_struct() may allocate new abd #11693 Intentionally allow ZFS_READONLY in zfs_write #11716 zpool import cachefile improvements #11720 FreeBSD: Clean up zfsdev_close to match Linux #11730 FreeBSD: bring back possibility to rewind the checkpoint from bootloader Obtained from: OpenZFS MFC after: 2 weeks
Diffstat (limited to 'sys/contrib/openzfs/module')
-rw-r--r--sys/contrib/openzfs/module/Makefile.in5
-rw-r--r--sys/contrib/openzfs/module/os/freebsd/zfs/kmod_core.c18
-rw-r--r--sys/contrib/openzfs/module/os/freebsd/zfs/zfs_dir.c2
-rw-r--r--sys/contrib/openzfs/module/os/freebsd/zfs/zvol_os.c9
-rw-r--r--sys/contrib/openzfs/module/os/linux/zfs/zfs_acl.c26
-rw-r--r--sys/contrib/openzfs/module/os/linux/zfs/zio_crypt.c1
-rw-r--r--sys/contrib/openzfs/module/os/linux/zfs/zvol_os.c102
-rw-r--r--sys/contrib/openzfs/module/zcommon/zfs_prop.c2
-rw-r--r--sys/contrib/openzfs/module/zfs/abd.c6
-rw-r--r--sys/contrib/openzfs/module/zfs/spa_misc.c4
-rw-r--r--sys/contrib/openzfs/module/zfs/zfs_vnops.c6
-rw-r--r--sys/contrib/openzfs/module/zfs/zvol.c15
12 files changed, 141 insertions, 55 deletions
diff --git a/sys/contrib/openzfs/module/Makefile.in b/sys/contrib/openzfs/module/Makefile.in
index 69caf48570e9..089b3ff88490 100644
--- a/sys/contrib/openzfs/module/Makefile.in
+++ b/sys/contrib/openzfs/module/Makefile.in
@@ -17,6 +17,10 @@ check:
modules_uninstall modules_uninstall-Linux modules_uninstall-FreeBSD \
cppcheck cppcheck-Linux cppcheck-FreeBSD
+# For FreeBSD, use debug options from ./configure if not overridden.
+export WITH_DEBUG ?= @WITH_DEBUG@
+export WITH_INVARIANTS ?= @WITH_INVARIANTS@
+
# Filter out options that FreeBSD make doesn't understand
getflags = ( \
set -- \
@@ -42,6 +46,7 @@ FMAKEFLAGS = -C @abs_srcdir@ -f Makefile.bsd $(shell $(getflags))
ifneq (@abs_srcdir@,@abs_builddir@)
FMAKEFLAGS += MAKEOBJDIR=@abs_builddir@
endif
+
FMAKE = env -u MAKEFLAGS make $(FMAKEFLAGS)
modules-Linux:
diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/kmod_core.c b/sys/contrib/openzfs/module/os/freebsd/zfs/kmod_core.c
index c11d4dbcf660..d5ba0d93a569 100644
--- a/sys/contrib/openzfs/module/os/freebsd/zfs/kmod_core.c
+++ b/sys/contrib/openzfs/module/os/freebsd/zfs/kmod_core.c
@@ -182,23 +182,21 @@ out:
static void
zfsdev_close(void *data)
{
- zfsdev_state_t *zs, *zsp = data;
+ zfsdev_state_t *zs = data;
+
+ ASSERT(zs != NULL);
mutex_enter(&zfsdev_state_lock);
- for (zs = zfsdev_state_list; zs != NULL; zs = zs->zs_next) {
- if (zs == zsp)
- break;
- }
- if (zs == NULL || zs->zs_minor <= 0) {
- mutex_exit(&zfsdev_state_lock);
- return;
- }
+
+ ASSERT(zs->zs_minor != 0);
+
zs->zs_minor = -1;
zfs_onexit_destroy(zs->zs_onexit);
zfs_zevent_destroy(zs->zs_zevent);
- mutex_exit(&zfsdev_state_lock);
zs->zs_onexit = NULL;
zs->zs_zevent = NULL;
+
+ mutex_exit(&zfsdev_state_lock);
}
static int
diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_dir.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_dir.c
index fb01012dd6e7..de145a677600 100644
--- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_dir.c
+++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_dir.c
@@ -209,7 +209,6 @@ zfs_dd_lookup(znode_t *dzp, znode_t **zpp)
#ifdef ZFS_DEBUG
if (zfsvfs->z_replay == B_FALSE)
ASSERT_VOP_LOCKED(ZTOV(dzp), __func__);
- ASSERT(ZFS_TEARDOWN_READ_HELD(zfsvfs));
#endif
if (dzp->z_unlinked)
return (ENOENT);
@@ -234,7 +233,6 @@ zfs_dirlook(znode_t *dzp, const char *name, znode_t **zpp)
#ifdef ZFS_DEBUG
if (zfsvfs->z_replay == B_FALSE)
ASSERT_VOP_LOCKED(ZTOV(dzp), __func__);
- ASSERT(ZFS_TEARDOWN_READ_HELD(zfsvfs));
#endif
if (dzp->z_unlinked)
return (SET_ERROR(ENOENT));
diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zvol_os.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zvol_os.c
index 2389b1a06355..ba315f104738 100644
--- a/sys/contrib/openzfs/module/os/freebsd/zfs/zvol_os.c
+++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zvol_os.c
@@ -1163,6 +1163,9 @@ zvol_ensure_zilog(zvol_state_t *zv)
zv->zv_zilog = zil_open(zv->zv_objset,
zvol_get_data);
zv->zv_flags |= ZVOL_WRITTEN_TO;
+ /* replay / destroy done in zvol_create_minor_impl() */
+ VERIFY0((zv->zv_zilog->zl_header->zh_flags &
+ ZIL_REPLAY_NEEDED));
}
rw_downgrade(&zv->zv_suspend_lock);
}
@@ -1387,12 +1390,16 @@ zvol_create_minor_impl(const char *name)
zv->zv_volsize = volsize;
zv->zv_objset = os;
+ ASSERT3P(zv->zv_zilog, ==, NULL);
+ zv->zv_zilog = zil_open(os, zvol_get_data);
if (spa_writeable(dmu_objset_spa(os))) {
if (zil_replay_disable)
- zil_destroy(dmu_objset_zil(os), B_FALSE);
+ zil_destroy(zv->zv_zilog, B_FALSE);
else
zil_replay(os, zv, zvol_replay_vector);
}
+ zil_close(zv->zv_zilog);
+ zv->zv_zilog = NULL;
ASSERT3P(zv->zv_kstat.dk_kstats, ==, NULL);
dataset_kstats_create(&zv->zv_kstat, zv->zv_objset);
diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zfs_acl.c b/sys/contrib/openzfs/module/os/linux/zfs/zfs_acl.c
index 2628325c0ba9..f8bf55f75e97 100644
--- a/sys/contrib/openzfs/module/os/linux/zfs/zfs_acl.c
+++ b/sys/contrib/openzfs/module/os/linux/zfs/zfs_acl.c
@@ -2214,13 +2214,11 @@ zfs_zaccess_dataset_check(znode_t *zp, uint32_t v4_mode)
}
/*
- * Only check for READONLY on non-directories.
+ * Intentionally allow ZFS_READONLY through here.
+ * See zfs_zaccess_common().
*/
if ((v4_mode & WRITE_MASK_DATA) &&
- ((!S_ISDIR(ZTOI(zp)->i_mode) &&
- (zp->z_pflags & (ZFS_READONLY | ZFS_IMMUTABLE))) ||
- (S_ISDIR(ZTOI(zp)->i_mode) &&
- (zp->z_pflags & ZFS_IMMUTABLE)))) {
+ (zp->z_pflags & ZFS_IMMUTABLE)) {
return (SET_ERROR(EPERM));
}
@@ -2434,6 +2432,24 @@ zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode,
return (0);
}
+ /*
+ * Note: ZFS_READONLY represents the "DOS R/O" attribute.
+ * When that flag is set, we should behave as if write access
+ * were not granted by anything in the ACL. In particular:
+ * We _must_ allow writes after opening the file r/w, then
+ * setting the DOS R/O attribute, and writing some more.
+ * (Similar to how you can write after fchmod(fd, 0444).)
+ *
+ * Therefore ZFS_READONLY is ignored in the dataset check
+ * above, and checked here as if part of the ACL check.
+ * Also note: DOS R/O is ignored for directories.
+ */
+ if ((v4_mode & WRITE_MASK_DATA) &&
+ S_ISDIR(ZTOI(zp)->i_mode) &&
+ (zp->z_pflags & ZFS_READONLY)) {
+ return (SET_ERROR(EPERM));
+ }
+
return (zfs_zaccess_aces_check(zp, working_mode, B_FALSE, cr));
}
diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zio_crypt.c b/sys/contrib/openzfs/module/os/linux/zfs/zio_crypt.c
index 284ca706ede5..2c58fecb2066 100644
--- a/sys/contrib/openzfs/module/os/linux/zfs/zio_crypt.c
+++ b/sys/contrib/openzfs/module/os/linux/zfs/zio_crypt.c
@@ -1412,6 +1412,7 @@ zio_crypt_init_uios_zil(boolean_t encrypt, uint8_t *plainbuf,
nr_src = 1;
nr_dst = 0;
}
+ bzero(dst, datalen);
/* find the start and end record of the log block */
zilc = (zil_chain_t *)src;
diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zvol_os.c b/sys/contrib/openzfs/module/os/linux/zfs/zvol_os.c
index 0d62b1490702..7756d819fdeb 100644
--- a/sys/contrib/openzfs/module/os/linux/zfs/zvol_os.c
+++ b/sys/contrib/openzfs/module/os/linux/zfs/zvol_os.c
@@ -56,12 +56,32 @@ struct zvol_state_os {
taskq_t *zvol_taskq;
static struct ida zvol_ida;
-typedef struct zv_request {
+typedef struct zv_request_stack {
zvol_state_t *zv;
struct bio *bio;
- taskq_ent_t ent;
} zv_request_t;
+typedef struct zv_request_task {
+ zv_request_t zvr;
+ taskq_ent_t ent;
+} zv_request_task_t;
+
+static zv_request_task_t *
+zv_request_task_create(zv_request_t zvr)
+{
+ zv_request_task_t *task;
+ task = kmem_alloc(sizeof (zv_request_task_t), KM_SLEEP);
+ taskq_init_ent(&task->ent);
+ task->zvr = zvr;
+ return (task);
+}
+
+static void
+zv_request_task_free(zv_request_task_t *task)
+{
+ kmem_free(task, sizeof (*task));
+}
+
/*
* Given a path, return TRUE if path is a ZVOL.
*/
@@ -80,9 +100,8 @@ zvol_is_zvol_impl(const char *path)
}
static void
-zvol_write(void *arg)
+zvol_write(zv_request_t *zvr)
{
- zv_request_t *zvr = arg;
struct bio *bio = zvr->bio;
int error = 0;
zfs_uio_t uio;
@@ -102,7 +121,6 @@ zvol_write(void *arg)
if (uio.uio_resid == 0) {
rw_exit(&zv->zv_suspend_lock);
BIO_END_IO(bio, 0);
- kmem_free(zvr, sizeof (zv_request_t));
return;
}
@@ -162,13 +180,19 @@ zvol_write(void *arg)
blk_generic_end_io_acct(q, disk, WRITE, bio, start_time);
BIO_END_IO(bio, -error);
- kmem_free(zvr, sizeof (zv_request_t));
}
static void
-zvol_discard(void *arg)
+zvol_write_task(void *arg)
+{
+ zv_request_task_t *task = arg;
+ zvol_write(&task->zvr);
+ zv_request_task_free(task);
+}
+
+static void
+zvol_discard(zv_request_t *zvr)
{
- zv_request_t *zvr = arg;
struct bio *bio = zvr->bio;
zvol_state_t *zv = zvr->zv;
uint64_t start = BIO_BI_SECTOR(bio) << 9;
@@ -238,13 +262,19 @@ unlock:
blk_generic_end_io_acct(q, disk, WRITE, bio, start_time);
BIO_END_IO(bio, -error);
- kmem_free(zvr, sizeof (zv_request_t));
}
static void
-zvol_read(void *arg)
+zvol_discard_task(void *arg)
+{
+ zv_request_task_t *task = arg;
+ zvol_discard(&task->zvr);
+ zv_request_task_free(task);
+}
+
+static void
+zvol_read(zv_request_t *zvr)
{
- zv_request_t *zvr = arg;
struct bio *bio = zvr->bio;
int error = 0;
zfs_uio_t uio;
@@ -295,7 +325,14 @@ zvol_read(void *arg)
blk_generic_end_io_acct(q, disk, READ, bio, start_time);
BIO_END_IO(bio, -error);
- kmem_free(zvr, sizeof (zv_request_t));
+}
+
+static void
+zvol_read_task(void *arg)
+{
+ zv_request_task_t *task = arg;
+ zvol_read(&task->zvr);
+ zv_request_task_free(task);
}
#ifdef HAVE_SUBMIT_BIO_IN_BLOCK_DEVICE_OPERATIONS
@@ -318,7 +355,6 @@ zvol_request(struct request_queue *q, struct bio *bio)
uint64_t offset = BIO_BI_SECTOR(bio) << 9;
uint64_t size = BIO_BI_SIZE(bio);
int rw = bio_data_dir(bio);
- zv_request_t *zvr;
if (bio_has_data(bio) && offset + size > zv->zv_volsize) {
printk(KERN_INFO
@@ -331,6 +367,12 @@ zvol_request(struct request_queue *q, struct bio *bio)
goto out;
}
+ zv_request_t zvr = {
+ .zv = zv,
+ .bio = bio,
+ };
+ zv_request_task_t *task;
+
if (rw == WRITE) {
if (unlikely(zv->zv_flags & ZVOL_RDONLY)) {
BIO_END_IO(bio, -SET_ERROR(EROFS));
@@ -357,15 +399,13 @@ zvol_request(struct request_queue *q, struct bio *bio)
zv->zv_zilog = zil_open(zv->zv_objset,
zvol_get_data);
zv->zv_flags |= ZVOL_WRITTEN_TO;
+ /* replay / destroy done in zvol_create_minor */
+ VERIFY0((zv->zv_zilog->zl_header->zh_flags &
+ ZIL_REPLAY_NEEDED));
}
rw_downgrade(&zv->zv_suspend_lock);
}
- zvr = kmem_alloc(sizeof (zv_request_t), KM_SLEEP);
- zvr->zv = zv;
- zvr->bio = bio;
- taskq_init_ent(&zvr->ent);
-
/*
* We don't want this thread to be blocked waiting for i/o to
* complete, so we instead wait from a taskq callback. The
@@ -398,17 +438,19 @@ zvol_request(struct request_queue *q, struct bio *bio)
*/
if (bio_is_discard(bio) || bio_is_secure_erase(bio)) {
if (zvol_request_sync) {
- zvol_discard(zvr);
+ zvol_discard(&zvr);
} else {
+ task = zv_request_task_create(zvr);
taskq_dispatch_ent(zvol_taskq,
- zvol_discard, zvr, 0, &zvr->ent);
+ zvol_discard_task, task, 0, &task->ent);
}
} else {
if (zvol_request_sync) {
- zvol_write(zvr);
+ zvol_write(&zvr);
} else {
+ task = zv_request_task_create(zvr);
taskq_dispatch_ent(zvol_taskq,
- zvol_write, zvr, 0, &zvr->ent);
+ zvol_write_task, task, 0, &task->ent);
}
}
} else {
@@ -422,19 +464,15 @@ zvol_request(struct request_queue *q, struct bio *bio)
goto out;
}
- zvr = kmem_alloc(sizeof (zv_request_t), KM_SLEEP);
- zvr->zv = zv;
- zvr->bio = bio;
- taskq_init_ent(&zvr->ent);
-
rw_enter(&zv->zv_suspend_lock, RW_READER);
/* See comment in WRITE case above. */
if (zvol_request_sync) {
- zvol_read(zvr);
+ zvol_read(&zvr);
} else {
+ task = zv_request_task_create(zvr);
taskq_dispatch_ent(zvol_taskq,
- zvol_read, zvr, 0, &zvr->ent);
+ zvol_read_task, task, 0, &task->ent);
}
}
@@ -947,12 +985,16 @@ zvol_os_create_minor(const char *name)
blk_queue_flag_set(QUEUE_FLAG_SCSI_PASSTHROUGH, zv->zv_zso->zvo_queue);
#endif
+ ASSERT3P(zv->zv_zilog, ==, NULL);
+ zv->zv_zilog = zil_open(os, zvol_get_data);
if (spa_writeable(dmu_objset_spa(os))) {
if (zil_replay_disable)
- zil_destroy(dmu_objset_zil(os), B_FALSE);
+ zil_destroy(zv->zv_zilog, B_FALSE);
else
zil_replay(os, zv, zvol_replay_vector);
}
+ zil_close(zv->zv_zilog);
+ zv->zv_zilog = NULL;
ASSERT3P(zv->zv_kstat.dk_kstats, ==, NULL);
dataset_kstats_create(&zv->zv_kstat, zv->zv_objset);
diff --git a/sys/contrib/openzfs/module/zcommon/zfs_prop.c b/sys/contrib/openzfs/module/zcommon/zfs_prop.c
index b78331187e13..402d749c1aeb 100644
--- a/sys/contrib/openzfs/module/zcommon/zfs_prop.c
+++ b/sys/contrib/openzfs/module/zcommon/zfs_prop.c
@@ -417,7 +417,7 @@ zfs_prop_init(void)
ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
"on | off | lzjb | gzip | gzip-[1-9] | zle | lz4 | "
"zstd | zstd-[1-19] | "
- "zstd-fast-[1-10,20,30,40,50,60,70,80,90,100,500,1000]",
+ "zstd-fast | zstd-fast-[1-10,20,30,40,50,60,70,80,90,100,500,1000]",
"COMPRESS", compress_table);
zprop_register_index(ZFS_PROP_SNAPDIR, "snapdir", ZFS_SNAPDIR_HIDDEN,
PROP_INHERIT, ZFS_TYPE_FILESYSTEM,
diff --git a/sys/contrib/openzfs/module/zfs/abd.c b/sys/contrib/openzfs/module/zfs/abd.c
index 7d3a2f6d69e2..1e6645c90c95 100644
--- a/sys/contrib/openzfs/module/zfs/abd.c
+++ b/sys/contrib/openzfs/module/zfs/abd.c
@@ -555,8 +555,12 @@ abd_get_offset_impl(abd_t *abd, abd_t *sabd, size_t off, size_t size)
abd_t *
abd_get_offset_struct(abd_t *abd, abd_t *sabd, size_t off, size_t size)
{
+ abd_t *result;
abd_init_struct(abd);
- return (abd_get_offset_impl(abd, sabd, off, size));
+ result = abd_get_offset_impl(abd, sabd, off, size);
+ if (result != abd)
+ abd_fini_struct(abd);
+ return (result);
}
abd_t *
diff --git a/sys/contrib/openzfs/module/zfs/spa_misc.c b/sys/contrib/openzfs/module/zfs/spa_misc.c
index 0dacf9027b27..1a2e5abc5335 100644
--- a/sys/contrib/openzfs/module/zfs/spa_misc.c
+++ b/sys/contrib/openzfs/module/zfs/spa_misc.c
@@ -2923,10 +2923,10 @@ ZFS_MODULE_PARAM(zfs, zfs_, recover, INT, ZMOD_RW,
ZFS_MODULE_PARAM(zfs, zfs_, free_leak_on_eio, INT, ZMOD_RW,
"Set to ignore IO errors during free and permanently leak the space");
-ZFS_MODULE_PARAM(zfs, zfs_, deadman_checktime_ms, ULONG, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_deadman, zfs_deadman_, checktime_ms, ULONG, ZMOD_RW,
"Dead I/O check interval in milliseconds");
-ZFS_MODULE_PARAM(zfs, zfs_, deadman_enabled, INT, ZMOD_RW,
+ZFS_MODULE_PARAM(zfs_deadman, zfs_deadman_, enabled, INT, ZMOD_RW,
"Enable deadman timer");
ZFS_MODULE_PARAM(zfs_spa, spa_, asize_inflation, INT, ZMOD_RW,
diff --git a/sys/contrib/openzfs/module/zfs/zfs_vnops.c b/sys/contrib/openzfs/module/zfs/zfs_vnops.c
index a35c17f86f93..0af03e9233b3 100644
--- a/sys/contrib/openzfs/module/zfs/zfs_vnops.c
+++ b/sys/contrib/openzfs/module/zfs/zfs_vnops.c
@@ -350,9 +350,11 @@ zfs_write(znode_t *zp, zfs_uio_t *uio, int ioflag, cred_t *cr)
}
/*
- * If immutable or not appending then return EPERM
+ * If immutable or not appending then return EPERM.
+ * Intentionally allow ZFS_READONLY through here.
+ * See zfs_zaccess_common()
*/
- if ((zp->z_pflags & (ZFS_IMMUTABLE | ZFS_READONLY)) ||
+ if ((zp->z_pflags & ZFS_IMMUTABLE) ||
((zp->z_pflags & ZFS_APPENDONLY) && !(ioflag & O_APPEND) &&
(zfs_uio_offset(uio) < zp->z_size))) {
ZFS_EXIT(zfsvfs);
diff --git a/sys/contrib/openzfs/module/zfs/zvol.c b/sys/contrib/openzfs/module/zfs/zvol.c
index 7c6dae8650c7..44f9832ce857 100644
--- a/sys/contrib/openzfs/module/zfs/zvol.c
+++ b/sys/contrib/openzfs/module/zfs/zvol.c
@@ -473,7 +473,19 @@ zvol_replay_truncate(void *arg1, void *arg2, boolean_t byteswap)
offset = lr->lr_offset;
length = lr->lr_length;
- return (dmu_free_long_range(zv->zv_objset, ZVOL_OBJ, offset, length));
+ dmu_tx_t *tx = dmu_tx_create(zv->zv_objset);
+ dmu_tx_mark_netfree(tx);
+ int error = dmu_tx_assign(tx, TXG_WAIT);
+ if (error != 0) {
+ dmu_tx_abort(tx);
+ } else {
+ zil_replaying(zv->zv_zilog, tx);
+ dmu_tx_commit(tx);
+ error = dmu_free_long_range(zv->zv_objset, ZVOL_OBJ, offset,
+ length);
+ }
+
+ return (error);
}
/*
@@ -513,6 +525,7 @@ zvol_replay_write(void *arg1, void *arg2, boolean_t byteswap)
dmu_tx_abort(tx);
} else {
dmu_write(os, ZVOL_OBJ, offset, length, data, tx);
+ zil_replaying(zv->zv_zilog, tx);
dmu_tx_commit(tx);
}