[PATCH v2] Handle OpenZFS ioctls

наб nabijaczleweli at gmail.com
Wed Dec 30 00:05:33 UTC 2020


Before/after of strace zfs list:
-ioctl(3, _IOC(_IOC_NONE, 0x5a, 0x4, 0), 0x7ffe7f41e3b0) = 0
-ioctl(3, _IOC(_IOC_NONE, 0x5a, 0x12, 0), 0x7ffe7f41e3c0) = 0
-ioctl(3, _IOC(_IOC_NONE, 0x5a, 0x5, 0), 0x7ffe7f41ad30) = 0
-ioctl(3, _IOC(_IOC_NONE, 0x5a, 0x27, 0), 0x7ffe7f41e320) = 0
-ioctl(3, _IOC(_IOC_NONE, 0x5a, 0x14, 0), 0x7ffe7f41e370) = 0
-ioctl(3, _IOC(_IOC_NONE, 0x5a, 0x14, 0), 0x7ffe7f41ad30) = -1 ESRCH (No such process)
+ioctl(3, ZFS_IOC_POOL_CONFIGS, 0x7ffffae160c0) = 0
+ioctl(3, ZFS_IOC_OBJSET_STATS, 0x7ffffae160d0) = 0
+ioctl(3, ZFS_IOC_POOL_STATS, 0x7ffffae12a40) = 0
+ioctl(3, ZFS_IOC_POOL_GET_PROPS, 0x7ffffae16030) = 0
+ioctl(3, ZFS_IOC_DATASET_LIST_NEXT, 0x7ffffae16080) = 0
+ioctl(3, ZFS_IOC_DATASET_LIST_NEXT, 0x7ffffae12a40) = -1 ESRCH (No such process)
-ioctl(3, _IOC(_IOC_NONE, 0x5a, 0x3f, 0), 0x7ffe7f41e5b0) = -1 EPERM (Operation not permitted)
+ioctl(3, ZFS_IOC_LOG_HISTORY, 0x7ffffae162c0) = -1 EPERM (Operation not permitted)

Before/after of strace zfs/cmd/zvol_id/zvol_id /dev/zd0:
-ioctl(3, _IOC(_IOC_READ, 0x12, 0x7d, 0x100), 0x7fffa7776e20) = 0
+ioctl(3, BLKZNAME, 0x7ffe02f435b0)      = 0

* maint/extract_zfs.sh: New file.
* maint/extract_zfs.awk: New file.
* ioctls_zfs.h: New file.
* ioctlsort.c: Always include ioctls_zfs.h,
as it's personality-independent
* tests/ioctl.c: Test a few ZFS ioctls.
---
On Wed, Dec 30, 2020 at 01:03:49AM +0300, Dmitry V. Levin wrote:
> Thanks for the patch.  Unfortunately, I don't see any changes
> to the test suite in this series.  How did you test these changes?
I, uh, ran zfs(8) and zpool(8) to cover a sensible amount of cases from
the ZFS_IOC_* namespace, built and ran zfs/cmd/zvol_id/zvol_id since
that's the only user of BLKZNAME, and confirmed there isn't anything
weird going on with KSTAT_IOC_*tls, since they have no binary users as
of OpenZFS 2.0.0.

I've added a couple tests into tests/ioctl.c now to ensure these
continue to work; hope that's the right place.

> This should go to maint/ directory along with other scripts of that
> nature.
Right, I just looked for contrib/ and didn't notice maint/ so I squished
everything into one file in the root. This and the rest of the comments
addressed in this patch.

> See also maint/ioctls_sym.sh file.
Most (all except for BLKZNAME) of the numbers are actually enum entries,
with varying degrees of declarative and formatting oddities, it makes
more sense to sequester all of that to one special-purpose script that
can be more easily updated if it breaks than to try to misapply the
general-purpose ones here, I think.

 ioctls_zfs.h          | 101 ++++++++++++++++++++++++++++++++++++++++++
 ioctlsort.c           |   2 +
 maint/extract_zfs.awk |  57 ++++++++++++++++++++++++
 maint/extract_zfs.sh  |  25 +++++++++++
 tests/ioctl.c         |  16 +++++++
 5 files changed, 201 insertions(+)
 create mode 100644 ioctls_zfs.h
 create mode 100644 maint/extract_zfs.awk
 create mode 100755 maint/extract_zfs.sh

