cherry-pick patches for Linux 6.11 compat

All merged already into upstream, only one conflict with (missing)
change in context had to be resolved for the flex-array in ZFS log
patch.

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
Thomas Lamprecht 2024-10-23 18:33:25 +02:00
parent e70c0fd2f7
commit d3e35db9c3
6 changed files with 1316 additions and 0 deletions

View File

@ -31,6 +31,7 @@ These are present in the current kernel, but lead to an exception, if
running the new user-space with an old kernel module.
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
---
cmd/arc_summary | 132 ++++++++++++++++++++++++------------------------
cmd/arcstat.in | 48 +++++++++---------

View File

@ -30,6 +30,7 @@ Closes #15369
Closes #15468
(cherry picked from commit 41e55b476bcfc90f1ad81c02c5375367fdace9e9)
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
---
lib/libshare/os/linux/nfs.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)

View File

@ -0,0 +1,229 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Pavel Snajdr <snajpa@snajpa.net>
Date: Tue, 17 Sep 2024 22:38:02 +0200
Subject: [PATCH] Linux 6.10 compat: Fix tracepoints definitions
__string field definition includes the source variable for a value
of the string when the TP hits; in 6.10+ kernels, __assign_str()
uses that to copy a value from src to the string, with older
kernels, __assign_str still accepted src as a second parameter.
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Pavel Snajdr <snajpa@snajpa.net>
Co-authored-by: Tony Hutter <hutter2@llnl.gov>
Closes #16475
Closes #16515
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
---
config/kernel-assign_str.m4 | 62 +++++++++++++++++++++++++
config/kernel.m4 | 1 +
include/os/linux/spl/sys/types.h | 6 +++
include/os/linux/zfs/sys/trace_dbgmsg.h | 3 +-
include/os/linux/zfs/sys/trace_dbuf.h | 29 +++++-------
5 files changed, 82 insertions(+), 19 deletions(-)
create mode 100644 config/kernel-assign_str.m4
diff --git a/config/kernel-assign_str.m4 b/config/kernel-assign_str.m4
new file mode 100644
index 000000000..cf4b00e7c
--- /dev/null
+++ b/config/kernel-assign_str.m4
@@ -0,0 +1,62 @@
+dnl #
+dnl # 6.10 kernel, check number of args of __assign_str() for trace:
+dnl
+dnl # 6.10+: one arg
+dnl # 6.9 and older: two args
+dnl #
+dnl # More specifically, this will test to see if __assign_str() takes one
+dnl # arg. If __assign_str() takes two args, or is not defined, then
+dnl # HAVE_1ARG_ASSIGN_STR will not be set.
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_1ARG_ASSIGN_STR], [
+ AC_MSG_CHECKING([whether __assign_str() has one arg])
+ ZFS_LINUX_TRY_COMPILE_HEADER([
+ #include <linux/module.h>
+ MODULE_LICENSE("$ZFS_META_LICENSE");
+
+ #define CREATE_TRACE_POINTS
+ #include "conftest.h"
+ ],[
+ trace_zfs_autoconf_event_one("1");
+ trace_zfs_autoconf_event_two("2");
+ ],[
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_1ARG_ASSIGN_STR, 1,
+ [__assign_str() has one arg])
+ ],[
+ AC_MSG_RESULT(no)
+ ],[
+ #if !defined(_CONFTEST_H) || defined(TRACE_HEADER_MULTI_READ)
+ #define _CONFTEST_H
+
+ #undef TRACE_SYSTEM
+ #define TRACE_SYSTEM zfs
+ #include <linux/tracepoint.h>
+
+ DECLARE_EVENT_CLASS(zfs_autoconf_event_class,
+ TP_PROTO(char *string),
+ TP_ARGS(string),
+ TP_STRUCT__entry(
+ __string(str, string)
+ ),
+ TP_fast_assign(
+ __assign_str(str);
+ ),
+ TP_printk("str = %s", __get_str(str))
+ );
+
+ #define DEFINE_AUTOCONF_EVENT(name) \
+ DEFINE_EVENT(zfs_autoconf_event_class, name, \
+ TP_PROTO(char * str), \
+ TP_ARGS(str))
+ DEFINE_AUTOCONF_EVENT(zfs_autoconf_event_one);
+ DEFINE_AUTOCONF_EVENT(zfs_autoconf_event_two);
+
+ #endif /* _CONFTEST_H */
+
+ #undef TRACE_INCLUDE_PATH
+ #define TRACE_INCLUDE_PATH .
+ #define TRACE_INCLUDE_FILE conftest
+ #include <trace/define_trace.h>
+ ])
+])
diff --git a/config/kernel.m4 b/config/kernel.m4
index f0cd76fd7..17d8694ce 100644
--- a/config/kernel.m4
+++ b/config/kernel.m4
@@ -326,6 +326,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
ZFS_AC_KERNEL_SYNC_BDEV
ZFS_AC_KERNEL_MM_PAGE_SIZE
ZFS_AC_KERNEL_MM_PAGE_MAPPING
+ ZFS_AC_KERNEL_1ARG_ASSIGN_STR
case "$host_cpu" in
powerpc*)
ZFS_AC_KERNEL_CPU_HAS_FEATURE
diff --git a/include/os/linux/spl/sys/types.h b/include/os/linux/spl/sys/types.h
index 94ba7b6ad..d3aefb184 100644
--- a/include/os/linux/spl/sys/types.h
+++ b/include/os/linux/spl/sys/types.h
@@ -83,4 +83,10 @@ typedef struct user_namespace zidmap_t;
extern zidmap_t *zfs_init_idmap;
+#ifdef HAVE_1ARG_ASSIGN_STR
+#define __assign_str_impl(a, b) __assign_str(a)
+#else
+#define __assign_str_impl(a, b) __assign_str(a, b)
+#endif
+
#endif /* _SPL_TYPES_H */
diff --git a/include/os/linux/zfs/sys/trace_dbgmsg.h b/include/os/linux/zfs/sys/trace_dbgmsg.h
index 19f533baa..58081d64c 100644
--- a/include/os/linux/zfs/sys/trace_dbgmsg.h
+++ b/include/os/linux/zfs/sys/trace_dbgmsg.h
@@ -32,6 +32,7 @@
#define _TRACE_DBGMSG_H
#include <linux/tracepoint.h>
+#include <sys/types.h>
/*
* This file defines tracepoint events for use by the dbgmsg(),
@@ -59,7 +60,7 @@ DECLARE_EVENT_CLASS(zfs_dprintf_class,
__string(msg, msg)
),
TP_fast_assign(
- __assign_str(msg, msg);
+ __assign_str_impl(msg, msg);
),
TP_printk("%s", __get_str(msg))
);
diff --git a/include/os/linux/zfs/sys/trace_dbuf.h b/include/os/linux/zfs/sys/trace_dbuf.h
index 0e9cbdd72..b61807744 100644
--- a/include/os/linux/zfs/sys/trace_dbuf.h
+++ b/include/os/linux/zfs/sys/trace_dbuf.h
@@ -45,9 +45,13 @@
* dmu_buf_impl_t *, ...,
* zio_t *, ...);
*/
+#define DBUF_TP_STRUCT_ENTRY_OS_SPA \
+ (db != NULL && \
+ POINTER_IS_VALID(DB_DNODE(db)->dn_objset)) \
+ ? spa_name(DB_DNODE(db)->dn_objset->os_spa) : "NULL"
#define DBUF_TP_STRUCT_ENTRY \
- __dynamic_array(char, os_spa, TRACE_DBUF_MSG_MAX) \
+ __string(os_spa, DBUF_TP_STRUCT_ENTRY_OS_SPA) \
__field(uint64_t, ds_object) \
__field(uint64_t, db_object) \
__field(uint64_t, db_level) \
@@ -55,18 +59,11 @@
__field(uint64_t, db_offset) \
__field(uint64_t, db_size) \
__field(uint64_t, db_state) \
- __field(int64_t, db_holds) \
- __dynamic_array(char, msg, TRACE_DBUF_MSG_MAX)
+ __field(int64_t, db_holds)
#define DBUF_TP_FAST_ASSIGN \
if (db != NULL) { \
- if (POINTER_IS_VALID(DB_DNODE(db)->dn_objset)) { \
- __assign_str(os_spa, \
- spa_name(DB_DNODE(db)->dn_objset->os_spa)); \
- } else { \
- __assign_str(os_spa, "NULL"); \
- } \
- \
+ __assign_str_impl(os_spa, DBUF_TP_STRUCT_ENTRY_OS_SPA); \
__entry->ds_object = db->db_objset->os_dsl_dataset ? \
db->db_objset->os_dsl_dataset->ds_object : 0; \
\
@@ -77,10 +74,8 @@
__entry->db_size = db->db.db_size; \
__entry->db_state = db->db_state; \
__entry->db_holds = zfs_refcount_count(&db->db_holds); \
- snprintf(__get_str(msg), TRACE_DBUF_MSG_MAX, \
- DBUF_TP_PRINTK_FMT, DBUF_TP_PRINTK_ARGS); \
} else { \
- __assign_str(os_spa, "NULL"); \
+ __assign_str_impl(os_spa, DBUF_TP_STRUCT_ENTRY_OS_SPA); \
__entry->ds_object = 0; \
__entry->db_object = 0; \
__entry->db_level = 0; \
@@ -89,8 +84,6 @@
__entry->db_size = 0; \
__entry->db_state = 0; \
__entry->db_holds = 0; \
- snprintf(__get_str(msg), TRACE_DBUF_MSG_MAX, \
- "dbuf { NULL }"); \
}
#define DBUF_TP_PRINTK_FMT \
@@ -109,7 +102,7 @@ DECLARE_EVENT_CLASS(zfs_dbuf_class,
TP_ARGS(db, zio),
TP_STRUCT__entry(DBUF_TP_STRUCT_ENTRY),
TP_fast_assign(DBUF_TP_FAST_ASSIGN),
- TP_printk("%s", __get_str(msg))
+ TP_printk(DBUF_TP_PRINTK_FMT, DBUF_TP_PRINTK_ARGS)
);
DECLARE_EVENT_CLASS(zfs_dbuf_state_class,
@@ -117,7 +110,7 @@ DECLARE_EVENT_CLASS(zfs_dbuf_state_class,
TP_ARGS(db, why),
TP_STRUCT__entry(DBUF_TP_STRUCT_ENTRY),
TP_fast_assign(DBUF_TP_FAST_ASSIGN),
- TP_printk("%s", __get_str(msg))
+ TP_printk(DBUF_TP_PRINTK_FMT, DBUF_TP_PRINTK_ARGS)
);
/* END CSTYLED */
@@ -139,7 +132,7 @@ DECLARE_EVENT_CLASS(zfs_dbuf_evict_one_class,
TP_ARGS(db, mls),
TP_STRUCT__entry(DBUF_TP_STRUCT_ENTRY),
TP_fast_assign(DBUF_TP_FAST_ASSIGN),
- TP_printk("%s", __get_str(msg))
+ TP_printk(DBUF_TP_PRINTK_FMT, DBUF_TP_PRINTK_ARGS)
);
/* END CSTYLED */

View File

@ -0,0 +1,979 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Rob Norris <robn@despairlabs.com>
Date: Sat, 28 Sep 2024 02:18:11 +1000
Subject: [PATCH] zfs_log: add flex array fields to log record structs
ZIL log record structs (lr_XX_t) are frequently allocated with extra
space after the struct to carry variable-sized "payload" items.
Linux 6.10+ compiled with CONFIG_FORTIFY_SOURCE has been doing runtime
bounds checking on memcpy() calls. Because these types had no indicator
that they might use more space than their simple definition,
__fortify_memcpy_chk will frequently complain about overruns eg:
memcpy: detected field-spanning write (size 7) of single field
"lr + 1" at zfs_log.c:425 (size 0)
memcpy: detected field-spanning write (size 9) of single field
"(char *)(lr + 1)" at zfs_log.c:593 (size 0)
memcpy: detected field-spanning write (size 4) of single field
"(char *)(lr + 1) + snamesize" at zfs_log.c:594 (size 0)
memcpy: detected field-spanning write (size 7) of single field
"lr + 1" at zfs_log.c:425 (size 0)
memcpy: detected field-spanning write (size 9) of single field
"(char *)(lr + 1)" at zfs_log.c:593 (size 0)
memcpy: detected field-spanning write (size 4) of single field
"(char *)(lr + 1) + snamesize" at zfs_log.c:594 (size 0)
memcpy: detected field-spanning write (size 7) of single field
"lr + 1" at zfs_log.c:425 (size 0)
memcpy: detected field-spanning write (size 9) of single field
"(char *)(lr + 1)" at zfs_log.c:593 (size 0)
memcpy: detected field-spanning write (size 4) of single field
"(char *)(lr + 1) + snamesize" at zfs_log.c:594 (size 0)
To fix this, this commit adds flex array fields to all lr_XX_t structs
that require them, and then uses those fields to access that
end-of-struct area rather than more complicated casts and pointer
addition.
Sponsored-by: https://despairlabs.com/sponsor/
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Rob Norris <robn@despairlabs.com>
Closes #16501
Closes #16539
(cherry picked from commit 6f50f8e16b7c4a3f1925b41e3d47b479cd7b2d9f)
[ TL: resolved context conflict stemming from not having commit
72ef6b06a ("Cleanup DB_DNODE() macros usage") ]
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
---
cmd/zdb/zdb_il.c | 6 +-
cmd/ztest.c | 24 +++----
include/sys/zil.h | 30 +++++++--
module/zfs/zfs_log.c | 90 ++++++++++++-------------
module/zfs/zfs_replay.c | 143 +++++++++++++++++++++-------------------
5 files changed, 162 insertions(+), 131 deletions(-)
diff --git a/cmd/zdb/zdb_il.c b/cmd/zdb/zdb_il.c
index 63d95dded..88b85f989 100644
--- a/cmd/zdb/zdb_il.c
+++ b/cmd/zdb/zdb_il.c
@@ -64,7 +64,8 @@ static void
zil_prt_rec_create(zilog_t *zilog, int txtype, const void *arg)
{
(void) zilog;
- const lr_create_t *lr = arg;
+ const lr_create_t *lrc = arg;
+ const _lr_create_t *lr = &lrc->lr_create;
time_t crtime = lr->lr_crtime[0];
char *name, *link;
lr_attr_t *lrattr;
@@ -121,7 +122,8 @@ static void
zil_prt_rec_rename(zilog_t *zilog, int txtype, const void *arg)
{
(void) zilog, (void) txtype;
- const lr_rename_t *lr = arg;
+ const lr_rename_t *lrr = arg;
+ const _lr_rename_t *lr = &lrr->lr_rename;
char *snm = (char *)(lr + 1);
char *tnm = snm + strlen(snm) + 1;
diff --git a/cmd/ztest.c b/cmd/ztest.c
index ca3105ffb..66b9c06bd 100644
--- a/cmd/ztest.c
+++ b/cmd/ztest.c
@@ -1861,7 +1861,7 @@ ztest_verify_unused_bonus(dmu_buf_t *db, void *end, uint64_t obj,
static void
ztest_log_create(ztest_ds_t *zd, dmu_tx_t *tx, lr_create_t *lr)
{
- char *name = (void *)(lr + 1); /* name follows lr */
+ char *name = (char *)&lr->lr_data[0]; /* name follows lr */
size_t namesize = strlen(name) + 1;
itx_t *itx;
@@ -1869,7 +1869,7 @@ ztest_log_create(ztest_ds_t *zd, dmu_tx_t *tx, lr_create_t *lr)
return;
itx = zil_itx_create(TX_CREATE, sizeof (*lr) + namesize);
- memcpy(&itx->itx_lr + 1, &lr->lr_common + 1,
+ memcpy(&itx->itx_lr + 1, &lr->lr_create.lr_common + 1,
sizeof (*lr) + namesize - sizeof (lr_t));
zil_itx_assign(zd->zd_zilog, itx, tx);
@@ -1878,7 +1878,7 @@ ztest_log_create(ztest_ds_t *zd, dmu_tx_t *tx, lr_create_t *lr)
static void
ztest_log_remove(ztest_ds_t *zd, dmu_tx_t *tx, lr_remove_t *lr, uint64_t object)
{
- char *name = (void *)(lr + 1); /* name follows lr */
+ char *name = (char *)&lr->lr_data[0]; /* name follows lr */
size_t namesize = strlen(name) + 1;
itx_t *itx;
@@ -1964,8 +1964,9 @@ static int
ztest_replay_create(void *arg1, void *arg2, boolean_t byteswap)
{
ztest_ds_t *zd = arg1;
- lr_create_t *lr = arg2;
- char *name = (void *)(lr + 1); /* name follows lr */
+ lr_create_t *lrc = arg2;
+ _lr_create_t *lr = &lrc->lr_create;
+ char *name = (char *)&lrc->lr_data[0]; /* name follows lr */
objset_t *os = zd->zd_os;
ztest_block_tag_t *bbt;
dmu_buf_t *db;
@@ -2043,7 +2044,7 @@ ztest_replay_create(void *arg1, void *arg2, boolean_t byteswap)
VERIFY0(zap_add(os, lr->lr_doid, name, sizeof (uint64_t), 1,
&lr->lr_foid, tx));
- (void) ztest_log_create(zd, tx, lr);
+ (void) ztest_log_create(zd, tx, lrc);
dmu_tx_commit(tx);
@@ -2055,7 +2056,7 @@ ztest_replay_remove(void *arg1, void *arg2, boolean_t byteswap)
{
ztest_ds_t *zd = arg1;
lr_remove_t *lr = arg2;
- char *name = (void *)(lr + 1); /* name follows lr */
+ char *name = (char *)&lr->lr_data[0]; /* name follows lr */
objset_t *os = zd->zd_os;
dmu_object_info_t doi;
dmu_tx_t *tx;
@@ -2109,9 +2110,9 @@ ztest_replay_write(void *arg1, void *arg2, boolean_t byteswap)
ztest_ds_t *zd = arg1;
lr_write_t *lr = arg2;
objset_t *os = zd->zd_os;
- void *data = lr + 1; /* data follows lr */
+ uint8_t *data = &lr->lr_data[0]; /* data follows lr */
uint64_t offset, length;
- ztest_block_tag_t *bt = data;
+ ztest_block_tag_t *bt = (ztest_block_tag_t *)data;
ztest_block_tag_t *bbt;
uint64_t gen, txg, lrtxg, crtxg;
dmu_object_info_t doi;
@@ -2563,7 +2564,8 @@ ztest_create(ztest_ds_t *zd, ztest_od_t *od, int count)
continue;
}
- lr_create_t *lr = ztest_lr_alloc(sizeof (*lr), od->od_name);
+ lr_create_t *lrc = ztest_lr_alloc(sizeof (*lrc), od->od_name);
+ _lr_create_t *lr = &lrc->lr_create;
lr->lr_doid = od->od_dir;
lr->lr_foid = 0; /* 0 to allocate, > 0 to claim */
@@ -2647,7 +2649,7 @@ ztest_write(ztest_ds_t *zd, uint64_t object, uint64_t offset, uint64_t size,
lr->lr_blkoff = 0;
BP_ZERO(&lr->lr_blkptr);
- memcpy(lr + 1, data, size);
+ memcpy(&lr->lr_data[0], data, size);
error = ztest_replay_write(zd, lr, B_FALSE);
diff --git a/include/sys/zil.h b/include/sys/zil.h
index 4747ecc06..bbe973bce 100644
--- a/include/sys/zil.h
+++ b/include/sys/zil.h
@@ -248,6 +248,7 @@ typedef struct {
uint32_t lr_attr_masksize; /* number of elements in array */
uint32_t lr_attr_bitmap; /* First entry of array */
/* remainder of array and additional lr_attr_end_t fields */
+ uint8_t lr_attr_data[];
} lr_attr_t;
/*
@@ -264,9 +265,14 @@ typedef struct {
uint64_t lr_gen; /* generation (txg of creation) */
uint64_t lr_crtime[2]; /* creation time */
uint64_t lr_rdev; /* rdev of object to create */
+} _lr_create_t;
+
+typedef struct {
+ _lr_create_t lr_create; /* common create portion */
/* name of object to create follows this */
/* for symlinks, link content follows name */
/* for creates with xvattr data, the name follows the xvattr info */
+ uint8_t lr_data[];
} lr_create_t;
/*
@@ -293,18 +299,20 @@ typedef struct {
* and group will be in lr_create. Name follows ACL data.
*/
typedef struct {
- lr_create_t lr_create; /* common create portion */
+ _lr_create_t lr_create; /* common create portion */
uint64_t lr_aclcnt; /* number of ACEs in ACL */
uint64_t lr_domcnt; /* number of unique domains */
uint64_t lr_fuidcnt; /* number of real fuids */
uint64_t lr_acl_bytes; /* number of bytes in ACL */
uint64_t lr_acl_flags; /* ACL flags */
+ uint8_t lr_data[];
} lr_acl_create_t;
typedef struct {
lr_t lr_common; /* common portion of log record */
uint64_t lr_doid; /* obj id of directory */
/* name of object to remove follows this */
+ uint8_t lr_data[];
} lr_remove_t;
typedef struct {
@@ -312,18 +320,24 @@ typedef struct {
uint64_t lr_doid; /* obj id of directory */
uint64_t lr_link_obj; /* obj id of link */
/* name of object to link follows this */
+ uint8_t lr_data[];
} lr_link_t;
typedef struct {
lr_t lr_common; /* common portion of log record */
uint64_t lr_sdoid; /* obj id of source directory */
uint64_t lr_tdoid; /* obj id of target directory */
+} _lr_rename_t;
+
+typedef struct {
+ _lr_rename_t lr_rename; /* common rename portion */
/* 2 strings: names of source and destination follow this */
+ uint8_t lr_data[];
} lr_rename_t;
typedef struct {
- lr_rename_t lr_rename; /* common rename portion */
- /* members related to the whiteout file (based on lr_create_t) */
+ _lr_rename_t lr_rename; /* common rename portion */
+ /* members related to the whiteout file (based on _lr_create_t) */
uint64_t lr_wfoid; /* obj id of the new whiteout file */
uint64_t lr_wmode; /* mode of object */
uint64_t lr_wuid; /* uid of whiteout */
@@ -332,6 +346,7 @@ typedef struct {
uint64_t lr_wcrtime[2]; /* creation time */
uint64_t lr_wrdev; /* always makedev(0, 0) */
/* 2 strings: names of source and destination follow this */
+ uint8_t lr_data[];
} lr_rename_whiteout_t;
typedef struct {
@@ -342,6 +357,7 @@ typedef struct {
uint64_t lr_blkoff; /* no longer used */
blkptr_t lr_blkptr; /* spa block pointer for replay */
/* write data will follow for small writes */
+ uint8_t lr_data[];
} lr_write_t;
typedef struct {
@@ -362,6 +378,7 @@ typedef struct {
uint64_t lr_atime[2]; /* access time */
uint64_t lr_mtime[2]; /* modification time */
/* optional attribute lr_attr_t may be here */
+ uint8_t lr_data[];
} lr_setattr_t;
typedef struct {
@@ -369,6 +386,7 @@ typedef struct {
uint64_t lr_foid; /* file object to change attributes */
uint64_t lr_size;
/* xattr name and value follows */
+ uint8_t lr_data[];
} lr_setsaxattr_t;
typedef struct {
@@ -376,6 +394,7 @@ typedef struct {
uint64_t lr_foid; /* obj id of file */
uint64_t lr_aclcnt; /* number of acl entries */
/* lr_aclcnt number of ace_t entries follow this */
+ uint8_t lr_data[];
} lr_acl_v0_t;
typedef struct {
@@ -387,6 +406,7 @@ typedef struct {
uint64_t lr_acl_bytes; /* number of bytes in ACL */
uint64_t lr_acl_flags; /* ACL flags */
/* lr_acl_bytes number of variable sized ace's follows */
+ uint8_t lr_data[];
} lr_acl_t;
typedef struct {
@@ -396,8 +416,8 @@ typedef struct {
uint64_t lr_length; /* length of the blocks to clone */
uint64_t lr_blksz; /* file's block size */
uint64_t lr_nbps; /* number of block pointers */
- blkptr_t lr_bps[];
/* block pointers of the blocks to clone follows */
+ blkptr_t lr_bps[];
} lr_clone_range_t;
/*
@@ -448,7 +468,7 @@ typedef struct itx {
uint64_t itx_oid; /* object id */
uint64_t itx_gen; /* gen number for zfs_get_data */
lr_t itx_lr; /* common part of log record */
- /* followed by type-specific part of lr_xx_t and its immediate data */
+ uint8_t itx_lr_data[]; /* type-specific part of lr_xx_t */
} itx_t;
/*
diff --git a/module/zfs/zfs_log.c b/module/zfs/zfs_log.c
index 006b91198..f50801130 100644
--- a/module/zfs/zfs_log.c
+++ b/module/zfs/zfs_log.c
@@ -300,14 +300,13 @@ zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
zfs_fuid_info_t *fuidp, vattr_t *vap)
{
itx_t *itx;
- lr_create_t *lr;
- lr_acl_create_t *lracl;
+ _lr_create_t *lr;
+ lr_acl_create_t *lracl = NULL;
+ uint8_t *lrdata;
size_t aclsize = 0;
size_t xvatsize = 0;
size_t txsize;
xvattr_t *xvap = (xvattr_t *)vap;
- void *end;
- size_t lrsize;
size_t namesize = strlen(name) + 1;
size_t fuidsz = 0;
@@ -329,18 +328,21 @@ zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
if ((int)txtype == TX_CREATE_ATTR || (int)txtype == TX_MKDIR_ATTR ||
(int)txtype == TX_CREATE || (int)txtype == TX_MKDIR ||
(int)txtype == TX_MKXATTR) {
- txsize = sizeof (*lr) + namesize + fuidsz + xvatsize;
- lrsize = sizeof (*lr);
+ txsize = sizeof (lr_create_t) + namesize + fuidsz + xvatsize;
+ itx = zil_itx_create(txtype, txsize);
+ lr_create_t *lrc = (lr_create_t *)&itx->itx_lr;
+ lrdata = &lrc->lr_data[0];
} else {
txsize =
sizeof (lr_acl_create_t) + namesize + fuidsz +
ZIL_ACE_LENGTH(aclsize) + xvatsize;
- lrsize = sizeof (lr_acl_create_t);
+ itx = zil_itx_create(txtype, txsize);
+ lracl = (lr_acl_create_t *)&itx->itx_lr;
+ lrdata = &lracl->lr_data[0];
}
- itx = zil_itx_create(txtype, txsize);
- lr = (lr_create_t *)&itx->itx_lr;
+ lr = (_lr_create_t *)&itx->itx_lr;
lr->lr_doid = dzp->z_id;
lr->lr_foid = zp->z_id;
/* Store dnode slot count in 8 bits above object id. */
@@ -369,16 +371,14 @@ zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
* Fill in xvattr info if any
*/
if (vap->va_mask & ATTR_XVATTR) {
- zfs_log_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), xvap);
- end = (caddr_t)lr + lrsize + xvatsize;
- } else {
- end = (caddr_t)lr + lrsize;
+ zfs_log_xvattr((lr_attr_t *)lrdata, xvap);
+ lrdata = &lrdata[xvatsize];
}
/* Now fill in any ACL info */
if (vsecp) {
- lracl = (lr_acl_create_t *)&itx->itx_lr;
+ ASSERT3P(lracl, !=, NULL);
lracl->lr_aclcnt = vsecp->vsa_aclcnt;
lracl->lr_acl_bytes = aclsize;
lracl->lr_domcnt = fuidp ? fuidp->z_domain_cnt : 0;
@@ -388,19 +388,19 @@ zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
else
lracl->lr_acl_flags = 0;
- memcpy(end, vsecp->vsa_aclentp, aclsize);
- end = (caddr_t)end + ZIL_ACE_LENGTH(aclsize);
+ memcpy(lrdata, vsecp->vsa_aclentp, aclsize);
+ lrdata = &lrdata[ZIL_ACE_LENGTH(aclsize)];
}
/* drop in FUID info */
if (fuidp) {
- end = zfs_log_fuid_ids(fuidp, end);
- end = zfs_log_fuid_domains(fuidp, end);
+ lrdata = zfs_log_fuid_ids(fuidp, lrdata);
+ lrdata = zfs_log_fuid_domains(fuidp, lrdata);
}
/*
* Now place file name in log record
*/
- memcpy(end, name, namesize);
+ memcpy(lrdata, name, namesize);
zil_itx_assign(zilog, itx, tx);
}
@@ -422,7 +422,7 @@ zfs_log_remove(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
itx = zil_itx_create(txtype, sizeof (*lr) + namesize);
lr = (lr_remove_t *)&itx->itx_lr;
lr->lr_doid = dzp->z_id;
- memcpy(lr + 1, name, namesize);
+ memcpy(&lr->lr_data[0], name, namesize);
itx->itx_oid = foid;
@@ -458,7 +458,7 @@ zfs_log_link(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
lr = (lr_link_t *)&itx->itx_lr;
lr->lr_doid = dzp->z_id;
lr->lr_link_obj = zp->z_id;
- memcpy(lr + 1, name, namesize);
+ memcpy(&lr->lr_data[0], name, namesize);
zil_itx_assign(zilog, itx, tx);
}
@@ -471,15 +471,17 @@ zfs_log_symlink(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
znode_t *dzp, znode_t *zp, const char *name, const char *link)
{
itx_t *itx;
- lr_create_t *lr;
+ _lr_create_t *lr;
+ lr_create_t *lrc;
size_t namesize = strlen(name) + 1;
size_t linksize = strlen(link) + 1;
if (zil_replaying(zilog, tx))
return;
- itx = zil_itx_create(txtype, sizeof (*lr) + namesize + linksize);
- lr = (lr_create_t *)&itx->itx_lr;
+ itx = zil_itx_create(txtype, sizeof (*lrc) + namesize + linksize);
+ lrc = (lr_create_t *)&itx->itx_lr;
+ lr = &lrc->lr_create;
lr->lr_doid = dzp->z_id;
lr->lr_foid = zp->z_id;
lr->lr_uid = KUID_TO_SUID(ZTOUID(zp));
@@ -489,8 +491,8 @@ zfs_log_symlink(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
sizeof (uint64_t));
(void) sa_lookup(zp->z_sa_hdl, SA_ZPL_CRTIME(ZTOZSB(zp)),
lr->lr_crtime, sizeof (uint64_t) * 2);
- memcpy((char *)(lr + 1), name, namesize);
- memcpy((char *)(lr + 1) + namesize, link, linksize);
+ memcpy(&lrc->lr_data[0], name, namesize);
+ memcpy(&lrc->lr_data[namesize], link, linksize);
zil_itx_assign(zilog, itx, tx);
}
@@ -500,7 +502,8 @@ do_zfs_log_rename(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, znode_t *sdzp,
const char *sname, znode_t *tdzp, const char *dname, znode_t *szp)
{
itx_t *itx;
- lr_rename_t *lr;
+ _lr_rename_t *lr;
+ lr_rename_t *lrr;
size_t snamesize = strlen(sname) + 1;
size_t dnamesize = strlen(dname) + 1;
@@ -508,11 +511,12 @@ do_zfs_log_rename(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, znode_t *sdzp,
return;
itx = zil_itx_create(txtype, sizeof (*lr) + snamesize + dnamesize);
- lr = (lr_rename_t *)&itx->itx_lr;
+ lrr = (lr_rename_t *)&itx->itx_lr;
+ lr = &lrr->lr_rename;
lr->lr_sdoid = sdzp->z_id;
lr->lr_tdoid = tdzp->z_id;
- memcpy((char *)(lr + 1), sname, snamesize);
- memcpy((char *)(lr + 1) + snamesize, dname, dnamesize);
+ memcpy(&lrr->lr_data[0], sname, snamesize);
+ memcpy(&lrr->lr_data[snamesize], dname, dnamesize);
itx->itx_oid = szp->z_id;
zil_itx_assign(zilog, itx, tx);
@@ -590,8 +594,8 @@ zfs_log_rename_whiteout(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
(void) sa_lookup(wzp->z_sa_hdl, SA_ZPL_RDEV(ZTOZSB(wzp)), &lr->lr_wrdev,
sizeof (lr->lr_wrdev));
- memcpy((char *)(lr + 1), sname, snamesize);
- memcpy((char *)(lr + 1) + snamesize, dname, dnamesize);
+ memcpy(&lr->lr_data[0], sname, snamesize);
+ memcpy(&lr->lr_data[snamesize], dname, dnamesize);
itx->itx_oid = szp->z_id;
zil_itx_assign(zilog, itx, tx);
@@ -668,8 +672,8 @@ zfs_log_write(zilog_t *zilog, dmu_tx_t *tx, int txtype,
if (wr_state == WR_COPIED) {
int err;
DB_DNODE_ENTER(db);
- err = dmu_read_by_dnode(DB_DNODE(db), off, len, lr + 1,
- DMU_READ_NO_PREFETCH);
+ err = dmu_read_by_dnode(DB_DNODE(db), off, len,
+ &lr->lr_data[0], DMU_READ_NO_PREFETCH);
if (err != 0) {
zil_itx_destroy(itx);
itx = zil_itx_create(txtype, sizeof (*lr));
@@ -741,7 +745,7 @@ zfs_log_setattr(zilog_t *zilog, dmu_tx_t *tx, int txtype,
lr_setattr_t *lr;
xvattr_t *xvap = (xvattr_t *)vap;
size_t recsize = sizeof (lr_setattr_t);
- void *start;
+ uint8_t *start;
if (zil_replaying(zilog, tx) || zp->z_unlinked)
return;
@@ -775,10 +779,10 @@ zfs_log_setattr(zilog_t *zilog, dmu_tx_t *tx, int txtype,
lr->lr_size = (uint64_t)vap->va_size;
ZFS_TIME_ENCODE(&vap->va_atime, lr->lr_atime);
ZFS_TIME_ENCODE(&vap->va_mtime, lr->lr_mtime);
- start = (lr_setattr_t *)(lr + 1);
+ start = &lr->lr_data[0];
if (vap->va_mask & ATTR_XVATTR) {
zfs_log_xvattr((lr_attr_t *)start, xvap);
- start = (caddr_t)start + ZIL_XVAT_SIZE(xvap->xva_mapsize);
+ start = &lr->lr_data[ZIL_XVAT_SIZE(xvap->xva_mapsize)];
}
/*
@@ -802,7 +806,6 @@ zfs_log_setsaxattr(zilog_t *zilog, dmu_tx_t *tx, int txtype,
itx_t *itx;
lr_setsaxattr_t *lr;
size_t recsize = sizeof (lr_setsaxattr_t);
- void *xattrstart;
int namelen;
if (zil_replaying(zilog, tx) || zp->z_unlinked)
@@ -813,10 +816,9 @@ zfs_log_setsaxattr(zilog_t *zilog, dmu_tx_t *tx, int txtype,
itx = zil_itx_create(txtype, recsize);
lr = (lr_setsaxattr_t *)&itx->itx_lr;
lr->lr_foid = zp->z_id;
- xattrstart = (char *)(lr + 1);
- memcpy(xattrstart, name, namelen);
+ memcpy(&lr->lr_data[0], name, namelen);
if (value != NULL) {
- memcpy((char *)xattrstart + namelen, value, size);
+ memcpy(&lr->lr_data[namelen], value, size);
lr->lr_size = size;
} else {
lr->lr_size = 0;
@@ -874,13 +876,13 @@ zfs_log_acl(zilog_t *zilog, dmu_tx_t *tx, znode_t *zp,
if (txtype == TX_ACL_V0) {
lrv0 = (lr_acl_v0_t *)lr;
- memcpy(lrv0 + 1, vsecp->vsa_aclentp, aclbytes);
+ memcpy(&lrv0->lr_data[0], vsecp->vsa_aclentp, aclbytes);
} else {
- void *start = (ace_t *)(lr + 1);
+ uint8_t *start = &lr->lr_data[0];
memcpy(start, vsecp->vsa_aclentp, aclbytes);
- start = (caddr_t)start + ZIL_ACE_LENGTH(aclbytes);
+ start = &lr->lr_data[ZIL_ACE_LENGTH(aclbytes)];
if (fuidp) {
start = zfs_log_fuid_ids(fuidp, start);
diff --git a/module/zfs/zfs_replay.c b/module/zfs/zfs_replay.c
index 2e0af60f6..3d735b5fb 100644
--- a/module/zfs/zfs_replay.c
+++ b/module/zfs/zfs_replay.c
@@ -293,16 +293,16 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap)
{
zfsvfs_t *zfsvfs = arg1;
lr_acl_create_t *lracl = arg2;
+ _lr_create_t *lr = &lracl->lr_create;
char *name = NULL; /* location determined later */
- lr_create_t *lr = (lr_create_t *)lracl;
znode_t *dzp;
znode_t *zp;
xvattr_t xva;
int vflg = 0;
vsecattr_t vsec = { 0 };
lr_attr_t *lrattr;
- void *aclstart;
- void *fuidstart;
+ uint8_t *aclstart;
+ uint8_t *fuidstart;
size_t xvatlen = 0;
uint64_t txtype;
uint64_t objid;
@@ -316,17 +316,18 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap)
byteswap_uint64_array(lracl, sizeof (*lracl));
if (txtype == TX_CREATE_ACL_ATTR ||
txtype == TX_MKDIR_ACL_ATTR) {
- lrattr = (lr_attr_t *)(caddr_t)(lracl + 1);
+ lrattr = (lr_attr_t *)&lracl->lr_data[0];
zfs_replay_swap_attrs(lrattr);
xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize);
}
- aclstart = (caddr_t)(lracl + 1) + xvatlen;
+ aclstart = &lracl->lr_data[xvatlen];
zfs_ace_byteswap(aclstart, lracl->lr_acl_bytes, B_FALSE);
+
/* swap fuids */
if (lracl->lr_fuidcnt) {
- byteswap_uint64_array((caddr_t)aclstart +
- ZIL_ACE_LENGTH(lracl->lr_acl_bytes),
+ byteswap_uint64_array(
+ &aclstart[ZIL_ACE_LENGTH(lracl->lr_acl_bytes)],
lracl->lr_fuidcnt * sizeof (uint64_t));
}
}
@@ -361,28 +362,27 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap)
vflg |= FIGNORECASE;
switch (txtype) {
case TX_CREATE_ACL:
- aclstart = (caddr_t)(lracl + 1);
- fuidstart = (caddr_t)aclstart +
- ZIL_ACE_LENGTH(lracl->lr_acl_bytes);
+ aclstart = &lracl->lr_data[0];
+ fuidstart = &aclstart[ZIL_ACE_LENGTH(lracl->lr_acl_bytes)];
zfsvfs->z_fuid_replay = zfs_replay_fuids(fuidstart,
(void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt,
lr->lr_uid, lr->lr_gid);
zfs_fallthrough;
case TX_CREATE_ACL_ATTR:
if (name == NULL) {
- lrattr = (lr_attr_t *)(caddr_t)(lracl + 1);
+ lrattr = (lr_attr_t *)&lracl->lr_data[0];
xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize);
xva.xva_vattr.va_mask |= ATTR_XVATTR;
zfs_replay_xvattr(lrattr, &xva);
}
vsec.vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS;
- vsec.vsa_aclentp = (caddr_t)(lracl + 1) + xvatlen;
+ vsec.vsa_aclentp = &lracl->lr_data[xvatlen];
vsec.vsa_aclcnt = lracl->lr_aclcnt;
vsec.vsa_aclentsz = lracl->lr_acl_bytes;
vsec.vsa_aclflags = lracl->lr_acl_flags;
if (zfsvfs->z_fuid_replay == NULL) {
- fuidstart = (caddr_t)(lracl + 1) + xvatlen +
- ZIL_ACE_LENGTH(lracl->lr_acl_bytes);
+ fuidstart = &lracl->lr_data[xvatlen +
+ ZIL_ACE_LENGTH(lracl->lr_acl_bytes)];
zfsvfs->z_fuid_replay =
zfs_replay_fuids(fuidstart,
(void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt,
@@ -398,9 +398,8 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap)
#endif
break;
case TX_MKDIR_ACL:
- aclstart = (caddr_t)(lracl + 1);
- fuidstart = (caddr_t)aclstart +
- ZIL_ACE_LENGTH(lracl->lr_acl_bytes);
+ aclstart = &lracl->lr_data[0];
+ fuidstart = &aclstart[ZIL_ACE_LENGTH(lracl->lr_acl_bytes)];
zfsvfs->z_fuid_replay = zfs_replay_fuids(fuidstart,
(void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt,
lr->lr_uid, lr->lr_gid);
@@ -412,13 +411,13 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap)
zfs_replay_xvattr(lrattr, &xva);
}
vsec.vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS;
- vsec.vsa_aclentp = (caddr_t)(lracl + 1) + xvatlen;
+ vsec.vsa_aclentp = &lracl->lr_data[xvatlen];
vsec.vsa_aclcnt = lracl->lr_aclcnt;
vsec.vsa_aclentsz = lracl->lr_acl_bytes;
vsec.vsa_aclflags = lracl->lr_acl_flags;
if (zfsvfs->z_fuid_replay == NULL) {
- fuidstart = (caddr_t)(lracl + 1) + xvatlen +
- ZIL_ACE_LENGTH(lracl->lr_acl_bytes);
+ fuidstart = &lracl->lr_data[xvatlen +
+ ZIL_ACE_LENGTH(lracl->lr_acl_bytes)];
zfsvfs->z_fuid_replay =
zfs_replay_fuids(fuidstart,
(void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt,
@@ -456,14 +455,14 @@ static int
zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap)
{
zfsvfs_t *zfsvfs = arg1;
- lr_create_t *lr = arg2;
+ lr_create_t *lrc = arg2;
+ _lr_create_t *lr = &lrc->lr_create;
char *name = NULL; /* location determined later */
char *link; /* symlink content follows name */
znode_t *dzp;
znode_t *zp = NULL;
xvattr_t xva;
int vflg = 0;
- size_t lrsize = sizeof (lr_create_t);
lr_attr_t *lrattr;
void *start;
size_t xvatlen;
@@ -476,9 +475,9 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap)
txtype = (lr->lr_common.lrc_txtype & ~TX_CI);
if (byteswap) {
- byteswap_uint64_array(lr, sizeof (*lr));
+ byteswap_uint64_array(lrc, sizeof (*lrc));
if (txtype == TX_CREATE_ATTR || txtype == TX_MKDIR_ATTR)
- zfs_replay_swap_attrs((lr_attr_t *)(lr + 1));
+ zfs_replay_swap_attrs((lr_attr_t *)&lrc->lr_data[0]);
}
@@ -520,7 +519,7 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap)
if (txtype != TX_SYMLINK &&
txtype != TX_MKDIR_ATTR &&
txtype != TX_CREATE_ATTR) {
- start = (lr + 1);
+ start = (void *)&lrc->lr_data[0];
zfsvfs->z_fuid_replay =
zfs_replay_fuid_domain(start, &start,
lr->lr_uid, lr->lr_gid);
@@ -528,10 +527,10 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap)
switch (txtype) {
case TX_CREATE_ATTR:
- lrattr = (lr_attr_t *)(caddr_t)(lr + 1);
+ lrattr = (lr_attr_t *)&lrc->lr_data[0];
xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize);
- zfs_replay_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), &xva);
- start = (caddr_t)(lr + 1) + xvatlen;
+ zfs_replay_xvattr(lrattr, &xva);
+ start = (void *)&lrc->lr_data[xvatlen];
zfsvfs->z_fuid_replay =
zfs_replay_fuid_domain(start, &start,
lr->lr_uid, lr->lr_gid);
@@ -551,10 +550,10 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap)
#endif
break;
case TX_MKDIR_ATTR:
- lrattr = (lr_attr_t *)(caddr_t)(lr + 1);
+ lrattr = (lr_attr_t *)&lrc->lr_data[0];
xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize);
- zfs_replay_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), &xva);
- start = (caddr_t)(lr + 1) + xvatlen;
+ zfs_replay_xvattr(lrattr, &xva);
+ start = &lrc->lr_data[xvatlen];
zfsvfs->z_fuid_replay =
zfs_replay_fuid_domain(start, &start,
lr->lr_uid, lr->lr_gid);
@@ -563,7 +562,7 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap)
case TX_MKDIR:
if (name == NULL)
- name = (char *)(lr + 1);
+ name = (char *)&lrc->lr_data[0];
#if defined(__linux__)
error = zfs_mkdir(dzp, name, &xva.xva_vattr,
@@ -578,8 +577,8 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap)
error = zfs_make_xattrdir(dzp, &xva.xva_vattr, &zp, kcred);
break;
case TX_SYMLINK:
- name = (char *)(lr + 1);
- link = name + strlen(name) + 1;
+ name = &lrc->lr_data[0];
+ link = &lrc->lr_data[strlen(name) + 1];
#if defined(__linux__)
error = zfs_symlink(dzp, name, &xva.xva_vattr,
link, &zp, kcred, vflg, zfs_init_idmap);
@@ -612,7 +611,7 @@ zfs_replay_remove(void *arg1, void *arg2, boolean_t byteswap)
{
zfsvfs_t *zfsvfs = arg1;
lr_remove_t *lr = arg2;
- char *name = (char *)(lr + 1); /* name follows lr_remove_t */
+ char *name = (char *)&lr->lr_data[0]; /* name follows lr_remove_t */
znode_t *dzp;
int error;
int vflg = 0;
@@ -649,7 +648,7 @@ zfs_replay_link(void *arg1, void *arg2, boolean_t byteswap)
{
zfsvfs_t *zfsvfs = arg1;
lr_link_t *lr = arg2;
- char *name = (char *)(lr + 1); /* name follows lr_link_t */
+ char *name = &lr->lr_data[0]; /* name follows lr_link_t */
znode_t *dzp, *zp;
int error;
int vflg = 0;
@@ -678,7 +677,7 @@ zfs_replay_link(void *arg1, void *arg2, boolean_t byteswap)
}
static int
-do_zfs_replay_rename(zfsvfs_t *zfsvfs, lr_rename_t *lr, char *sname,
+do_zfs_replay_rename(zfsvfs_t *zfsvfs, _lr_rename_t *lr, char *sname,
char *tname, uint64_t rflags, vattr_t *wo_vap)
{
znode_t *sdzp, *tdzp;
@@ -722,15 +721,17 @@ static int
zfs_replay_rename(void *arg1, void *arg2, boolean_t byteswap)
{
zfsvfs_t *zfsvfs = arg1;
- lr_rename_t *lr = arg2;
+ lr_rename_t *lrr = arg2;
+ _lr_rename_t *lr = &lrr->lr_rename;
ASSERT3U(lr->lr_common.lrc_reclen, >, sizeof (*lr));
if (byteswap)
- byteswap_uint64_array(lr, sizeof (*lr));
+ byteswap_uint64_array(lrr, sizeof (*lrr));
- char *sname = (char *)(lr + 1); /* sname and tname follow lr_rename_t */
- char *tname = sname + strlen(sname) + 1;
+ /* sname and tname follow lr_rename_t */
+ char *sname = (char *)&lrr->lr_data[0];
+ char *tname = (char *)&lrr->lr_data[strlen(sname)+1];
return (do_zfs_replay_rename(zfsvfs, lr, sname, tname, 0, NULL));
}
@@ -739,15 +740,17 @@ zfs_replay_rename_exchange(void *arg1, void *arg2, boolean_t byteswap)
{
#ifdef __linux__
zfsvfs_t *zfsvfs = arg1;
- lr_rename_t *lr = arg2;
+ lr_rename_t *lrr = arg2;
+ _lr_rename_t *lr = &lrr->lr_rename;
ASSERT3U(lr->lr_common.lrc_reclen, >, sizeof (*lr));
if (byteswap)
- byteswap_uint64_array(lr, sizeof (*lr));
+ byteswap_uint64_array(lrr, sizeof (*lrr));
- char *sname = (char *)(lr + 1); /* sname and tname follow lr_rename_t */
- char *tname = sname + strlen(sname) + 1;
+ /* sname and tname follow lr_rename_t */
+ char *sname = (char *)&lrr->lr_data[0];
+ char *tname = (char *)&lrr->lr_data[strlen(sname)+1];
return (do_zfs_replay_rename(zfsvfs, lr, sname, tname, RENAME_EXCHANGE,
NULL));
#else
@@ -760,24 +763,26 @@ zfs_replay_rename_whiteout(void *arg1, void *arg2, boolean_t byteswap)
{
#ifdef __linux__
zfsvfs_t *zfsvfs = arg1;
- lr_rename_whiteout_t *lr = arg2;
+ lr_rename_whiteout_t *lrrw = arg2;
+ _lr_rename_t *lr = &lrrw->lr_rename;
int error;
/* For the whiteout file. */
xvattr_t xva;
uint64_t objid;
uint64_t dnodesize;
- ASSERT3U(lr->lr_rename.lr_common.lrc_reclen, >, sizeof (*lr));
+ ASSERT3U(lr->lr_common.lrc_reclen, >, sizeof (*lr));
if (byteswap)
- byteswap_uint64_array(lr, sizeof (*lr));
+ byteswap_uint64_array(lrrw, sizeof (*lrrw));
- objid = LR_FOID_GET_OBJ(lr->lr_wfoid);
- dnodesize = LR_FOID_GET_SLOTS(lr->lr_wfoid) << DNODE_SHIFT;
+ objid = LR_FOID_GET_OBJ(lrrw->lr_wfoid);
+ dnodesize = LR_FOID_GET_SLOTS(lrrw->lr_wfoid) << DNODE_SHIFT;
xva_init(&xva);
zfs_init_vattr(&xva.xva_vattr, ATTR_MODE | ATTR_UID | ATTR_GID,
- lr->lr_wmode, lr->lr_wuid, lr->lr_wgid, lr->lr_wrdev, objid);
+ lrrw->lr_wmode, lrrw->lr_wuid, lrrw->lr_wgid, lrrw->lr_wrdev,
+ objid);
/*
* As with TX_CREATE, RENAME_WHITEOUT ends up in zfs_mknode(), which
@@ -786,8 +791,8 @@ zfs_replay_rename_whiteout(void *arg1, void *arg2, boolean_t byteswap)
* attributes, so we smuggle the values inside the vattr's otherwise
* unused va_ctime, va_nblocks, and va_fsid fields.
*/
- ZFS_TIME_DECODE(&xva.xva_vattr.va_ctime, lr->lr_wcrtime);
- xva.xva_vattr.va_nblocks = lr->lr_wgen;
+ ZFS_TIME_DECODE(&xva.xva_vattr.va_ctime, lrrw->lr_wcrtime);
+ xva.xva_vattr.va_nblocks = lrrw->lr_wgen;
xva.xva_vattr.va_fsid = dnodesize;
error = dnode_try_claim(zfsvfs->z_os, objid, dnodesize >> DNODE_SHIFT);
@@ -795,9 +800,9 @@ zfs_replay_rename_whiteout(void *arg1, void *arg2, boolean_t byteswap)
return (error);
/* sname and tname follow lr_rename_whiteout_t */
- char *sname = (char *)(lr + 1);
- char *tname = sname + strlen(sname) + 1;
- return (do_zfs_replay_rename(zfsvfs, &lr->lr_rename, sname, tname,
+ char *sname = (char *)&lrrw->lr_data[0];
+ char *tname = (char *)&lrrw->lr_data[strlen(sname)+1];
+ return (do_zfs_replay_rename(zfsvfs, lr, sname, tname,
RENAME_WHITEOUT, &xva.xva_vattr));
#else
return (SET_ERROR(ENOTSUP));
@@ -809,7 +814,7 @@ zfs_replay_write(void *arg1, void *arg2, boolean_t byteswap)
{
zfsvfs_t *zfsvfs = arg1;
lr_write_t *lr = arg2;
- char *data = (char *)(lr + 1); /* data follows lr_write_t */
+ char *data = &lr->lr_data[0]; /* data follows lr_write_t */
znode_t *zp;
int error;
uint64_t eod, offset, length;
@@ -968,7 +973,7 @@ zfs_replay_setattr(void *arg1, void *arg2, boolean_t byteswap)
if ((lr->lr_mask & ATTR_XVATTR) &&
zfsvfs->z_version >= ZPL_VERSION_INITIAL)
- zfs_replay_swap_attrs((lr_attr_t *)(lr + 1));
+ zfs_replay_swap_attrs((lr_attr_t *)&lr->lr_data[0]);
}
if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0)
@@ -987,11 +992,11 @@ zfs_replay_setattr(void *arg1, void *arg2, boolean_t byteswap)
* Fill in xvattr_t portions if necessary.
*/
- start = (lr_setattr_t *)(lr + 1);
+ start = (void *)&lr->lr_data[0];
if (vap->va_mask & ATTR_XVATTR) {
zfs_replay_xvattr((lr_attr_t *)start, &xva);
- start = (caddr_t)start +
- ZIL_XVAT_SIZE(((lr_attr_t *)start)->lr_attr_masksize);
+ start = &lr->lr_data[
+ ZIL_XVAT_SIZE(((lr_attr_t *)start)->lr_attr_masksize)];
} else
xva.xva_vattr.va_mask &= ~ATTR_XVATTR;
@@ -1049,12 +1054,12 @@ zfs_replay_setsaxattr(void *arg1, void *arg2, boolean_t byteswap)
/* Get xattr name, value and size from log record */
size = lr->lr_size;
- name = (char *)(lr + 1);
+ name = (char *)&lr->lr_data[0];
if (size == 0) {
value = NULL;
error = nvlist_remove(nvl, name, DATA_TYPE_BYTE_ARRAY);
} else {
- value = name + strlen(name) + 1;
+ value = &lr->lr_data[strlen(name) + 1];
/* Limited to 32k to keep nvpair memory allocations small */
if (size > DXATTR_MAX_ENTRY_SIZE) {
error = SET_ERROR(EFBIG);
@@ -1099,7 +1104,7 @@ zfs_replay_acl_v0(void *arg1, void *arg2, boolean_t byteswap)
{
zfsvfs_t *zfsvfs = arg1;
lr_acl_v0_t *lr = arg2;
- ace_t *ace = (ace_t *)(lr + 1); /* ace array follows lr_acl_t */
+ ace_t *ace = (ace_t *)&lr->lr_data[0];
vsecattr_t vsa = {0};
znode_t *zp;
int error;
@@ -1148,7 +1153,7 @@ zfs_replay_acl(void *arg1, void *arg2, boolean_t byteswap)
{
zfsvfs_t *zfsvfs = arg1;
lr_acl_t *lr = arg2;
- ace_t *ace = (ace_t *)(lr + 1);
+ ace_t *ace = (ace_t *)&lr->lr_data[0];
vsecattr_t vsa = {0};
znode_t *zp;
int error;
@@ -1160,8 +1165,8 @@ zfs_replay_acl(void *arg1, void *arg2, boolean_t byteswap)
byteswap_uint64_array(lr, sizeof (*lr));
zfs_ace_byteswap(ace, lr->lr_acl_bytes, B_FALSE);
if (lr->lr_fuidcnt) {
- byteswap_uint64_array((caddr_t)ace +
- ZIL_ACE_LENGTH(lr->lr_acl_bytes),
+ byteswap_uint64_array(&lr->lr_data[
+ ZIL_ACE_LENGTH(lr->lr_acl_bytes)],
lr->lr_fuidcnt * sizeof (uint64_t));
}
}
@@ -1176,8 +1181,8 @@ zfs_replay_acl(void *arg1, void *arg2, boolean_t byteswap)
vsa.vsa_aclflags = lr->lr_acl_flags;
if (lr->lr_fuidcnt) {
- void *fuidstart = (caddr_t)ace +
- ZIL_ACE_LENGTH(lr->lr_acl_bytes);
+ void *fuidstart = &lr->lr_data[
+ ZIL_ACE_LENGTH(lr->lr_acl_bytes)];
zfsvfs->z_fuid_replay =
zfs_replay_fuids(fuidstart, &fuidstart,

View File

@ -0,0 +1,103 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Rob Norris <robn@despairlabs.com>
Date: Tue, 1 Oct 2024 03:30:03 +1000
Subject: [PATCH] lua: add flex array field to TString type
Linux 6.10+ with CONFIG_FORTIFY_SOURCE notices memcpy() accessing past
the end of TString, because it has no indication that there there may be
an additional allocation there.
There's no appropriate upstream change for this (ancient) version of
Lua, so this is the narrowest change I could come up with to add a flex
array field to the end of TString to satisfy the check. It's loosely
based on changes from lua/lua@ca41b43f and lua/lua@9514abc2.
Sponsored-by: https://despairlabs.com/sponsor/
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Rob Norris <robn@despairlabs.com>
Closes #16541
Closes #16583
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
---
module/lua/lobject.h | 21 ++++++++++++---------
module/lua/lstate.h | 2 +-
module/lua/lstring.c | 2 +-
module/lua/lstring.h | 2 +-
4 files changed, 15 insertions(+), 12 deletions(-)
diff --git a/module/lua/lobject.h b/module/lua/lobject.h
index b7c6b41ac..06fdcdcbc 100644
--- a/module/lua/lobject.h
+++ b/module/lua/lobject.h
@@ -404,19 +404,22 @@ typedef TValue *StkId; /* index to stack elements */
/*
** Header for string value; string bytes follow the end of this structure
*/
-typedef union TString {
- L_Umaxalign dummy; /* ensures maximum alignment for strings */
- struct {
- CommonHeader;
- lu_byte extra; /* reserved words for short strings; "has hash" for longs */
- unsigned int hash;
- size_t len; /* number of characters in string */
- } tsv;
+typedef struct TString {
+ union {
+ L_Umaxalign dummy; /* ensures maximum alignment for strings */
+ struct {
+ CommonHeader;
+ lu_byte extra; /* reserved words for short strings; "has hash" for longs */
+ unsigned int hash;
+ size_t len; /* number of characters in string */
+ } tsv;
+ };
+ char contents[];
} TString;
/* get the actual string (array of bytes) from a TString */
-#define getstr(ts) cast(const char *, (ts) + 1)
+#define getstr(ts) ((ts)->contents)
/* get the actual string (array of bytes) from a Lua value */
#define svalue(o) getstr(rawtsvalue(o))
diff --git a/module/lua/lstate.h b/module/lua/lstate.h
index 75c6ceda6..c5fa59335 100644
--- a/module/lua/lstate.h
+++ b/module/lua/lstate.h
@@ -185,7 +185,7 @@ struct lua_State {
*/
union GCObject {
GCheader gch; /* common header */
- union TString ts;
+ struct TString ts;
union Udata u;
union Closure cl;
struct Table h;
diff --git a/module/lua/lstring.c b/module/lua/lstring.c
index 15a73116b..149a4ffc5 100644
--- a/module/lua/lstring.c
+++ b/module/lua/lstring.c
@@ -103,7 +103,7 @@ static TString *createstrobj (lua_State *L, const char *str, size_t l,
ts->tsv.len = l;
ts->tsv.hash = h;
ts->tsv.extra = 0;
- sbuf = (char *)(TString *)(ts + 1);
+ sbuf = ts->contents;
memcpy(sbuf, str, l*sizeof(char));
sbuf[l] = '\0'; /* ending 0 */
return ts;
diff --git a/module/lua/lstring.h b/module/lua/lstring.h
index 260e7f169..257b38417 100644
--- a/module/lua/lstring.h
+++ b/module/lua/lstring.h
@@ -12,7 +12,7 @@
#include "lstate.h"
-#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char))
+#define sizestring(s) (sizeof(struct TString)+((s)->len+1)*sizeof(char))
#define sizeudata(u) (sizeof(union Udata)+(u)->len)

View File

@ -9,3 +9,6 @@
0009-arc-stat-summary-guard-access-to-freshly-introduced-.patch
0010-Fix-nfs_truncate_shares-without-etc-exports.d.patch
0011-zpool-status-tighten-bounds-for-noalloc-stat-availab.patch
0012-Linux-6.10-compat-Fix-tracepoints-definitions.patch
0013-zfs_log-add-flex-array-fields-to-log-record-structs.patch
0014-lua-add-flex-array-field-to-TString-type.patch