aboutsummaryrefslogtreecommitdiff
path: root/sys/contrib/openzfs/module
diff options
context:
space:
mode:
authorMartin Matuska <mm@FreeBSD.org>2021-12-19 15:21:10 +0000
committerMartin Matuska <mm@FreeBSD.org>2021-12-19 15:25:26 +0000
commit3aa1cabca37db4ef3da06e92af17688783ccb00c (patch)
treeac6e97937df069c532ea8f3d18eb2429789be8ae /sys/contrib/openzfs/module
parent19592949abd2953a3c00cda59231113d29d4dd63 (diff)
parentaf88d47f1ee86fae4abcfe0dabca67ea3c94d377 (diff)
zfs: merge openzfs/zfs@af88d47f1 (zfs-2.1-release) into stable/13
OpenZFS release 2.1.2 Notable upstream pull request merges: #12668 FreeBSD: Catch up with recent VFS changes #12704 Fix some FreeBSD VOPs to synchronize properly with teardown #12717 VOP_RENAME fixes for FreeBSD #12724 Fix lseek(SEEK_DATA/SEEK_HOLE) mmap consistency #12745 Restore dirty dnode detection logic #12770 ZFS send/recv with ashift 9->12 leads to data corruption #12828 FreeBSD: Add vop_standard_writecount_nomsyn #12828 FreeBSD: Catch up with more VFS changes Obtained from: OpenZFS OpenZFS commit: af88d47f1ee86fae4abcfe0dabca67ea3c94d377 OpenZFS tag: zfs-2.1.2 Relnotes: yes
Diffstat (limited to 'sys/contrib/openzfs/module')
-rw-r--r--sys/contrib/openzfs/module/Makefile.in4
-rw-r--r--sys/contrib/openzfs/module/icp/core/kcf_prov_tabs.c2
-rw-r--r--sys/contrib/openzfs/module/icp/io/aes.c2
-rw-r--r--sys/contrib/openzfs/module/lua/lcode.c4
-rw-r--r--sys/contrib/openzfs/module/lua/lgc.c2
-rw-r--r--sys/contrib/openzfs/module/lua/llex.c2
-rw-r--r--sys/contrib/openzfs/module/lua/lstrlib.c2
-rw-r--r--sys/contrib/openzfs/module/lua/ltable.c2
-rw-r--r--sys/contrib/openzfs/module/nvpair/nvpair.c6
-rw-r--r--sys/contrib/openzfs/module/os/freebsd/zfs/vdev_geom.c1
-rw-r--r--sys/contrib/openzfs/module/os/freebsd/zfs/zfs_acl.c4
-rw-r--r--sys/contrib/openzfs/module/os/freebsd/zfs/zfs_ctldir.c9
-rw-r--r--sys/contrib/openzfs/module/os/freebsd/zfs/zfs_file_os.c4
-rw-r--r--sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c331
-rw-r--r--sys/contrib/openzfs/module/os/linux/spl/spl-generic.c1
-rw-r--r--sys/contrib/openzfs/module/os/linux/zfs/vdev_disk.c39
-rw-r--r--sys/contrib/openzfs/module/os/linux/zfs/zfs_acl.c4
-rw-r--r--sys/contrib/openzfs/module/os/linux/zfs/zfs_vnops_os.c4
-rw-r--r--sys/contrib/openzfs/module/os/linux/zfs/zfs_znode.c2
-rw-r--r--sys/contrib/openzfs/module/os/linux/zfs/zpl_file.c6
-rw-r--r--sys/contrib/openzfs/module/os/linux/zfs/zvol_os.c69
-rw-r--r--sys/contrib/openzfs/module/unicode/u8_textprep.c4
-rw-r--r--sys/contrib/openzfs/module/zfs/abd.c8
-rw-r--r--sys/contrib/openzfs/module/zfs/arc.c1
-rw-r--r--sys/contrib/openzfs/module/zfs/dmu.c53
-rw-r--r--sys/contrib/openzfs/module/zfs/dmu_send.c23
-rw-r--r--sys/contrib/openzfs/module/zfs/dnode.c20
-rw-r--r--sys/contrib/openzfs/module/zfs/dsl_prop.c2
-rw-r--r--sys/contrib/openzfs/module/zfs/spa.c2
-rw-r--r--sys/contrib/openzfs/module/zfs/vdev.c24
-rw-r--r--sys/contrib/openzfs/module/zfs/vdev_label.c2
-rw-r--r--sys/contrib/openzfs/module/zfs/vdev_raidz_math_scalar.c2
-rw-r--r--sys/contrib/openzfs/module/zfs/zfs_replay.c10
-rw-r--r--sys/contrib/openzfs/module/zfs/zfs_vnops.c9
-rw-r--r--sys/contrib/openzfs/module/zfs/zio_compress.c2
-rw-r--r--sys/contrib/openzfs/module/zfs/zvol.c102
-rw-r--r--sys/contrib/openzfs/module/zstd/include/zstd_compat_wrapper.h1
-rw-r--r--sys/contrib/openzfs/module/zstd/lib/zstd.c2
38 files changed, 508 insertions, 259 deletions
diff --git a/sys/contrib/openzfs/module/Makefile.in b/sys/contrib/openzfs/module/Makefile.in
index 089b3ff88490..05c673231cc5 100644
--- a/sys/contrib/openzfs/module/Makefile.in
+++ b/sys/contrib/openzfs/module/Makefile.in
@@ -114,7 +114,9 @@ modules_uninstall: modules_uninstall-@ac_system@
cppcheck-Linux:
@CPPCHECK@ -j@CPU_COUNT@ --std=c99 --quiet --force --error-exitcode=2 \
- --inline-suppr --suppress=noValidConfiguration \
+ --inline-suppr \
+ --suppress=unmatchedSuppression \
+ --suppress=noValidConfiguration \
--enable=warning,information -D_KERNEL \
--include=@LINUX_OBJ@/include/generated/autoconf.h \
--include=@top_srcdir@/zfs_config.h \
diff --git a/sys/contrib/openzfs/module/icp/core/kcf_prov_tabs.c b/sys/contrib/openzfs/module/icp/core/kcf_prov_tabs.c
index 94e6937bcd76..9d303d022517 100644
--- a/sys/contrib/openzfs/module/icp/core/kcf_prov_tabs.c
+++ b/sys/contrib/openzfs/module/icp/core/kcf_prov_tabs.c
@@ -377,7 +377,7 @@ kcf_provider_zero_refcnt(kcf_provider_desc_t *desc)
mutex_exit(&desc->pd_lock);
break;
}
- /* FALLTHRU */
+ fallthrough;
case CRYPTO_HW_PROVIDER:
case CRYPTO_LOGICAL_PROVIDER:
diff --git a/sys/contrib/openzfs/module/icp/io/aes.c b/sys/contrib/openzfs/module/icp/io/aes.c
index e540af4473f7..c47c7567b900 100644
--- a/sys/contrib/openzfs/module/icp/io/aes.c
+++ b/sys/contrib/openzfs/module/icp/io/aes.c
@@ -976,7 +976,7 @@ aes_encrypt_atomic(crypto_provider_handle_t provider,
case AES_GMAC_MECH_INFO_TYPE:
if (plaintext->cd_length != 0)
return (CRYPTO_ARGUMENTS_BAD);
- /* FALLTHRU */
+ fallthrough;
case AES_GCM_MECH_INFO_TYPE:
length_needed = plaintext->cd_length + aes_ctx.ac_tag_len;
break;
diff --git a/sys/contrib/openzfs/module/lua/lcode.c b/sys/contrib/openzfs/module/lua/lcode.c
index ae9a3d91d810..4d88c792a281 100644
--- a/sys/contrib/openzfs/module/lua/lcode.c
+++ b/sys/contrib/openzfs/module/lua/lcode.c
@@ -8,6 +8,10 @@
#define lcode_c
#define LUA_CORE
+#if defined(HAVE_IMPLICIT_FALLTHROUGH)
+#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
+#endif
+
#include <sys/lua/lua.h>
#include "lcode.h"
diff --git a/sys/contrib/openzfs/module/lua/lgc.c b/sys/contrib/openzfs/module/lua/lgc.c
index 55feb24119d3..227ad723a0b8 100644
--- a/sys/contrib/openzfs/module/lua/lgc.c
+++ b/sys/contrib/openzfs/module/lua/lgc.c
@@ -676,7 +676,7 @@ static void freeobj (lua_State *L, GCObject *o) {
case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break;
case LUA_TSHRSTR:
G(L)->strt.nuse--;
- /* FALLTHROUGH */
+ fallthrough;
case LUA_TLNGSTR: {
luaM_freemem(L, o, sizestring(gco2ts(o)));
break;
diff --git a/sys/contrib/openzfs/module/lua/llex.c b/sys/contrib/openzfs/module/lua/llex.c
index 50c301f599f1..f2c9bf826c82 100644
--- a/sys/contrib/openzfs/module/lua/llex.c
+++ b/sys/contrib/openzfs/module/lua/llex.c
@@ -477,7 +477,7 @@ static int llex (LexState *ls, SemInfo *seminfo) {
else if (!lisdigit(ls->current)) return '.';
/* else go through */
}
- /* FALLTHROUGH */
+ fallthrough;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': {
read_numeral(ls, seminfo);
diff --git a/sys/contrib/openzfs/module/lua/lstrlib.c b/sys/contrib/openzfs/module/lua/lstrlib.c
index 12027757bf53..46e3d8fb35bb 100644
--- a/sys/contrib/openzfs/module/lua/lstrlib.c
+++ b/sys/contrib/openzfs/module/lua/lstrlib.c
@@ -501,7 +501,7 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
}
case '+': /* 1 or more repetitions */
s++; /* 1 match already done */
- /* FALLTHROUGH */
+ fallthrough;
case '*': /* 0 or more repetitions */
s = max_expand(ms, s, p, ep);
break;
diff --git a/sys/contrib/openzfs/module/lua/ltable.c b/sys/contrib/openzfs/module/lua/ltable.c
index f60418721bef..f6872babc6e7 100644
--- a/sys/contrib/openzfs/module/lua/ltable.c
+++ b/sys/contrib/openzfs/module/lua/ltable.c
@@ -492,7 +492,7 @@ const TValue *luaH_get (Table *t, const TValue *key) {
return luaH_getint(t, k); /* use specialized version */
/* else go through */
}
- /* FALLTHROUGH */
+ fallthrough;
default: {
Node *n = mainposition(t, key);
do { /* check whether `key' is somewhere in the chain */
diff --git a/sys/contrib/openzfs/module/nvpair/nvpair.c b/sys/contrib/openzfs/module/nvpair/nvpair.c
index 5f427c8cf2e7..9834dedd859d 100644
--- a/sys/contrib/openzfs/module/nvpair/nvpair.c
+++ b/sys/contrib/openzfs/module/nvpair/nvpair.c
@@ -533,12 +533,14 @@ nvt_add_nvpair(nvlist_t *nvl, nvpair_t *nvp)
uint64_t index = hash & (priv->nvp_nbuckets - 1);
ASSERT3U(index, <, priv->nvp_nbuckets);
+ // cppcheck-suppress nullPointerRedundantCheck
i_nvp_t *bucket = tab[index];
/* insert link at the beginning of the bucket */
i_nvp_t *new_entry = NVPAIR2I_NVP(nvp);
ASSERT3P(new_entry->nvi_hashtable_next, ==, NULL);
new_entry->nvi_hashtable_next = bucket;
+ // cppcheck-suppress nullPointerRedundantCheck
tab[index] = new_entry;
priv->nvp_nentries++;
@@ -3270,6 +3272,8 @@ NVS_BUILD_XDRPROC_T(u_longlong_t);
static int
nvs_xdr_nvp_op(nvstream_t *nvs, nvpair_t *nvp)
{
+ ASSERT(nvs != NULL && nvp != NULL);
+
data_type_t type;
char *buf;
char *buf_end = (char *)nvp + nvp->nvp_size;
@@ -3278,7 +3282,7 @@ nvs_xdr_nvp_op(nvstream_t *nvs, nvpair_t *nvp)
bool_t ret = FALSE;
XDR *xdr = nvs->nvs_private;
- ASSERT(xdr != NULL && nvp != NULL);
+ ASSERT(xdr != NULL);
/* name string */
if ((buf = NVP_NAME(nvp)) >= buf_end)
diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/vdev_geom.c b/sys/contrib/openzfs/module/os/freebsd/zfs/vdev_geom.c
index 4ffa21495e74..2ef4811a8a4e 100644
--- a/sys/contrib/openzfs/module/os/freebsd/zfs/vdev_geom.c
+++ b/sys/contrib/openzfs/module/os/freebsd/zfs/vdev_geom.c
@@ -199,7 +199,6 @@ vdev_geom_orphan(struct g_consumer *cp)
* async removal support to invoke a close on this
* vdev once it is safe to do so.
*/
- // cppcheck-suppress All
SLIST_FOREACH(elem, priv, elems) {
// cppcheck-suppress uninitvar
vdev_t *vd = elem->vd;
diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_acl.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_acl.c
index 9b410863019e..ae758bcefe21 100644
--- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_acl.c
+++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_acl.c
@@ -269,7 +269,7 @@ zfs_ace_fuid_size(void *acep)
entry_type == OWNING_GROUP ||
entry_type == ACE_EVERYONE)
return (sizeof (zfs_ace_hdr_t));
- /*FALLTHROUGH*/
+ fallthrough;
default:
return (sizeof (zfs_ace_t));
}
@@ -2153,7 +2153,7 @@ zfs_zaccess_aces_check(znode_t *zp, uint32_t *working_mode,
break;
case OWNING_GROUP:
who = gowner;
- /*FALLTHROUGH*/
+ fallthrough;
case ACE_IDENTIFIER_GROUP:
checkit = zfs_groupmember(zfsvfs, who, cr);
break;
diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_ctldir.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_ctldir.c
index a9fe1b647238..cde40e87698b 100644
--- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_ctldir.c
+++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_ctldir.c
@@ -815,6 +815,9 @@ static struct vop_vector zfsctl_ops_root = {
.vop_vptocnp = zfsctl_root_vptocnp,
.vop_pathconf = zfsctl_common_pathconf,
.vop_getacl = zfsctl_common_getacl,
+#if __FreeBSD_version >= 1400043
+ .vop_add_writecount = vop_stdadd_writecount_nomsync,
+#endif
};
VFS_VOP_VECTOR_REGISTER(zfsctl_ops_root);
@@ -1134,6 +1137,9 @@ static struct vop_vector zfsctl_ops_snapdir = {
.vop_print = zfsctl_common_print,
.vop_pathconf = zfsctl_common_pathconf,
.vop_getacl = zfsctl_common_getacl,
+#if __FreeBSD_version >= 1400043
+ .vop_add_writecount = vop_stdadd_writecount_nomsync,
+#endif
};
VFS_VOP_VECTOR_REGISTER(zfsctl_ops_snapdir);
@@ -1238,6 +1244,9 @@ static struct vop_vector zfsctl_ops_snapshot = {
.vop_islocked = vop_stdislocked,
.vop_advlockpurge = vop_stdadvlockpurge, /* called by vgone */
.vop_print = zfsctl_common_print,
+#if __FreeBSD_version >= 1400043
+ .vop_add_writecount = vop_stdadd_writecount_nomsync,
+#endif
};
VFS_VOP_VECTOR_REGISTER(zfsctl_ops_snapshot);
diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_file_os.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_file_os.c
index a3d67aaa11ba..fd86a75416e6 100644
--- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_file_os.c
+++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_file_os.c
@@ -207,7 +207,11 @@ zfs_file_getattr(zfs_file_t *fp, zfs_file_attr_t *zfattr)
td = curthread;
+#if __FreeBSD_version < 1400037
rc = fo_stat(fp, &sb, td->td_ucred, td);
+#else
+ rc = fo_stat(fp, &sb, td->td_ucred);
+#endif
if (rc)
return (SET_ERROR(rc));
zfattr->zfa_size = sb.st_size;
diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c
index 4672b9c2b8b3..8e48f78b7311 100644
--- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c
+++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c
@@ -775,8 +775,8 @@ zfs_lookup_lock(vnode_t *dvp, vnode_t *vp, const char *name, int lkflags)
/* ARGSUSED */
static int
zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp,
- struct componentname *cnp, int nameiop, cred_t *cr, kthread_t *td,
- int flags, boolean_t cached)
+ struct componentname *cnp, int nameiop, cred_t *cr, int flags,
+ boolean_t cached)
{
znode_t *zdp = VTOZ(dvp);
znode_t *zp;
@@ -974,7 +974,7 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp,
cnp->cn_flags |= SAVENAME;
break;
}
- /* FALLTHROUGH */
+ fallthrough;
case DELETE:
if (error == 0)
cnp->cn_flags |= SAVENAME;
@@ -1338,7 +1338,9 @@ zfs_lookup_internal(znode_t *dzp, const char *name, vnode_t **vpp,
cnp->cn_flags = ISLASTCN | SAVENAME;
cnp->cn_lkflags = LK_EXCLUSIVE | LK_RETRY;
cnp->cn_cred = kcred;
+#if __FreeBSD_version < 1400037
cnp->cn_thread = curthread;
+#endif
if (zfsvfs->z_use_namecache && !zfsvfs->z_replay) {
struct vop_lookup_args a;
@@ -1349,8 +1351,8 @@ zfs_lookup_internal(znode_t *dzp, const char *name, vnode_t **vpp,
a.a_cnp = cnp;
error = vfs_cache_lookup(&a);
} else {
- error = zfs_lookup(ZTOV(dzp), name, vpp, cnp, nameiop, kcred,
- curthread, 0, B_FALSE);
+ error = zfs_lookup(ZTOV(dzp), name, vpp, cnp, nameiop, kcred, 0,
+ B_FALSE);
}
#ifdef ZFS_DEBUG
if (error) {
@@ -2220,7 +2222,7 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr)
{
vnode_t *vp = ZTOV(zp);
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
- objset_t *os = zfsvfs->z_os;
+ objset_t *os;
zilog_t *zilog;
dmu_tx_t *tx;
vattr_t oldva;
@@ -2255,6 +2257,7 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr)
ZFS_ENTER(zfsvfs);
ZFS_VERIFY_ZP(zp);
+ os = zfsvfs->z_os;
zilog = zfsvfs->z_log;
/*
@@ -2932,6 +2935,66 @@ out2:
}
/*
+ * Look up the directory entries corresponding to the source and target
+ * directory/name pairs.
+ */
+static int
+zfs_rename_relock_lookup(znode_t *sdzp, const struct componentname *scnp,
+ znode_t **szpp, znode_t *tdzp, const struct componentname *tcnp,
+ znode_t **tzpp)
+{
+ zfsvfs_t *zfsvfs;
+ znode_t *szp, *tzp;
+ int error;
+
+ /*
+ * Before using sdzp and tdzp we must ensure that they are live.
+ * As a porting legacy from illumos we have two things to worry
+ * about. One is typical for FreeBSD and it is that the vnode is
+ * not reclaimed (doomed). The other is that the znode is live.
+ * The current code can invalidate the znode without acquiring the
+ * corresponding vnode lock if the object represented by the znode
+ * and vnode is no longer valid after a rollback or receive operation.
+ * z_teardown_lock hidden behind ZFS_ENTER and ZFS_EXIT is the lock
+ * that protects the znodes from the invalidation.
+ */
+ zfsvfs = sdzp->z_zfsvfs;
+ ASSERT3P(zfsvfs, ==, tdzp->z_zfsvfs);
+ ZFS_ENTER(zfsvfs);
+ ZFS_VERIFY_ZP(sdzp);
+ ZFS_VERIFY_ZP(tdzp);
+
+ /*
+ * Re-resolve svp to be certain it still exists and fetch the
+ * correct vnode.
+ */
+ error = zfs_dirent_lookup(sdzp, scnp->cn_nameptr, &szp, ZEXISTS);
+ if (error != 0) {
+ /* Source entry invalid or not there. */
+ if ((scnp->cn_flags & ISDOTDOT) != 0 ||
+ (scnp->cn_namelen == 1 && scnp->cn_nameptr[0] == '.'))
+ error = SET_ERROR(EINVAL);
+ goto out;
+ }
+ *szpp = szp;
+
+ /*
+ * Re-resolve tvp, if it disappeared we just carry on.
+ */
+ error = zfs_dirent_lookup(tdzp, tcnp->cn_nameptr, &tzp, 0);
+ if (error != 0) {
+ vrele(ZTOV(szp));
+ if ((tcnp->cn_flags & ISDOTDOT) != 0)
+ error = SET_ERROR(EINVAL);
+ goto out;
+ }
+ *tzpp = tzp;
+out:
+ ZFS_EXIT(zfsvfs);
+ return (error);
+}
+
+/*
* We acquire all but fdvp locks using non-blocking acquisitions. If we
* fail to acquire any lock in the path we will drop all held locks,
* acquire the new lock in a blocking fashion, and then release it and
@@ -2944,12 +3007,9 @@ zfs_rename_relock(struct vnode *sdvp, struct vnode **svpp,
struct vnode *tdvp, struct vnode **tvpp,
const struct componentname *scnp, const struct componentname *tcnp)
{
- zfsvfs_t *zfsvfs;
struct vnode *nvp, *svp, *tvp;
znode_t *sdzp, *tdzp, *szp, *tzp;
- const char *snm = scnp->cn_nameptr;
- const char *tnm = tcnp->cn_nameptr;
- int error;
+ int error;
VOP_UNLOCK1(tdvp);
if (*tvpp != NULL && *tvpp != tdvp)
@@ -2959,8 +3019,6 @@ relock:
error = vn_lock(sdvp, LK_EXCLUSIVE);
if (error)
goto out;
- sdzp = VTOZ(sdvp);
-
error = vn_lock(tdvp, LK_EXCLUSIVE | LK_NOWAIT);
if (error != 0) {
VOP_UNLOCK1(sdvp);
@@ -2973,74 +3031,16 @@ relock:
goto relock;
}
tdzp = VTOZ(tdvp);
+ sdzp = VTOZ(sdvp);
- /*
- * Before using sdzp and tdzp we must ensure that they are live.
- * As a porting legacy from illumos we have two things to worry
- * about. One is typical for FreeBSD and it is that the vnode is
- * not reclaimed (doomed). The other is that the znode is live.
- * The current code can invalidate the znode without acquiring the
- * corresponding vnode lock if the object represented by the znode
- * and vnode is no longer valid after a rollback or receive operation.
- * z_teardown_lock hidden behind ZFS_ENTER and ZFS_EXIT is the lock
- * that protects the znodes from the invalidation.
- */
- zfsvfs = sdzp->z_zfsvfs;
- ASSERT3P(zfsvfs, ==, tdzp->z_zfsvfs);
- ZFS_ENTER(zfsvfs);
-
- /*
- * We can not use ZFS_VERIFY_ZP() here because it could directly return
- * bypassing the cleanup code in the case of an error.
- */
- if (tdzp->z_sa_hdl == NULL || sdzp->z_sa_hdl == NULL) {
- ZFS_EXIT(zfsvfs);
- VOP_UNLOCK1(sdvp);
- VOP_UNLOCK1(tdvp);
- error = SET_ERROR(EIO);
- goto out;
- }
-
- /*
- * Re-resolve svp to be certain it still exists and fetch the
- * correct vnode.
- */
- error = zfs_dirent_lookup(sdzp, snm, &szp, ZEXISTS);
+ error = zfs_rename_relock_lookup(sdzp, scnp, &szp, tdzp, tcnp, &tzp);
if (error != 0) {
- /* Source entry invalid or not there. */
- ZFS_EXIT(zfsvfs);
VOP_UNLOCK1(sdvp);
VOP_UNLOCK1(tdvp);
- if ((scnp->cn_flags & ISDOTDOT) != 0 ||
- (scnp->cn_namelen == 1 && scnp->cn_nameptr[0] == '.'))
- error = SET_ERROR(EINVAL);
goto out;
}
svp = ZTOV(szp);
-
- /*
- * Re-resolve tvp, if it disappeared we just carry on.
- */
- error = zfs_dirent_lookup(tdzp, tnm, &tzp, 0);
- if (error != 0) {
- ZFS_EXIT(zfsvfs);
- VOP_UNLOCK1(sdvp);
- VOP_UNLOCK1(tdvp);
- vrele(svp);
- if ((tcnp->cn_flags & ISDOTDOT) != 0)
- error = SET_ERROR(EINVAL);
- goto out;
- }
- if (tzp != NULL)
- tvp = ZTOV(tzp);
- else
- tvp = NULL;
-
- /*
- * At present the vnode locks must be acquired before z_teardown_lock,
- * although it would be more logical to use the opposite order.
- */
- ZFS_EXIT(zfsvfs);
+ tvp = tzp != NULL ? ZTOV(tzp) : NULL;
/*
* Now try acquire locks on svp and tvp.
@@ -3177,17 +3177,22 @@ cache_vop_rename(struct vnode *fdvp, struct vnode *fvp, struct vnode *tdvp,
}
#endif
+static int
+zfs_do_rename_impl(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
+ vnode_t *tdvp, vnode_t **tvpp, struct componentname *tcnp,
+ cred_t *cr);
+
/*
* Move an entry from the provided source directory to the target
* directory. Change the entry name as indicated.
*
* IN: sdvp - Source directory containing the "old entry".
- * snm - Old entry name.
+ * scnp - Old entry name.
* tdvp - Target directory to contain the "new entry".
- * tnm - New entry name.
+ * tcnp - New entry name.
* cr - credentials of caller.
- * ct - caller context
- * flags - case flags
+ * INOUT: svpp - Source file
+ * tvpp - Target file, may point to NULL initially
*
* RETURN: 0 on success, error code on failure.
*
@@ -3196,18 +3201,15 @@ cache_vop_rename(struct vnode *fdvp, struct vnode *fvp, struct vnode *tdvp,
*/
/*ARGSUSED*/
static int
-zfs_rename_(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
+zfs_do_rename(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
vnode_t *tdvp, vnode_t **tvpp, struct componentname *tcnp,
- cred_t *cr, int log)
+ cred_t *cr)
{
- zfsvfs_t *zfsvfs;
- znode_t *sdzp, *tdzp, *szp, *tzp;
- zilog_t *zilog = NULL;
- dmu_tx_t *tx;
- const char *snm = scnp->cn_nameptr;
- const char *tnm = tcnp->cn_nameptr;
- int error = 0;
- bool want_seqc_end __maybe_unused = false;
+ int error;
+
+ ASSERT_VOP_ELOCKED(tdvp, __func__);
+ if (*tvpp != NULL)
+ ASSERT_VOP_ELOCKED(*tvpp, __func__);
/* Reject renames across filesystems. */
if ((*svpp)->v_mount != tdvp->v_mount ||
@@ -3230,51 +3232,64 @@ zfs_rename_(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
return (error);
}
+ error = zfs_do_rename_impl(sdvp, svpp, scnp, tdvp, tvpp, tcnp, cr);
+ VOP_UNLOCK1(sdvp);
+ VOP_UNLOCK1(*svpp);
+out:
+ if (*tvpp != NULL)
+ VOP_UNLOCK1(*tvpp);
+ if (tdvp != *tvpp)
+ VOP_UNLOCK1(tdvp);
+
+ return (error);
+}
+
+static int
+zfs_do_rename_impl(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
+ vnode_t *tdvp, vnode_t **tvpp, struct componentname *tcnp,
+ cred_t *cr)
+{
+ dmu_tx_t *tx;
+ zfsvfs_t *zfsvfs;
+ zilog_t *zilog;
+ znode_t *tdzp, *sdzp, *tzp, *szp;
+ const char *snm = scnp->cn_nameptr;
+ const char *tnm = tcnp->cn_nameptr;
+ int error;
+
tdzp = VTOZ(tdvp);
sdzp = VTOZ(sdvp);
zfsvfs = tdzp->z_zfsvfs;
- zilog = zfsvfs->z_log;
- /*
- * After we re-enter ZFS_ENTER() we will have to revalidate all
- * znodes involved.
- */
ZFS_ENTER(zfsvfs);
+ ZFS_VERIFY_ZP(tdzp);
+ ZFS_VERIFY_ZP(sdzp);
+ zilog = zfsvfs->z_log;
if (zfsvfs->z_utf8 && u8_validate(tnm,
strlen(tnm), NULL, U8_VALIDATE_ENTIRE, &error) < 0) {
error = SET_ERROR(EILSEQ);
- goto unlockout;
+ goto out;
}
/* If source and target are the same file, there is nothing to do. */
if ((*svpp) == (*tvpp)) {
error = 0;
- goto unlockout;
+ goto out;
}
if (((*svpp)->v_type == VDIR && (*svpp)->v_mountedhere != NULL) ||
((*tvpp) != NULL && (*tvpp)->v_type == VDIR &&
(*tvpp)->v_mountedhere != NULL)) {
error = SET_ERROR(EXDEV);
- goto unlockout;
- }
-
- /*
- * We can not use ZFS_VERIFY_ZP() here because it could directly return
- * bypassing the cleanup code in the case of an error.
- */
- if (tdzp->z_sa_hdl == NULL || sdzp->z_sa_hdl == NULL) {
- error = SET_ERROR(EIO);
- goto unlockout;
+ goto out;
}
szp = VTOZ(*svpp);
+ ZFS_VERIFY_ZP(szp);
tzp = *tvpp == NULL ? NULL : VTOZ(*tvpp);
- if (szp->z_sa_hdl == NULL || (tzp != NULL && tzp->z_sa_hdl == NULL)) {
- error = SET_ERROR(EIO);
- goto unlockout;
- }
+ if (tzp != NULL)
+ ZFS_VERIFY_ZP(tzp);
/*
* This is to prevent the creation of links into attribute space
@@ -3283,7 +3298,7 @@ zfs_rename_(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
*/
if ((tdzp->z_pflags & ZFS_XATTR) != (sdzp->z_pflags & ZFS_XATTR)) {
error = SET_ERROR(EINVAL);
- goto unlockout;
+ goto out;
}
/*
@@ -3296,7 +3311,7 @@ zfs_rename_(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
if (tdzp->z_pflags & ZFS_PROJINHERIT &&
tdzp->z_projid != szp->z_projid) {
error = SET_ERROR(EXDEV);
- goto unlockout;
+ goto out;
}
/*
@@ -3306,7 +3321,7 @@ zfs_rename_(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
* done in a single check.
*/
if ((error = zfs_zaccess_rename(sdzp, szp, tdzp, tzp, cr)))
- goto unlockout;
+ goto out;
if ((*svpp)->v_type == VDIR) {
/*
@@ -3316,7 +3331,7 @@ zfs_rename_(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
sdzp == szp ||
(scnp->cn_flags | tcnp->cn_flags) & ISDOTDOT) {
error = EINVAL;
- goto unlockout;
+ goto out;
}
/*
@@ -3324,7 +3339,7 @@ zfs_rename_(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
* Can't do a move like this: /usr/a/b to /usr/a/b/c/d
*/
if ((error = zfs_rename_check(szp, sdzp, tdzp)))
- goto unlockout;
+ goto out;
}
/*
@@ -3337,7 +3352,7 @@ zfs_rename_(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
if ((*svpp)->v_type == VDIR) {
if ((*tvpp)->v_type != VDIR) {
error = SET_ERROR(ENOTDIR);
- goto unlockout;
+ goto out;
} else {
cache_purge(tdvp);
if (sdvp != tdvp)
@@ -3346,7 +3361,7 @@ zfs_rename_(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
} else {
if ((*tvpp)->v_type == VDIR) {
error = SET_ERROR(EISDIR);
- goto unlockout;
+ goto out;
}
}
}
@@ -3357,9 +3372,7 @@ zfs_rename_(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
vn_seqc_write_begin(*tvpp);
if (tdvp != *tvpp)
vn_seqc_write_begin(tdvp);
-#if __FreeBSD_version >= 1300102
- want_seqc_end = true;
-#endif
+
vnevent_rename_src(*svpp, sdvp, scnp->cn_nameptr, ct);
if (tzp)
vnevent_rename_dest(*tvpp, tdvp, tnm, ct);
@@ -3391,10 +3404,9 @@ zfs_rename_(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
error = dmu_tx_assign(tx, TXG_WAIT);
if (error) {
dmu_tx_abort(tx);
- goto unlockout;
+ goto out_seq;
}
-
if (tzp) /* Attempt to remove the existing target */
error = zfs_link_destroy(tdzp, tnm, tzp, tx, 0, NULL);
@@ -3441,29 +3453,19 @@ zfs_rename_(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp,
dmu_tx_commit(tx);
-unlockout: /* all 4 vnodes are locked, ZFS_ENTER called */
- ZFS_EXIT(zfsvfs);
- if (want_seqc_end) {
- vn_seqc_write_end(*svpp);
- vn_seqc_write_end(sdvp);
- if (*tvpp != NULL)
- vn_seqc_write_end(*tvpp);
- if (tdvp != *tvpp)
- vn_seqc_write_end(tdvp);
- want_seqc_end = false;
- }
- VOP_UNLOCK1(*svpp);
- VOP_UNLOCK1(sdvp);
+out_seq:
+ vn_seqc_write_end(*svpp);
+ vn_seqc_write_end(sdvp);
+ if (*tvpp != NULL)
+ vn_seqc_write_end(*tvpp);
+ if (tdvp != *tvpp)
+ vn_seqc_write_end(tdvp);
-out: /* original two vnodes are locked */
- MPASS(!want_seqc_end);
+out:
if (error == 0 && zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
zil_commit(zilog, 0);
+ ZFS_EXIT(zfsvfs);
- if (*tvpp != NULL)
- VOP_UNLOCK1(*tvpp);
- if (tdvp != *tvpp)
- VOP_UNLOCK1(tdvp);
return (error);
}
@@ -3495,7 +3497,7 @@ zfs_rename(znode_t *sdzp, const char *sname, znode_t *tdzp, const char *tname,
goto fail;
}
- error = zfs_rename_(sdvp, &svp, &scn, tdvp, &tvp, &tcn, cr, 0);
+ error = zfs_do_rename(sdvp, &svp, &scn, tdvp, &tvp, &tcn, cr);
fail:
if (svp != NULL)
vrele(svp);
@@ -4058,7 +4060,6 @@ zfs_getpages(struct vnode *vp, vm_page_t *ma, int count, int *rbehind,
{
znode_t *zp = VTOZ(vp);
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
- objset_t *os = zp->z_zfsvfs->z_os;
zfs_locked_range_t *lr;
vm_object_t object;
off_t start, end, obj_size;
@@ -4128,8 +4129,8 @@ zfs_getpages(struct vnode *vp, vm_page_t *ma, int count, int *rbehind,
* ZFS will panic if we request DMU to read beyond the end of the last
* allocated block.
*/
- error = dmu_read_pages(os, zp->z_id, ma, count, &pgsin_b, &pgsin_a,
- MIN(end, obj_size) - (end - PAGE_SIZE));
+ error = dmu_read_pages(zfsvfs->z_os, zp->z_id, ma, count, &pgsin_b,
+ &pgsin_a, MIN(end, obj_size) - (end - PAGE_SIZE));
if (lr != NULL)
zfs_rangelock_exit(lr);
@@ -4593,7 +4594,7 @@ zfs_freebsd_lookup(struct vop_lookup_args *ap, boolean_t cached)
strlcpy(nm, cnp->cn_nameptr, MIN(cnp->cn_namelen + 1, sizeof (nm)));
return (zfs_lookup(ap->a_dvp, nm, ap->a_vpp, cnp, cnp->cn_nameiop,
- cnp->cn_cred, cnp->cn_thread, 0, cached));
+ cnp->cn_cred, 0, cached));
}
static int
@@ -4976,8 +4977,8 @@ zfs_freebsd_rename(struct vop_rename_args *ap)
ASSERT(ap->a_fcnp->cn_flags & (SAVENAME|SAVESTART));
ASSERT(ap->a_tcnp->cn_flags & (SAVENAME|SAVESTART));
- error = zfs_rename_(fdvp, &fvp, ap->a_fcnp, tdvp, &tvp,
- ap->a_tcnp, ap->a_fcnp->cn_cred, 1);
+ error = zfs_do_rename(fdvp, &fvp, ap->a_fcnp, tdvp, &tvp,
+ ap->a_tcnp, ap->a_fcnp->cn_cred);
vrele(fdvp);
vrele(fvp);
@@ -5345,14 +5346,18 @@ zfs_getextattr_dir(struct vop_getextattr_args *ap, const char *attrname)
vnode_t *xvp = NULL, *vp;
int error, flags;
- error = zfs_lookup(ap->a_vp, NULL, &xvp, NULL, 0, ap->a_cred, td,
+ error = zfs_lookup(ap->a_vp, NULL, &xvp, NULL, 0, ap->a_cred,
LOOKUP_XATTR, B_FALSE);
if (error != 0)
return (error);
flags = FREAD;
+#if __FreeBSD_version < 1400043
NDINIT_ATVP(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, attrname,
xvp, td);
+#else
+ NDINIT_ATVP(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, attrname, xvp);
+#endif
error = vn_open_cred(&nd, &flags, 0, VN_OPEN_INVFS, ap->a_cred, NULL);
vp = nd.ni_vp;
NDFREE(&nd, NDF_ONLY_PNBUF);
@@ -5454,18 +5459,22 @@ struct vop_deleteextattr {
static int
zfs_deleteextattr_dir(struct vop_deleteextattr_args *ap, const char *attrname)
{
- struct thread *td = ap->a_td;
struct nameidata nd;
vnode_t *xvp = NULL, *vp;
int error;
- error = zfs_lookup(ap->a_vp, NULL, &xvp, NULL, 0, ap->a_cred, td,
+ error = zfs_lookup(ap->a_vp, NULL, &xvp, NULL, 0, ap->a_cred,
LOOKUP_XATTR, B_FALSE);
if (error != 0)
return (error);
+#if __FreeBSD_version < 1400043
+ NDINIT_ATVP(&nd, DELETE, NOFOLLOW | LOCKPARENT | LOCKLEAF,
+ UIO_SYSSPACE, attrname, xvp, ap->a_td);
+#else
NDINIT_ATVP(&nd, DELETE, NOFOLLOW | LOCKPARENT | LOCKLEAF,
- UIO_SYSSPACE, attrname, xvp, td);
+ UIO_SYSSPACE, attrname, xvp);
+#endif
error = namei(&nd);
vp = nd.ni_vp;
if (error != 0) {
@@ -5585,13 +5594,17 @@ zfs_setextattr_dir(struct vop_setextattr_args *ap, const char *attrname)
vnode_t *xvp = NULL, *vp;
int error, flags;
- error = zfs_lookup(ap->a_vp, NULL, &xvp, NULL, 0, ap->a_cred, td,
+ error = zfs_lookup(ap->a_vp, NULL, &xvp, NULL, 0, ap->a_cred,
LOOKUP_XATTR | CREATE_XATTR_DIR, B_FALSE);
if (error != 0)
return (error);
flags = FFLAGS(O_WRONLY | O_CREAT);
+#if __FreeBSD_version < 1400043
NDINIT_ATVP(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, attrname, xvp, td);
+#else
+ NDINIT_ATVP(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, attrname, xvp);
+#endif
error = vn_open_cred(&nd, &flags, 0600, VN_OPEN_INVFS, ap->a_cred,
NULL);
vp = nd.ni_vp;
@@ -5729,7 +5742,7 @@ zfs_listextattr_dir(struct vop_listextattr_args *ap, const char *attrprefix)
vnode_t *xvp = NULL, *vp;
int error, eof;
- error = zfs_lookup(ap->a_vp, NULL, &xvp, NULL, 0, ap->a_cred, td,
+ error = zfs_lookup(ap->a_vp, NULL, &xvp, NULL, 0, ap->a_cred,
LOOKUP_XATTR, B_FALSE);
if (error != 0) {
/*
@@ -5741,8 +5754,13 @@ zfs_listextattr_dir(struct vop_listextattr_args *ap, const char *attrprefix)
return (error);
}
+#if __FreeBSD_version < 1400043
NDINIT_ATVP(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKSHARED,
UIO_SYSSPACE, ".", xvp, td);
+#else
+ NDINIT_ATVP(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKSHARED,
+ UIO_SYSSPACE, ".", xvp);
+#endif
error = namei(&nd);
vp = nd.ni_vp;
NDFREE(&nd, NDF_ONLY_PNBUF);
@@ -6115,6 +6133,9 @@ struct vop_vector zfs_vnodeops = {
.vop_unlock = vop_unlock,
.vop_islocked = vop_islocked,
#endif
+#if __FreeBSD_version >= 1400043
+ .vop_add_writecount = vop_stdadd_writecount_nomsync,
+#endif
};
VFS_VOP_VECTOR_REGISTER(zfs_vnodeops);
@@ -6139,6 +6160,9 @@ struct vop_vector zfs_fifoops = {
.vop_getacl = zfs_freebsd_getacl,
.vop_setacl = zfs_freebsd_setacl,
.vop_aclcheck = zfs_freebsd_aclcheck,
+#if __FreeBSD_version >= 1400043
+ .vop_add_writecount = vop_stdadd_writecount_nomsync,
+#endif
};
VFS_VOP_VECTOR_REGISTER(zfs_fifoops);
@@ -6158,5 +6182,8 @@ struct vop_vector zfs_shareops = {
.vop_reclaim = zfs_freebsd_reclaim,
.vop_fid = zfs_freebsd_fid,
.vop_pathconf = zfs_freebsd_pathconf,
+#if __FreeBSD_version >= 1400043
+ .vop_add_writecount = vop_stdadd_writecount_nomsync,
+#endif
};
VFS_VOP_VECTOR_REGISTER(zfs_shareops);
diff --git a/sys/contrib/openzfs/module/os/linux/spl/spl-generic.c b/sys/contrib/openzfs/module/os/linux/spl/spl-generic.c
index 91eeaccfdc47..5ea4fc635165 100644
--- a/sys/contrib/openzfs/module/os/linux/spl/spl-generic.c
+++ b/sys/contrib/openzfs/module/os/linux/spl/spl-generic.c
@@ -657,6 +657,7 @@ hostid_read(uint32_t *hostid)
return (error);
}
size = stat.size;
+ // cppcheck-suppress sizeofwithnumericparameter
if (size < sizeof (HW_HOSTID_MASK)) {
filp_close(filp, 0);
return (EINVAL);
diff --git a/sys/contrib/openzfs/module/os/linux/zfs/vdev_disk.c b/sys/contrib/openzfs/module/os/linux/zfs/vdev_disk.c
index c56fd3a6ff21..a432a736453c 100644
--- a/sys/contrib/openzfs/module/os/linux/zfs/vdev_disk.c
+++ b/sys/contrib/openzfs/module/os/linux/zfs/vdev_disk.c
@@ -37,6 +37,9 @@
#include <linux/blkpg.h>
#include <linux/msdos_fs.h>
#include <linux/vfs_compat.h>
+#ifdef HAVE_LINUX_BLK_CGROUP_HEADER
+#include <linux/blk-cgroup.h>
+#endif
typedef struct vdev_disk {
struct block_device *vd_bdev;
@@ -265,6 +268,11 @@ vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *max_psize,
* a ENOENT failure at this point is highly likely to be transient
* and it is reasonable to sleep and retry before giving up. In
* practice delays have been observed to be on the order of 100ms.
+ *
+ * When ERESTARTSYS is returned it indicates the block device is
+ * a zvol which could not be opened due to the deadlock detection
+ * logic in zvol_open(). Extend the timeout and retry the open
+ * subsequent attempts are expected to eventually succeed.
*/
hrtime_t start = gethrtime();
bdev = ERR_PTR(-ENXIO);
@@ -273,6 +281,9 @@ vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *max_psize,
zfs_vdev_holder);
if (unlikely(PTR_ERR(bdev) == -ENOENT)) {
schedule_timeout(MSEC_TO_TICK(10));
+ } else if (unlikely(PTR_ERR(bdev) == -ERESTARTSYS)) {
+ timeout = MSEC2NSEC(zfs_vdev_open_timeout_ms * 10);
+ continue;
} else if (IS_ERR(bdev)) {
break;
}
@@ -433,9 +444,9 @@ static inline void
vdev_submit_bio_impl(struct bio *bio)
{
#ifdef HAVE_1ARG_SUBMIT_BIO
- submit_bio(bio);
+ (void) submit_bio(bio);
#else
- submit_bio(0, bio);
+ (void) submit_bio(0, bio);
#endif
}
@@ -485,6 +496,7 @@ vdev_blkg_tryget(struct blkcg_gq *blkg)
#elif defined(HAVE_BLKG_TRYGET)
#define vdev_blkg_tryget(bg) blkg_tryget(bg)
#endif
+#ifdef HAVE_BIO_SET_DEV_MACRO
/*
* The Linux 5.0 kernel updated the bio_set_dev() macro so it calls the
* GPL-only bio_associate_blkg() symbol thus inadvertently converting
@@ -506,7 +518,30 @@ vdev_bio_associate_blkg(struct bio *bio)
if (q->root_blkg && vdev_blkg_tryget(q->root_blkg))
bio->bi_blkg = q->root_blkg;
}
+
#define bio_associate_blkg vdev_bio_associate_blkg
+#else
+static inline void
+vdev_bio_set_dev(struct bio *bio, struct block_device *bdev)
+{
+#if defined(HAVE_BIO_BDEV_DISK)
+ struct request_queue *q = bdev->bd_disk->queue;
+#else
+ struct request_queue *q = bio->bi_disk->queue;
+#endif
+ bio_clear_flag(bio, BIO_REMAPPED);
+ if (bio->bi_bdev != bdev)
+ bio_clear_flag(bio, BIO_THROTTLED);
+ bio->bi_bdev = bdev;
+
+ ASSERT3P(q, !=, NULL);
+ ASSERT3P(bio->bi_blkg, ==, NULL);
+
+ if (q->root_blkg && vdev_blkg_tryget(q->root_blkg))
+ bio->bi_blkg = q->root_blkg;
+}
+#define bio_set_dev vdev_bio_set_dev
+#endif
#endif
#else
/*
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 f8bf55f75e97..cf37aecf8a22 100644
--- a/sys/contrib/openzfs/module/os/linux/zfs/zfs_acl.c
+++ b/sys/contrib/openzfs/module/os/linux/zfs/zfs_acl.c
@@ -269,7 +269,7 @@ zfs_ace_fuid_size(void *acep)
entry_type == OWNING_GROUP ||
entry_type == ACE_EVERYONE)
return (sizeof (zfs_ace_hdr_t));
- /*FALLTHROUGH*/
+ fallthrough;
default:
return (sizeof (zfs_ace_t));
}
@@ -2317,7 +2317,7 @@ zfs_zaccess_aces_check(znode_t *zp, uint32_t *working_mode,
break;
case OWNING_GROUP:
who = gowner;
- /*FALLTHROUGH*/
+ fallthrough;
case ACE_IDENTIFIER_GROUP:
checkit = zfs_groupmember(zfsvfs, who, cr);
break;
diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zfs_vnops_os.c b/sys/contrib/openzfs/module/os/linux/zfs/zfs_vnops_os.c
index ef99c4864d3c..a1a0e44bb31f 100644
--- a/sys/contrib/openzfs/module/os/linux/zfs/zfs_vnops_os.c
+++ b/sys/contrib/openzfs/module/os/linux/zfs/zfs_vnops_os.c
@@ -3556,7 +3556,11 @@ zfs_putpage(struct inode *ip, struct page *pp, struct writeback_control *wbc)
if (wbc->sync_mode != WB_SYNC_NONE) {
if (PageWriteback(pp))
+#ifdef HAVE_PAGEMAP_FOLIO_WAIT_BIT
+ folio_wait_bit(page_folio(pp), PG_writeback);
+#else
wait_on_page_bit(pp, PG_writeback);
+#endif
}
ZFS_EXIT(zfsvfs);
diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zfs_znode.c b/sys/contrib/openzfs/module/os/linux/zfs/zfs_znode.c
index c841cc0fc8b5..cd80049df142 100644
--- a/sys/contrib/openzfs/module/os/linux/zfs/zfs_znode.c
+++ b/sys/contrib/openzfs/module/os/linux/zfs/zfs_znode.c
@@ -430,7 +430,7 @@ zfs_inode_set_ops(zfsvfs_t *zfsvfs, struct inode *ip)
case S_IFBLK:
(void) sa_lookup(ITOZ(ip)->z_sa_hdl, SA_ZPL_RDEV(zfsvfs), &rdev,
sizeof (rdev));
- /*FALLTHROUGH*/
+ fallthrough;
case S_IFIFO:
case S_IFSOCK:
init_special_inode(ip, ip->i_mode, rdev);
diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zpl_file.c b/sys/contrib/openzfs/module/os/linux/zfs/zpl_file.c
index 63002fe3b932..7e88eae33711 100644
--- a/sys/contrib/openzfs/module/os/linux/zfs/zpl_file.c
+++ b/sys/contrib/openzfs/module/os/linux/zfs/zpl_file.c
@@ -251,10 +251,16 @@ zpl_uio_init(zfs_uio_t *uio, struct kiocb *kiocb, struct iov_iter *to,
#if defined(HAVE_VFS_IOV_ITER)
zfs_uio_iov_iter_init(uio, to, pos, count, skip);
#else
+#ifdef HAVE_IOV_ITER_TYPE
+ zfs_uio_iovec_init(uio, to->iov, to->nr_segs, pos,
+ iov_iter_type(to) & ITER_KVEC ? UIO_SYSSPACE : UIO_USERSPACE,
+ count, skip);
+#else
zfs_uio_iovec_init(uio, to->iov, to->nr_segs, pos,
to->type & ITER_KVEC ? UIO_SYSSPACE : UIO_USERSPACE,
count, skip);
#endif
+#endif
}
static ssize_t
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 c17423426319..44caadd587f7 100644
--- a/sys/contrib/openzfs/module/os/linux/zfs/zvol_os.c
+++ b/sys/contrib/openzfs/module/os/linux/zfs/zvol_os.c
@@ -46,6 +46,7 @@ unsigned int zvol_request_sync = 0;
unsigned int zvol_prefetch_bytes = (128 * 1024);
unsigned long zvol_max_discard_blocks = 16384;
unsigned int zvol_threads = 32;
+unsigned int zvol_open_timeout_ms = 1000;
struct zvol_state_os {
struct gendisk *zvo_disk; /* generic disk */
@@ -336,8 +337,13 @@ zvol_read_task(void *arg)
}
#ifdef HAVE_SUBMIT_BIO_IN_BLOCK_DEVICE_OPERATIONS
+#ifdef HAVE_BDEV_SUBMIT_BIO_RETURNS_VOID
+static void
+zvol_submit_bio(struct bio *bio)
+#else
static blk_qc_t
zvol_submit_bio(struct bio *bio)
+#endif
#else
static MAKE_REQUEST_FN_RET
zvol_request(struct request_queue *q, struct bio *bio)
@@ -478,8 +484,9 @@ zvol_request(struct request_queue *q, struct bio *bio)
out:
spl_fstrans_unmark(cookie);
-#if defined(HAVE_MAKE_REQUEST_FN_RET_QC) || \
- defined(HAVE_SUBMIT_BIO_IN_BLOCK_DEVICE_OPERATIONS)
+#if (defined(HAVE_MAKE_REQUEST_FN_RET_QC) || \
+ defined(HAVE_SUBMIT_BIO_IN_BLOCK_DEVICE_OPERATIONS)) && \
+ !defined(HAVE_BDEV_SUBMIT_BIO_RETURNS_VOID)
return (BLK_QC_T_NONE);
#endif
}
@@ -490,7 +497,13 @@ zvol_open(struct block_device *bdev, fmode_t flag)
zvol_state_t *zv;
int error = 0;
boolean_t drop_suspend = B_TRUE;
+ boolean_t drop_namespace = B_FALSE;
+#ifndef HAVE_BLKDEV_GET_ERESTARTSYS
+ hrtime_t timeout = MSEC2NSEC(zvol_open_timeout_ms);
+ hrtime_t start = gethrtime();
+retry:
+#endif
rw_enter(&zvol_state_lock, RW_READER);
/*
* Obtain a copy of private_data under the zvol_state_lock to make
@@ -504,6 +517,49 @@ zvol_open(struct block_device *bdev, fmode_t flag)
return (SET_ERROR(-ENXIO));
}
+ if (zv->zv_open_count == 0 && !mutex_owned(&spa_namespace_lock)) {
+ /*
+ * In all other call paths the spa_namespace_lock is taken
+ * before the bdev->bd_mutex lock. However, on open(2)
+ * the __blkdev_get() function calls fops->open() with the
+ * bdev->bd_mutex lock held. This can result in a deadlock
+ * when zvols from one pool are used as vdevs in another.
+ *
+ * To prevent a lock inversion deadlock we preemptively
+ * take the spa_namespace_lock. Normally the lock will not
+ * be contended and this is safe because spa_open_common()
+ * handles the case where the caller already holds the
+ * spa_namespace_lock.
+ *
+ * When the lock cannot be aquired after multiple retries
+ * this must be the vdev on zvol deadlock case and we have
+ * no choice but to return an error. For 5.12 and older
+ * kernels returning -ERESTARTSYS will result in the
+ * bdev->bd_mutex being dropped, then reacquired, and
+ * fops->open() being called again. This process can be
+ * repeated safely until both locks are acquired. For 5.13
+ * and newer the -ERESTARTSYS retry logic was removed from
+ * the kernel so the only option is to return the error for
+ * the caller to handle it.
+ */
+ if (!mutex_tryenter(&spa_namespace_lock)) {
+ rw_exit(&zvol_state_lock);
+
+#ifdef HAVE_BLKDEV_GET_ERESTARTSYS
+ schedule();
+ return (SET_ERROR(-ERESTARTSYS));
+#else
+ if ((gethrtime() - start) > timeout)
+ return (SET_ERROR(-ERESTARTSYS));
+
+ schedule_timeout(MSEC_TO_TICK(10));
+ goto retry;
+#endif
+ } else {
+ drop_namespace = B_TRUE;
+ }
+ }
+
mutex_enter(&zv->zv_state_lock);
/*
* make sure zvol is not suspended during first open
@@ -543,6 +599,8 @@ zvol_open(struct block_device *bdev, fmode_t flag)
zv->zv_open_count++;
mutex_exit(&zv->zv_state_lock);
+ if (drop_namespace)
+ mutex_exit(&spa_namespace_lock);
if (drop_suspend)
rw_exit(&zv->zv_suspend_lock);
@@ -556,12 +614,11 @@ out_open_count:
out_mutex:
mutex_exit(&zv->zv_state_lock);
+ if (drop_namespace)
+ mutex_exit(&spa_namespace_lock);
if (drop_suspend)
rw_exit(&zv->zv_suspend_lock);
- if (error == -EINTR) {
- error = -ERESTARTSYS;
- schedule();
- }
+
return (SET_ERROR(error));
}
diff --git a/sys/contrib/openzfs/module/unicode/u8_textprep.c b/sys/contrib/openzfs/module/unicode/u8_textprep.c
index c1d9a325f511..bce5f19625cb 100644
--- a/sys/contrib/openzfs/module/unicode/u8_textprep.c
+++ b/sys/contrib/openzfs/module/unicode/u8_textprep.c
@@ -865,7 +865,9 @@ do_decomp(size_t uv, uchar_t *u8s, uchar_t *s, int sz,
start_id = u8_decomp_b4_16bit_tbl[uv][b3_tbl][b4];
end_id = u8_decomp_b4_16bit_tbl[uv][b3_tbl][b4 + 1];
} else {
+ // cppcheck-suppress arrayIndexOutOfBoundsCond
start_id = u8_decomp_b4_tbl[uv][b3_tbl][b4];
+ // cppcheck-suppress arrayIndexOutOfBoundsCond
end_id = u8_decomp_b4_tbl[uv][b3_tbl][b4 + 1];
}
@@ -1012,7 +1014,9 @@ find_composition_start(size_t uv, uchar_t *s, size_t sz)
start_id = u8_composition_b4_16bit_tbl[uv][b3_tbl][b4];
end_id = u8_composition_b4_16bit_tbl[uv][b3_tbl][b4 + 1];
} else {
+ // cppcheck-suppress arrayIndexOutOfBoundsCond
start_id = u8_composition_b4_tbl[uv][b3_tbl][b4];
+ // cppcheck-suppress arrayIndexOutOfBoundsCond
end_id = u8_composition_b4_tbl[uv][b3_tbl][b4 + 1];
}
diff --git a/sys/contrib/openzfs/module/zfs/abd.c b/sys/contrib/openzfs/module/zfs/abd.c
index cc2d3575db63..03a7b1e033b3 100644
--- a/sys/contrib/openzfs/module/zfs/abd.c
+++ b/sys/contrib/openzfs/module/zfs/abd.c
@@ -1066,10 +1066,10 @@ abd_raidz_gen_iterate(abd_t **cabds, abd_t *dabd,
switch (parity) {
case 3:
len = MIN(caiters[2].iter_mapsize, len);
- /* falls through */
+ fallthrough;
case 2:
len = MIN(caiters[1].iter_mapsize, len);
- /* falls through */
+ fallthrough;
case 1:
len = MIN(caiters[0].iter_mapsize, len);
}
@@ -1179,11 +1179,11 @@ abd_raidz_rec_iterate(abd_t **cabds, abd_t **tabds,
case 3:
len = MIN(xiters[2].iter_mapsize, len);
len = MIN(citers[2].iter_mapsize, len);
- /* falls through */
+ fallthrough;
case 2:
len = MIN(xiters[1].iter_mapsize, len);
len = MIN(citers[1].iter_mapsize, len);
- /* falls through */
+ fallthrough;
case 1:
len = MIN(xiters[0].iter_mapsize, len);
len = MIN(citers[0].iter_mapsize, len);
diff --git a/sys/contrib/openzfs/module/zfs/arc.c b/sys/contrib/openzfs/module/zfs/arc.c
index b864394b42a0..875986de99f0 100644
--- a/sys/contrib/openzfs/module/zfs/arc.c
+++ b/sys/contrib/openzfs/module/zfs/arc.c
@@ -2063,7 +2063,6 @@ arc_buf_fill(arc_buf_t *buf, spa_t *spa, const zbookmark_phys_t *zb,
} else {
ASSERT(hdr_compressed);
ASSERT(!compressed);
- ASSERT3U(HDR_GET_LSIZE(hdr), !=, HDR_GET_PSIZE(hdr));
/*
* If the buf is sharing its data with the hdr, unlink it and
diff --git a/sys/contrib/openzfs/module/zfs/dmu.c b/sys/contrib/openzfs/module/zfs/dmu.c
index 1c47430953b1..8302d506146f 100644
--- a/sys/contrib/openzfs/module/zfs/dmu.c
+++ b/sys/contrib/openzfs/module/zfs/dmu.c
@@ -2095,42 +2095,41 @@ int
dmu_offset_next(objset_t *os, uint64_t object, boolean_t hole, uint64_t *off)
{
dnode_t *dn;
- int i, err;
- boolean_t clean = B_TRUE;
+ int err;
+restart:
err = dnode_hold(os, object, FTAG, &dn);
if (err)
return (err);
- /*
- * Check if dnode is dirty
- */
- for (i = 0; i < TXG_SIZE; i++) {
- if (multilist_link_active(&dn->dn_dirty_link[i])) {
- clean = B_FALSE;
- break;
- }
- }
+ rw_enter(&dn->dn_struct_rwlock, RW_READER);
- /*
- * If compatibility option is on, sync any current changes before
- * we go trundling through the block pointers.
- */
- if (!clean && zfs_dmu_offset_next_sync) {
- clean = B_TRUE;
- dnode_rele(dn, FTAG);
- txg_wait_synced(dmu_objset_pool(os), 0);
- err = dnode_hold(os, object, FTAG, &dn);
- if (err)
- return (err);
- }
+ if (dnode_is_dirty(dn)) {
+ /*
+ * If the zfs_dmu_offset_next_sync module option is enabled
+ * then strict hole reporting has been requested. Dirty
+ * dnodes must be synced to disk to accurately report all
+ * holes. When disabled (the default) dirty dnodes are
+ * reported to not have any holes which is always safe.
+ *
+ * When called by zfs_holey_common() the zp->z_rangelock
+ * is held to prevent zfs_write() and mmap writeback from
+ * re-dirtying the dnode after txg_wait_synced().
+ */
+ if (zfs_dmu_offset_next_sync) {
+ rw_exit(&dn->dn_struct_rwlock);
+ dnode_rele(dn, FTAG);
+ txg_wait_synced(dmu_objset_pool(os), 0);
+ goto restart;
+ }
- if (clean)
- err = dnode_next_offset(dn,
- (hole ? DNODE_FIND_HOLE : 0), off, 1, 1, 0);
- else
err = SET_ERROR(EBUSY);
+ } else {
+ err = dnode_next_offset(dn, DNODE_FIND_HAVELOCK |
+ (hole ? DNODE_FIND_HOLE : 0), off, 1, 1, 0);
+ }
+ rw_exit(&dn->dn_struct_rwlock);
dnode_rele(dn, FTAG);
return (err);
diff --git a/sys/contrib/openzfs/module/zfs/dmu_send.c b/sys/contrib/openzfs/module/zfs/dmu_send.c
index 0658e13c2d25..2f2fd4c3d6c8 100644
--- a/sys/contrib/openzfs/module/zfs/dmu_send.c
+++ b/sys/contrib/openzfs/module/zfs/dmu_send.c
@@ -165,6 +165,7 @@ struct send_range {
kmutex_t lock;
kcondvar_t cv;
boolean_t io_outstanding;
+ boolean_t io_compressed;
int io_err;
} data;
struct srh {
@@ -450,7 +451,8 @@ dump_redact(dmu_send_cookie_t *dscp, uint64_t object, uint64_t offset,
static int
dmu_dump_write(dmu_send_cookie_t *dscp, dmu_object_type_t type, uint64_t object,
- uint64_t offset, int lsize, int psize, const blkptr_t *bp, void *data)
+ uint64_t offset, int lsize, int psize, const blkptr_t *bp,
+ boolean_t io_compressed, void *data)
{
uint64_t payload_size;
boolean_t raw = (dscp->dsc_featureflags & DMU_BACKUP_FEATURE_RAW);
@@ -487,7 +489,10 @@ dmu_dump_write(dmu_send_cookie_t *dscp, dmu_object_type_t type, uint64_t object,
drrw->drr_logical_size = lsize;
/* only set the compression fields if the buf is compressed or raw */
- if (raw || lsize != psize) {
+ boolean_t compressed =
+ (bp != NULL ? BP_GET_COMPRESS(bp) != ZIO_COMPRESS_OFF &&
+ io_compressed : lsize != psize);
+ if (raw || compressed) {
ASSERT(raw || dscp->dsc_featureflags &
DMU_BACKUP_FEATURE_COMPRESSED);
ASSERT(!BP_IS_EMBEDDED(bp));
@@ -1014,7 +1019,8 @@ do_dump(dmu_send_cookie_t *dscp, struct send_range *range)
int n = MIN(srdp->datablksz,
SPA_OLD_MAXBLOCKSIZE);
err = dmu_dump_write(dscp, srdp->obj_type,
- range->object, offset, n, n, NULL, data);
+ range->object, offset, n, n, NULL, B_FALSE,
+ data);
offset += n;
/*
* When doing dry run, data==NULL is used as a
@@ -1028,7 +1034,8 @@ do_dump(dmu_send_cookie_t *dscp, struct send_range *range)
} else {
err = dmu_dump_write(dscp, srdp->obj_type,
range->object, offset,
- srdp->datablksz, srdp->datasz, bp, data);
+ srdp->datablksz, srdp->datasz, bp,
+ srdp->io_compressed, data);
}
return (err);
}
@@ -1081,6 +1088,7 @@ range_alloc(enum type type, uint64_t object, uint64_t start_blkid,
cv_init(&range->sru.data.cv, NULL, CV_DEFAULT, NULL);
range->sru.data.io_outstanding = 0;
range->sru.data.io_err = 0;
+ range->sru.data.io_compressed = B_FALSE;
}
return (range);
}
@@ -1646,10 +1654,13 @@ issue_data_read(struct send_reader_thread_arg *srta, struct send_range *range)
enum zio_flag zioflags = ZIO_FLAG_CANFAIL;
- if (srta->featureflags & DMU_BACKUP_FEATURE_RAW)
+ if (srta->featureflags & DMU_BACKUP_FEATURE_RAW) {
zioflags |= ZIO_FLAG_RAW;
- else if (request_compressed)
+ srdp->io_compressed = B_TRUE;
+ } else if (request_compressed) {
zioflags |= ZIO_FLAG_RAW_COMPRESS;
+ srdp->io_compressed = B_TRUE;
+ }
srdp->datasz = (zioflags & ZIO_FLAG_RAW_COMPRESS) ?
BP_GET_PSIZE(bp) : BP_GET_LSIZE(bp);
diff --git a/sys/contrib/openzfs/module/zfs/dnode.c b/sys/contrib/openzfs/module/zfs/dnode.c
index 7f741542ce02..7044c1fc6342 100644
--- a/sys/contrib/openzfs/module/zfs/dnode.c
+++ b/sys/contrib/openzfs/module/zfs/dnode.c
@@ -1648,6 +1648,26 @@ dnode_try_claim(objset_t *os, uint64_t object, int slots)
slots, NULL, NULL));
}
+/*
+ * Checks if the dnode contains any uncommitted dirty records.
+ */
+boolean_t
+dnode_is_dirty(dnode_t *dn)
+{
+ mutex_enter(&dn->dn_mtx);
+
+ for (int i = 0; i < TXG_SIZE; i++) {
+ if (multilist_link_active(&dn->dn_dirty_link[i])) {
+ mutex_exit(&dn->dn_mtx);
+ return (B_TRUE);
+ }
+ }
+
+ mutex_exit(&dn->dn_mtx);
+
+ return (B_FALSE);
+}
+
void
dnode_setdirty(dnode_t *dn, dmu_tx_t *tx)
{
diff --git a/sys/contrib/openzfs/module/zfs/dsl_prop.c b/sys/contrib/openzfs/module/zfs/dsl_prop.c
index f6ff9ae47192..dfa04d7681be 100644
--- a/sys/contrib/openzfs/module/zfs/dsl_prop.c
+++ b/sys/contrib/openzfs/module/zfs/dsl_prop.c
@@ -749,7 +749,7 @@ dsl_prop_set_sync_impl(dsl_dataset_t *ds, const char *propname,
ASSERT(err == 0 || err == ENOENT);
err = zap_remove(mos, zapobj, inheritstr, tx);
ASSERT(err == 0 || err == ENOENT);
- /* FALLTHRU */
+ fallthrough;
case (ZPROP_SRC_NONE | ZPROP_SRC_RECEIVED):
/*
* remove propname$recvd
diff --git a/sys/contrib/openzfs/module/zfs/spa.c b/sys/contrib/openzfs/module/zfs/spa.c
index 55870bee47fb..a02fd198bed0 100644
--- a/sys/contrib/openzfs/module/zfs/spa.c
+++ b/sys/contrib/openzfs/module/zfs/spa.c
@@ -9710,7 +9710,7 @@ spa_activity_in_progress(spa_t *spa, zpool_wait_activity_t activity,
case ZPOOL_WAIT_RESILVER:
if ((*in_progress = vdev_rebuild_active(spa->spa_root_vdev)))
break;
- /* fall through */
+ fallthrough;
case ZPOOL_WAIT_SCRUB:
{
boolean_t scanning, paused, is_scrub;
diff --git a/sys/contrib/openzfs/module/zfs/vdev.c b/sys/contrib/openzfs/module/zfs/vdev.c
index 4e316d8135ee..d659ec5bf333 100644
--- a/sys/contrib/openzfs/module/zfs/vdev.c
+++ b/sys/contrib/openzfs/module/zfs/vdev.c
@@ -2374,6 +2374,7 @@ vdev_validate(vdev_t *vd)
static void
vdev_copy_path_impl(vdev_t *svd, vdev_t *dvd)
{
+ char *old, *new;
if (svd->vdev_path != NULL && dvd->vdev_path != NULL) {
if (strcmp(svd->vdev_path, dvd->vdev_path) != 0) {
zfs_dbgmsg("vdev_copy_path: vdev %llu: path changed "
@@ -2387,6 +2388,29 @@ vdev_copy_path_impl(vdev_t *svd, vdev_t *dvd)
zfs_dbgmsg("vdev_copy_path: vdev %llu: path set to '%s'",
(u_longlong_t)dvd->vdev_guid, dvd->vdev_path);
}
+
+ /*
+ * Our enclosure sysfs path may have changed between imports
+ */
+ old = dvd->vdev_enc_sysfs_path;
+ new = svd->vdev_enc_sysfs_path;
+ if ((old != NULL && new == NULL) ||
+ (old == NULL && new != NULL) ||
+ ((old != NULL && new != NULL) && strcmp(new, old) != 0)) {
+ zfs_dbgmsg("vdev_copy_path: vdev %llu: vdev_enc_sysfs_path "
+ "changed from '%s' to '%s'", (u_longlong_t)dvd->vdev_guid,
+ old, new);
+
+ if (dvd->vdev_enc_sysfs_path)
+ spa_strfree(dvd->vdev_enc_sysfs_path);
+
+ if (svd->vdev_enc_sysfs_path) {
+ dvd->vdev_enc_sysfs_path = spa_strdup(
+ svd->vdev_enc_sysfs_path);
+ } else {
+ dvd->vdev_enc_sysfs_path = NULL;
+ }
+ }
}
/*
diff --git a/sys/contrib/openzfs/module/zfs/vdev_label.c b/sys/contrib/openzfs/module/zfs/vdev_label.c
index 04202a9f8960..ec6bbc6fc610 100644
--- a/sys/contrib/openzfs/module/zfs/vdev_label.c
+++ b/sys/contrib/openzfs/module/zfs/vdev_label.c
@@ -1287,7 +1287,7 @@ vdev_label_read_bootenv(vdev_t *rvd, nvlist_t *bootenv)
nvlist_free(config);
break;
}
- /* FALLTHROUGH */
+ fallthrough;
default:
/* Check for FreeBSD zfs bootonce command string */
buf = abd_to_buf(abd);
diff --git a/sys/contrib/openzfs/module/zfs/vdev_raidz_math_scalar.c b/sys/contrib/openzfs/module/zfs/vdev_raidz_math_scalar.c
index cd742e146ca6..9e9c15ff4ba2 100644
--- a/sys/contrib/openzfs/module/zfs/vdev_raidz_math_scalar.c
+++ b/sys/contrib/openzfs/module/zfs/vdev_raidz_math_scalar.c
@@ -142,7 +142,7 @@ static const struct {
a.b[6] = mul_lt[a.b[6]]; \
a.b[5] = mul_lt[a.b[5]]; \
a.b[4] = mul_lt[a.b[4]]; \
- /* falls through */ \
+ fallthrough; \
case 4: \
a.b[3] = mul_lt[a.b[3]]; \
a.b[2] = mul_lt[a.b[2]]; \
diff --git a/sys/contrib/openzfs/module/zfs/zfs_replay.c b/sys/contrib/openzfs/module/zfs/zfs_replay.c
index cba5e8c9cd0b..f3d209f1fbdb 100644
--- a/sys/contrib/openzfs/module/zfs/zfs_replay.c
+++ b/sys/contrib/openzfs/module/zfs/zfs_replay.c
@@ -362,7 +362,7 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap)
zfsvfs->z_fuid_replay = zfs_replay_fuids(fuidstart,
(void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt,
lr->lr_uid, lr->lr_gid);
- /*FALLTHROUGH*/
+ fallthrough;
case TX_CREATE_ACL_ATTR:
if (name == NULL) {
lrattr = (lr_attr_t *)(caddr_t)(lracl + 1);
@@ -394,7 +394,7 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap)
zfsvfs->z_fuid_replay = zfs_replay_fuids(fuidstart,
(void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt,
lr->lr_uid, lr->lr_gid);
- /*FALLTHROUGH*/
+ fallthrough;
case TX_MKDIR_ACL_ATTR:
if (name == NULL) {
lrattr = (lr_attr_t *)(caddr_t)(lracl + 1);
@@ -519,8 +519,7 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap)
zfs_replay_fuid_domain(start, &start,
lr->lr_uid, lr->lr_gid);
name = (char *)start;
-
- /*FALLTHROUGH*/
+ fallthrough;
case TX_CREATE:
if (name == NULL)
name = (char *)start;
@@ -537,8 +536,7 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap)
zfs_replay_fuid_domain(start, &start,
lr->lr_uid, lr->lr_gid);
name = (char *)start;
-
- /*FALLTHROUGH*/
+ fallthrough;
case TX_MKDIR:
if (name == NULL)
name = (char *)(lr + 1);
diff --git a/sys/contrib/openzfs/module/zfs/zfs_vnops.c b/sys/contrib/openzfs/module/zfs/zfs_vnops.c
index 8229bc9a93e5..170e392abe93 100644
--- a/sys/contrib/openzfs/module/zfs/zfs_vnops.c
+++ b/sys/contrib/openzfs/module/zfs/zfs_vnops.c
@@ -85,6 +85,7 @@ zfs_fsync(znode_t *zp, int syncflag, cred_t *cr)
static int
zfs_holey_common(znode_t *zp, ulong_t cmd, loff_t *off)
{
+ zfs_locked_range_t *lr;
uint64_t noff = (uint64_t)*off; /* new offset */
uint64_t file_sz;
int error;
@@ -100,12 +101,18 @@ zfs_holey_common(znode_t *zp, ulong_t cmd, loff_t *off)
else
hole = B_FALSE;
+ /* Flush any mmap()'d data to disk */
+ if (zn_has_cached_data(zp))
+ zn_flush_cached_data(zp, B_FALSE);
+
+ lr = zfs_rangelock_enter(&zp->z_rangelock, 0, file_sz, RL_READER);
error = dmu_offset_next(ZTOZSB(zp)->z_os, zp->z_id, hole, &noff);
+ zfs_rangelock_exit(lr);
if (error == ESRCH)
return (SET_ERROR(ENXIO));
- /* file was dirty, so fall back to using generic logic */
+ /* File was dirty, so fall back to using generic logic */
if (error == EBUSY) {
if (hole)
*off = file_sz;
diff --git a/sys/contrib/openzfs/module/zfs/zio_compress.c b/sys/contrib/openzfs/module/zfs/zio_compress.c
index 33602bd471f3..1ff1e76d7f22 100644
--- a/sys/contrib/openzfs/module/zfs/zio_compress.c
+++ b/sys/contrib/openzfs/module/zfs/zio_compress.c
@@ -214,7 +214,7 @@ zio_compress_to_feature(enum zio_compress comp)
case ZIO_COMPRESS_ZSTD:
return (SPA_FEATURE_ZSTD_COMPRESS);
default:
- /* fallthru */;
+ break;
}
return (SPA_FEATURE_NONE);
}
diff --git a/sys/contrib/openzfs/module/zfs/zvol.c b/sys/contrib/openzfs/module/zfs/zvol.c
index 88450aabb469..721a7b4b878e 100644
--- a/sys/contrib/openzfs/module/zfs/zvol.c
+++ b/sys/contrib/openzfs/module/zfs/zvol.c
@@ -909,54 +909,26 @@ int
zvol_first_open(zvol_state_t *zv, boolean_t readonly)
{
objset_t *os;
- int error, locked = 0;
- boolean_t ro;
+ int error;
ASSERT(RW_READ_HELD(&zv->zv_suspend_lock));
ASSERT(MUTEX_HELD(&zv->zv_state_lock));
+ ASSERT(mutex_owned(&spa_namespace_lock));
- /*
- * In all other cases the spa_namespace_lock is taken before the
- * bdev->bd_mutex lock. But in this case the Linux __blkdev_get()
- * function calls fops->open() with the bdev->bd_mutex lock held.
- * This deadlock can be easily observed with zvols used as vdevs.
- *
- * To avoid a potential lock inversion deadlock we preemptively
- * try to take the spa_namespace_lock(). Normally it will not
- * be contended and this is safe because spa_open_common() handles
- * the case where the caller already holds the spa_namespace_lock.
- *
- * When it is contended we risk a lock inversion if we were to
- * block waiting for the lock. Luckily, the __blkdev_get()
- * function allows us to return -ERESTARTSYS which will result in
- * bdev->bd_mutex being dropped, reacquired, and fops->open() being
- * called again. This process can be repeated safely until both
- * locks are acquired.
- */
- if (!mutex_owned(&spa_namespace_lock)) {
- locked = mutex_tryenter(&spa_namespace_lock);
- if (!locked)
- return (SET_ERROR(EINTR));
- }
-
- ro = (readonly || (strchr(zv->zv_name, '@') != NULL));
+ boolean_t ro = (readonly || (strchr(zv->zv_name, '@') != NULL));
error = dmu_objset_own(zv->zv_name, DMU_OST_ZVOL, ro, B_TRUE, zv, &os);
if (error)
- goto out_mutex;
+ return (SET_ERROR(error));
zv->zv_objset = os;
error = zvol_setup_zv(zv);
-
if (error) {
dmu_objset_disown(os, 1, zv);
zv->zv_objset = NULL;
}
-out_mutex:
- if (locked)
- mutex_exit(&spa_namespace_lock);
- return (SET_ERROR(error));
+ return (error);
}
void
@@ -1038,6 +1010,68 @@ zvol_create_snap_minor_cb(const char *dsname, void *arg)
}
/*
+ * If spa_keystore_load_wkey() is called for an encrypted zvol,
+ * we need to look for any clones also using the key. This function
+ * is "best effort" - so we just skip over it if there are failures.
+ */
+static void
+zvol_add_clones(const char *dsname, list_t *minors_list)
+{
+ /* Also check if it has clones */
+ dsl_dir_t *dd = NULL;
+ dsl_pool_t *dp = NULL;
+
+ if (dsl_pool_hold(dsname, FTAG, &dp) != 0)
+ return;
+
+ if (!spa_feature_is_enabled(dp->dp_spa,
+ SPA_FEATURE_ENCRYPTION))
+ goto out;
+
+ if (dsl_dir_hold(dp, dsname, FTAG, &dd, NULL) != 0)
+ goto out;
+
+ if (dsl_dir_phys(dd)->dd_clones == 0)
+ goto out;
+
+ zap_cursor_t *zc = kmem_alloc(sizeof (zap_cursor_t), KM_SLEEP);
+ zap_attribute_t *za = kmem_alloc(sizeof (zap_attribute_t), KM_SLEEP);
+ objset_t *mos = dd->dd_pool->dp_meta_objset;
+
+ for (zap_cursor_init(zc, mos, dsl_dir_phys(dd)->dd_clones);
+ zap_cursor_retrieve(zc, za) == 0;
+ zap_cursor_advance(zc)) {
+ dsl_dataset_t *clone;
+ minors_job_t *job;
+
+ if (dsl_dataset_hold_obj(dd->dd_pool,
+ za->za_first_integer, FTAG, &clone) == 0) {
+
+ char name[ZFS_MAX_DATASET_NAME_LEN];
+ dsl_dataset_name(clone, name);
+
+ char *n = kmem_strdup(name);
+ job = kmem_alloc(sizeof (minors_job_t), KM_SLEEP);
+ job->name = n;
+ job->list = minors_list;
+ job->error = 0;
+ list_insert_tail(minors_list, job);
+
+ dsl_dataset_rele(clone, FTAG);
+ }
+ }
+ zap_cursor_fini(zc);
+ kmem_free(za, sizeof (zap_attribute_t));
+ kmem_free(zc, sizeof (zap_cursor_t));
+
+out:
+ if (dd != NULL)
+ dsl_dir_rele(dd, FTAG);
+ if (dp != NULL)
+ dsl_pool_rele(dp, FTAG);
+}
+
+/*
* Mask errors to continue dmu_objset_find() traversal
*/
static int
@@ -1075,6 +1109,8 @@ zvol_create_minors_cb(const char *dsname, void *arg)
taskq_dispatch(system_taskq, zvol_prefetch_minors_impl, job,
TQ_SLEEP);
+ zvol_add_clones(dsname, minors_list);
+
if (snapdev == ZFS_SNAPDEV_VISIBLE) {
/*
* traverse snapshots only, do not traverse children,
diff --git a/sys/contrib/openzfs/module/zstd/include/zstd_compat_wrapper.h b/sys/contrib/openzfs/module/zstd/include/zstd_compat_wrapper.h
index 71adc78040fb..339713590f96 100644
--- a/sys/contrib/openzfs/module/zstd/include/zstd_compat_wrapper.h
+++ b/sys/contrib/openzfs/module/zstd/include/zstd_compat_wrapper.h
@@ -406,6 +406,7 @@
zfs_ZSTD_insertAndFindFirstIndex_internal
#define ZSTD_insertBlock zfs_ZSTD_insertBlock
#define ZSTD_invalidateRepCodes zfs_ZSTD_invalidateRepCodes
+#define ZSTD_isError zfs_ZSTD_isError
#define ZSTD_isFrame zfs_ZSTD_isFrame
#define ZSTD_ldm_adjustParameters zfs_ZSTD_ldm_adjustParameters
#define ZSTD_ldm_blockCompress zfs_ZSTD_ldm_blockCompress
diff --git a/sys/contrib/openzfs/module/zstd/lib/zstd.c b/sys/contrib/openzfs/module/zstd/lib/zstd.c
index acdd4d9dac9d..2766e5b74f55 100644
--- a/sys/contrib/openzfs/module/zstd/lib/zstd.c
+++ b/sys/contrib/openzfs/module/zstd/lib/zstd.c
@@ -6340,7 +6340,6 @@ extern "C" {
/* ---- static assert (debug) --- */
#define ZSTD_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c)
-#define ZSTD_isError ERR_isError /* for inlining */
#define FSE_isError ERR_isError
#define HUF_isError ERR_isError
@@ -7347,7 +7346,6 @@ const char* ZSTD_versionString(void) { return ZSTD_VERSION_STRING; }
/*-****************************************
* ZSTD Error Management
******************************************/
-#undef ZSTD_isError /* defined within zstd_internal.h */
/*! ZSTD_isError() :
* tells if a return value is an error code
* symbol is required for external callers */