diff --git a/ioctls_zfs.h b/ioctls_zfs.h
new file mode 100644
index 00000000..08f48bea
--- /dev/null
+++ b/ioctls_zfs.h
@@ -0,0 +1,101 @@
+/* Generated by extract_zfs.sh from OpenZFS version 2.0.0 */
+{ "include/sys/fs/zfs.h", "ZFS_IOC_POOL_CREATE", 0, 0x5A00, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_POOL_DESTROY", 0, 0x5A01, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_POOL_IMPORT", 0, 0x5A02, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_POOL_EXPORT", 0, 0x5A03, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_POOL_CONFIGS", 0, 0x5A04, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_POOL_STATS", 0, 0x5A05, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_POOL_TRYIMPORT", 0, 0x5A06, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_POOL_SCAN", 0, 0x5A07, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_POOL_FREEZE", 0, 0x5A08, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_POOL_UPGRADE", 0, 0x5A09, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_POOL_GET_HISTORY", 0, 0x5A0A, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_VDEV_ADD", 0, 0x5A0B, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_VDEV_REMOVE", 0, 0x5A0C, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_VDEV_SET_STATE", 0, 0x5A0D, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_VDEV_ATTACH", 0, 0x5A0E, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_VDEV_DETACH", 0, 0x5A0F, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_VDEV_SETPATH", 0, 0x5A10, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_VDEV_SETFRU", 0, 0x5A11, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_OBJSET_STATS", 0, 0x5A12, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_OBJSET_ZPLPROPS", 0, 0x5A13, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_DATASET_LIST_NEXT", 0, 0x5A14, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_SNAPSHOT_LIST_NEXT", 0, 0x5A15, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_SET_PROP", 0, 0x5A16, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_CREATE", 0, 0x5A17, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_DESTROY", 0, 0x5A18, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_ROLLBACK", 0, 0x5A19, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_RENAME", 0, 0x5A1A, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_RECV", 0, 0x5A1B, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_SEND", 0, 0x5A1C, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_INJECT_FAULT", 0, 0x5A1D, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_CLEAR_FAULT", 0, 0x5A1E, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_INJECT_LIST_NEXT", 0, 0x5A1F, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_ERROR_LOG", 0, 0x5A20, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_CLEAR", 0, 0x5A21, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_PROMOTE", 0, 0x5A22, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_SNAPSHOT", 0, 0x5A23, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_DSOBJ_TO_DSNAME", 0, 0x5A24, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_OBJ_TO_PATH", 0, 0x5A25, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_POOL_SET_PROPS", 0, 0x5A26, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_POOL_GET_PROPS", 0, 0x5A27, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_SET_FSACL", 0, 0x5A28, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_GET_FSACL", 0, 0x5A29, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_SHARE", 0, 0x5A2A, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_INHERIT_PROP", 0, 0x5A2B, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_SMB_ACL", 0, 0x5A2C, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_USERSPACE_ONE", 0, 0x5A2D, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_USERSPACE_MANY", 0, 0x5A2E, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_USERSPACE_UPGRADE", 0, 0x5A2F, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_HOLD", 0, 0x5A30, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_RELEASE", 0, 0x5A31, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_GET_HOLDS", 0, 0x5A32, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_OBJSET_RECVD_PROPS", 0, 0x5A33, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_VDEV_SPLIT", 0, 0x5A34, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_NEXT_OBJ", 0, 0x5A35, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_DIFF", 0, 0x5A36, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_TMP_SNAPSHOT", 0, 0x5A37, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_OBJ_TO_STATS", 0, 0x5A38, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_SPACE_WRITTEN", 0, 0x5A39, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_SPACE_SNAPS", 0, 0x5A3A, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_DESTROY_SNAPS", 0, 0x5A3B, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_POOL_REGUID", 0, 0x5A3C, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_POOL_REOPEN", 0, 0x5A3D, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_SEND_PROGRESS", 0, 0x5A3E, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_LOG_HISTORY", 0, 0x5A3F, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_SEND_NEW", 0, 0x5A40, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_SEND_SPACE", 0, 0x5A41, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_CLONE", 0, 0x5A42, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_BOOKMARK", 0, 0x5A43, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_GET_BOOKMARKS", 0, 0x5A44, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_DESTROY_BOOKMARKS", 0, 0x5A45, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_RECV_NEW", 0, 0x5A46, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_POOL_SYNC", 0, 0x5A47, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_CHANNEL_PROGRAM", 0, 0x5A48, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_LOAD_KEY", 0, 0x5A49, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_UNLOAD_KEY", 0, 0x5A4A, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_CHANGE_KEY", 0, 0x5A4B, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_REMAP", 0, 0x5A4C, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_POOL_CHECKPOINT", 0, 0x5A4D, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_POOL_DISCARD_CHECKPOINT", 0, 0x5A4E, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_POOL_INITIALIZE", 0, 0x5A4F, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_POOL_TRIM", 0, 0x5A50, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_REDACT", 0, 0x5A51, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_GET_BOOKMARK_PROPS", 0, 0x5A52, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_WAIT", 0, 0x5A53, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_WAIT_FS", 0, 0x5A54, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_PLATFORM", 0, 0x5A80, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_EVENTS_NEXT", 0, 0x5A81, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_EVENTS_CLEAR", 0, 0x5A82, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_EVENTS_SEEK", 0, 0x5A83, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_NEXTBOOT", 0, 0x5A84, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_JAIL", 0, 0x5A85, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_UNJAIL", 0, 0x5A86, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_SET_BOOTENV", 0, 0x5A87, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_GET_BOOTENV", 0, 0x5A88, 0 },
+{ "include/sys/fs/zfs.h", "ZFS_IOC_LAST", 0, 0x5A89, 0 },
+{ "include/sys/fs/zfs.h", "BLKZNAME", _IOC_READ, (0x12 << 8) | 125, 256 },
+{ "lib/libspl/include/sys/kstat.h", "KSTAT_IOC_BASE", 0, 0x4B00, 0 },
+{ "lib/libspl/include/sys/kstat.h", "KSTAT_IOC_CHAIN_ID", 0, 0x4B01, 0 },
+{ "lib/libspl/include/sys/kstat.h", "KSTAT_IOC_READ", 0, 0x4B02, 0 },
+{ "lib/libspl/include/sys/kstat.h", "KSTAT_IOC_WRITE", 0, 0x4B03, 0 },
diff --git a/ioctlsort.c b/ioctlsort.c
index b090d162..908a63c4 100644
--- a/ioctlsort.c
+++ b/ioctlsort.c
@@ -135,6 +135,8 @@ static struct ioctlent ioctls[] = {
 # include "ioctls_arch.h"
 # include "ioctls_inc.h"
 #endif
+
+#include "ioctls_zfs.h"
 };
 
 int
diff --git a/maint/extract_zfs.awk b/maint/extract_zfs.awk
new file mode 100644
index 00000000..e674ad61
--- /dev/null
+++ b/maint/extract_zfs.awk
@@ -0,0 +1,57 @@
+#!/bin/sh -e
+#
+# Parse OpenZFS headers into C source
+# that writes them in ioctlsort.c format.
+#
+# See extract_zfs.sh for the driver.
+#
+# Copyright (c) 2020 The strace developers.
+# All rights reserved
+#
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+BEGIN {
+	print "#include <stdio.h>"
+	print "#include <stdint.h>"
+	print "#include \"lib/libspl/include/sys/stdtypes.h\""
+	print "typedef uint64_t hrtime_t;"
+	for(i = 1; i < ARGC; ++i)
+		print "#include \"" ARGV[i] "\""
+	print "int main() {"
+	print "	puts(\"/* Generated by extract_zfs.sh from OpenZFS version " ENVIRON["ZVER"] " */\");"
+}
+
+
+/enum zfs_ioc/ {
+	in_ioc = 1
+}
+
+in_ioc && $1 ~ /ZFS_IOC_/ {
+	gsub(/,/, "", $1)
+	if($1 == "ZFS_IOC_FIRST" || $1 == "ZFS_IOC")
+		next
+	print "	printf(\"{ \\\"" FILENAME  "\\\", \\\"" $1 "\\\", 0, 0x%04X, 0 },\\n\", " $1 ");"
+}
+
+in_ioc && /\}/ {
+	in_ioc = 0
+}
+
+
+/^#define\tBLKZNAME/ {
+	$1 = $2 = ""
+	gsub(/_IOR\(/, "", $0)
+	gsub(/\)/, "", $0)
+	gsub(/,/, "", $0)
+	print "	printf(\"{ \\\"" FILENAME  "\\\", \\\"" "BLKZNAME" "\\\", _IOC_READ, (" $1 " << 8) | " $2 ", %zu },\\n\", sizeof(" $3 "));"
+}
+
+
+/^#define\tKSTAT_IOC_/ {
+	print "	printf(\"{ \\\"" FILENAME  "\\\", \\\"" $2 "\\\", 0, 0x%04X, 0 },\\n\", " $2 ");"
+}
+
+
+END {
+	print "}"
+}
diff --git a/maint/extract_zfs.sh b/maint/extract_zfs.sh
new file mode 100755
index 00000000..b2652684
--- /dev/null
+++ b/maint/extract_zfs.sh
@@ -0,0 +1,25 @@
+#!/bin/sh -e
+#
+# Scrape out ioctls from an OpenZFS tree.
+# This should only be needed for getting new definitions,
+# since OpenZFS is committed to this ABI.
+#
+# Copyright (c) 2020 The strace developers.
+# All rights reserved
+#
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+[ -z "$1" ] && {
+	echo "Usage: $0 <path to OpenZFS clone>" >&2
+	exit 1
+}
+
+executable="$(mktemp)"
+self="$(realpath "$0")"
+ZVER="$(awk '/Version/ {print $2}' "$1/META")"
+export ZVER
+
+cd "$1"
+awk -f "${self%sh}awk" include/sys/fs/zfs.h lib/libspl/include/sys/kstat.h | cc -isystem include -xc - -o "$executable"
+"$executable"
+rm "$executable"
diff --git a/tests/ioctl.c b/tests/ioctl.c
index 4f8e2e9f..3a33449d 100644
--- a/tests/ioctl.c
+++ b/tests/ioctl.c
@@ -84,6 +84,22 @@ main(void)
 	printf("ioctl(-1, _IOC(_IOC_READ, 0xde, 0xad, 0x8), %p)"
 	       " = -1 EBADF (%m)\n", &data);
 
+	(void) ioctl(-1, 'Z' << 8, &data);
+	printf("ioctl(-1, ZFS_IOC_POOL_CREATE, %p)"
+	       " = -1 EBADF (%m)\n", &data);
+
+	(void) ioctl(-1, 'Z' << 8 | 'A', &data);
+	printf("ioctl(-1, ZFS_IOC_SEND_SPACE, %p)"
+	       " = -1 EBADF (%m)\n", &data);
+
+	(void) ioctl(-1, _IOR(0x12, 125, char[256]), &data);
+	printf("ioctl(-1, BLKZNAME, %p)"
+	       " = -1 EBADF (%m)\n", &data);
+
+	(void) ioctl(-1, 'K' << 8, &data);
+	printf("ioctl(-1, KSTAT_IOC_BASE, %p)"
+	       " = -1 EBADF (%m)\n", &data);
+
 	puts("+++ exited with 0 +++");
 	return 0;
 }
-- 
2.20.1
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.strace.io/pipermail/strace-devel/attachments/20201230/6aa304c7/attachment.bin>


More information about the Strace-devel mailing list