aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Schoenebeck <qemu_oss@crudebyte.com>2025-01-03 12:33:40 +0100
committerChristian Schoenebeck <qemu_oss@crudebyte.com>2025-02-06 17:10:46 +0100
commit9a0dd4b3e4e0b06ec35c5ac370f54a36ea1846ed (patch)
tree4512485ce20a7de796bdecbc55c675254105a1ed
parenta2f17bd40b3d302f6c1ddf0da75d2343966e0a3f (diff)
downloadqemu-9a0dd4b3e4e0b06ec35c5ac370f54a36ea1846ed.zip
qemu-9a0dd4b3e4e0b06ec35c5ac370f54a36ea1846ed.tar.gz
qemu-9a0dd4b3e4e0b06ec35c5ac370f54a36ea1846ed.tar.bz2
9pfs: improve v9fs_open() tracing
Improve tracing of 9p 'Topen' request type by showing open() flags as human-readable text. E.g. trace output: v9fs_open tag 0 id 12 fid 2 mode 100352 would become: v9fs_open tag=0 id=12 fid=2 mode=100352(RDONLY|NONBLOCK|DIRECTORY| TMPFILE|NDELAY) Therefor add a new utility function qemu_open_flags_tostr() that converts numeric open() flags from host's native O_* flag constants to a string presentation. 9p2000.L and 9p2000.u protocol variants use different numeric 'mode' constants for 'Topen' requests. Instead of writing string conversion code for both protocol variants, use the already existing conversion functions that convert the mode flags from respective protocol constants to host's native open() numeric flag constants and pass that result to the new string conversion function qemu_open_flags_tostr(). Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com> Message-Id: <E1tTgDR-000oRr-9g@kylie.crudebyte.com>
-rw-r--r--hw/9pfs/9p-util-generic.c50
-rw-r--r--hw/9pfs/9p-util.h6
-rw-r--r--hw/9pfs/9p.c9
-rw-r--r--hw/9pfs/meson.build1
-rw-r--r--hw/9pfs/trace-events2
5 files changed, 66 insertions, 2 deletions
diff --git a/hw/9pfs/9p-util-generic.c b/hw/9pfs/9p-util-generic.c
new file mode 100644
index 0000000..4c1e9c8
--- /dev/null
+++ b/hw/9pfs/9p-util-generic.c
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "qemu/osdep.h"
+#include "9p-util.h"
+#include <glib/gstrfuncs.h>
+
+char *qemu_open_flags_tostr(int flags)
+{
+ int acc = flags & O_ACCMODE;
+ return g_strconcat(
+ (acc == O_WRONLY) ? "WRONLY" : (acc == O_RDONLY) ? "RDONLY" : "RDWR",
+ (flags & O_CREAT) ? "|CREAT" : "",
+ (flags & O_EXCL) ? "|EXCL" : "",
+ (flags & O_NOCTTY) ? "|NOCTTY" : "",
+ (flags & O_TRUNC) ? "|TRUNC" : "",
+ (flags & O_APPEND) ? "|APPEND" : "",
+ (flags & O_NONBLOCK) ? "|NONBLOCK" : "",
+ (flags & O_DSYNC) ? "|DSYNC" : "",
+ #ifdef O_DIRECT
+ (flags & O_DIRECT) ? "|DIRECT" : "",
+ #endif
+ (flags & O_LARGEFILE) ? "|LARGEFILE" : "",
+ (flags & O_DIRECTORY) ? "|DIRECTORY" : "",
+ (flags & O_NOFOLLOW) ? "|NOFOLLOW" : "",
+ #ifdef O_NOATIME
+ (flags & O_NOATIME) ? "|NOATIME" : "",
+ #endif
+ #ifdef O_CLOEXEC
+ (flags & O_CLOEXEC) ? "|CLOEXEC" : "",
+ #endif
+ #ifdef __O_SYNC
+ (flags & __O_SYNC) ? "|SYNC" : "",
+ #else
+ ((flags & O_SYNC) == O_SYNC) ? "|SYNC" : "",
+ #endif
+ #ifdef O_PATH
+ (flags & O_PATH) ? "|PATH" : "",
+ #endif
+ #ifdef __O_TMPFILE
+ (flags & __O_TMPFILE) ? "|TMPFILE" : "",
+ #elif defined(O_TMPFILE)
+ ((flags & O_TMPFILE) == O_TMPFILE) ? "|TMPFILE" : "",
+ #endif
+ /* O_NDELAY is usually just an alias of O_NONBLOCK */
+ #if defined(O_NDELAY) && O_NDELAY != O_NONBLOCK
+ (flags & O_NDELAY) ? "|NDELAY" : "",
+ #endif
+ NULL /* always last (required NULL termination) */
+ );
+}
diff --git a/hw/9pfs/9p-util.h b/hw/9pfs/9p-util.h
index 95ee4da..7bc4ec8 100644
--- a/hw/9pfs/9p-util.h
+++ b/hw/9pfs/9p-util.h
@@ -267,4 +267,10 @@ int pthread_fchdir_np(int fd) __attribute__((weak_import));
#endif
int qemu_mknodat(int dirfd, const char *filename, mode_t mode, dev_t dev);
+/*
+ * Returns a newly allocated string presentation of open() flags, intended
+ * for debugging (tracing) purposes only.
+ */
+char *qemu_open_flags_tostr(int flags);
+
#endif
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 6f24c1a..7cad2bc 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -2008,6 +2008,7 @@ static void coroutine_fn v9fs_open(void *opaque)
V9fsFidState *fidp;
V9fsPDU *pdu = opaque;
V9fsState *s = pdu->s;
+ g_autofree char *trace_oflags = NULL;
if (s->proto_version == V9FS_PROTO_2000L) {
err = pdu_unmarshal(pdu, offset, "dd", &fid, &mode);
@@ -2019,7 +2020,13 @@ static void coroutine_fn v9fs_open(void *opaque)
if (err < 0) {
goto out_nofid;
}
- trace_v9fs_open(pdu->tag, pdu->id, fid, mode);
+ if (trace_event_get_state_backends(TRACE_V9FS_OPEN)) {
+ trace_oflags = qemu_open_flags_tostr(
+ (s->proto_version == V9FS_PROTO_2000L) ?
+ dotl_to_open_flags(mode) : omode_to_uflags(mode)
+ );
+ trace_v9fs_open(pdu->tag, pdu->id, fid, mode, trace_oflags);
+ }
fidp = get_fid(pdu, fid);
if (fidp == NULL) {
diff --git a/hw/9pfs/meson.build b/hw/9pfs/meson.build
index eceffdb..d35d4f4 100644
--- a/hw/9pfs/meson.build
+++ b/hw/9pfs/meson.build
@@ -3,6 +3,7 @@ fs_ss.add(files(
'9p-local.c',
'9p-posix-acl.c',
'9p-synth.c',
+ '9p-util-generic.c',
'9p-xattr-user.c',
'9p-xattr.c',
'9p.c',
diff --git a/hw/9pfs/trace-events b/hw/9pfs/trace-events
index ed9f4e7..0e0fc37 100644
--- a/hw/9pfs/trace-events
+++ b/hw/9pfs/trace-events
@@ -13,7 +13,7 @@ v9fs_getattr(uint16_t tag, uint8_t id, int32_t fid, uint64_t request_mask) "tag
v9fs_getattr_return(uint16_t tag, uint8_t id, uint64_t result_mask, uint32_t mode, uint32_t uid, uint32_t gid) "tag %d id %d getattr={result_mask %"PRId64" mode %u uid %u gid %u}"
v9fs_walk(uint16_t tag, uint8_t id, int32_t fid, int32_t newfid, uint16_t nwnames, const char* wnames) "tag=%d id=%d fid=%d newfid=%d nwnames=%d wnames={%s}"
v9fs_walk_return(uint16_t tag, uint8_t id, uint16_t nwnames, void* qids) "tag %d id %d nwnames %d qids %p"
-v9fs_open(uint16_t tag, uint8_t id, int32_t fid, int32_t mode) "tag %d id %d fid %d mode %d"
+v9fs_open(uint16_t tag, uint8_t id, int32_t fid, int32_t mode, const char* oflags) "tag=%d id=%d fid=%d mode=%d(%s)"
v9fs_open_return(uint16_t tag, uint8_t id, uint8_t type, uint32_t version, uint64_t path, int iounit) "tag %u id %u qid={type %u version %u path %"PRIu64"} iounit %d"
v9fs_lcreate(uint16_t tag, uint8_t id, int32_t dfid, int32_t flags, int32_t mode, uint32_t gid) "tag %d id %d dfid %d flags %d mode %d gid %u"
v9fs_lcreate_return(uint16_t tag, uint8_t id, uint8_t type, uint32_t version, uint64_t path, int32_t iounit) "tag %u id %u qid={type %u version %u path %"PRIu64"} iounit %d"