* [PATCH 01/29] xen/public: add some more 9pfs xenstore paths
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
@ 2023-11-01 9:32 ` Juergen Gross
2023-11-01 18:31 ` Jason Andryuk
2023-11-01 9:32 ` [PATCH 02/29] tools: add a new xen logging daemon Juergen Gross
` (27 subsequent siblings)
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:32 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross
Add some optional additional backend paths for 9pfs PV devices. Those
paths will be supported by the new xenlogd 9pfs backend.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
xen/include/public/io/9pfs.h | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/xen/include/public/io/9pfs.h b/xen/include/public/io/9pfs.h
index 9ad2773082..ac4bf0434b 100644
--- a/xen/include/public/io/9pfs.h
+++ b/xen/include/public/io/9pfs.h
@@ -71,6 +71,40 @@
* created on the guest (no user ownership squash or remap)
* Only "none" is supported in this version of the protocol.
*
+ * max-files
+ * Values: <uint32_t>
+ *
+ * The maximum number of files (including directories) allowed for
+ * this device. Backend support of this node is optional. If the node
+ * is not present or the value is zero the number of files is not
+ * limited.
+ *
+ * max-open-files
+ * Values: <uint32_t>
+ *
+ * The maximum number of files the guest is allowed to have opened
+ * concurrently. Multiple concurrent opens of the same file are counted
+ * individually. Backend support of this node is optional. If the node
+ * is not present or the value is zero a backend specific default is
+ * applied.
+ *
+ * max-space
+ * Values: <uint32_t>
+ *
+ * The maximum file space in MiBs the guest is allowed to use for this
+ * device. Backend support of this node is optional. If the node is
+ * not present or the value is zero the space is not limited.
+ *
+ * auto-delete
+ * Values: <bool>
+ *
+ * When set to "1" the backend will delete the file with the oldest
+ * modification date below <path> in case the allowed maximum file
+ * space (see <max-space>) or file number (see <max-files>) is being
+ * exceeded due to guest activity (creation or extension of files).
+ * Files currently opened by the guest won't be deleted. Backend
+ * support of this node is optional.
+ *
******************************************************************************
* Frontend XenBus Nodes
******************************************************************************
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* Re: [PATCH 01/29] xen/public: add some more 9pfs xenstore paths
2023-11-01 9:32 ` [PATCH 01/29] xen/public: add some more 9pfs xenstore paths Juergen Gross
@ 2023-11-01 18:31 ` Jason Andryuk
2023-11-02 7:15 ` Juergen Gross
0 siblings, 1 reply; 81+ messages in thread
From: Jason Andryuk @ 2023-11-01 18:31 UTC (permalink / raw)
To: Juergen Gross; +Cc: xen-devel
On Wed, Nov 1, 2023 at 7:24 AM Juergen Gross <jgross@suse.com> wrote:
>
> Add some optional additional backend paths for 9pfs PV devices. Those
> paths will be supported by the new xenlogd 9pfs backend.
>
> Signed-off-by: Juergen Gross <jgross@suse.com>
> ---
> xen/include/public/io/9pfs.h | 34 ++++++++++++++++++++++++++++++++++
> 1 file changed, 34 insertions(+)
>
> diff --git a/xen/include/public/io/9pfs.h b/xen/include/public/io/9pfs.h
> index 9ad2773082..ac4bf0434b 100644
> --- a/xen/include/public/io/9pfs.h
> +++ b/xen/include/public/io/9pfs.h
> @@ -71,6 +71,40 @@
> * created on the guest (no user ownership squash or remap)
> * Only "none" is supported in this version of the protocol.
> *
> + * max-files
> + * Values: <uint32_t>
> + *
> + * The maximum number of files (including directories) allowed for
> + * this device. Backend support of this node is optional. If the node
> + * is not present or the value is zero the number of files is not
> + * limited.
> + *
> + * max-open-files
> + * Values: <uint32_t>
> + *
> + * The maximum number of files the guest is allowed to have opened
> + * concurrently. Multiple concurrent opens of the same file are counted
> + * individually. Backend support of this node is optional. If the node
> + * is not present or the value is zero a backend specific default is
> + * applied.
> + *
> + * max-space
> + * Values: <uint32_t>
> + *
> + * The maximum file space in MiBs the guest is allowed to use for this
> + * device. Backend support of this node is optional. If the node is
> + * not present or the value is zero the space is not limited.
> + *
> + * auto-delete
> + * Values: <bool>
> + *
> + * When set to "1" the backend will delete the file with the oldest
> + * modification date below <path> in case the allowed maximum file
> + * space (see <max-space>) or file number (see <max-files>) is being
> + * exceeded due to guest activity (creation or extension of files).
> + * Files currently opened by the guest won't be deleted. Backend
> + * support of this node is optional.
> + *
These seem reasonable, but it looks like xenlogd only implements
max-open-files. They are all marked optional, so I guess it's okay to
include them. Is there a plan to implement them? Maybe hold off
until an implementation comes along?
Regards,
Jason
^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: [PATCH 01/29] xen/public: add some more 9pfs xenstore paths
2023-11-01 18:31 ` Jason Andryuk
@ 2023-11-02 7:15 ` Juergen Gross
0 siblings, 0 replies; 81+ messages in thread
From: Juergen Gross @ 2023-11-02 7:15 UTC (permalink / raw)
To: Jason Andryuk; +Cc: xen-devel
[-- Attachment #1.1.1: Type: text/plain, Size: 2761 bytes --]
On 01.11.23 19:31, Jason Andryuk wrote:
> On Wed, Nov 1, 2023 at 7:24 AM Juergen Gross <jgross@suse.com> wrote:
>>
>> Add some optional additional backend paths for 9pfs PV devices. Those
>> paths will be supported by the new xenlogd 9pfs backend.
>>
>> Signed-off-by: Juergen Gross <jgross@suse.com>
>> ---
>> xen/include/public/io/9pfs.h | 34 ++++++++++++++++++++++++++++++++++
>> 1 file changed, 34 insertions(+)
>>
>> diff --git a/xen/include/public/io/9pfs.h b/xen/include/public/io/9pfs.h
>> index 9ad2773082..ac4bf0434b 100644
>> --- a/xen/include/public/io/9pfs.h
>> +++ b/xen/include/public/io/9pfs.h
>> @@ -71,6 +71,40 @@
>> * created on the guest (no user ownership squash or remap)
>> * Only "none" is supported in this version of the protocol.
>> *
>> + * max-files
>> + * Values: <uint32_t>
>> + *
>> + * The maximum number of files (including directories) allowed for
>> + * this device. Backend support of this node is optional. If the node
>> + * is not present or the value is zero the number of files is not
>> + * limited.
>> + *
>> + * max-open-files
>> + * Values: <uint32_t>
>> + *
>> + * The maximum number of files the guest is allowed to have opened
>> + * concurrently. Multiple concurrent opens of the same file are counted
>> + * individually. Backend support of this node is optional. If the node
>> + * is not present or the value is zero a backend specific default is
>> + * applied.
>> + *
>> + * max-space
>> + * Values: <uint32_t>
>> + *
>> + * The maximum file space in MiBs the guest is allowed to use for this
>> + * device. Backend support of this node is optional. If the node is
>> + * not present or the value is zero the space is not limited.
>> + *
>> + * auto-delete
>> + * Values: <bool>
>> + *
>> + * When set to "1" the backend will delete the file with the oldest
>> + * modification date below <path> in case the allowed maximum file
>> + * space (see <max-space>) or file number (see <max-files>) is being
>> + * exceeded due to guest activity (creation or extension of files).
>> + * Files currently opened by the guest won't be deleted. Backend
>> + * support of this node is optional.
>> + *
>
> These seem reasonable, but it looks like xenlogd only implements
> max-open-files. They are all marked optional, so I guess it's okay to
> include them. Is there a plan to implement them? Maybe hold off
> until an implementation comes along?
See the cover letter of the series.
Juergen
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3149 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]
^ permalink raw reply [flat|nested] 81+ messages in thread
* [PATCH 02/29] tools: add a new xen logging daemon
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
2023-11-01 9:32 ` [PATCH 01/29] xen/public: add some more 9pfs xenstore paths Juergen Gross
@ 2023-11-01 9:32 ` Juergen Gross
2023-11-01 18:36 ` Jason Andryuk
2023-11-01 9:32 ` [PATCH 03/29] tools/xenlogd: connect to frontend Juergen Gross
` (26 subsequent siblings)
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:32 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Anthony PERARD
Add "xenlogd", a new logging daemon meant to support infrastructure
domains (e.g. xenstore-stubdom) to write log files in dom0.
For now only add the code needed for starting the daemon and
registering it with Xenstore via a new "/tool/xenlog/state" node by
writing the "running" state to it.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/Makefile | 1 +
tools/xenlogd/.gitignore | 1 +
tools/xenlogd/Makefile | 38 ++++++++++
tools/xenlogd/xenlogd.c | 145 +++++++++++++++++++++++++++++++++++++++
4 files changed, 185 insertions(+)
create mode 100644 tools/xenlogd/.gitignore
create mode 100644 tools/xenlogd/Makefile
create mode 100644 tools/xenlogd/xenlogd.c
diff --git a/tools/Makefile b/tools/Makefile
index 3a510663a0..0225020416 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -32,6 +32,7 @@ SUBDIRS-y += xenpmd
SUBDIRS-$(CONFIG_GOLANG) += golang
SUBDIRS-y += xl
SUBDIRS-y += helpers
+SUBDIRS-y += xenlogd
SUBDIRS-$(CONFIG_X86) += xenpaging
SUBDIRS-$(CONFIG_X86) += debugger
SUBDIRS-$(CONFIG_TESTS) += tests
diff --git a/tools/xenlogd/.gitignore b/tools/xenlogd/.gitignore
new file mode 100644
index 0000000000..a0305ae096
--- /dev/null
+++ b/tools/xenlogd/.gitignore
@@ -0,0 +1 @@
+/xenlogd
diff --git a/tools/xenlogd/Makefile b/tools/xenlogd/Makefile
new file mode 100644
index 0000000000..550e914f59
--- /dev/null
+++ b/tools/xenlogd/Makefile
@@ -0,0 +1,38 @@
+#
+# tools/helpers/Makefile
+#
+
+XEN_ROOT = $(CURDIR)/../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+CFLAGS += $(PTHREAD_CFLAGS)
+LDFLAGS += $(PTHREAD_LDFLAGS)
+
+TARGETS := xenlogd
+
+XENLOGD_OBJS = xenlogd.o
+$(XENLOGD_OBJS): CFLAGS += $(CFLAGS_libxenstore)
+$(XENLOGD_OBJS): CFLAGS += $(CFLAGS_libxenevtchn)
+$(XENLOGD_OBJS): CFLAGS += $(CFLAGS_libxengnttab)
+xenlogd: LDLIBS += $(call xenlibs-ldlibs,store evtchn gnttab)
+
+.PHONY: all
+all: $(TARGETS)
+
+xenlogd: $(XENLOGD_OBJS)
+ $(CC) $(LDFLAGS) -o $@ $(XENLOGD_OBJS) $(LDLIBS) $(APPEND_LDFLAGS)
+
+.PHONY: install
+install: all
+ $(INSTALL_DIR) $(DESTDIR)$(LIBEXEC_BIN)
+ for i in $(TARGETS); do $(INSTALL_PROG) $$i $(DESTDIR)$(LIBEXEC_BIN); done
+
+.PHONY: uninstall
+uninstall:
+ for i in $(TARGETS); do rm -f $(DESTDIR)$(LIBEXEC_BIN)/$$i; done
+
+.PHONY: clean
+clean:
+ $(RM) *.o $(TARGETS) $(DEPS_RM)
+
+distclean: clean
diff --git a/tools/xenlogd/xenlogd.c b/tools/xenlogd/xenlogd.c
new file mode 100644
index 0000000000..792d1026a3
--- /dev/null
+++ b/tools/xenlogd/xenlogd.c
@@ -0,0 +1,145 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * xenlogd - Xen logging daemon
+ *
+ * Copyright (C) 2023 Juergen Gross <jgross@suse.com>
+ *
+ * Daemon to enable guests to access a directory of the dom0 file system.
+ * Access is made via the 9pfs protocol (xenlogd acts as a PV 9pfs backend).
+ *
+ * Usage: xenlogd
+ *
+ * xenlogd does NOT support writing any links (neither soft links nor hard
+ * links), and it is accepting only canonicalized file paths in order to
+ * avoid the possibility to "escape" from the guest specific directory.
+ *
+ * The backend device string is "xen_9pfs", the tag used for mounting the
+ * 9pfs device is "Xen".
+ *
+ * As an additional security measure the maximum file space used by the guest
+ * can be limited by the backend Xenstore node "max-size" specifying the size
+ * in MBytes. This size includes the size of the root directory of the guest.
+ */
+
+#include <err.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <xenevtchn.h>
+#include <xengnttab.h>
+#include <xenstore.h>
+
+static bool stop_me;
+static bool daemon_running;
+static struct xs_handle *xs;
+static xengnttab_handle *xg;
+static xenevtchn_handle *xe;
+
+static void handle_stop(int sig)
+{
+ stop_me = true;
+}
+
+static void close_all(void)
+{
+ if ( daemon_running )
+ xs_rm(xs, XBT_NULL, "/tool/xenlog");
+ if ( xe )
+ xenevtchn_close(xe);
+ if ( xg )
+ xengnttab_close(xg);
+ if ( xs )
+ xs_close(xs);
+ closelog();
+}
+
+static void do_err(const char *msg)
+{
+ syslog(LOG_ALERT, "%s, errno = %d", msg, errno);
+ close_all();
+ exit(1);
+}
+
+static void xen_connect(void)
+{
+ xs_transaction_t t;
+ char *val;
+ unsigned int len;
+
+ xs = xs_open(0);
+ if ( xs == NULL )
+ do_err("xs_open() failed");
+
+ xg = xengnttab_open(NULL, 0);
+ if ( xg == NULL )
+ do_err("xengnttab_open() failed");
+
+ xe = xenevtchn_open(NULL, 0);
+ if ( xe == NULL )
+ do_err("xenevtchn_open() failed");
+
+ while ( true )
+ {
+ t = xs_transaction_start(xs);
+ if ( t == XBT_NULL )
+ do_err("xs_transaction_start() failed");
+
+ val = xs_read(xs, t, "/tool/xenlog/state", &len);
+ if ( val )
+ {
+ free(val);
+ xs_transaction_end(xs, t, true);
+ do_err("daemon already running");
+ }
+
+ if ( !xs_write(xs, t, "/tool/xenlog/state", "running",
+ strlen("running")) )
+ {
+ xs_transaction_end(xs, t, true);
+ do_err("xs_write() failed writing state");
+ }
+
+ if ( xs_transaction_end(xs, t, false) )
+ break;
+ if ( errno != EAGAIN )
+ do_err("xs_transaction_end() failed");
+ }
+
+ daemon_running = true;
+}
+
+int main(int argc, char *argv[])
+{
+ struct sigaction act = { .sa_handler = handle_stop, };
+ int syslog_mask = LOG_MASK(LOG_WARNING) | LOG_MASK(LOG_ERR) |
+ LOG_MASK(LOG_CRIT) | LOG_MASK(LOG_ALERT) |
+ LOG_MASK(LOG_EMERG);
+
+ umask(027);
+ if ( getenv("XENLOGD_VERBOSE") )
+ syslog_mask |= LOG_MASK(LOG_NOTICE) | LOG_MASK(LOG_INFO);
+ openlog("xenlogd", LOG_CONS, LOG_DAEMON);
+ setlogmask(syslog_mask);
+
+ sigemptyset(&act.sa_mask);
+ sigaction(SIGHUP, &act, NULL);
+
+ xen_connect();
+
+ while ( !stop_me )
+ {
+ sleep(60);
+ }
+
+ close_all();
+
+ return 0;
+}
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* Re: [PATCH 02/29] tools: add a new xen logging daemon
2023-11-01 9:32 ` [PATCH 02/29] tools: add a new xen logging daemon Juergen Gross
@ 2023-11-01 18:36 ` Jason Andryuk
2023-11-02 7:44 ` Juergen Gross
0 siblings, 1 reply; 81+ messages in thread
From: Jason Andryuk @ 2023-11-01 18:36 UTC (permalink / raw)
To: Juergen Gross; +Cc: xen-devel, Wei Liu, Anthony PERARD
On Wed, Nov 1, 2023 at 10:27 AM Juergen Gross <jgross@suse.com> wrote:
>
> Add "xenlogd", a new logging daemon meant to support infrastructure
> domains (e.g. xenstore-stubdom) to write log files in dom0.
As I understand it, your new daemon is a generic 9pfs backend, which
you use for logging. I think naming it something like xen9pfsd would
more accurately describe its functionality.
> For now only add the code needed for starting the daemon and
> registering it with Xenstore via a new "/tool/xenlog/state" node by
> writing the "running" state to it.
To support driver domain use cases, I think you want to use a relative
Xenstore path. While this daemon is independent from libxl, it might
be easiest to use "libxl/xenlog/" ("libxl/xen9pfs/") to take advantage
of driver domains having a read-write "libxl/" directory.
> Signed-off-by: Juergen Gross <jgross@suse.com>
The code looks good to me.
Regards,
Jason
^ permalink raw reply [flat|nested] 81+ messages in thread* Re: [PATCH 02/29] tools: add a new xen logging daemon
2023-11-01 18:36 ` Jason Andryuk
@ 2023-11-02 7:44 ` Juergen Gross
2023-11-02 19:15 ` Andrew Cooper
0 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-02 7:44 UTC (permalink / raw)
To: Jason Andryuk; +Cc: xen-devel, Wei Liu, Anthony PERARD
[-- Attachment #1.1.1: Type: text/plain, Size: 1221 bytes --]
On 01.11.23 19:36, Jason Andryuk wrote:
> On Wed, Nov 1, 2023 at 10:27 AM Juergen Gross <jgross@suse.com> wrote:
>>
>> Add "xenlogd", a new logging daemon meant to support infrastructure
>> domains (e.g. xenstore-stubdom) to write log files in dom0.
>
> As I understand it, your new daemon is a generic 9pfs backend, which
> you use for logging. I think naming it something like xen9pfsd would
> more accurately describe its functionality.
Fine with me. I'll wait a little bit to see what others think.
>> For now only add the code needed for starting the daemon and
>> registering it with Xenstore via a new "/tool/xenlog/state" node by
>> writing the "running" state to it.
>
> To support driver domain use cases, I think you want to use a relative
> Xenstore path. While this daemon is independent from libxl, it might
> be easiest to use "libxl/xenlog/" ("libxl/xen9pfs/") to take advantage
> of driver domains having a read-write "libxl/" directory.
You have a point here. And as it is libxl controlling the start of the
daemon, putting it under "libxl" is fine IMO.
>
>> Signed-off-by: Juergen Gross <jgross@suse.com>
>
> The code looks good to me.
Thanks,
Juergen
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3149 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]
^ permalink raw reply [flat|nested] 81+ messages in thread* Re: [PATCH 02/29] tools: add a new xen logging daemon
2023-11-02 7:44 ` Juergen Gross
@ 2023-11-02 19:15 ` Andrew Cooper
2023-11-03 7:36 ` Juergen Gross
0 siblings, 1 reply; 81+ messages in thread
From: Andrew Cooper @ 2023-11-02 19:15 UTC (permalink / raw)
To: Juergen Gross, Jason Andryuk; +Cc: xen-devel, Wei Liu, Anthony PERARD
On 02/11/2023 7:44 am, Juergen Gross wrote:
> On 01.11.23 19:36, Jason Andryuk wrote:
>> On Wed, Nov 1, 2023 at 10:27 AM Juergen Gross <jgross@suse.com> wrote:
>>>
>>> Add "xenlogd", a new logging daemon meant to support infrastructure
>>> domains (e.g. xenstore-stubdom) to write log files in dom0.
>>
>> As I understand it, your new daemon is a generic 9pfs backend, which
>> you use for logging. I think naming it something like xen9pfsd would
>> more accurately describe its functionality.
>
> Fine with me. I'll wait a little bit to see what others think.
FWIW, I too looked at xenlogd and thought it probably wasn't ideal, but
I was going to wait until glancing at the whole series before suggesting
an alternative.
If it really is a generic 9pfs backend, then +1 to Jason's suggestion,
although preferably as xen-9pfsd for improved legibility.
But a couple of other remarks while I'm here.
It's great to see that it only uses stable libraries, and I hope that
remains true to the end of the series. If we end up wanting unstable
APIs, can I suggest that we take the opportunity to stabilise them as a
prerequisite.
In this patch, stop_me needs to be volatile or read with
ACCESS_ONCE()/etc. The only thing stopping GCC turning it into an
infinite loop is sleep() being an external call. daemon_running may
need similar treatment, depending on how it gets used in later patches.
~Andrew
^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: [PATCH 02/29] tools: add a new xen logging daemon
2023-11-02 19:15 ` Andrew Cooper
@ 2023-11-03 7:36 ` Juergen Gross
0 siblings, 0 replies; 81+ messages in thread
From: Juergen Gross @ 2023-11-03 7:36 UTC (permalink / raw)
To: Andrew Cooper, Jason Andryuk; +Cc: xen-devel, Wei Liu, Anthony PERARD
[-- Attachment #1.1.1: Type: text/plain, Size: 1757 bytes --]
On 02.11.23 20:15, Andrew Cooper wrote:
> On 02/11/2023 7:44 am, Juergen Gross wrote:
>> On 01.11.23 19:36, Jason Andryuk wrote:
>>> On Wed, Nov 1, 2023 at 10:27 AM Juergen Gross <jgross@suse.com> wrote:
>>>>
>>>> Add "xenlogd", a new logging daemon meant to support infrastructure
>>>> domains (e.g. xenstore-stubdom) to write log files in dom0.
>>>
>>> As I understand it, your new daemon is a generic 9pfs backend, which
>>> you use for logging. I think naming it something like xen9pfsd would
>>> more accurately describe its functionality.
>>
>> Fine with me. I'll wait a little bit to see what others think.
>
> FWIW, I too looked at xenlogd and thought it probably wasn't ideal, but
> I was going to wait until glancing at the whole series before suggesting
> an alternative.
>
> If it really is a generic 9pfs backend, then +1 to Jason's suggestion,
> although preferably as xen-9pfsd for improved legibility.
Okay.
> But a couple of other remarks while I'm here.
>
> It's great to see that it only uses stable libraries, and I hope that
> remains true to the end of the series. If we end up wanting unstable
> APIs, can I suggest that we take the opportunity to stabilise them as a
> prerequisite.
No unstable APIs. It does use xenctrl.h, but it needs that only for the
cpu barriers. Maybe we should extract those to another header?
> In this patch, stop_me needs to be volatile or read with
> ACCESS_ONCE()/etc. The only thing stopping GCC turning it into an
> infinite loop is sleep() being an external call.
Okay, will use volatile.
> daemon_running may
> need similar treatment, depending on how it gets used in later patches.
I don't think it needs special treatment.
Juergen
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3149 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]
^ permalink raw reply [flat|nested] 81+ messages in thread
* [PATCH 03/29] tools/xenlogd: connect to frontend
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
2023-11-01 9:32 ` [PATCH 01/29] xen/public: add some more 9pfs xenstore paths Juergen Gross
2023-11-01 9:32 ` [PATCH 02/29] tools: add a new xen logging daemon Juergen Gross
@ 2023-11-01 9:32 ` Juergen Gross
2023-11-01 19:21 ` Jason Andryuk
2023-11-01 9:33 ` [PATCH 04/29] tools/xenlogd: add transport layer Juergen Gross
` (25 subsequent siblings)
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:32 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Anthony PERARD
Add the code for connecting to frontends to xenlogd.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/xenlogd/Makefile | 2 +-
tools/xenlogd/io.c | 45 ++++
tools/xenlogd/xenlogd.c | 575 +++++++++++++++++++++++++++++++++++++++-
tools/xenlogd/xenlogd.h | 50 ++++
4 files changed, 668 insertions(+), 4 deletions(-)
create mode 100644 tools/xenlogd/io.c
create mode 100644 tools/xenlogd/xenlogd.h
diff --git a/tools/xenlogd/Makefile b/tools/xenlogd/Makefile
index 550e914f59..0d44cd0e85 100644
--- a/tools/xenlogd/Makefile
+++ b/tools/xenlogd/Makefile
@@ -10,7 +10,7 @@ LDFLAGS += $(PTHREAD_LDFLAGS)
TARGETS := xenlogd
-XENLOGD_OBJS = xenlogd.o
+XENLOGD_OBJS = xenlogd.o io.o
$(XENLOGD_OBJS): CFLAGS += $(CFLAGS_libxenstore)
$(XENLOGD_OBJS): CFLAGS += $(CFLAGS_libxenevtchn)
$(XENLOGD_OBJS): CFLAGS += $(CFLAGS_libxengnttab)
diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
new file mode 100644
index 0000000000..ef0954d69d
--- /dev/null
+++ b/tools/xenlogd/io.c
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * xenlogd - Xen logging daemon
+ *
+ * Copyright (C) 2023 Juergen Gross <jgross@suse.com>
+ *
+ * I/O thread handling.
+ */
+
+#include <stdbool.h>
+#include <string.h>
+#include <syslog.h>
+
+#include "xenlogd.h"
+
+static bool io_work_pending(device *device)
+{
+ if ( device->stop_thread )
+ return true;
+ return false;
+}
+
+void *io_thread(void *arg)
+{
+ device *device = arg;
+
+ while ( !device->stop_thread )
+ {
+ pthread_mutex_lock(&device->mutex);
+ if ( !io_work_pending(device) )
+ {
+ if ( xenevtchn_unmask(xe, device->evtchn) < 0 )
+ syslog(LOG_WARNING, "xenevtchn_unmask() failed");
+ pthread_cond_wait(&device->cond, &device->mutex);
+ }
+ pthread_mutex_unlock(&device->mutex);
+
+ /* TODO: I/O handling. */
+ }
+
+ device->thread_active = false;
+
+ return NULL;
+}
diff --git a/tools/xenlogd/xenlogd.c b/tools/xenlogd/xenlogd.c
index 792d1026a3..da0a09a122 100644
--- a/tools/xenlogd/xenlogd.c
+++ b/tools/xenlogd/xenlogd.c
@@ -24,34 +24,562 @@
#include <err.h>
#include <errno.h>
+#include <poll.h>
+#include <pthread.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
+#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
-#include <xenevtchn.h>
#include <xengnttab.h>
#include <xenstore.h>
+#include "xenlogd.h"
+
+/*
+ * List of currently known devices.
+ * The list itself is modified only in the main thread. When a device is being
+ * removed its memory needs to be freed after the I/O thread (if existing)
+ * has stopped.
+ */
+static XEN_TAILQ_HEAD(devhead, device) devs = XEN_TAILQ_HEAD_INITIALIZER(devs);
+
+struct path {
+ char path[100];
+};
+
static bool stop_me;
static bool daemon_running;
static struct xs_handle *xs;
static xengnttab_handle *xg;
-static xenevtchn_handle *xe;
+static unsigned int now;
+
+xenevtchn_handle *xe;
static void handle_stop(int sig)
{
stop_me = true;
}
+static int check_host_path(device *device)
+{
+ struct stat statbuf;
+ char *path, *p;
+ int ret = 1;
+
+ if ( !device->host_path )
+ return 1;
+
+ if ( device->host_path[0] != '/' )
+ return 1;
+
+ path = strdup(device->host_path);
+ if ( !path )
+ {
+ syslog(LOG_CRIT, "memory allocation failure!");
+ return 1;
+ }
+
+ for ( p = path; p; )
+ {
+ p = strchr(p + 1, '/');
+ if ( p )
+ *p = 0;
+ if ( !stat(path, &statbuf) )
+ {
+ if ( !(statbuf.st_mode & S_IFDIR) )
+ break;
+ if ( !p )
+ {
+ ret = 0;
+ break;
+ }
+ *p = '/';
+ continue;
+ }
+ if ( mkdir(path, 0777) )
+ break;
+ if ( p )
+ *p = '/';
+ }
+
+ free(path);
+ return ret;
+}
+
+static void construct_frontend_path(device *device, const char *node,
+ struct path *p)
+{
+ snprintf(p->path, sizeof(p->path), "/local/domain/%u/device/9pfs/%u/%s",
+ device->domid, device->devid, node);
+}
+
+static void construct_backend_path(device *device, const char *node,
+ struct path *p)
+{
+ snprintf(p->path, sizeof(p->path), "backend/xen_9pfs/%u/%u/%s",
+ device->domid, device->devid, node);
+}
+
+static char *read_backend_node(device *device, const char *node)
+{
+ struct path p;
+ char *val;
+ unsigned int len;
+
+ construct_backend_path(device, node, &p);
+ val = xs_read(xs, XBT_NULL, p.path, &len);
+
+ return val;
+}
+
+static unsigned int uint_from_string(char *string, unsigned int def)
+{
+ unsigned long val;
+ char *end;
+
+ if ( !string )
+ return def;
+
+ val = strtoul(string, &end, 10);
+ if ( *end || val > UINT_MAX )
+ val = def;
+ free(string);
+
+ return val;
+}
+
+static unsigned int read_backend_node_uint(device *device, const char *node,
+ unsigned int def)
+{
+ return uint_from_string(read_backend_node(device, node), def);
+}
+
+static unsigned int read_frontend_node_uint(device *device, const char *node,
+ unsigned int def)
+{
+ struct path p;
+ unsigned int len;
+
+ construct_frontend_path(device, node, &p);
+
+ return uint_from_string(xs_read(xs, XBT_NULL, p.path, &len), def);
+}
+
+static int write_backend_node(device *device, const char *node, const char *val)
+{
+ struct path p;
+ struct xs_permissions perms[2] = {
+ { .id = 0, .perms = XS_PERM_NONE },
+ { .id = device->domid, .perms = XS_PERM_READ }
+ };
+
+ construct_backend_path(device, node, &p);
+ if ( !xs_write(xs, XBT_NULL, p.path, val, strlen(val)) )
+ {
+ syslog(LOG_ERR, "error writing bacḱend node \"%s\" for device %u/%u",
+ node, device->domid, device->devid);
+ return 1;
+ }
+
+ if ( !xs_set_permissions(xs, XBT_NULL, p.path, perms, 2) )
+ {
+ syslog(LOG_ERR, "error setting permissions for \"%s\"", p.path);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int write_backend_state(device *device, enum xenbus_state state)
+{
+ struct path p;
+ char val[2];
+
+ snprintf(val, sizeof(val), "%u", state);
+ construct_backend_path(device, "state", &p);
+ if ( !xs_write(xs, XBT_NULL, p.path, val, 1) )
+ {
+ syslog(LOG_ERR, "error writing backend state %u for device %u/%u",
+ state, device->domid, device->devid);
+ return 1;
+ }
+
+ device->backend_state = state;
+
+ return 0;
+}
+
+static device *find_device(unsigned int domid, unsigned int devid)
+{
+ device *device;
+
+ XEN_TAILQ_FOREACH( device, &devs, list )
+ {
+ if ( domid == device->domid && devid == device->devid )
+ return device;
+ }
+
+ return NULL;
+}
+
+static void free_device(device *device)
+{
+ char token[20];
+ struct path p;
+
+ construct_frontend_path(device, "state", &p);
+ snprintf(token, sizeof(token), "%u/%u", device->domid, device->devid);
+ xs_unwatch(xs, p.path, token);
+
+ free(device->host_path);
+
+ pthread_mutex_destroy(&device->mutex);
+ pthread_cond_destroy(&device->cond);
+
+ free(device);
+}
+
+static device *new_device(unsigned int domid, unsigned int devid)
+{
+ device *device;
+ char token[20];
+ struct path p;
+ char *val;
+
+ device = calloc(1, sizeof(*device));
+ if ( !device )
+ {
+ syslog(LOG_CRIT, "Got no memory for new device %u/%u", domid, devid);
+ return NULL;
+ }
+
+ device->domid = domid;
+ device->devid = devid;
+
+ construct_frontend_path(device, "state", &p);
+ snprintf(token, sizeof(token), "%u/%u", domid, devid);
+ if ( !xs_watch(xs, p.path, token) )
+ {
+ syslog(LOG_ERR, "Setting up watch for device %u/%u failed",
+ domid, devid);
+ free(device);
+ return NULL;
+ }
+
+ pthread_cond_init(&device->cond, NULL);
+ pthread_mutex_init(&device->mutex, NULL);
+
+ val = read_backend_node(device, "security_model");
+ if ( !val || strcmp(val, "none") )
+ {
+ syslog(LOG_ERR, "Security model \"%s\" for device %u/%u invalid.",
+ val, domid, devid);
+ free(val);
+ goto err;
+ }
+ free(val);
+
+ device->max_space = read_backend_node_uint(device, "max-space", 0);
+ device->max_files = read_backend_node_uint(device, "max-files", 0);
+ device->max_open_files =
+ read_backend_node_uint(device, "max-open-files", 0)
+ ?: MAX_OPEN_FILES_DEFAULT;
+ device->auto_delete = !!read_backend_node_uint(device, "auto-delete", 0);
+
+ device->host_path = read_backend_node(device, "path");
+ if ( check_host_path(device) )
+ {
+ syslog(LOG_ERR, "Host path \"%s\" for device %u/%u invalid.",
+ device->host_path, domid, devid);
+ goto err;
+ }
+
+ if ( write_backend_node(device, "versions", "1") )
+ goto err;
+ if ( write_backend_node(device, "max-rings", "1") )
+ goto err;
+ if ( write_backend_node(device, "max-ring-page-order", "9") )
+ goto err;
+
+ if ( write_backend_state(device, XenbusStateInitWait) )
+ goto err;
+
+ XEN_TAILQ_INSERT_TAIL(&devs, device, list);
+ syslog(LOG_INFO, "New device %u/%u added", domid, devid);
+
+ return device;
+
+ err:
+ free_device(device);
+ return NULL;
+}
+
+static void disconnect_guest(device *device)
+{
+ if ( device->thread_active )
+ {
+ device->stop_thread = true;
+ pthread_cond_signal(&device->cond);
+ pthread_join(device->thread, NULL);
+ device->stop_thread = false;
+ }
+
+ if ( device->data.in )
+ {
+ xengnttab_unmap(xg, device->data.in, 1 << device->ring_order);
+ device->data.in = NULL;
+ }
+ if ( device->intf )
+ {
+ xengnttab_unmap(xg, device->intf, 1 );
+ device->intf = NULL;
+ }
+
+ if ( device->evtchn )
+ {
+ xenevtchn_unbind(xe, device->evtchn);
+ device->evtchn = 0;
+ }
+}
+
+static void close_device(device *device, enum xenbus_state state)
+{
+ disconnect_guest(device);
+ write_backend_state(device, state);
+}
+
+static void connect_err(device *device, const char *msg)
+{
+ syslog(LOG_WARNING, "%s", msg);
+ close_device(device, XenbusStateClosed);
+}
+
+static void connect_device(device *device)
+{
+ unsigned int val;
+ xenevtchn_port_or_error_t evtchn;
+
+ val = read_frontend_node_uint(device, "version", 0);
+ if ( val != 1 )
+ return connect_err(device, "frontend specifies illegal version");
+ val = read_frontend_node_uint(device, "num-rings", 0);
+ if ( val != 1 )
+ return connect_err(device, "frontend specifies illegal ring number");
+
+ val = read_frontend_node_uint(device, "event-channel-0", 0);
+ if ( val == 0 )
+ return connect_err(device, "frontend specifies illegal evtchn");
+ evtchn = xenevtchn_bind_interdomain(xe, device->domid, val);
+ if ( evtchn < 0 )
+ return connect_err(device, "could not bind to event channel");
+ device->evtchn = evtchn;
+
+ val = read_frontend_node_uint(device, "ring-ref0", 0);
+ if ( val == 0 )
+ return connect_err(device, "frontend specifies illegal grant for ring");
+ device->intf = xengnttab_map_grant_ref(xg, device->domid, val,
+ PROT_READ | PROT_WRITE);
+ if ( !device->intf )
+ return connect_err(device, "could not map interface page");
+ device->ring_order = device->intf->ring_order;
+ if ( device->ring_order > 9 || device->ring_order < 1 )
+ return connect_err(device, "frontend specifies illegal ring order");
+ device->ring_size = XEN_FLEX_RING_SIZE(device->ring_order);
+ device->data.in = xengnttab_map_domain_grant_refs(xg,
+ 1 << device->ring_order,
+ device->domid,
+ device->intf->ref,
+ PROT_READ | PROT_WRITE);
+ if ( !device->data.in )
+ return connect_err(device, "could not map ring pages");
+ device->data.out = device->data.in + device->ring_size;
+
+ if ( pthread_create(&device->thread, NULL, io_thread, device) )
+ return connect_err(device, "could not start I/O thread");
+ device->thread_active = true;
+
+ write_backend_state(device, XenbusStateConnected);
+}
+
+static void remove_device(device *device)
+{
+ XEN_TAILQ_REMOVE(&devs, device, list);
+
+ disconnect_guest(device);
+ free_device(device);
+}
+
+static void remove_all_devices(void)
+{
+ device *device, *tmp;
+
+ XEN_TAILQ_FOREACH_SAFE( device, &devs, list, tmp )
+ remove_device(device);
+}
+
+static void frontend_changed(device *device)
+{
+ struct path p;
+ char *state, *end;
+ unsigned int len;
+ unsigned long new_state;
+
+ construct_frontend_path(device, "state", &p);
+ state = xs_read(xs, XBT_NULL, p.path, &len);
+ if ( !state )
+ {
+ close_device(device, XenbusStateClosed);
+ return;
+ }
+
+ new_state = strtoul(state, &end, 10);
+ if ( *end || new_state > XenbusStateReconfigured )
+ {
+ syslog(LOG_WARNING, "unknown state \"%s\" seen for device %u/%u", state,
+ device->domid, device->devid);
+ new_state = XenbusStateUnknown;
+ }
+ free(state);
+
+ if ( new_state == device->frontend_state )
+ return;
+
+ switch ( new_state )
+ {
+ case XenbusStateInitialising:
+ break;
+
+ case XenbusStateInitialised:
+ connect_device(device);
+ break;
+
+ case XenbusStateConnected:
+ break;
+
+ case XenbusStateClosing:
+ close_device(device, XenbusStateClosing);
+ break;
+
+ case XenbusStateClosed:
+ close_device(device, XenbusStateClosed);
+ break;
+
+ default:
+ syslog(LOG_WARNING, "not handled frontend state %lu for device %u/%u",
+ new_state, device->domid, device->devid);
+ break;
+ }
+
+ device->frontend_state = new_state;
+}
+
+static void check_device(unsigned int domid, unsigned int devid)
+{
+ device *device;
+
+ device = find_device(domid, devid);
+ if ( !device )
+ {
+ device = new_device(domid, devid);
+ if ( !device )
+ return;
+ }
+
+ device->last_seen = now;
+}
+
+static void scan_backend(void)
+{
+ char **doms;
+ unsigned int n_doms, dom;
+ char **devices;
+ unsigned int n_devs, dev;
+ char dom_path[24];
+ unsigned long domid, devid;
+ char *end;
+ device *device, *tmp;
+
+ now++;
+
+ doms = xs_directory(xs, XBT_NULL, "backend/xen_9pfs", &n_doms);
+ if ( doms == NULL )
+ return;
+
+ for ( dom = 0; dom < n_doms; dom++ )
+ {
+ errno = 0;
+ domid = strtoul(doms[dom], &end, 10);
+ if ( errno || *end || domid >= DOMID_FIRST_RESERVED )
+ continue;
+
+ snprintf(dom_path, sizeof(dom_path), "backend/xen_9pfs/%lu", domid);
+ devices = xs_directory(xs, XBT_NULL, dom_path, &n_devs);
+
+ for ( dev = 0; dev < n_devs; dev++ )
+ {
+ errno = 0;
+ devid = strtoul(devices[dev], &end, 10);
+ if ( errno || *end || devid > UINT_MAX )
+ continue;
+
+ check_device(domid, devid);
+ }
+
+ free(devices);
+ }
+
+ free(doms);
+
+ XEN_TAILQ_FOREACH_SAFE( device, &devs, list, tmp )
+ {
+ if ( device->last_seen != now )
+ remove_device(device);
+ }
+}
+
+static void handle_watch(char *path, char *token)
+{
+ unsigned int domid, devid;
+ device *device;
+
+ if ( !strcmp(token, "main") )
+ {
+ scan_backend();
+ return;
+ }
+
+ if ( sscanf(token, "%u/%u", &domid, &devid) != 2 )
+ {
+ syslog(LOG_WARNING, "unknown watch event %s %s", path, token);
+ return;
+ }
+
+ device = find_device(domid, devid);
+ if ( !device )
+ {
+ syslog(LOG_WARNING, "watch event for unknown device %u/%u",
+ domid, devid);
+ return;
+ }
+
+ frontend_changed(device);
+}
+
static void close_all(void)
{
if ( daemon_running )
+ {
xs_rm(xs, XBT_NULL, "/tool/xenlog");
+ xs_unwatch(xs, "backend/xen_9pfs", "main");
+
+ remove_all_devices();
+ }
if ( xe )
xenevtchn_close(xe);
if ( xg )
@@ -68,6 +596,25 @@ static void do_err(const char *msg)
exit(1);
}
+static void handle_event(void)
+{
+ xenevtchn_port_or_error_t evtchn;
+ device *device;
+
+ evtchn = xenevtchn_pending(xe);
+ if ( evtchn < 0 )
+ do_err("xenevtchn_pending() failed");
+
+ XEN_TAILQ_FOREACH( device, &devs, list )
+ {
+ if ( device->evtchn == evtchn )
+ {
+ pthread_cond_signal(&device->cond);
+ break;
+ }
+ }
+}
+
static void xen_connect(void)
{
xs_transaction_t t;
@@ -122,6 +669,11 @@ int main(int argc, char *argv[])
int syslog_mask = LOG_MASK(LOG_WARNING) | LOG_MASK(LOG_ERR) |
LOG_MASK(LOG_CRIT) | LOG_MASK(LOG_ALERT) |
LOG_MASK(LOG_EMERG);
+ char **watch;
+ struct pollfd p[2] = {
+ { .events = POLLIN, .revents = POLLIN },
+ { .events = POLLIN }
+ };
umask(027);
if ( getenv("XENLOGD_VERBOSE") )
@@ -134,9 +686,26 @@ int main(int argc, char *argv[])
xen_connect();
+ if ( !xs_watch(xs, "backend/xen_9pfs", "main") )
+ do_err("xs_watch() in main thread failed");
+ p[0].fd = xs_fileno(xs);
+ p[1].fd = xenevtchn_fd(xe);
+
+ scan_backend();
+
while ( !stop_me )
{
- sleep(60);
+ while ( (p[0].revents & POLLIN) &&
+ (watch = xs_check_watch(xs)) != NULL )
+ {
+ handle_watch(watch[XS_WATCH_PATH], watch[XS_WATCH_TOKEN]);
+ free(watch);
+ }
+
+ if ( p[1].revents & POLLIN )
+ handle_event();
+
+ poll(p, 2, 10000);
}
close_all();
diff --git a/tools/xenlogd/xenlogd.h b/tools/xenlogd/xenlogd.h
new file mode 100644
index 0000000000..a8e9f9ca22
--- /dev/null
+++ b/tools/xenlogd/xenlogd.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef XENLOGD_H
+#define XENLOGD_H
+
+#include <pthread.h>
+#include <stdbool.h>
+#include <xenevtchn.h>
+#include <xen_list.h>
+#include <xen/xen.h>
+#include <xen/io/xenbus.h>
+#include <xen/io/9pfs.h>
+
+#define MAX_OPEN_FILES_DEFAULT 5
+
+typedef struct device device;
+struct device {
+ /* Admin data. */
+ XEN_TAILQ_ENTRY(device) list;
+ unsigned int last_seen; /* Set in scan_backend(). */
+ unsigned int domid;
+ unsigned int devid;
+ bool thread_active;
+ bool stop_thread;
+ pthread_t thread;
+ pthread_cond_t cond;
+ pthread_mutex_t mutex;
+
+ /* Tool side configuration data. */
+ char *host_path;
+ unsigned int max_space;
+ unsigned int max_files;
+ unsigned int max_open_files;
+ bool auto_delete;
+
+ /* Connection data. */
+ enum xenbus_state backend_state;
+ enum xenbus_state frontend_state;
+ evtchn_port_t evtchn;
+ struct xen_9pfs_data_intf *intf;
+ unsigned int ring_order;
+ RING_IDX ring_size;
+ struct xen_9pfs_data data;
+};
+
+extern xenevtchn_handle *xe;
+
+void *io_thread(void *arg);
+
+#endif /* XENLOGD_H */
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* Re: [PATCH 03/29] tools/xenlogd: connect to frontend
2023-11-01 9:32 ` [PATCH 03/29] tools/xenlogd: connect to frontend Juergen Gross
@ 2023-11-01 19:21 ` Jason Andryuk
2023-11-02 8:23 ` Juergen Gross
0 siblings, 1 reply; 81+ messages in thread
From: Jason Andryuk @ 2023-11-01 19:21 UTC (permalink / raw)
To: Juergen Gross; +Cc: xen-devel, Wei Liu, Anthony PERARD
On Wed, Nov 1, 2023 at 5:34 AM Juergen Gross <jgross@suse.com> wrote:
>
> Add the code for connecting to frontends to xenlogd.
>
> Signed-off-by: Juergen Gross <jgross@suse.com>
> diff --git a/tools/xenlogd/xenlogd.c b/tools/xenlogd/xenlogd.c
> index 792d1026a3..da0a09a122 100644
> --- a/tools/xenlogd/xenlogd.c
> +++ b/tools/xenlogd/xenlogd.c
> +static void connect_device(device *device)
> +{
> + unsigned int val;
> + xenevtchn_port_or_error_t evtchn;
1.> +
> + val = read_frontend_node_uint(device, "version", 0);
> + if ( val != 1 )
> + return connect_err(device, "frontend specifies illegal version");
> + val = read_frontend_node_uint(device, "num-rings", 0);
> + if ( val != 1 )
> + return connect_err(device, "frontend specifies illegal ring number");
Linux uses 2 rings (XEN_9PFS_NUM_RINGS), and it doesn't connect when
max-rings is less than that.
max_rings = xenbus_read_unsigned(dev->otherend, "max-rings", 0);
if (max_rings < XEN_9PFS_NUM_RINGS)
return -EINVAL;
new_device() writes max-rings as 1. So this works for mini-os, but
not Linux. I'm not requesting you to change it - just noting it.
> +
> + val = read_frontend_node_uint(device, "event-channel-0", 0);
> + if ( val == 0 )
> + return connect_err(device, "frontend specifies illegal evtchn");
> + evtchn = xenevtchn_bind_interdomain(xe, device->domid, val);
> + if ( evtchn < 0 )
> + return connect_err(device, "could not bind to event channel");
> + device->evtchn = evtchn;
> +
> + val = read_frontend_node_uint(device, "ring-ref0", 0);
> + if ( val == 0 )
> + return connect_err(device, "frontend specifies illegal grant for ring");
> + device->intf = xengnttab_map_grant_ref(xg, device->domid, val,
> + PROT_READ | PROT_WRITE);
> + if ( !device->intf )
> + return connect_err(device, "could not map interface page");
> + device->ring_order = device->intf->ring_order;
> + if ( device->ring_order > 9 || device->ring_order < 1 )
> + return connect_err(device, "frontend specifies illegal ring order");
> + device->ring_size = XEN_FLEX_RING_SIZE(device->ring_order);
> + device->data.in = xengnttab_map_domain_grant_refs(xg,
> + 1 << device->ring_order,
> + device->domid,
> + device->intf->ref,
> + PROT_READ | PROT_WRITE);
> + if ( !device->data.in )
> + return connect_err(device, "could not map ring pages");
> + device->data.out = device->data.in + device->ring_size;
> +
> + if ( pthread_create(&device->thread, NULL, io_thread, device) )
> + return connect_err(device, "could not start I/O thread");
> + device->thread_active = true;
> +
> + write_backend_state(device, XenbusStateConnected);
> +}
> +
> @@ -122,6 +669,11 @@ int main(int argc, char *argv[])
> int syslog_mask = LOG_MASK(LOG_WARNING) | LOG_MASK(LOG_ERR) |
> LOG_MASK(LOG_CRIT) | LOG_MASK(LOG_ALERT) |
> LOG_MASK(LOG_EMERG);
> + char **watch;
> + struct pollfd p[2] = {
> + { .events = POLLIN, .revents = POLLIN },
Are you intentionally setting revents to enter the loop initially?
Shouldn't the watch registration trigger it to fire anyway?
> + { .events = POLLIN }
> + };
>
> umask(027);
> if ( getenv("XENLOGD_VERBOSE") )
> @@ -134,9 +686,26 @@ int main(int argc, char *argv[])
>
> xen_connect();
>
> + if ( !xs_watch(xs, "backend/xen_9pfs", "main") )
> + do_err("xs_watch() in main thread failed");
> + p[0].fd = xs_fileno(xs);
> + p[1].fd = xenevtchn_fd(xe);
> +
> + scan_backend();
> +
> while ( !stop_me )
> {
> - sleep(60);
> + while ( (p[0].revents & POLLIN) &&
> + (watch = xs_check_watch(xs)) != NULL )
> + {
> + handle_watch(watch[XS_WATCH_PATH], watch[XS_WATCH_TOKEN]);
> + free(watch);
> + }
> +
> + if ( p[1].revents & POLLIN )
> + handle_event();
> +
> + poll(p, 2, 10000);
Can you just use an infinite timeout and rely on the signal
interrupting the system call?
Regards,
Jason
^ permalink raw reply [flat|nested] 81+ messages in thread* Re: [PATCH 03/29] tools/xenlogd: connect to frontend
2023-11-01 19:21 ` Jason Andryuk
@ 2023-11-02 8:23 ` Juergen Gross
2023-11-03 1:42 ` Jason Andryuk
0 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-02 8:23 UTC (permalink / raw)
To: Jason Andryuk; +Cc: xen-devel, Wei Liu, Anthony PERARD
[-- Attachment #1.1.1: Type: text/plain, Size: 4921 bytes --]
On 01.11.23 20:21, Jason Andryuk wrote:
> On Wed, Nov 1, 2023 at 5:34 AM Juergen Gross <jgross@suse.com> wrote:
>>
>> Add the code for connecting to frontends to xenlogd.
>>
>> Signed-off-by: Juergen Gross <jgross@suse.com>
>
>> diff --git a/tools/xenlogd/xenlogd.c b/tools/xenlogd/xenlogd.c
>> index 792d1026a3..da0a09a122 100644
>> --- a/tools/xenlogd/xenlogd.c
>> +++ b/tools/xenlogd/xenlogd.c
>
>> +static void connect_device(device *device)
>> +{
>> + unsigned int val;
>> + xenevtchn_port_or_error_t evtchn;
> 1.> +
>> + val = read_frontend_node_uint(device, "version", 0);
>> + if ( val != 1 )
>> + return connect_err(device, "frontend specifies illegal version");
>> + val = read_frontend_node_uint(device, "num-rings", 0);
>> + if ( val != 1 )
>> + return connect_err(device, "frontend specifies illegal ring number");
>
> Linux uses 2 rings (XEN_9PFS_NUM_RINGS), and it doesn't connect when
> max-rings is less than that.
>
> max_rings = xenbus_read_unsigned(dev->otherend, "max-rings", 0);
> if (max_rings < XEN_9PFS_NUM_RINGS)
> return -EINVAL;
>
> new_device() writes max-rings as 1. So this works for mini-os, but
> not Linux. I'm not requesting you to change it - just noting it.
Thanks for the note. I'll change it to allow more rings.
>
>> +
>> + val = read_frontend_node_uint(device, "event-channel-0", 0);
>> + if ( val == 0 )
>> + return connect_err(device, "frontend specifies illegal evtchn");
>> + evtchn = xenevtchn_bind_interdomain(xe, device->domid, val);
>> + if ( evtchn < 0 )
>> + return connect_err(device, "could not bind to event channel");
>> + device->evtchn = evtchn;
>> +
>> + val = read_frontend_node_uint(device, "ring-ref0", 0);
>> + if ( val == 0 )
>> + return connect_err(device, "frontend specifies illegal grant for ring");
>> + device->intf = xengnttab_map_grant_ref(xg, device->domid, val,
>> + PROT_READ | PROT_WRITE);
>> + if ( !device->intf )
>> + return connect_err(device, "could not map interface page");
>> + device->ring_order = device->intf->ring_order;
>> + if ( device->ring_order > 9 || device->ring_order < 1 )
>> + return connect_err(device, "frontend specifies illegal ring order");
>> + device->ring_size = XEN_FLEX_RING_SIZE(device->ring_order);
>> + device->data.in = xengnttab_map_domain_grant_refs(xg,
>> + 1 << device->ring_order,
>> + device->domid,
>> + device->intf->ref,
>> + PROT_READ | PROT_WRITE);
>> + if ( !device->data.in )
>> + return connect_err(device, "could not map ring pages");
>> + device->data.out = device->data.in + device->ring_size;
>> +
>> + if ( pthread_create(&device->thread, NULL, io_thread, device) )
>> + return connect_err(device, "could not start I/O thread");
>> + device->thread_active = true;
>> +
>> + write_backend_state(device, XenbusStateConnected);
>> +}
>> +
>
>> @@ -122,6 +669,11 @@ int main(int argc, char *argv[])
>> int syslog_mask = LOG_MASK(LOG_WARNING) | LOG_MASK(LOG_ERR) |
>> LOG_MASK(LOG_CRIT) | LOG_MASK(LOG_ALERT) |
>> LOG_MASK(LOG_EMERG);
>> + char **watch;
>> + struct pollfd p[2] = {
>> + { .events = POLLIN, .revents = POLLIN },
>
> Are you intentionally setting revents to enter the loop initially?
> Shouldn't the watch registration trigger it to fire anyway?
I don't remember where I got this from. Probably I really wanted to use
the first loop iteration already for processing the first response.
I think I can drop setting revents.
>
>> + { .events = POLLIN }
>> + };
>>
>> umask(027);
>> if ( getenv("XENLOGD_VERBOSE") )
>> @@ -134,9 +686,26 @@ int main(int argc, char *argv[])
>>
>> xen_connect();
>>
>> + if ( !xs_watch(xs, "backend/xen_9pfs", "main") )
>> + do_err("xs_watch() in main thread failed");
>> + p[0].fd = xs_fileno(xs);
>> + p[1].fd = xenevtchn_fd(xe);
>> +
>> + scan_backend();
>> +
>> while ( !stop_me )
>> {
>> - sleep(60);
>> + while ( (p[0].revents & POLLIN) &&
>> + (watch = xs_check_watch(xs)) != NULL )
>> + {
>> + handle_watch(watch[XS_WATCH_PATH], watch[XS_WATCH_TOKEN]);
>> + free(watch);
>> + }
>> +
>> + if ( p[1].revents & POLLIN )
>> + handle_event();
>> +
>> + poll(p, 2, 10000);
>
> Can you just use an infinite timeout and rely on the signal
> interrupting the system call?
Yes, probably.
Juergen
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3149 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]
^ permalink raw reply [flat|nested] 81+ messages in thread* Re: [PATCH 03/29] tools/xenlogd: connect to frontend
2023-11-02 8:23 ` Juergen Gross
@ 2023-11-03 1:42 ` Jason Andryuk
2023-11-03 7:37 ` Juergen Gross
0 siblings, 1 reply; 81+ messages in thread
From: Jason Andryuk @ 2023-11-03 1:42 UTC (permalink / raw)
To: Juergen Gross; +Cc: xen-devel, Wei Liu, Anthony PERARD
On Thu, Nov 2, 2023 at 4:23 AM Juergen Gross <jgross@suse.com> wrote:
>
> On 01.11.23 20:21, Jason Andryuk wrote:
> > On Wed, Nov 1, 2023 at 5:34 AM Juergen Gross <jgross@suse.com> wrote:
> >>
> >> Add the code for connecting to frontends to xenlogd.
> >>
> >> Signed-off-by: Juergen Gross <jgross@suse.com>
> >
> >> diff --git a/tools/xenlogd/xenlogd.c b/tools/xenlogd/xenlogd.c
> >> index 792d1026a3..da0a09a122 100644
> >> --- a/tools/xenlogd/xenlogd.c
> >> +++ b/tools/xenlogd/xenlogd.c
> >
> >> +static void connect_device(device *device)
> >> +{
> >> + unsigned int val;
> >> + xenevtchn_port_or_error_t evtchn;
> > 1.> +
> >> + val = read_frontend_node_uint(device, "version", 0);
> >> + if ( val != 1 )
> >> + return connect_err(device, "frontend specifies illegal version");
> >> + val = read_frontend_node_uint(device, "num-rings", 0);
> >> + if ( val != 1 )
> >> + return connect_err(device, "frontend specifies illegal ring number");
> >
> > Linux uses 2 rings (XEN_9PFS_NUM_RINGS), and it doesn't connect when
> > max-rings is less than that.
> >
> > max_rings = xenbus_read_unsigned(dev->otherend, "max-rings", 0);
> > if (max_rings < XEN_9PFS_NUM_RINGS)
> > return -EINVAL;
> >
> > new_device() writes max-rings as 1. So this works for mini-os, but
> > not Linux. I'm not requesting you to change it - just noting it.
>
> Thanks for the note. I'll change it to allow more rings.
I'm happy to work on Linux compatibility as a follow up, if you just
want to focus on your Mini-OS use case.
Regards,
Jason
^ permalink raw reply [flat|nested] 81+ messages in thread* Re: [PATCH 03/29] tools/xenlogd: connect to frontend
2023-11-03 1:42 ` Jason Andryuk
@ 2023-11-03 7:37 ` Juergen Gross
0 siblings, 0 replies; 81+ messages in thread
From: Juergen Gross @ 2023-11-03 7:37 UTC (permalink / raw)
To: Jason Andryuk; +Cc: xen-devel, Wei Liu, Anthony PERARD
[-- Attachment #1.1.1: Type: text/plain, Size: 1720 bytes --]
On 03.11.23 02:42, Jason Andryuk wrote:
> On Thu, Nov 2, 2023 at 4:23 AM Juergen Gross <jgross@suse.com> wrote:
>>
>> On 01.11.23 20:21, Jason Andryuk wrote:
>>> On Wed, Nov 1, 2023 at 5:34 AM Juergen Gross <jgross@suse.com> wrote:
>>>>
>>>> Add the code for connecting to frontends to xenlogd.
>>>>
>>>> Signed-off-by: Juergen Gross <jgross@suse.com>
>>>
>>>> diff --git a/tools/xenlogd/xenlogd.c b/tools/xenlogd/xenlogd.c
>>>> index 792d1026a3..da0a09a122 100644
>>>> --- a/tools/xenlogd/xenlogd.c
>>>> +++ b/tools/xenlogd/xenlogd.c
>>>
>>>> +static void connect_device(device *device)
>>>> +{
>>>> + unsigned int val;
>>>> + xenevtchn_port_or_error_t evtchn;
>>> 1.> +
>>>> + val = read_frontend_node_uint(device, "version", 0);
>>>> + if ( val != 1 )
>>>> + return connect_err(device, "frontend specifies illegal version");
>>>> + val = read_frontend_node_uint(device, "num-rings", 0);
>>>> + if ( val != 1 )
>>>> + return connect_err(device, "frontend specifies illegal ring number");
>>>
>>> Linux uses 2 rings (XEN_9PFS_NUM_RINGS), and it doesn't connect when
>>> max-rings is less than that.
>>>
>>> max_rings = xenbus_read_unsigned(dev->otherend, "max-rings", 0);
>>> if (max_rings < XEN_9PFS_NUM_RINGS)
>>> return -EINVAL;
>>>
>>> new_device() writes max-rings as 1. So this works for mini-os, but
>>> not Linux. I'm not requesting you to change it - just noting it.
>>
>> Thanks for the note. I'll change it to allow more rings.
>
> I'm happy to work on Linux compatibility as a follow up, if you just
> want to focus on your Mini-OS use case.
Thanks, but I think this should be part of the initial series.
Juergen
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3149 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]
^ permalink raw reply [flat|nested] 81+ messages in thread
* [PATCH 04/29] tools/xenlogd: add transport layer
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
` (2 preceding siblings ...)
2023-11-01 9:32 ` [PATCH 03/29] tools/xenlogd: connect to frontend Juergen Gross
@ 2023-11-01 9:33 ` Juergen Gross
2023-11-02 18:30 ` Jason Andryuk
2023-11-01 9:33 ` [PATCH 05/29] tools/xenlogd: add 9pfs response generation support Juergen Gross
` (24 subsequent siblings)
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:33 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Anthony PERARD
Add the transport layer of 9pfs. This is basically the infrastructure
to receive requests from the frontend and to send the related answers
via the rings.
In order to avoid unaligned accesses e.g. on Arm, add the definition of
__packed to the common-macros.h header.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/include/xen-tools/common-macros.h | 4 +
tools/xenlogd/io.c | 142 +++++++++++++++++++++++-
tools/xenlogd/xenlogd.h | 16 +++
3 files changed, 160 insertions(+), 2 deletions(-)
diff --git a/tools/include/xen-tools/common-macros.h b/tools/include/xen-tools/common-macros.h
index e5ed603904..c3fd7d2a30 100644
--- a/tools/include/xen-tools/common-macros.h
+++ b/tools/include/xen-tools/common-macros.h
@@ -79,6 +79,10 @@
#define __must_check __attribute__((__warn_unused_result__))
#endif
+#ifndef __packed
+#define __packed __attribute__((__packed__))
+#endif
+
#define container_of(ptr, type, member) ({ \
typeof(((type *)0)->member) *mptr__ = (ptr); \
(type *)((char *)mptr__ - offsetof(type, member)); \
diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
index ef0954d69d..590d06e906 100644
--- a/tools/xenlogd/io.c
+++ b/tools/xenlogd/io.c
@@ -6,24 +6,115 @@
* Copyright (C) 2023 Juergen Gross <jgross@suse.com>
*
* I/O thread handling.
+ *
+ * Only handle one request at a time, pushing out the complete response
+ * before looking for the next request.
*/
#include <stdbool.h>
+#include <stdlib.h>
#include <string.h>
#include <syslog.h>
+#include <xenctrl.h> /* For cpu barriers. */
+#include <xen-tools/common-macros.h>
#include "xenlogd.h"
+/*
+ * Note that the ring names "in" and "out" are from the frontend's
+ * perspective, so the "in" ring will be used for responses to the frontend,
+ * while the "out" ring is used for requests from the frontend to the
+ * backend.
+ */
+static unsigned int ring_in_free(device *device)
+{
+ unsigned int queued;
+
+ queued = xen_9pfs_queued(device->prod_pvt_in, device->intf->in_cons,
+ device->ring_size);
+ xen_rmb();
+
+ return device->ring_size - queued;
+}
+
+static unsigned int ring_out_data(device *device)
+{
+ unsigned int queued;
+
+ queued = xen_9pfs_queued(device->intf->out_prod, device->cons_pvt_out,
+ device->ring_size);
+ xen_rmb();
+
+ return queued;
+}
+
+static unsigned int get_request_bytes(device *device, unsigned int off,
+ unsigned int len)
+{
+ unsigned int size;
+ unsigned int out_data = ring_out_data(device);
+ RING_IDX prod, cons;
+
+ size = min(len - off, out_data);
+ prod = xen_9pfs_mask(device->intf->out_prod, device->ring_size);
+ cons = xen_9pfs_mask(device->cons_pvt_out, device->ring_size);
+ xen_9pfs_read_packet(device->buffer + off, device->data.out, size,
+ prod, &cons, device->ring_size);
+
+ xen_rmb(); /* Read data out before setting visible consumer. */
+ device->cons_pvt_out += size;
+ device->intf->out_cons = device->cons_pvt_out;
+
+ /* Signal that more space is available now. */
+ xenevtchn_notify(xe, device->evtchn);
+
+ return size;
+}
+
+static unsigned int put_request_bytes(device *device, unsigned int off,
+ unsigned int len)
+{
+ unsigned int size;
+ unsigned int in_data = ring_in_free(device);
+ RING_IDX prod, cons;
+
+ size = min(len - off, in_data);
+ prod = xen_9pfs_mask(device->prod_pvt_in, device->ring_size);
+ cons = xen_9pfs_mask(device->intf->in_cons, device->ring_size);
+ xen_9pfs_write_packet(device->data.in, device->buffer + off, size,
+ &prod, cons, device->ring_size);
+
+ xen_wmb(); /* Write data out before setting visible producer. */
+ device->prod_pvt_in += size;
+ device->intf->in_prod = device->prod_pvt_in;
+
+ return size;
+}
+
static bool io_work_pending(device *device)
{
if ( device->stop_thread )
return true;
- return false;
+ if ( device->error )
+ return false;
+ return device->handle_response ? ring_in_free(device)
+ : ring_out_data(device);
}
void *io_thread(void *arg)
{
device *device = arg;
+ unsigned int count = 0;
+ struct p9_header hdr;
+ bool in_hdr = true;
+
+ device->max_size = device->ring_size;
+ device->buffer = malloc(device->max_size);
+ if ( !device->buffer )
+ {
+ syslog(LOG_CRIT, "memory allocation failure!");
+ return NULL;
+ }
while ( !device->stop_thread )
{
@@ -36,9 +127,56 @@ void *io_thread(void *arg)
}
pthread_mutex_unlock(&device->mutex);
- /* TODO: I/O handling. */
+ if ( device->stop_thread || device->error )
+ continue;
+
+ if ( !device->handle_response )
+ {
+ if ( in_hdr )
+ {
+ count += get_request_bytes(device, count, sizeof(hdr));
+ if ( count != sizeof(hdr) )
+ continue;
+ hdr = *(struct p9_header *)device->buffer;
+ if ( hdr.size > device->max_size || hdr.size < sizeof(hdr) )
+ {
+ syslog(LOG_ERR, "%u.%u specified illegal request length %u",
+ device->domid, device->devid, hdr.size);
+ device->error = true;
+ continue;
+ }
+ in_hdr = false;
+ }
+
+ count += get_request_bytes(device, count, hdr.size);
+ if ( count < hdr.size )
+ continue;
+
+ /* TODO: handle request. */
+
+ device->handle_response = true;
+ hdr.size = ((struct p9_header *)device->buffer)->size;
+ count = 0;
+ }
+
+ if ( device->handle_response )
+ {
+ count += put_request_bytes(device, count, hdr.size);
+
+ if ( count == hdr.size )
+ {
+ /* Signal presence of response. */
+ xenevtchn_notify(xe, device->evtchn);
+
+ device->handle_response = false;
+ in_hdr = true;
+ count = 0;
+ }
+ }
}
+ free(device->buffer);
+
device->thread_active = false;
return NULL;
diff --git a/tools/xenlogd/xenlogd.h b/tools/xenlogd/xenlogd.h
index a8e9f9ca22..40aa7cd03a 100644
--- a/tools/xenlogd/xenlogd.h
+++ b/tools/xenlogd/xenlogd.h
@@ -13,6 +13,12 @@
#define MAX_OPEN_FILES_DEFAULT 5
+struct p9_header {
+ uint32_t size;
+ uint8_t cmd;
+ uint16_t tag;
+} __attribute__((packed));
+
typedef struct device device;
struct device {
/* Admin data. */
@@ -40,7 +46,17 @@ struct device {
struct xen_9pfs_data_intf *intf;
unsigned int ring_order;
RING_IDX ring_size;
+
+ /* Transport layer data. */
struct xen_9pfs_data data;
+ RING_IDX prod_pvt_in;
+ RING_IDX cons_pvt_out;
+
+ /* Request and response handling. */
+ uint32_t max_size;
+ bool error; /* Protocol error - stop processing. */
+ bool handle_response; /* Main loop now handling response. */
+ void *buffer; /* Request/response buffer. */
};
extern xenevtchn_handle *xe;
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* Re: [PATCH 04/29] tools/xenlogd: add transport layer
2023-11-01 9:33 ` [PATCH 04/29] tools/xenlogd: add transport layer Juergen Gross
@ 2023-11-02 18:30 ` Jason Andryuk
2023-11-03 7:50 ` Juergen Gross
0 siblings, 1 reply; 81+ messages in thread
From: Jason Andryuk @ 2023-11-02 18:30 UTC (permalink / raw)
To: Juergen Gross; +Cc: xen-devel, Wei Liu, Anthony PERARD
On Wed, Nov 1, 2023 at 5:34 AM Juergen Gross <jgross@suse.com> wrote:
>
> Add the transport layer of 9pfs. This is basically the infrastructure
> to receive requests from the frontend and to send the related answers
> via the rings.
>
> In order to avoid unaligned accesses e.g. on Arm, add the definition of
> __packed to the common-macros.h header.
>
> Signed-off-by: Juergen Gross <jgross@suse.com>
> ---
> diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
> index ef0954d69d..590d06e906 100644
> --- a/tools/xenlogd/io.c
> +++ b/tools/xenlogd/io.c
> +static unsigned int get_request_bytes(device *device, unsigned int off,
> + unsigned int len)
> +{
> + unsigned int size;
> + unsigned int out_data = ring_out_data(device);
> + RING_IDX prod, cons;
> +
> + size = min(len - off, out_data);
> + prod = xen_9pfs_mask(device->intf->out_prod, device->ring_size);
> + cons = xen_9pfs_mask(device->cons_pvt_out, device->ring_size);
> + xen_9pfs_read_packet(device->buffer + off, device->data.out, size,
> + prod, &cons, device->ring_size);
> +
> + xen_rmb(); /* Read data out before setting visible consumer. */
> + device->cons_pvt_out += size;
> + device->intf->out_cons = device->cons_pvt_out;
> +
> + /* Signal that more space is available now. */
> + xenevtchn_notify(xe, device->evtchn);
> +
> + return size;
> +}
> +
> +static unsigned int put_request_bytes(device *device, unsigned int off,
> + unsigned int len)
Should this be named put_response_bytes?
> +{
> + unsigned int size;
> + unsigned int in_data = ring_in_free(device);
> + RING_IDX prod, cons;
> +
> + size = min(len - off, in_data);
IIUC, len is the total length of the outgoing data. Maybe total_len
would be a better name? I at least read len as just a length for a
particular call. Same comment applies to get_request_bytes() if you
want to follow it.
> + prod = xen_9pfs_mask(device->prod_pvt_in, device->ring_size);
> + cons = xen_9pfs_mask(device->intf->in_cons, device->ring_size);
> + xen_9pfs_write_packet(device->data.in, device->buffer + off, size,
> + &prod, cons, device->ring_size);
> +
> + xen_wmb(); /* Write data out before setting visible producer. */
> + device->prod_pvt_in += size;
> + device->intf->in_prod = device->prod_pvt_in;
> +
> + return size;
> +}
> +
> static bool io_work_pending(device *device)
> {
> if ( device->stop_thread )
> return true;
> - return false;
> + if ( device->error )
> + return false;
> + return device->handle_response ? ring_in_free(device)
> + : ring_out_data(device);
> }
>
> void *io_thread(void *arg)
> {
> device *device = arg;
> + unsigned int count = 0;
> + struct p9_header hdr;
> + bool in_hdr = true;
> +
> + device->max_size = device->ring_size;
> + device->buffer = malloc(device->max_size);
> + if ( !device->buffer )
> + {
> + syslog(LOG_CRIT, "memory allocation failure!");
> + return NULL;
> + }
>
> while ( !device->stop_thread )
> {
> @@ -36,9 +127,56 @@ void *io_thread(void *arg)
> }
> pthread_mutex_unlock(&device->mutex);
>
> - /* TODO: I/O handling. */
> + if ( device->stop_thread || device->error )
> + continue;
> +
> + if ( !device->handle_response )
> + {
> + if ( in_hdr )
> + {
> + count += get_request_bytes(device, count, sizeof(hdr));
> + if ( count != sizeof(hdr) )
> + continue;
> + hdr = *(struct p9_header *)device->buffer;
> + if ( hdr.size > device->max_size || hdr.size < sizeof(hdr) )
> + {
> + syslog(LOG_ERR, "%u.%u specified illegal request length %u",
> + device->domid, device->devid, hdr.size);
> + device->error = true;
When device->error is set, io_thread stops processing requests, but do
we want to also tear down this backend? The event channel at least is
left in place and unmasked.
> + continue;
> + }
> + in_hdr = false;
> + }
> +
> + count += get_request_bytes(device, count, hdr.size);
> + if ( count < hdr.size )
> + continue;
> +
> + /* TODO: handle request. */
> +
> + device->handle_response = true;
> + hdr.size = ((struct p9_header *)device->buffer)->size;
hdr.size is set during the struct copy above, so this isn't needed?
Thanks,
Jason
^ permalink raw reply [flat|nested] 81+ messages in thread* Re: [PATCH 04/29] tools/xenlogd: add transport layer
2023-11-02 18:30 ` Jason Andryuk
@ 2023-11-03 7:50 ` Juergen Gross
0 siblings, 0 replies; 81+ messages in thread
From: Juergen Gross @ 2023-11-03 7:50 UTC (permalink / raw)
To: Jason Andryuk; +Cc: xen-devel, Wei Liu, Anthony PERARD
[-- Attachment #1.1.1: Type: text/plain, Size: 5342 bytes --]
On 02.11.23 19:30, Jason Andryuk wrote:
> On Wed, Nov 1, 2023 at 5:34 AM Juergen Gross <jgross@suse.com> wrote:
>>
>> Add the transport layer of 9pfs. This is basically the infrastructure
>> to receive requests from the frontend and to send the related answers
>> via the rings.
>>
>> In order to avoid unaligned accesses e.g. on Arm, add the definition of
>> __packed to the common-macros.h header.
>>
>> Signed-off-by: Juergen Gross <jgross@suse.com>
>> ---
>
>> diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
>> index ef0954d69d..590d06e906 100644
>> --- a/tools/xenlogd/io.c
>> +++ b/tools/xenlogd/io.c
>
>> +static unsigned int get_request_bytes(device *device, unsigned int off,
>> + unsigned int len)
>> +{
>> + unsigned int size;
>> + unsigned int out_data = ring_out_data(device);
>> + RING_IDX prod, cons;
>> +
>> + size = min(len - off, out_data);
>> + prod = xen_9pfs_mask(device->intf->out_prod, device->ring_size);
>> + cons = xen_9pfs_mask(device->cons_pvt_out, device->ring_size);
>> + xen_9pfs_read_packet(device->buffer + off, device->data.out, size,
>> + prod, &cons, device->ring_size);
>> +
>> + xen_rmb(); /* Read data out before setting visible consumer. */
>> + device->cons_pvt_out += size;
>> + device->intf->out_cons = device->cons_pvt_out;
>> +
>> + /* Signal that more space is available now. */
>> + xenevtchn_notify(xe, device->evtchn);
>> +
>> + return size;
>> +}
>> +
>> +static unsigned int put_request_bytes(device *device, unsigned int off,
>> + unsigned int len)
>
> Should this be named put_response_bytes?
Yes.
>
>> +{
>> + unsigned int size;
>> + unsigned int in_data = ring_in_free(device);
>> + RING_IDX prod, cons;
>> +
>> + size = min(len - off, in_data);
>
> IIUC, len is the total length of the outgoing data. Maybe total_len
> would be a better name? I at least read len as just a length for a
> particular call. Same comment applies to get_request_bytes() if you
> want to follow it.
Fine with me.
>
>> + prod = xen_9pfs_mask(device->prod_pvt_in, device->ring_size);
>> + cons = xen_9pfs_mask(device->intf->in_cons, device->ring_size);
>> + xen_9pfs_write_packet(device->data.in, device->buffer + off, size,
>> + &prod, cons, device->ring_size);
>> +
>> + xen_wmb(); /* Write data out before setting visible producer. */
>> + device->prod_pvt_in += size;
>> + device->intf->in_prod = device->prod_pvt_in;
>> +
>> + return size;
>> +}
>> +
>> static bool io_work_pending(device *device)
>> {
>> if ( device->stop_thread )
>> return true;
>> - return false;
>> + if ( device->error )
>> + return false;
>> + return device->handle_response ? ring_in_free(device)
>> + : ring_out_data(device);
>> }
>>
>> void *io_thread(void *arg)
>> {
>> device *device = arg;
>> + unsigned int count = 0;
>> + struct p9_header hdr;
>> + bool in_hdr = true;
>> +
>> + device->max_size = device->ring_size;
>> + device->buffer = malloc(device->max_size);
>> + if ( !device->buffer )
>> + {
>> + syslog(LOG_CRIT, "memory allocation failure!");
>> + return NULL;
>> + }
>>
>> while ( !device->stop_thread )
>> {
>> @@ -36,9 +127,56 @@ void *io_thread(void *arg)
>> }
>> pthread_mutex_unlock(&device->mutex);
>>
>> - /* TODO: I/O handling. */
>> + if ( device->stop_thread || device->error )
>> + continue;
>> +
>> + if ( !device->handle_response )
>> + {
>> + if ( in_hdr )
>> + {
>> + count += get_request_bytes(device, count, sizeof(hdr));
>> + if ( count != sizeof(hdr) )
>> + continue;
>> + hdr = *(struct p9_header *)device->buffer;
>> + if ( hdr.size > device->max_size || hdr.size < sizeof(hdr) )
>> + {
>> + syslog(LOG_ERR, "%u.%u specified illegal request length %u",
>> + device->domid, device->devid, hdr.size);
>> + device->error = true;
>
> When device->error is set, io_thread stops processing requests, but do
> we want to also tear down this backend? The event channel at least is
> left in place and unmasked.
I think tearing down the backend shouldn't be done, but you are right that
the event channel should be kept masked.
>
>> + continue;
>> + }
>> + in_hdr = false;
>> + }
>> +
>> + count += get_request_bytes(device, count, hdr.size);
>> + if ( count < hdr.size )
>> + continue;
>> +
>> + /* TODO: handle request. */
>> +
>> + device->handle_response = true;
>> + hdr.size = ((struct p9_header *)device->buffer)->size;
>
> hdr.size is set during the struct copy above, so this isn't needed?
It will be needed later when the "TODO" is filled in, as it will then be the
response size.
Juergen
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3149 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]
^ permalink raw reply [flat|nested] 81+ messages in thread
* [PATCH 05/29] tools/xenlogd: add 9pfs response generation support
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
` (3 preceding siblings ...)
2023-11-01 9:33 ` [PATCH 04/29] tools/xenlogd: add transport layer Juergen Gross
@ 2023-11-01 9:33 ` Juergen Gross
2023-11-02 18:48 ` Jason Andryuk
2023-11-01 9:33 ` [PATCH 06/29] tools/xenlogd: add 9pfs version request support Juergen Gross
` (23 subsequent siblings)
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:33 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Anthony PERARD
Add support for generation a 9pfs protocol response via a format based
approach.
Strings are stored in a per device string buffer and they are
referenced via their offset in this buffer. This allows to avoid
having to dynamically allocate memory for each single string.
As a first user of the response handling add a generic p9_error()
function which will be used to return any error to the client.
Add all format parsing variants in order to avoid additional code churn
later when adding the users of those variants. Prepare a special case
for the "read" case already (format character 'D'): in order to avoid
adding another buffer for read data support doing the read I/O directly
into the response buffer.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/xenlogd/io.c | 189 +++++++++++++++++++++++++++++++++++++++-
tools/xenlogd/xenlogd.h | 3 +
2 files changed, 191 insertions(+), 1 deletion(-)
diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
index 590d06e906..5a06f72338 100644
--- a/tools/xenlogd/io.c
+++ b/tools/xenlogd/io.c
@@ -11,6 +11,7 @@
* before looking for the next request.
*/
+#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
@@ -20,6 +21,16 @@
#include "xenlogd.h"
+/* P9 protocol commands (response is either cmd+1 or P9_CMD_ERROR). */
+#define P9_CMD_ERROR 107
+
+struct p9_qid {
+ uint8_t type;
+#define QID_TYPE_DIR 0x80
+ uint32_t version;
+ uint64_t path;
+};
+
/*
* Note that the ring names "in" and "out" are from the frontend's
* perspective, so the "in" ring will be used for responses to the frontend,
@@ -101,6 +112,172 @@ static bool io_work_pending(device *device)
: ring_out_data(device);
}
+static void fmt_err(const char *fmt)
+{
+ syslog(LOG_CRIT, "illegal format %s passed to fill_buffer()", fmt);
+ exit(1);
+}
+
+/*
+ * Fill buffer with response data.
+ * fmt is a sequence of format characters. Supported characters are:
+ * a: an array (2 bytes number of elements + the following format as elements)
+ * The number of elements is passed in the first unsigned int parameter, the
+ * next parameter is a pointer to an array of elements as denoted by the next
+ * format character.
+ * b: 2 byte unsigned integer
+ * The parameter is a pointer to a uint16_t value
+ * D: Data blob (4 byte length + <length> bytes)
+ * 2 parameters are consumed, first an unsigned int for the length, then a
+ * pointer to the first uint8_t value.
+ * No array support.
+ * L: 8 byte unsigned integer
+ * The parameter is a pointer to a uint64_t value
+ * Q: Qid (struct p9_qid)
+ * S: String (2 byte length + <length> characters)
+ * The length is obtained via strlen() of the parameter, being a pointer
+ * to the first character of the string
+ * U: 4 byte unsigned integer
+ * The parameter is a pointer to a uint32_t value
+ */
+static void fill_buffer(device *device, uint8_t cmd, uint16_t tag,
+ const char *fmt, ...)
+{
+ struct p9_header *hdr = device->buffer;
+ void *data = hdr + 1;
+ const char *f;
+ const void *par;
+ const char *str_val;
+ const struct p9_qid *qid;
+ unsigned int len;
+ va_list ap;
+ unsigned int array_sz = 0;
+ unsigned int elem_sz = 0;
+
+ hdr->cmd = cmd;
+ hdr->tag = tag;
+
+ va_start(ap, fmt);
+
+ for ( f = fmt; *f; f++ )
+ {
+ if ( !array_sz )
+ par = va_arg(ap, const void *);
+ else
+ {
+ par += elem_sz;
+ array_sz--;
+ }
+
+ switch ( *f )
+ {
+ case 'a':
+ f++;
+ if ( !*f || array_sz )
+ fmt_err(fmt);
+ array_sz = *(const unsigned int *)par;
+ *(__packed uint16_t *)data = array_sz;
+ data += sizeof(uint16_t);
+ par = va_arg(ap, const void *);
+ elem_sz = 0;
+ break;
+
+ case 'u':
+ *(__packed uint16_t *)data = *(const uint16_t *)par;
+ elem_sz = sizeof(uint16_t);
+ data += sizeof(uint16_t);
+ break;
+
+ case 'D':
+ if ( array_sz )
+ fmt_err(fmt);
+ len = *(const unsigned int *)par;
+ *(__packed uint32_t *)data = len;
+ data += sizeof(uint32_t);
+ par = va_arg(ap, const void *);
+ if ( data != par )
+ memcpy(data, par, len);
+ data += len;
+ break;
+
+ case 'L':
+ *(__packed uint64_t *)data = *(const uint64_t *)par;
+ elem_sz = sizeof(uint64_t);
+ data += sizeof(uint64_t);
+ break;
+
+ case 'Q':
+ qid = par;
+ elem_sz = sizeof(*qid);
+ *(uint8_t *)data = qid->type;
+ data += sizeof(uint8_t);
+ *(__packed uint32_t *)data = qid->version;
+ data += sizeof(uint32_t);
+ *(__packed uint64_t *)data = qid->path;
+ data += sizeof(uint64_t);
+ break;
+
+ case 'S':
+ str_val = par;
+ elem_sz = sizeof(str_val);
+ len = strlen(str_val);
+ *(__packed uint16_t *)data = len;
+ data += sizeof(uint16_t);
+ memcpy(data, str_val, len);
+ data += len;
+ break;
+
+ case 'U':
+ *(__packed uint32_t *)data = *(const uint32_t *)par;
+ elem_sz = sizeof(uint32_t);
+ data += sizeof(uint32_t);
+ break;
+
+ default:
+ fmt_err(fmt);
+ }
+
+ if ( array_sz )
+ f--;
+ }
+
+ hdr->size = data - device->buffer;
+}
+
+static unsigned int add_string(device *device, const char *str,
+ unsigned int len)
+{
+ char *tmp;
+ unsigned int ret;
+
+ if ( device->str_used + len + 1 > device->str_size )
+ {
+ tmp = realloc(device->str, device->str_used + len + 1);
+ if ( !tmp )
+ return ~0;
+ device->str = tmp;
+ device->str_size = device->str_used + len + 1;
+ }
+
+ ret = device->str_used;
+ memcpy(device->str + ret, str, len);
+ device->str_used += len;
+ device->str[device->str_used++] = 0;
+
+ return ret;
+}
+
+static void p9_error(device *device, uint16_t tag, uint32_t err)
+{
+ unsigned int erroff;
+
+ strerror_r(err, device->buffer, device->ring_size);
+ erroff = add_string(device, device->buffer, strlen(device->buffer));
+ fill_buffer(device, P9_CMD_ERROR, tag, "SU",
+ erroff != ~0 ? device->str + erroff : "cannot allocate memory",
+ &err);
+}
+
void *io_thread(void *arg)
{
device *device = arg;
@@ -152,7 +329,16 @@ void *io_thread(void *arg)
if ( count < hdr.size )
continue;
- /* TODO: handle request. */
+ device->str_used = 0;
+
+ switch ( hdr.cmd )
+ {
+ default:
+ syslog(LOG_DEBUG, "%u.%u sent unhandled command %u\n",
+ device->domid, device->devid, hdr.cmd);
+ p9_error(device, hdr.tag, EOPNOTSUPP);
+ break;
+ }
device->handle_response = true;
hdr.size = ((struct p9_header *)device->buffer)->size;
@@ -175,6 +361,7 @@ void *io_thread(void *arg)
}
}
+ free(device->str);
free(device->buffer);
device->thread_active = false;
diff --git a/tools/xenlogd/xenlogd.h b/tools/xenlogd/xenlogd.h
index 40aa7cd03a..c10c6aa9e5 100644
--- a/tools/xenlogd/xenlogd.h
+++ b/tools/xenlogd/xenlogd.h
@@ -57,6 +57,9 @@ struct device {
bool error; /* Protocol error - stop processing. */
bool handle_response; /* Main loop now handling response. */
void *buffer; /* Request/response buffer. */
+ char *str; /* String work space. */
+ unsigned int str_size; /* Size of *str. */
+ unsigned int str_used; /* Currently used size of *str. */
};
extern xenevtchn_handle *xe;
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* Re: [PATCH 05/29] tools/xenlogd: add 9pfs response generation support
2023-11-01 9:33 ` [PATCH 05/29] tools/xenlogd: add 9pfs response generation support Juergen Gross
@ 2023-11-02 18:48 ` Jason Andryuk
2023-11-03 7:52 ` Juergen Gross
0 siblings, 1 reply; 81+ messages in thread
From: Jason Andryuk @ 2023-11-02 18:48 UTC (permalink / raw)
To: Juergen Gross; +Cc: xen-devel, Wei Liu, Anthony PERARD
On Wed, Nov 1, 2023 at 6:56 AM Juergen Gross <jgross@suse.com> wrote:
>
> Add support for generation a 9pfs protocol response via a format based
> approach.
>
> Strings are stored in a per device string buffer and they are
> referenced via their offset in this buffer. This allows to avoid
> having to dynamically allocate memory for each single string.
>
> As a first user of the response handling add a generic p9_error()
> function which will be used to return any error to the client.
>
> Add all format parsing variants in order to avoid additional code churn
> later when adding the users of those variants. Prepare a special case
> for the "read" case already (format character 'D'): in order to avoid
> adding another buffer for read data support doing the read I/O directly
> into the response buffer.
>
> Signed-off-by: Juergen Gross <jgross@suse.com>
> ---
> diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
> index 590d06e906..5a06f72338 100644
> --- a/tools/xenlogd/io.c
> +++ b/tools/xenlogd/io.c
> @@ -101,6 +112,172 @@ static bool io_work_pending(device *device)
> : ring_out_data(device);
> }
>
> +static void fmt_err(const char *fmt)
> +{
> + syslog(LOG_CRIT, "illegal format %s passed to fill_buffer()", fmt);
> + exit(1);
> +}
> +
> +/*
> + * Fill buffer with response data.
> + * fmt is a sequence of format characters. Supported characters are:
> + * a: an array (2 bytes number of elements + the following format as elements)
> + * The number of elements is passed in the first unsigned int parameter, the
> + * next parameter is a pointer to an array of elements as denoted by the next
> + * format character.
> + * b: 2 byte unsigned integer
> + * The parameter is a pointer to a uint16_t value
> + * D: Data blob (4 byte length + <length> bytes)
> + * 2 parameters are consumed, first an unsigned int for the length, then a
> + * pointer to the first uint8_t value.
> + * No array support.
> + * L: 8 byte unsigned integer
> + * The parameter is a pointer to a uint64_t value
> + * Q: Qid (struct p9_qid)
> + * S: String (2 byte length + <length> characters)
> + * The length is obtained via strlen() of the parameter, being a pointer
> + * to the first character of the string
> + * U: 4 byte unsigned integer
> + * The parameter is a pointer to a uint32_t value
> + */
> +static void fill_buffer(device *device, uint8_t cmd, uint16_t tag,
> + const char *fmt, ...)
> +{
> + struct p9_header *hdr = device->buffer;
> + void *data = hdr + 1;
> + const char *f;
> + const void *par;
> + const char *str_val;
> + const struct p9_qid *qid;
> + unsigned int len;
> + va_list ap;
> + unsigned int array_sz = 0;
> + unsigned int elem_sz = 0;
> +
> + hdr->cmd = cmd;
> + hdr->tag = tag;
> +
> + va_start(ap, fmt);
> +
> + for ( f = fmt; *f; f++ )
> + {
> + if ( !array_sz )
> + par = va_arg(ap, const void *);
> + else
> + {
> + par += elem_sz;
> + array_sz--;
> + }
> +
> + switch ( *f )
> + {
> + case 'a':
> + f++;
> + if ( !*f || array_sz )
> + fmt_err(fmt);
> + array_sz = *(const unsigned int *)par;
> + *(__packed uint16_t *)data = array_sz;
Is it worth checking that array_sz doesn't exceed 0xffff?
> + data += sizeof(uint16_t);
> + par = va_arg(ap, const void *);
> + elem_sz = 0;
> + break;
> +
> + case 'u':
> + *(__packed uint16_t *)data = *(const uint16_t *)par;
> + elem_sz = sizeof(uint16_t);
> + data += sizeof(uint16_t);
> + break;
> +
> + case 'D':
> + if ( array_sz )
> + fmt_err(fmt);
> + len = *(const unsigned int *)par;
> + *(__packed uint32_t *)data = len;
> + data += sizeof(uint32_t);
> + par = va_arg(ap, const void *);
> + if ( data != par )
> + memcpy(data, par, len);
> + data += len;
> + break;
> +
> + case 'L':
> + *(__packed uint64_t *)data = *(const uint64_t *)par;
> + elem_sz = sizeof(uint64_t);
> + data += sizeof(uint64_t);
> + break;
> +
> + case 'Q':
> + qid = par;
> + elem_sz = sizeof(*qid);
> + *(uint8_t *)data = qid->type;
> + data += sizeof(uint8_t);
> + *(__packed uint32_t *)data = qid->version;
> + data += sizeof(uint32_t);
> + *(__packed uint64_t *)data = qid->path;
> + data += sizeof(uint64_t);
> + break;
> +
> + case 'S':
> + str_val = par;
> + elem_sz = sizeof(str_val);
> + len = strlen(str_val);
Should len be checked to ensure it doesn't exceed 0xffff?
Regards,
Jason
^ permalink raw reply [flat|nested] 81+ messages in thread* Re: [PATCH 05/29] tools/xenlogd: add 9pfs response generation support
2023-11-02 18:48 ` Jason Andryuk
@ 2023-11-03 7:52 ` Juergen Gross
0 siblings, 0 replies; 81+ messages in thread
From: Juergen Gross @ 2023-11-03 7:52 UTC (permalink / raw)
To: Jason Andryuk; +Cc: xen-devel, Wei Liu, Anthony PERARD
[-- Attachment #1.1.1: Type: text/plain, Size: 5344 bytes --]
On 02.11.23 19:48, Jason Andryuk wrote:
> On Wed, Nov 1, 2023 at 6:56 AM Juergen Gross <jgross@suse.com> wrote:
>>
>> Add support for generation a 9pfs protocol response via a format based
>> approach.
>>
>> Strings are stored in a per device string buffer and they are
>> referenced via their offset in this buffer. This allows to avoid
>> having to dynamically allocate memory for each single string.
>>
>> As a first user of the response handling add a generic p9_error()
>> function which will be used to return any error to the client.
>>
>> Add all format parsing variants in order to avoid additional code churn
>> later when adding the users of those variants. Prepare a special case
>> for the "read" case already (format character 'D'): in order to avoid
>> adding another buffer for read data support doing the read I/O directly
>> into the response buffer.
>>
>> Signed-off-by: Juergen Gross <jgross@suse.com>
>> ---
>
>> diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
>> index 590d06e906..5a06f72338 100644
>> --- a/tools/xenlogd/io.c
>> +++ b/tools/xenlogd/io.c
>
>> @@ -101,6 +112,172 @@ static bool io_work_pending(device *device)
>> : ring_out_data(device);
>> }
>>
>> +static void fmt_err(const char *fmt)
>> +{
>> + syslog(LOG_CRIT, "illegal format %s passed to fill_buffer()", fmt);
>> + exit(1);
>> +}
>> +
>> +/*
>> + * Fill buffer with response data.
>> + * fmt is a sequence of format characters. Supported characters are:
>> + * a: an array (2 bytes number of elements + the following format as elements)
>> + * The number of elements is passed in the first unsigned int parameter, the
>> + * next parameter is a pointer to an array of elements as denoted by the next
>> + * format character.
>> + * b: 2 byte unsigned integer
>> + * The parameter is a pointer to a uint16_t value
>> + * D: Data blob (4 byte length + <length> bytes)
>> + * 2 parameters are consumed, first an unsigned int for the length, then a
>> + * pointer to the first uint8_t value.
>> + * No array support.
>> + * L: 8 byte unsigned integer
>> + * The parameter is a pointer to a uint64_t value
>> + * Q: Qid (struct p9_qid)
>> + * S: String (2 byte length + <length> characters)
>> + * The length is obtained via strlen() of the parameter, being a pointer
>> + * to the first character of the string
>> + * U: 4 byte unsigned integer
>> + * The parameter is a pointer to a uint32_t value
>> + */
>> +static void fill_buffer(device *device, uint8_t cmd, uint16_t tag,
>> + const char *fmt, ...)
>> +{
>> + struct p9_header *hdr = device->buffer;
>> + void *data = hdr + 1;
>> + const char *f;
>> + const void *par;
>> + const char *str_val;
>> + const struct p9_qid *qid;
>> + unsigned int len;
>> + va_list ap;
>> + unsigned int array_sz = 0;
>> + unsigned int elem_sz = 0;
>> +
>> + hdr->cmd = cmd;
>> + hdr->tag = tag;
>> +
>> + va_start(ap, fmt);
>> +
>> + for ( f = fmt; *f; f++ )
>> + {
>> + if ( !array_sz )
>> + par = va_arg(ap, const void *);
>> + else
>> + {
>> + par += elem_sz;
>> + array_sz--;
>> + }
>> +
>> + switch ( *f )
>> + {
>> + case 'a':
>> + f++;
>> + if ( !*f || array_sz )
>> + fmt_err(fmt);
>> + array_sz = *(const unsigned int *)par;
>> + *(__packed uint16_t *)data = array_sz;
>
> Is it worth checking that array_sz doesn't exceed 0xffff?
I can add that.
>
>> + data += sizeof(uint16_t);
>> + par = va_arg(ap, const void *);
>> + elem_sz = 0;
>> + break;
>> +
>> + case 'u':
>> + *(__packed uint16_t *)data = *(const uint16_t *)par;
>> + elem_sz = sizeof(uint16_t);
>> + data += sizeof(uint16_t);
>> + break;
>> +
>> + case 'D':
>> + if ( array_sz )
>> + fmt_err(fmt);
>> + len = *(const unsigned int *)par;
>> + *(__packed uint32_t *)data = len;
>> + data += sizeof(uint32_t);
>> + par = va_arg(ap, const void *);
>> + if ( data != par )
>> + memcpy(data, par, len);
>> + data += len;
>> + break;
>> +
>> + case 'L':
>> + *(__packed uint64_t *)data = *(const uint64_t *)par;
>> + elem_sz = sizeof(uint64_t);
>> + data += sizeof(uint64_t);
>> + break;
>> +
>> + case 'Q':
>> + qid = par;
>> + elem_sz = sizeof(*qid);
>> + *(uint8_t *)data = qid->type;
>> + data += sizeof(uint8_t);
>> + *(__packed uint32_t *)data = qid->version;
>> + data += sizeof(uint32_t);
>> + *(__packed uint64_t *)data = qid->path;
>> + data += sizeof(uint64_t);
>> + break;
>> +
>> + case 'S':
>> + str_val = par;
>> + elem_sz = sizeof(str_val);
>> + len = strlen(str_val);
>
> Should len be checked to ensure it doesn't exceed 0xffff?
I'll add that check.
Juergen
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3149 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]
^ permalink raw reply [flat|nested] 81+ messages in thread
* [PATCH 06/29] tools/xenlogd: add 9pfs version request support
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
` (4 preceding siblings ...)
2023-11-01 9:33 ` [PATCH 05/29] tools/xenlogd: add 9pfs response generation support Juergen Gross
@ 2023-11-01 9:33 ` Juergen Gross
2023-11-02 19:25 ` Jason Andryuk
2023-11-01 9:33 ` [PATCH 07/29] tools/xenlogd: add 9pfs attach " Juergen Gross
` (22 subsequent siblings)
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:33 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Anthony PERARD
Add the version request of the 9pfs protocol. For the version use the
"9P2000.u" variant, as it is supported by Mini-OS and Linux.
For the request parsing add all format items needed even in future in
order to avoid code churn for those additions later.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/xenlogd/io.c | 202 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 202 insertions(+)
diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
index 5a06f72338..f35520018f 100644
--- a/tools/xenlogd/io.c
+++ b/tools/xenlogd/io.c
@@ -22,8 +22,12 @@
#include "xenlogd.h"
/* P9 protocol commands (response is either cmd+1 or P9_CMD_ERROR). */
+#define P9_CMD_VERSION 100
#define P9_CMD_ERROR 107
+#define P9_MIN_MSIZE 2048
+#define P9_VERSION "9P2000.u"
+
struct p9_qid {
uint8_t type;
#define QID_TYPE_DIR 0x80
@@ -267,6 +271,169 @@ static unsigned int add_string(device *device, const char *str,
return ret;
}
+static bool chk_data(device *device, void *data, unsigned int len)
+{
+ struct p9_header *hdr = device->buffer;
+
+ if ( data + len <= device->buffer + hdr->size )
+ return true;
+
+ errno = E2BIG;
+
+ return false;
+}
+
+static bool fill_data_elem(void **par, void **array, unsigned int *array_sz,
+ unsigned int elem_sz, void *data)
+{
+ if ( *array_sz && !*array )
+ {
+ *array = calloc(*array_sz, elem_sz);
+ if ( !*array )
+ return false;
+ *par = *array;
+ }
+
+ memcpy(*par, data, elem_sz);
+
+ if ( *array_sz )
+ {
+ *par += elem_sz;
+ *array_sz -= 1;
+ }
+
+ return true;
+}
+
+/*
+ * Fill variables with request data.
+ * fmt is a sequence of format characters. Supported characters are:
+ * a: an array (2 bytes number of elements + the following format as elements)
+ * The number of elements is stored in the first unsigned int parameter, the
+ * next parameter is a pointer to an array of elements as denoted by the next
+ * format character. The array is allocated dynamically.
+ * b: 1 byte unsigned integer
+ * The value is stored in the next parameter with type uint8_t.
+ * D: Data blob (4 byte length + <length> bytes)
+ * 2 parameters are consumed, first an unsigned int for the length, then a
+ * pointer to the first uint8_t value.
+ * No array support.
+ * L: 8 byte unsigned integer
+ * The value is stored in the next parameter with type uint64_t.
+ * S: String (2 byte length + <length> characters)
+ * The 0-terminated string is stored in device->str + off, off is stored in
+ * the next parameter with type unsigned int.
+ * U: 4 byte unsigned integer
+ * The value is stored in the next parameter with type uint32_t.
+ *
+ * Return value: number of filled variables, errno will be set in case of
+ * error.
+ */
+static int fill_data(device *device, const char *fmt, ...)
+{
+ struct p9_header *hdr = device->buffer;
+ void *data = hdr + 1;
+ void *par;
+ unsigned int pars = 0;
+ const char *f;
+ va_list ap;
+ unsigned int len;
+ unsigned int str_off;
+ unsigned int array_sz = 0;
+ void **array = NULL;
+
+ va_start(ap, fmt);
+
+ for ( f = fmt; *f; f++ )
+ {
+ if ( !array_sz )
+ par = va_arg(ap, void *);
+
+ switch ( *f )
+ {
+ case 'a':
+ f++;
+ if ( !*f || array_sz )
+ fmt_err(fmt);
+ if ( !chk_data(device, data, sizeof(uint16_t)) )
+ return pars;
+ array_sz = *(__packed uint16_t *)data;
+ data += sizeof(uint16_t);
+ *(unsigned int *)par = array_sz;
+ array = va_arg(ap, void **);
+ *array = NULL;
+ break;
+
+ case 'b':
+ if ( !chk_data(device, data, sizeof(uint8_t)) )
+ return pars;
+ if ( !fill_data_elem(&par, array, &array_sz, sizeof(uint8_t),
+ data) )
+ return pars;
+ data += sizeof(uint8_t);
+ break;
+
+ case 'D':
+ if ( array_sz )
+ fmt_err(fmt);
+ if ( !chk_data(device, data, sizeof(uint32_t)) )
+ return pars;
+ len = *(__packed uint32_t *)data;
+ data += sizeof(uint32_t);
+ *(unsigned int *)par = len;
+ par = va_arg(ap, void *);
+ if ( !chk_data(device, data, len) )
+ return pars;
+ memcpy(par, data, len);
+ data += len;
+ break;
+
+ case 'L':
+ if ( !chk_data(device, data, sizeof(uint64_t)) )
+ return pars;
+ if ( !fill_data_elem(&par, array, &array_sz, sizeof(uint64_t),
+ data) )
+ return pars;
+ data += sizeof(uint64_t);
+ break;
+
+ case 'S':
+ if ( !chk_data(device, data, sizeof(uint16_t)) )
+ return pars;
+ len = *(__packed uint16_t *)data;
+ data += sizeof(uint16_t);
+ if ( !chk_data(device, data, len) )
+ return pars;
+ str_off = add_string(device, data, len);
+ if ( str_off == ~0 )
+ return pars;
+ if ( !fill_data_elem(&par, array, &array_sz, sizeof(unsigned int),
+ &str_off) )
+ return pars;
+ data += len;
+ break;
+
+ case 'U':
+ if ( !chk_data(device, data, sizeof(uint32_t)) )
+ return pars;
+ if ( !fill_data_elem(&par, array, &array_sz, sizeof(uint32_t),
+ data) )
+ return pars;
+ data += sizeof(uint32_t);
+ break;
+
+ default:
+ fmt_err(fmt);
+ }
+
+ if ( array_sz )
+ f--;
+ pars++;
+ }
+
+ return pars;
+}
+
static void p9_error(device *device, uint16_t tag, uint32_t err)
{
unsigned int erroff;
@@ -278,6 +445,37 @@ static void p9_error(device *device, uint16_t tag, uint32_t err)
&err);
}
+static void p9_version(device *device, struct p9_header *hdr)
+{
+ uint32_t max_size;
+ unsigned int off;
+ char *version;
+ int ret;
+
+ ret = fill_data(device, "US", &max_size, &off);
+ if ( ret != 2 )
+ {
+ p9_error(device, hdr->tag, errno);
+ return;
+ }
+
+ if ( max_size < P9_MIN_MSIZE )
+ {
+ p9_error(device, hdr->tag, EMSGSIZE);
+ return;
+ }
+
+ if ( max_size < device->max_size )
+ device->max_size = max_size;
+
+ version = device->str + off;
+ if ( strcmp(version, P9_VERSION) )
+ version = "unknown";
+
+ fill_buffer(device, hdr->cmd + 1, hdr->tag, "US", &device->max_size,
+ version);
+}
+
void *io_thread(void *arg)
{
device *device = arg;
@@ -333,6 +531,10 @@ void *io_thread(void *arg)
switch ( hdr.cmd )
{
+ case P9_CMD_VERSION:
+ p9_version(device, &hdr);
+ break;
+
default:
syslog(LOG_DEBUG, "%u.%u sent unhandled command %u\n",
device->domid, device->devid, hdr.cmd);
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* Re: [PATCH 06/29] tools/xenlogd: add 9pfs version request support
2023-11-01 9:33 ` [PATCH 06/29] tools/xenlogd: add 9pfs version request support Juergen Gross
@ 2023-11-02 19:25 ` Jason Andryuk
0 siblings, 0 replies; 81+ messages in thread
From: Jason Andryuk @ 2023-11-02 19:25 UTC (permalink / raw)
To: Juergen Gross; +Cc: xen-devel, Wei Liu, Anthony PERARD
On Wed, Nov 1, 2023 at 5:54 AM Juergen Gross <jgross@suse.com> wrote:
>
> Add the version request of the 9pfs protocol. For the version use the
> "9P2000.u" variant, as it is supported by Mini-OS and Linux.
>
> For the request parsing add all format items needed even in future in
> order to avoid code churn for those additions later.
>
> Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Jason Andryuk <jandryuk@gmail.com>
^ permalink raw reply [flat|nested] 81+ messages in thread
* [PATCH 07/29] tools/xenlogd: add 9pfs attach request support
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
` (5 preceding siblings ...)
2023-11-01 9:33 ` [PATCH 06/29] tools/xenlogd: add 9pfs version request support Juergen Gross
@ 2023-11-01 9:33 ` Juergen Gross
2023-11-03 15:13 ` Jason Andryuk
2023-11-01 9:33 ` [PATCH 08/29] tools/xenlogd: add 9pfs walk " Juergen Gross
` (21 subsequent siblings)
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:33 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Anthony PERARD
Add the attach request of the 9pfs protocol. This introduces the "fid"
scheme of the 9pfs protocol.
As this will be needed later, use a dedicated memory allocation
function in alloc_fid().
For filling the qid data take the approach from the qemu 9pfs backend
implementation.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/xenlogd/io.c | 128 ++++++++++++++++++++++++++++++++++++++++
tools/xenlogd/xenlogd.c | 1 +
tools/xenlogd/xenlogd.h | 11 ++++
3 files changed, 140 insertions(+)
diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
index f35520018f..fa825c9f39 100644
--- a/tools/xenlogd/io.c
+++ b/tools/xenlogd/io.c
@@ -16,6 +16,8 @@
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#include <xenctrl.h> /* For cpu barriers. */
#include <xen-tools/common-macros.h>
@@ -23,6 +25,7 @@
/* P9 protocol commands (response is either cmd+1 or P9_CMD_ERROR). */
#define P9_CMD_VERSION 100
+#define P9_CMD_ATTACH 104
#define P9_CMD_ERROR 107
#define P9_MIN_MSIZE 2048
@@ -434,6 +437,92 @@ static int fill_data(device *device, const char *fmt, ...)
return pars;
}
+static struct p9_fid *find_fid(device *device, unsigned int fid)
+{
+ struct p9_fid *fidp;
+
+ XEN_TAILQ_FOREACH(fidp, &device->fids, list)
+ {
+ if ( fidp->fid == fid )
+ return fidp;
+ }
+
+ return NULL;
+}
+
+static struct p9_fid *alloc_fid_mem(device *device, unsigned int fid,
+ const char *path)
+{
+ struct p9_fid *fidp;
+ size_t pathlen;
+
+ pathlen = strlen(device->host_path) + strlen(path) + 1;
+ fidp = calloc(sizeof(*fidp) + pathlen, 1);
+ if ( !fidp )
+ return NULL;
+
+ fidp->fid = fid;
+ snprintf(fidp->path, pathlen, "%s%s", device->host_path, path);
+
+ return fidp;
+}
+
+static struct p9_fid *alloc_fid(device *device, unsigned int fid,
+ const char *path)
+{
+ struct p9_fid *fidp;
+
+ if ( find_fid(device, fid) )
+ {
+ errno = EBADFD;
+ return NULL;
+ }
+
+ if ( device->n_fids >= device->max_open_files )
+ {
+ errno = EMFILE;
+ return NULL;
+ }
+
+ fidp = alloc_fid_mem(device, fid, path);
+ if ( !fidp )
+ return NULL;
+
+ XEN_TAILQ_INSERT_HEAD(&device->fids, fidp, list);
+ device->n_fids++;
+
+ return fidp;
+}
+
+static void free_fid(device *device, struct p9_fid *fidp)
+{
+ if ( !fidp )
+ return;
+
+ device->n_fids--;
+ XEN_TAILQ_REMOVE(&device->fids, fidp, list);
+ free(fidp);
+}
+
+static int fill_qid(const char *path, struct p9_qid *qid, struct stat *stbuf)
+{
+ struct stat st;
+
+ if ( !stbuf )
+ {
+ if ( stat(path, &st) )
+ return errno;
+
+ stbuf = &st;
+ }
+
+ qid->type = S_ISDIR(stbuf->st_mode) ? QID_TYPE_DIR : 0;
+ qid->version = stbuf->st_mtime ^ (stbuf->st_size << 8);
+ qid->path = stbuf->st_ino;
+
+ return 0;
+}
+
static void p9_error(device *device, uint16_t tag, uint32_t err)
{
unsigned int erroff;
@@ -476,6 +565,41 @@ static void p9_version(device *device, struct p9_header *hdr)
version);
}
+static void p9_attach(device *device, struct p9_header *hdr)
+{
+ uint32_t fid;
+ uint32_t dummy_u32;
+ unsigned int dummy_uint;
+ struct p9_qid qid;
+ int ret;
+
+ ret = fill_data(device, "UUSSU", &fid, &dummy_u32, &dummy_uint, &dummy_uint,
+ &dummy_u32);
+ if ( ret != 5 )
+ {
+ p9_error(device, hdr->tag, errno);
+ return;
+ }
+
+ device->root_fid = alloc_fid(device, fid, "");
+ if ( !device->root_fid )
+ {
+ p9_error(device, hdr->tag, errno);
+ return;
+ }
+
+ ret = fill_qid(device->host_path, &qid, NULL);
+ if ( ret )
+ {
+ free_fid(device, device->root_fid);
+ device->root_fid = NULL;
+ p9_error(device, hdr->tag, ret);
+ return;
+ }
+
+ fill_buffer(device, hdr->cmd + 1, hdr->tag, "Q", &qid);
+}
+
void *io_thread(void *arg)
{
device *device = arg;
@@ -535,6 +659,10 @@ void *io_thread(void *arg)
p9_version(device, &hdr);
break;
+ case P9_CMD_ATTACH:
+ p9_attach(device, &hdr);
+ break;
+
default:
syslog(LOG_DEBUG, "%u.%u sent unhandled command %u\n",
device->domid, device->devid, hdr.cmd);
diff --git a/tools/xenlogd/xenlogd.c b/tools/xenlogd/xenlogd.c
index da0a09a122..d2de7bfbf2 100644
--- a/tools/xenlogd/xenlogd.c
+++ b/tools/xenlogd/xenlogd.c
@@ -274,6 +274,7 @@ static device *new_device(unsigned int domid, unsigned int devid)
pthread_cond_init(&device->cond, NULL);
pthread_mutex_init(&device->mutex, NULL);
+ XEN_TAILQ_INIT(&device->fids);
val = read_backend_node(device, "security_model");
if ( !val || strcmp(val, "none") )
diff --git a/tools/xenlogd/xenlogd.h b/tools/xenlogd/xenlogd.h
index c10c6aa9e5..bd2a283ccb 100644
--- a/tools/xenlogd/xenlogd.h
+++ b/tools/xenlogd/xenlogd.h
@@ -19,6 +19,12 @@ struct p9_header {
uint16_t tag;
} __attribute__((packed));
+struct p9_fid {
+ XEN_TAILQ_ENTRY(struct p9_fid) list;
+ unsigned int fid;
+ char path[];
+};
+
typedef struct device device;
struct device {
/* Admin data. */
@@ -60,6 +66,11 @@ struct device {
char *str; /* String work space. */
unsigned int str_size; /* Size of *str. */
unsigned int str_used; /* Currently used size of *str. */
+
+ /* File system handling. */
+ XEN_TAILQ_HEAD(fidhead, struct p9_fid) fids;
+ struct p9_fid *root_fid;
+ unsigned int n_fids;
};
extern xenevtchn_handle *xe;
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* Re: [PATCH 07/29] tools/xenlogd: add 9pfs attach request support
2023-11-01 9:33 ` [PATCH 07/29] tools/xenlogd: add 9pfs attach " Juergen Gross
@ 2023-11-03 15:13 ` Jason Andryuk
2023-11-06 7:52 ` Juergen Gross
0 siblings, 1 reply; 81+ messages in thread
From: Jason Andryuk @ 2023-11-03 15:13 UTC (permalink / raw)
To: Juergen Gross; +Cc: xen-devel, Wei Liu, Anthony PERARD
On Wed, Nov 1, 2023 at 5:54 AM Juergen Gross <jgross@suse.com> wrote:
>
> Add the attach request of the 9pfs protocol. This introduces the "fid"
> scheme of the 9pfs protocol.
>
> As this will be needed later, use a dedicated memory allocation
> function in alloc_fid().
>
> For filling the qid data take the approach from the qemu 9pfs backend
> implementation.
>
> Signed-off-by: Juergen Gross <jgross@suse.com>
> ---
> tools/xenlogd/io.c | 128 ++++++++++++++++++++++++++++++++++++++++
> tools/xenlogd/xenlogd.c | 1 +
> tools/xenlogd/xenlogd.h | 11 ++++
> 3 files changed, 140 insertions(+)
>
> diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
> index f35520018f..fa825c9f39 100644
> --- a/tools/xenlogd/io.c
> +++ b/tools/xenlogd/io.c
> +static struct p9_fid *alloc_fid_mem(device *device, unsigned int fid,
> + const char *path)
> +{
> + struct p9_fid *fidp;
> + size_t pathlen;
> +
> + pathlen = strlen(device->host_path) + strlen(path) + 1;
> + fidp = calloc(sizeof(*fidp) + pathlen, 1);
> + if ( !fidp )
> + return NULL;
> +
> + fidp->fid = fid;
> + snprintf(fidp->path, pathlen, "%s%s", device->host_path, path);
check_host_path() should be enhanced to ensure host_path has a
trailing '/', or switch this to "%s/%s" to ensure it's always present?
> +
> + return fidp;
> +}
> +
> +static void free_fid(device *device, struct p9_fid *fidp)
> +{
> + if ( !fidp )
> + return;
> +
> + device->n_fids--;
> + XEN_TAILQ_REMOVE(&device->fids, fidp, list);
> + free(fidp);
> +}
> +
> +static int fill_qid(const char *path, struct p9_qid *qid, struct stat *stbuf)
Nit: ordering is input, output, optional input, so you might want to re-order?
stbuf can be const?
> +{
> + struct stat st;
> +
> + if ( !stbuf )
> + {
> + if ( stat(path, &st) )
> + return errno;
> +
> + stbuf = &st;
> + }
> +
> + qid->type = S_ISDIR(stbuf->st_mode) ? QID_TYPE_DIR : 0;
> + qid->version = stbuf->st_mtime ^ (stbuf->st_size << 8);
> + qid->path = stbuf->st_ino;
> +
> + return 0;
> +}
> +
> static void p9_error(device *device, uint16_t tag, uint32_t err)
> {
> unsigned int erroff;
> @@ -476,6 +565,41 @@ static void p9_version(device *device, struct p9_header *hdr)
> version);
> }
>
> +static void p9_attach(device *device, struct p9_header *hdr)
> +{
> + uint32_t fid;
> + uint32_t dummy_u32;
> + unsigned int dummy_uint;
> + struct p9_qid qid;
> + int ret;
> +
> + ret = fill_data(device, "UUSSU", &fid, &dummy_u32, &dummy_uint, &dummy_uint,
> + &dummy_u32);
> + if ( ret != 5 )
> + {
> + p9_error(device, hdr->tag, errno);
> + return;
> + }
We might want to check the first dummy_u32 (afid) to ensure it's NOFID?
"""
If the client does not wish to authenticate the connection, or knows
that authentication is not required, the afid field in the attach mes-
sage should be set to NOFID, defined as (u32int)~0 in fcall.h. If the
client does wish to authenticate, it must acquire and validate an afid
using an auth message before doing the attach.
"""
Since auth isn't implemented, it's probably not necessary to check afid?
I've been looking at these as reference:
https://ericvh.github.io/9p-rfc/rfc9p2000.html
https://ericvh.github.io/9p-rfc/rfc9p2000.u.html
> +
> + device->root_fid = alloc_fid(device, fid, "");
> + if ( !device->root_fid )
> + {
> + p9_error(device, hdr->tag, errno);
> + return;
> + }
> +
> + ret = fill_qid(device->host_path, &qid, NULL);
> + if ( ret )
> + {
> + free_fid(device, device->root_fid);
root_fid is only freed in this error path. Maybe free_device() should
free all the fids?
Regards,
Jason
^ permalink raw reply [flat|nested] 81+ messages in thread* Re: [PATCH 07/29] tools/xenlogd: add 9pfs attach request support
2023-11-03 15:13 ` Jason Andryuk
@ 2023-11-06 7:52 ` Juergen Gross
0 siblings, 0 replies; 81+ messages in thread
From: Juergen Gross @ 2023-11-06 7:52 UTC (permalink / raw)
To: Jason Andryuk; +Cc: xen-devel, Wei Liu, Anthony PERARD
[-- Attachment #1.1.1: Type: text/plain, Size: 4382 bytes --]
On 03.11.23 16:13, Jason Andryuk wrote:
> On Wed, Nov 1, 2023 at 5:54 AM Juergen Gross <jgross@suse.com> wrote:
>>
>> Add the attach request of the 9pfs protocol. This introduces the "fid"
>> scheme of the 9pfs protocol.
>>
>> As this will be needed later, use a dedicated memory allocation
>> function in alloc_fid().
>>
>> For filling the qid data take the approach from the qemu 9pfs backend
>> implementation.
>>
>> Signed-off-by: Juergen Gross <jgross@suse.com>
>> ---
>> tools/xenlogd/io.c | 128 ++++++++++++++++++++++++++++++++++++++++
>> tools/xenlogd/xenlogd.c | 1 +
>> tools/xenlogd/xenlogd.h | 11 ++++
>> 3 files changed, 140 insertions(+)
>>
>> diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
>> index f35520018f..fa825c9f39 100644
>> --- a/tools/xenlogd/io.c
>> +++ b/tools/xenlogd/io.c
>
>> +static struct p9_fid *alloc_fid_mem(device *device, unsigned int fid,
>> + const char *path)
>> +{
>> + struct p9_fid *fidp;
>> + size_t pathlen;
>> +
>> + pathlen = strlen(device->host_path) + strlen(path) + 1;
>> + fidp = calloc(sizeof(*fidp) + pathlen, 1);
>> + if ( !fidp )
>> + return NULL;
>> +
>> + fidp->fid = fid;
>> + snprintf(fidp->path, pathlen, "%s%s", device->host_path, path);
>
> check_host_path() should be enhanced to ensure host_path has a
> trailing '/', or switch this to "%s/%s" to ensure it's always present?
No, "path" is always starting with a "/" if it is not empty.
>
>> +
>> + return fidp;
>> +}
>> +
>
>
>> +static void free_fid(device *device, struct p9_fid *fidp)
>> +{
>> + if ( !fidp )
>> + return;
>> +
>> + device->n_fids--;
>> + XEN_TAILQ_REMOVE(&device->fids, fidp, list);
>> + free(fidp);
>> +}
>> +
>> +static int fill_qid(const char *path, struct p9_qid *qid, struct stat *stbuf)
>
> Nit: ordering is input, output, optional input, so you might want to re-order?
Hmm, I did it on purpose, as the last parameter is optional (as you said).
>
> stbuf can be const?
Yes.
>
>> +{
>> + struct stat st;
>> +
>> + if ( !stbuf )
>> + {
>> + if ( stat(path, &st) )
>> + return errno;
>> +
>> + stbuf = &st;
>> + }
>> +
>> + qid->type = S_ISDIR(stbuf->st_mode) ? QID_TYPE_DIR : 0;
>> + qid->version = stbuf->st_mtime ^ (stbuf->st_size << 8);
>> + qid->path = stbuf->st_ino;
>> +
>> + return 0;
>> +}
>> +
>> static void p9_error(device *device, uint16_t tag, uint32_t err)
>> {
>> unsigned int erroff;
>> @@ -476,6 +565,41 @@ static void p9_version(device *device, struct p9_header *hdr)
>> version);
>> }
>>
>> +static void p9_attach(device *device, struct p9_header *hdr)
>> +{
>> + uint32_t fid;
>> + uint32_t dummy_u32;
>> + unsigned int dummy_uint;
>> + struct p9_qid qid;
>> + int ret;
>> +
>> + ret = fill_data(device, "UUSSU", &fid, &dummy_u32, &dummy_uint, &dummy_uint,
>> + &dummy_u32);
>> + if ( ret != 5 )
>> + {
>> + p9_error(device, hdr->tag, errno);
>> + return;
>> + }
>
> We might want to check the first dummy_u32 (afid) to ensure it's NOFID?
> """
> If the client does not wish to authenticate the connection, or knows
> that authentication is not required, the afid field in the attach mes-
> sage should be set to NOFID, defined as (u32int)~0 in fcall.h. If the
> client does wish to authenticate, it must acquire and validate an afid
> using an auth message before doing the attach.
> """
>
> Since auth isn't implemented, it's probably not necessary to check afid?
That was the idea, yes.
>
> I've been looking at these as reference:
> https://ericvh.github.io/9p-rfc/rfc9p2000.html
> https://ericvh.github.io/9p-rfc/rfc9p2000.u.html
>
>> +
>> + device->root_fid = alloc_fid(device, fid, "");
>> + if ( !device->root_fid )
>> + {
>> + p9_error(device, hdr->tag, errno);
>> + return;
>> + }
>> +
>> + ret = fill_qid(device->host_path, &qid, NULL);
>> + if ( ret )
>> + {
>> + free_fid(device, device->root_fid);
>
> root_fid is only freed in this error path. Maybe free_device() should
> free all the fids?
No, but io_thread() should do so at the end.
Juergen
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3149 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]
^ permalink raw reply [flat|nested] 81+ messages in thread
* [PATCH 08/29] tools/xenlogd: add 9pfs walk request support
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
` (6 preceding siblings ...)
2023-11-01 9:33 ` [PATCH 07/29] tools/xenlogd: add 9pfs attach " Juergen Gross
@ 2023-11-01 9:33 ` Juergen Gross
2023-11-03 19:48 ` Jason Andryuk
2023-11-01 9:33 ` [PATCH 09/29] tools/xenlogd: add 9pfs open " Juergen Gross
` (20 subsequent siblings)
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:33 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Anthony PERARD
Add the walk request of the 9pfs protocol.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/xenlogd/io.c | 138 ++++++++++++++++++++++++++++++++++++++++
tools/xenlogd/xenlogd.h | 1 +
2 files changed, 139 insertions(+)
diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
index fa825c9f39..778e1dc2c9 100644
--- a/tools/xenlogd/io.c
+++ b/tools/xenlogd/io.c
@@ -27,9 +27,11 @@
#define P9_CMD_VERSION 100
#define P9_CMD_ATTACH 104
#define P9_CMD_ERROR 107
+#define P9_CMD_WALK 110
#define P9_MIN_MSIZE 2048
#define P9_VERSION "9P2000.u"
+#define P9_WALK_MAXELEM 16
struct p9_qid {
uint8_t type;
@@ -523,6 +525,20 @@ static int fill_qid(const char *path, struct p9_qid *qid, struct stat *stbuf)
return 0;
}
+static bool name_ok(const char *str)
+{
+ if ( !*str )
+ return false;
+
+ if ( strchr(str, '/' ) )
+ return false;
+
+ if ( !strcmp(str, "..") || !strcmp(str, ".") )
+ return false;
+
+ return true;
+}
+
static void p9_error(device *device, uint16_t tag, uint32_t err)
{
unsigned int erroff;
@@ -600,6 +616,124 @@ static void p9_attach(device *device, struct p9_header *hdr)
fill_buffer(device, hdr->cmd + 1, hdr->tag, "Q", &qid);
}
+static void p9_walk(device *device, struct p9_header *hdr)
+{
+ uint32_t fid;
+ uint32_t newfid;
+ struct p9_fid *fidp;
+ struct p9_qid *qids = NULL;
+ unsigned int n_names = 0;
+ unsigned int *names = NULL;
+ unsigned int walked = 0;
+ unsigned int i;
+ char *path = NULL;
+ unsigned int path_len;
+ int ret;
+
+ ret = fill_data(device, "UUaS", &fid, &newfid, &n_names, &names);
+ if ( n_names > P9_WALK_MAXELEM )
+ {
+ p9_error(device, hdr->tag, EINVAL);
+ goto out;
+ }
+ if ( ret != 3 + n_names )
+ {
+ p9_error(device, hdr->tag, errno);
+ goto out;
+ }
+
+ fidp = find_fid(device, fid);
+ if ( !fidp )
+ {
+ p9_error(device, hdr->tag, ENOENT);
+ goto out;
+ }
+ if ( fidp->opened )
+ {
+ p9_error(device, hdr->tag, EINVAL);
+ goto out;
+ }
+
+ path_len = strlen(fidp->path) + 1;
+ for ( i = 0; i < n_names; i++ )
+ {
+ if ( !name_ok(device->str + names[i]) )
+ {
+ p9_error(device, hdr->tag, ENOENT);
+ goto out;
+ }
+ path_len += strlen(device->str + names[i]) + 1;
+ }
+ path = calloc(path_len + 1, 1);
+ if ( !path )
+ {
+ p9_error(device, hdr->tag, ENOMEM);
+ goto out;
+ }
+ strcpy(path, fidp->path);
+
+ if ( n_names )
+ {
+ qids = calloc(n_names, sizeof(*qids));
+ if ( !qids )
+ {
+ p9_error(device, hdr->tag, ENOMEM);
+ goto out;
+ }
+ for ( i = 0; i < n_names; i++ )
+ {
+ strcat(path, "/");
+ strcat(path, device->str + names[i]);
+ ret = fill_qid(path, qids + i, NULL);
+ if ( ret )
+ {
+ if ( !walked )
+ {
+ p9_error(device, hdr->tag, errno);
+ goto out;
+ }
+ break;
+ }
+ walked++;
+ }
+ }
+
+ if ( walked == n_names )
+ {
+ const char *rel_path = path + strlen(device->host_path);
+ bool ok = false;
+
+ if ( fid == newfid )
+ {
+ struct p9_fid *new_fidp;
+
+ new_fidp = alloc_fid_mem(device, fid, rel_path);
+ if ( new_fidp )
+ {
+ XEN_TAILQ_REMOVE(&device->fids, fidp, list);
+ XEN_TAILQ_INSERT_HEAD(&device->fids, new_fidp, list);
+ free(fidp);
+ ok = true;
+ }
+ }
+ else
+ ok = alloc_fid(device, newfid, rel_path);
+
+ if ( !ok )
+ {
+ p9_error(device, hdr->tag, errno);
+ goto out;
+ }
+ }
+
+ fill_buffer(device, hdr->cmd + 1, hdr->tag, "aQ", &walked, qids);
+
+ out:
+ free(qids);
+ free(path);
+ free(names);
+}
+
void *io_thread(void *arg)
{
device *device = arg;
@@ -663,6 +797,10 @@ void *io_thread(void *arg)
p9_attach(device, &hdr);
break;
+ case P9_CMD_WALK:
+ p9_walk(device, &hdr);
+ break;
+
default:
syslog(LOG_DEBUG, "%u.%u sent unhandled command %u\n",
device->domid, device->devid, hdr.cmd);
diff --git a/tools/xenlogd/xenlogd.h b/tools/xenlogd/xenlogd.h
index bd2a283ccb..23f013af9e 100644
--- a/tools/xenlogd/xenlogd.h
+++ b/tools/xenlogd/xenlogd.h
@@ -22,6 +22,7 @@ struct p9_header {
struct p9_fid {
XEN_TAILQ_ENTRY(struct p9_fid) list;
unsigned int fid;
+ bool opened;
char path[];
};
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* Re: [PATCH 08/29] tools/xenlogd: add 9pfs walk request support
2023-11-01 9:33 ` [PATCH 08/29] tools/xenlogd: add 9pfs walk " Juergen Gross
@ 2023-11-03 19:48 ` Jason Andryuk
2023-11-06 7:53 ` Juergen Gross
0 siblings, 1 reply; 81+ messages in thread
From: Jason Andryuk @ 2023-11-03 19:48 UTC (permalink / raw)
To: Juergen Gross; +Cc: xen-devel, Wei Liu, Anthony PERARD
On Wed, Nov 1, 2023 at 6:09 AM Juergen Gross <jgross@suse.com> wrote:
>
> Add the walk request of the 9pfs protocol.
>
> Signed-off-by: Juergen Gross <jgross@suse.com>
> ---
> tools/xenlogd/io.c | 138 ++++++++++++++++++++++++++++++++++++++++
> tools/xenlogd/xenlogd.h | 1 +
> 2 files changed, 139 insertions(+)
>
> diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
> index fa825c9f39..778e1dc2c9 100644
> --- a/tools/xenlogd/io.c
> +++ b/tools/xenlogd/io.c
> @@ -600,6 +616,124 @@ static void p9_attach(device *device, struct p9_header *hdr)
> fill_buffer(device, hdr->cmd + 1, hdr->tag, "Q", &qid);
> }
>
> +static void p9_walk(device *device, struct p9_header *hdr)
> +{
> + uint32_t fid;
> + uint32_t newfid;
> + struct p9_fid *fidp;
> + struct p9_qid *qids = NULL;
> + unsigned int n_names = 0;
> + unsigned int *names = NULL;
> + unsigned int walked = 0;
> + unsigned int i;
> + char *path = NULL;
> + unsigned int path_len;
> + int ret;
> +
> + ret = fill_data(device, "UUaS", &fid, &newfid, &n_names, &names);
> + if ( n_names > P9_WALK_MAXELEM )
> + {
> + p9_error(device, hdr->tag, EINVAL);
> + goto out;
> + }
> + if ( ret != 3 + n_names )
> + {
> + p9_error(device, hdr->tag, errno);
> + goto out;
> + }
> +
> + fidp = find_fid(device, fid);
> + if ( !fidp )
> + {
> + p9_error(device, hdr->tag, ENOENT);
> + goto out;
> + }
> + if ( fidp->opened )
> + {
> + p9_error(device, hdr->tag, EINVAL);
> + goto out;
> + }
https://ericvh.github.io/9p-rfc/rfc9p2000.html#anchor33
"""
The fid must represent a directory unless zero path name elements are specified.
"""
and
"""
For the first elementwise walk to succeed, the file identified by fid
must be a directory, and the implied user of the request must have
permission to search the directory (see intro(5)). Subsequent
elementwise walks have equivalent restrictions applied to the implicit
fid that results from the preceding elementwise walk.
"""
Maybe a dir check should be added? However, it doesn't look like QEMU
does this check. Seems like it is implicitly checked by the path
concatenation, so it may be fine as-is.
If you think it's ok as-is:
Reviewed-by: Jason Andryuk <jandryuk@gmail.com>
Regards,
Jason
^ permalink raw reply [flat|nested] 81+ messages in thread* Re: [PATCH 08/29] tools/xenlogd: add 9pfs walk request support
2023-11-03 19:48 ` Jason Andryuk
@ 2023-11-06 7:53 ` Juergen Gross
0 siblings, 0 replies; 81+ messages in thread
From: Juergen Gross @ 2023-11-06 7:53 UTC (permalink / raw)
To: Jason Andryuk; +Cc: xen-devel, Wei Liu, Anthony PERARD
[-- Attachment #1.1.1: Type: text/plain, Size: 2594 bytes --]
On 03.11.23 20:48, Jason Andryuk wrote:
> On Wed, Nov 1, 2023 at 6:09 AM Juergen Gross <jgross@suse.com> wrote:
>>
>> Add the walk request of the 9pfs protocol.
>>
>> Signed-off-by: Juergen Gross <jgross@suse.com>
>> ---
>> tools/xenlogd/io.c | 138 ++++++++++++++++++++++++++++++++++++++++
>> tools/xenlogd/xenlogd.h | 1 +
>> 2 files changed, 139 insertions(+)
>>
>> diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
>> index fa825c9f39..778e1dc2c9 100644
>> --- a/tools/xenlogd/io.c
>> +++ b/tools/xenlogd/io.c
>
>> @@ -600,6 +616,124 @@ static void p9_attach(device *device, struct p9_header *hdr)
>> fill_buffer(device, hdr->cmd + 1, hdr->tag, "Q", &qid);
>> }
>>
>> +static void p9_walk(device *device, struct p9_header *hdr)
>> +{
>> + uint32_t fid;
>> + uint32_t newfid;
>> + struct p9_fid *fidp;
>> + struct p9_qid *qids = NULL;
>> + unsigned int n_names = 0;
>> + unsigned int *names = NULL;
>> + unsigned int walked = 0;
>> + unsigned int i;
>> + char *path = NULL;
>> + unsigned int path_len;
>> + int ret;
>> +
>> + ret = fill_data(device, "UUaS", &fid, &newfid, &n_names, &names);
>> + if ( n_names > P9_WALK_MAXELEM )
>> + {
>> + p9_error(device, hdr->tag, EINVAL);
>> + goto out;
>> + }
>> + if ( ret != 3 + n_names )
>> + {
>> + p9_error(device, hdr->tag, errno);
>> + goto out;
>> + }
>> +
>> + fidp = find_fid(device, fid);
>> + if ( !fidp )
>> + {
>> + p9_error(device, hdr->tag, ENOENT);
>> + goto out;
>> + }
>> + if ( fidp->opened )
>> + {
>> + p9_error(device, hdr->tag, EINVAL);
>> + goto out;
>> + }
>
> https://ericvh.github.io/9p-rfc/rfc9p2000.html#anchor33
> """
> The fid must represent a directory unless zero path name elements are specified.
> """
> and
> """
> For the first elementwise walk to succeed, the file identified by fid
> must be a directory, and the implied user of the request must have
> permission to search the directory (see intro(5)). Subsequent
> elementwise walks have equivalent restrictions applied to the implicit
> fid that results from the preceding elementwise walk.
> """
>
> Maybe a dir check should be added? However, it doesn't look like QEMU
> does this check. Seems like it is implicitly checked by the path
> concatenation, so it may be fine as-is.
>
> If you think it's ok as-is:
> Reviewed-by: Jason Andryuk <jandryuk@gmail.com>
Thanks.
I think I'll leave it as is.
Juergen
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3149 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]
^ permalink raw reply [flat|nested] 81+ messages in thread
* [PATCH 09/29] tools/xenlogd: add 9pfs open request support
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
` (7 preceding siblings ...)
2023-11-01 9:33 ` [PATCH 08/29] tools/xenlogd: add 9pfs walk " Juergen Gross
@ 2023-11-01 9:33 ` Juergen Gross
2023-11-06 19:33 ` Jason Andryuk
2023-11-01 9:33 ` [PATCH 10/29] tools/xenlogd: add 9pfs clunk " Juergen Gross
` (19 subsequent siblings)
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:33 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Anthony PERARD
Add the open request of the 9pfs protocol.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/xenlogd/io.c | 130 ++++++++++++++++++++++++++++++++++++++++
tools/xenlogd/xenlogd.h | 4 ++
2 files changed, 134 insertions(+)
diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
index 778e1dc2c9..c2b259f42e 100644
--- a/tools/xenlogd/io.c
+++ b/tools/xenlogd/io.c
@@ -18,6 +18,8 @@
#include <syslog.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <dirent.h>
+#include <fcntl.h>
#include <xenctrl.h> /* For cpu barriers. */
#include <xen-tools/common-macros.h>
@@ -28,6 +30,15 @@
#define P9_CMD_ATTACH 104
#define P9_CMD_ERROR 107
#define P9_CMD_WALK 110
+#define P9_CMD_OPEN 112
+
+/* P9 protocol open flags. */
+#define P9_OREAD 0 /* read */
+#define P9_OWRITE 1 /* write */
+#define P9_ORDWR 2 /* read and write */
+#define P9_OMODEMASK 0x03
+#define P9_OTRUNC 0x10 /* or'ed in, truncate file first */
+#define P9_OREMOVE 0x40 /* or'ed in, remove file after clunk */
#define P9_MIN_MSIZE 2048
#define P9_VERSION "9P2000.u"
@@ -734,6 +745,121 @@ static void p9_walk(device *device, struct p9_header *hdr)
free(names);
}
+static int open_flags_from_mode(uint8_t mode)
+{
+ int flags;
+
+ switch ( mode & P9_OMODEMASK )
+ {
+ case P9_OREAD:
+ flags = O_RDONLY;
+ break;
+
+ case P9_OWRITE:
+ flags = O_WRONLY;
+ break;
+
+ case P9_ORDWR:
+ flags = O_RDWR;
+ break;
+
+ default:
+ return -1;
+ }
+
+ if ( mode & P9_OTRUNC )
+ flags |= O_TRUNC;
+
+ return flags;
+}
+
+static unsigned int get_iounit(device *device, struct stat *st)
+{
+ return (device->max_size - st->st_blksize) & ~(st->st_blksize - 1);
+}
+
+static void p9_open(device *device, struct p9_header *hdr)
+{
+ uint32_t fid;
+ uint8_t mode;
+ struct p9_fid *fidp;
+ struct stat st;
+ struct p9_qid qid;
+ uint32_t iounit;
+ int flags;
+ int ret;
+
+ ret = fill_data(device, "Ub", &fid, &mode);
+ if ( ret != 2 )
+ {
+ p9_error(device, hdr->tag, EINVAL);
+ return;
+ }
+ if ( mode & ~(P9_OMODEMASK | P9_OTRUNC | P9_OREMOVE) )
+ {
+ p9_error(device, hdr->tag, EINVAL);
+ return;
+ }
+
+ fidp = find_fid(device, fid);
+ if ( !fidp )
+ {
+ p9_error(device, hdr->tag, ENOENT);
+ return;
+ }
+ if ( fidp->opened )
+ {
+ p9_error(device, hdr->tag, EINVAL);
+ return;
+ }
+
+ if ( stat(fidp->path, &st) < 0 )
+ {
+ p9_error(device, hdr->tag, ENOENT);
+ return;
+ }
+
+ fidp->isdir = S_ISDIR(st.st_mode);
+ fidp->mode = mode;
+ if ( fidp->isdir )
+ {
+ if ( mode != P9_OREAD )
+ {
+ p9_error(device, hdr->tag, EINVAL);
+ return;
+ }
+ fidp->data = opendir(fidp->path);
+ if ( !fidp->data )
+ {
+ p9_error(device, hdr->tag, errno);
+ return;
+ }
+ fidp->fd = dirfd(fidp->data);
+ }
+ else
+ {
+ flags = open_flags_from_mode(mode);
+ if ( flags < 0 )
+ {
+ p9_error(device, hdr->tag, EINVAL);
+ return;
+ }
+
+ fidp->fd = open(fidp->path, flags);
+ if ( fidp->fd < 0 )
+ {
+ p9_error(device, hdr->tag, errno);
+ return;
+ }
+ }
+
+ fill_qid(fidp->path, &qid, &st);
+ iounit = get_iounit(device, &st);
+ fidp->opened = true;
+
+ fill_buffer(device, hdr->cmd + 1, hdr->tag, "QU", &qid, &iounit);
+}
+
void *io_thread(void *arg)
{
device *device = arg;
@@ -801,6 +927,10 @@ void *io_thread(void *arg)
p9_walk(device, &hdr);
break;
+ case P9_CMD_OPEN:
+ p9_open(device, &hdr);
+ break;
+
default:
syslog(LOG_DEBUG, "%u.%u sent unhandled command %u\n",
device->domid, device->devid, hdr.cmd);
diff --git a/tools/xenlogd/xenlogd.h b/tools/xenlogd/xenlogd.h
index 23f013af9e..6b7b5e2b91 100644
--- a/tools/xenlogd/xenlogd.h
+++ b/tools/xenlogd/xenlogd.h
@@ -22,7 +22,11 @@ struct p9_header {
struct p9_fid {
XEN_TAILQ_ENTRY(struct p9_fid) list;
unsigned int fid;
+ int fd;
+ uint8_t mode;
bool opened;
+ bool isdir;
+ void *data; /* File type specific. */
char path[];
};
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* Re: [PATCH 09/29] tools/xenlogd: add 9pfs open request support
2023-11-01 9:33 ` [PATCH 09/29] tools/xenlogd: add 9pfs open " Juergen Gross
@ 2023-11-06 19:33 ` Jason Andryuk
2023-11-07 7:03 ` Juergen Gross
0 siblings, 1 reply; 81+ messages in thread
From: Jason Andryuk @ 2023-11-06 19:33 UTC (permalink / raw)
To: Juergen Gross; +Cc: xen-devel, Wei Liu, Anthony PERARD
On Wed, Nov 1, 2023 at 6:13 AM Juergen Gross <jgross@suse.com> wrote:
>
> Add the open request of the 9pfs protocol.
>
> Signed-off-by: Juergen Gross <jgross@suse.com>
> ---
> tools/xenlogd/io.c | 130 ++++++++++++++++++++++++++++++++++++++++
> tools/xenlogd/xenlogd.h | 4 ++
> 2 files changed, 134 insertions(+)
>
> diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
> index 778e1dc2c9..c2b259f42e 100644
> --- a/tools/xenlogd/io.c
> +++ b/tools/xenlogd/io.c
> @@ -734,6 +745,121 @@ static void p9_walk(device *device, struct p9_header *hdr)
> free(names);
> }
>
> +static int open_flags_from_mode(uint8_t mode)
> +{
> + int flags;
> +
> + switch ( mode & P9_OMODEMASK )
> + {
> + case P9_OREAD:
> + flags = O_RDONLY;
> + break;
> +
> + case P9_OWRITE:
> + flags = O_WRONLY;
> + break;
> +
> + case P9_ORDWR:
> + flags = O_RDWR;
> + break;
> +
> + default:
> + return -1;
> + }
> +
> + if ( mode & P9_OTRUNC )
> + flags |= O_TRUNC;
"""
In addition, if mode has the OTRUNC (0x10) bit set, the file is to be
truncated, which requires write permission (if the file is
append-only, and permission is granted, the open succeeds but the file
will not be trun- cated);
"""
This relies on libc O_TRUNC handling - I think that is probably better
than something custom so you get the libc semantics.
> +
> + return flags;
> +}
> +
> +static unsigned int get_iounit(device *device, struct stat *st)
> +{
> + return (device->max_size - st->st_blksize) & ~(st->st_blksize - 1);
> +}
> +
> +static void p9_open(device *device, struct p9_header *hdr)
> +{
> + uint32_t fid;
> + uint8_t mode;
> + struct p9_fid *fidp;
> + struct stat st;
> + struct p9_qid qid;
> + uint32_t iounit;
> + int flags;
> + int ret;
> +
> + ret = fill_data(device, "Ub", &fid, &mode);
> + if ( ret != 2 )
> + {
> + p9_error(device, hdr->tag, EINVAL);
> + return;
> + }
> + if ( mode & ~(P9_OMODEMASK | P9_OTRUNC | P9_OREMOVE) )
> + {
> + p9_error(device, hdr->tag, EINVAL);
> + return;
> + }
> +
> + fidp = find_fid(device, fid);
> + if ( !fidp )
> + {
> + p9_error(device, hdr->tag, ENOENT);
If the host_path points at a populated directory, there is nothing
that populates the fids for pre-existing files and directories? So
those files cannot be opened? I guess that's not needed for
Xenstore-stubdom?
Thanks,
Jason
^ permalink raw reply [flat|nested] 81+ messages in thread* Re: [PATCH 09/29] tools/xenlogd: add 9pfs open request support
2023-11-06 19:33 ` Jason Andryuk
@ 2023-11-07 7:03 ` Juergen Gross
0 siblings, 0 replies; 81+ messages in thread
From: Juergen Gross @ 2023-11-07 7:03 UTC (permalink / raw)
To: Jason Andryuk; +Cc: xen-devel, Wei Liu, Anthony PERARD
[-- Attachment #1.1.1: Type: text/plain, Size: 2999 bytes --]
On 06.11.23 20:33, Jason Andryuk wrote:
> On Wed, Nov 1, 2023 at 6:13 AM Juergen Gross <jgross@suse.com> wrote:
>>
>> Add the open request of the 9pfs protocol.
>>
>> Signed-off-by: Juergen Gross <jgross@suse.com>
>> ---
>> tools/xenlogd/io.c | 130 ++++++++++++++++++++++++++++++++++++++++
>> tools/xenlogd/xenlogd.h | 4 ++
>> 2 files changed, 134 insertions(+)
>>
>> diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
>> index 778e1dc2c9..c2b259f42e 100644
>> --- a/tools/xenlogd/io.c
>> +++ b/tools/xenlogd/io.c
>
>> @@ -734,6 +745,121 @@ static void p9_walk(device *device, struct p9_header *hdr)
>> free(names);
>> }
>>
>> +static int open_flags_from_mode(uint8_t mode)
>> +{
>> + int flags;
>> +
>> + switch ( mode & P9_OMODEMASK )
>> + {
>> + case P9_OREAD:
>> + flags = O_RDONLY;
>> + break;
>> +
>> + case P9_OWRITE:
>> + flags = O_WRONLY;
>> + break;
>> +
>> + case P9_ORDWR:
>> + flags = O_RDWR;
>> + break;
>> +
>> + default:
>> + return -1;
>> + }
>> +
>> + if ( mode & P9_OTRUNC )
>> + flags |= O_TRUNC;
>
> """
> In addition, if mode has the OTRUNC (0x10) bit set, the file is to be
> truncated, which requires write permission (if the file is
> append-only, and permission is granted, the open succeeds but the file
> will not be trun- cated);
> """
>
> This relies on libc O_TRUNC handling - I think that is probably better
> than something custom so you get the libc semantics.
That was my thinking, yes.
>
>> +
>> + return flags;
>> +}
>> +
>> +static unsigned int get_iounit(device *device, struct stat *st)
>> +{
>> + return (device->max_size - st->st_blksize) & ~(st->st_blksize - 1);
>> +}
>> +
>> +static void p9_open(device *device, struct p9_header *hdr)
>> +{
>> + uint32_t fid;
>> + uint8_t mode;
>> + struct p9_fid *fidp;
>> + struct stat st;
>> + struct p9_qid qid;
>> + uint32_t iounit;
>> + int flags;
>> + int ret;
>> +
>> + ret = fill_data(device, "Ub", &fid, &mode);
>> + if ( ret != 2 )
>> + {
>> + p9_error(device, hdr->tag, EINVAL);
>> + return;
>> + }
>> + if ( mode & ~(P9_OMODEMASK | P9_OTRUNC | P9_OREMOVE) )
>> + {
>> + p9_error(device, hdr->tag, EINVAL);
>> + return;
>> + }
>> +
>> + fidp = find_fid(device, fid);
>> + if ( !fidp )
>> + {
>> + p9_error(device, hdr->tag, ENOENT);
>
> If the host_path points at a populated directory, there is nothing
> that populates the fids for pre-existing files and directories? So
> those files cannot be opened? I guess that's not needed for
> Xenstore-stubdom?
It is the guest which is associating a fid with a file. For opening an
existing file the guest should use the WALK command to walk the path from
a known fid (e.g. the root fid associated at ATTACH time) to the target
file.
Juergen
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3149 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]
^ permalink raw reply [flat|nested] 81+ messages in thread
* [PATCH 10/29] tools/xenlogd: add 9pfs clunk request support
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
` (8 preceding siblings ...)
2023-11-01 9:33 ` [PATCH 09/29] tools/xenlogd: add 9pfs open " Juergen Gross
@ 2023-11-01 9:33 ` Juergen Gross
2023-11-06 19:35 ` Jason Andryuk
2023-11-01 9:33 ` [PATCH 11/29] tools/xenlogd: add 9pfs create " Juergen Gross
` (18 subsequent siblings)
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:33 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Anthony PERARD
Add the clunk request of the 9pfs protocol.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/xenlogd/io.c | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
index c2b259f42e..2607095e51 100644
--- a/tools/xenlogd/io.c
+++ b/tools/xenlogd/io.c
@@ -31,6 +31,7 @@
#define P9_CMD_ERROR 107
#define P9_CMD_WALK 110
#define P9_CMD_OPEN 112
+#define P9_CMD_CLUNK 120
/* P9 protocol open flags. */
#define P9_OREAD 0 /* read */
@@ -860,6 +861,38 @@ static void p9_open(device *device, struct p9_header *hdr)
fill_buffer(device, hdr->cmd + 1, hdr->tag, "QU", &qid, &iounit);
}
+static void p9_clunk(device *device, struct p9_header *hdr)
+{
+ uint32_t fid;
+ struct p9_fid *fidp;
+ int ret;
+
+ ret = fill_data(device, "U", &fid);
+ if ( ret != 1 )
+ {
+ p9_error(device, hdr->tag, EINVAL);
+ return;
+ }
+
+ fidp = find_fid(device, fid);
+ if ( !fidp )
+ {
+ p9_error(device, hdr->tag, ENOENT);
+ return;
+ }
+
+ if ( fidp->opened )
+ {
+ close(fidp->fd);
+ if ( fidp->mode & P9_OREMOVE )
+ unlink(fidp->path);
+ }
+
+ free_fid(device, fidp);
+
+ fill_buffer(device, hdr->cmd + 1, hdr->tag, "");
+}
+
void *io_thread(void *arg)
{
device *device = arg;
@@ -931,6 +964,10 @@ void *io_thread(void *arg)
p9_open(device, &hdr);
break;
+ case P9_CMD_CLUNK:
+ p9_clunk(device, &hdr);
+ break;
+
default:
syslog(LOG_DEBUG, "%u.%u sent unhandled command %u\n",
device->domid, device->devid, hdr.cmd);
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH 11/29] tools/xenlogd: add 9pfs create request support
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
` (9 preceding siblings ...)
2023-11-01 9:33 ` [PATCH 10/29] tools/xenlogd: add 9pfs clunk " Juergen Gross
@ 2023-11-01 9:33 ` Juergen Gross
2023-11-06 19:53 ` Jason Andryuk
2023-11-01 9:33 ` [PATCH 12/29] tools/xenlogd: add 9pfs stat " Juergen Gross
` (17 subsequent siblings)
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:33 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Anthony PERARD
Add the create request of the 9pfs protocol.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/xenlogd/io.c | 133 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 133 insertions(+)
diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
index 2607095e51..34f137be1b 100644
--- a/tools/xenlogd/io.c
+++ b/tools/xenlogd/io.c
@@ -31,6 +31,7 @@
#define P9_CMD_ERROR 107
#define P9_CMD_WALK 110
#define P9_CMD_OPEN 112
+#define P9_CMD_CREATE 114
#define P9_CMD_CLUNK 120
/* P9 protocol open flags. */
@@ -41,6 +42,12 @@
#define P9_OTRUNC 0x10 /* or'ed in, truncate file first */
#define P9_OREMOVE 0x40 /* or'ed in, remove file after clunk */
+/* P9 protocol create permission masks. */
+#define P9_CREATE_PERM_DIR 0x80000000
+#define P9_CREATE_PERM_NOTSUPP 0x03b00000 /* link, symlink, ... */
+#define P9_CREATE_PERM_DIR_MASK 0777
+#define P9_CREATE_PERM_FILE_MASK 0666
+
#define P9_MIN_MSIZE 2048
#define P9_VERSION "9P2000.u"
#define P9_WALK_MAXELEM 16
@@ -861,6 +868,128 @@ static void p9_open(device *device, struct p9_header *hdr)
fill_buffer(device, hdr->cmd + 1, hdr->tag, "QU", &qid, &iounit);
}
+static void p9_create(device *device, struct p9_header *hdr)
+{
+ uint32_t fid;
+ unsigned int name_off;
+ uint32_t perm;
+ uint8_t mode;
+ unsigned int ext_off;
+ struct p9_fid *fidp;
+ struct p9_fid *new_fidp;
+ char *path;
+ struct stat st;
+ struct p9_qid qid;
+ uint32_t iounit;
+ int flags;
+ int ret;
+
+ ret = fill_data(device, "USUbS", &fid, &name_off, &perm, &mode, &ext_off);
+ if ( ret != 5 )
+ {
+ p9_error(device, hdr->tag, EINVAL);
+ return;
+ }
+
+ if ( !name_ok(device->str + name_off) )
+ {
+ p9_error(device, hdr->tag, ENOENT);
+ return;
+ }
+
+ if ( perm & P9_CREATE_PERM_NOTSUPP )
+ {
+ p9_error(device, hdr->tag, EINVAL);
+ return;
+ }
+
+ fidp = find_fid(device, fid);
+ if ( !fidp || fidp->opened )
+ {
+ p9_error(device, hdr->tag, EINVAL);
+ return;
+ }
+
+ path = malloc(strlen(fidp->path) + strlen(device->str + name_off) + 2 -
+ strlen(device->host_path));
+ if ( !path )
+ {
+ p9_error(device, hdr->tag, ENOMEM);
+ return;
+ }
+ sprintf(path, "%s/%s", fidp->path + strlen(device->host_path),
+ device->str + name_off);
+ new_fidp = alloc_fid_mem(device, fid, path);
+ free(path);
+ if ( !new_fidp )
+ {
+ p9_error(device, hdr->tag, ENOMEM);
+ return;
+ }
+
+ if ( perm & P9_CREATE_PERM_DIR )
+ {
+ if ( mode != P9_OREAD )
+ {
+ p9_error(device, hdr->tag, EINVAL);
+ free(new_fidp);
+ return;
+ }
+ if ( mkdir(new_fidp->path, perm & P9_CREATE_PERM_DIR_MASK) < 0 )
+ {
+ p9_error(device, hdr->tag, errno);
+ free(new_fidp);
+ return;
+ }
+
+ XEN_TAILQ_REMOVE(&device->fids, fidp, list);
+ XEN_TAILQ_INSERT_HEAD(&device->fids, new_fidp, list);
+ free(fidp);
+ fidp = new_fidp;
+
+ fidp->data = opendir(fidp->path);
+ if ( !fidp->data )
+ {
+ p9_error(device, hdr->tag, errno);
+ return;
+ }
+ fidp->fd = dirfd(fidp->data);
+ }
+ else
+ {
+ flags = open_flags_from_mode(mode);
+ if ( flags < 0 )
+ {
+ p9_error(device, hdr->tag, EINVAL);
+ free(new_fidp);
+ return;
+ }
+
+ XEN_TAILQ_REMOVE(&device->fids, fidp, list);
+ XEN_TAILQ_INSERT_HEAD(&device->fids, new_fidp, list);
+ free(fidp);
+ fidp = new_fidp;
+
+ fidp->fd = creat(fidp->path, flags);
+ if ( fidp->fd < 0 )
+ {
+ p9_error(device, hdr->tag, errno);
+ return;
+ }
+ }
+
+ if ( stat(fidp->path, &st) < 0 )
+ {
+ p9_error(device, hdr->tag, errno);
+ return;
+ }
+ fill_qid(fidp->path, &qid, &st);
+ iounit = get_iounit(device, &st);
+ fidp->opened = true;
+
+ fill_buffer(device, hdr->cmd + 1, hdr->tag, "QU", &qid, &iounit);
+}
+
static void p9_clunk(device *device, struct p9_header *hdr)
{
uint32_t fid;
@@ -964,6 +1093,10 @@ void *io_thread(void *arg)
p9_open(device, &hdr);
break;
+ case P9_CMD_CREATE:
+ p9_create(device, &hdr);
+ break;
+
case P9_CMD_CLUNK:
p9_clunk(device, &hdr);
break;
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* Re: [PATCH 11/29] tools/xenlogd: add 9pfs create request support
2023-11-01 9:33 ` [PATCH 11/29] tools/xenlogd: add 9pfs create " Juergen Gross
@ 2023-11-06 19:53 ` Jason Andryuk
2023-11-07 7:15 ` Juergen Gross
0 siblings, 1 reply; 81+ messages in thread
From: Jason Andryuk @ 2023-11-06 19:53 UTC (permalink / raw)
To: Juergen Gross; +Cc: xen-devel, Wei Liu, Anthony PERARD
On Wed, Nov 1, 2023 at 6:48 AM Juergen Gross <jgross@suse.com> wrote:
>
> Add the create request of the 9pfs protocol.
>
> Signed-off-by: Juergen Gross <jgross@suse.com>
> ---
> tools/xenlogd/io.c | 133 +++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 133 insertions(+)
>
> diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
> index 2607095e51..34f137be1b 100644
> --- a/tools/xenlogd/io.c
> +++ b/tools/xenlogd/io.c
> @@ -31,6 +31,7 @@
> #define P9_CMD_ERROR 107
> #define P9_CMD_WALK 110
> #define P9_CMD_OPEN 112
> +#define P9_CMD_CREATE 114
> #define P9_CMD_CLUNK 120
>
> /* P9 protocol open flags. */
> @@ -41,6 +42,12 @@
> #define P9_OTRUNC 0x10 /* or'ed in, truncate file first */
> #define P9_OREMOVE 0x40 /* or'ed in, remove file after clunk */
>
> +/* P9 protocol create permission masks. */
> +#define P9_CREATE_PERM_DIR 0x80000000
> +#define P9_CREATE_PERM_NOTSUPP 0x03b00000 /* link, symlink, ... */
> +#define P9_CREATE_PERM_DIR_MASK 0777
> +#define P9_CREATE_PERM_FILE_MASK 0666
> +
> #define P9_MIN_MSIZE 2048
> #define P9_VERSION "9P2000.u"
> #define P9_WALK_MAXELEM 16
> @@ -861,6 +868,128 @@ static void p9_open(device *device, struct p9_header *hdr)
> fill_buffer(device, hdr->cmd + 1, hdr->tag, "QU", &qid, &iounit);
> }
>
> +static void p9_create(device *device, struct p9_header *hdr)
> +{
> + uint32_t fid;
> + unsigned int name_off;
> + uint32_t perm;
> + uint8_t mode;
> + unsigned int ext_off;
> + struct p9_fid *fidp;
> + struct p9_fid *new_fidp;
> + char *path;
> + struct stat st;
> + struct p9_qid qid;
> + uint32_t iounit;
> + int flags;
> + int ret;
> +
> + ret = fill_data(device, "USUbS", &fid, &name_off, &perm, &mode, &ext_off);
> + if ( ret != 5 )
> + {
> + p9_error(device, hdr->tag, EINVAL);
> + return;
> + }
> +
> + if ( !name_ok(device->str + name_off) )
> + {
> + p9_error(device, hdr->tag, ENOENT);
> + return;
> + }
> +
> + if ( perm & P9_CREATE_PERM_NOTSUPP )
> + {
> + p9_error(device, hdr->tag, EINVAL);
> + return;
> + }
> +
> + fidp = find_fid(device, fid);
> + if ( !fidp || fidp->opened )
> + {
> + p9_error(device, hdr->tag, EINVAL);
> + return;
> + }
> +
> + path = malloc(strlen(fidp->path) + strlen(device->str + name_off) + 2 -
> + strlen(device->host_path));
> + if ( !path )
> + {
> + p9_error(device, hdr->tag, ENOMEM);
> + return;
> + }
> + sprintf(path, "%s/%s", fidp->path + strlen(device->host_path),
> + device->str + name_off);
> + new_fidp = alloc_fid_mem(device, fid, path);
> + free(path);
> + if ( !new_fidp )
> + {
> + p9_error(device, hdr->tag, ENOMEM);
> + return;
> + }
> +
> + if ( perm & P9_CREATE_PERM_DIR )
> + {
> + if ( mode != P9_OREAD )
> + {
> + p9_error(device, hdr->tag, EINVAL);
> + free(new_fidp);
> + return;
> + }
> + if ( mkdir(new_fidp->path, perm & P9_CREATE_PERM_DIR_MASK) < 0 )
> + {
> + p9_error(device, hdr->tag, errno);
> + free(new_fidp);
> + return;
> + }
> +
> + XEN_TAILQ_REMOVE(&device->fids, fidp, list);
> + XEN_TAILQ_INSERT_HEAD(&device->fids, new_fidp, list);
> + free(fidp);
> + fidp = new_fidp;
> +
> + fidp->data = opendir(fidp->path);
> + if ( !fidp->data )
> + {
> + p9_error(device, hdr->tag, errno);
> + return;
> + }
> + fidp->fd = dirfd(fidp->data);
> + }
> + else
> + {
> + flags = open_flags_from_mode(mode);
> + if ( flags < 0 )
> + {
> + p9_error(device, hdr->tag, EINVAL);
> + free(new_fidp);
> + return;
> + }
> +
> + XEN_TAILQ_REMOVE(&device->fids, """fidp, list);
> + XEN_TAILQ_INSERT_HEAD(&device->fids, new_fidp, list);
> + free(fidp);
> + fidp = new_fidp;
> +
> + fidp->fd = creat(fidp->path, flags);
https://ericvh.github.io/9p-rfc/rfc9p2000.html#anchor29
"""
The create request asks the file server to create a new file with the
name supplied, in the directory (dir) represented by fid, and requires
write permission in the directory. The owner of the file is the
implied user id of the request, the group of the file is the same as
dir, and the permissions are the value of
perm & (~0666 | (dir.perm & 0666))
if a regular file is being created and
perm & (~0777 | (dir.perm & 0777))
if a directory is being created. This means, for example, that if the
create allows read permission to others, but the containing directory
does not, then the created file will not allow others to read the
file.
"""
So P9_CREATE_PERM_FILE_MASK (which is otherwise unused) should be
incorporated. Also the mode and the permissions are handled
independently:
"""
Finally, the newly created file is opened according to mode, and fid
will represent the newly opened file. Mode is not checked against the
permissions in perm.
"""
I think fidp->mode should be set in here somewhere based on mode. And
`flags` for creat should be derived from the incoming perms.
Regards,
Jason
^ permalink raw reply [flat|nested] 81+ messages in thread* Re: [PATCH 11/29] tools/xenlogd: add 9pfs create request support
2023-11-06 19:53 ` Jason Andryuk
@ 2023-11-07 7:15 ` Juergen Gross
0 siblings, 0 replies; 81+ messages in thread
From: Juergen Gross @ 2023-11-07 7:15 UTC (permalink / raw)
To: Jason Andryuk; +Cc: xen-devel, Wei Liu, Anthony PERARD
[-- Attachment #1.1.1: Type: text/plain, Size: 5778 bytes --]
On 06.11.23 20:53, Jason Andryuk wrote:
> On Wed, Nov 1, 2023 at 6:48 AM Juergen Gross <jgross@suse.com> wrote:
>>
>> Add the create request of the 9pfs protocol.
>>
>> Signed-off-by: Juergen Gross <jgross@suse.com>
>> ---
>> tools/xenlogd/io.c | 133 +++++++++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 133 insertions(+)
>>
>> diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
>> index 2607095e51..34f137be1b 100644
>> --- a/tools/xenlogd/io.c
>> +++ b/tools/xenlogd/io.c
>> @@ -31,6 +31,7 @@
>> #define P9_CMD_ERROR 107
>> #define P9_CMD_WALK 110
>> #define P9_CMD_OPEN 112
>> +#define P9_CMD_CREATE 114
>> #define P9_CMD_CLUNK 120
>>
>> /* P9 protocol open flags. */
>> @@ -41,6 +42,12 @@
>> #define P9_OTRUNC 0x10 /* or'ed in, truncate file first */
>> #define P9_OREMOVE 0x40 /* or'ed in, remove file after clunk */
>>
>> +/* P9 protocol create permission masks. */
>> +#define P9_CREATE_PERM_DIR 0x80000000
>> +#define P9_CREATE_PERM_NOTSUPP 0x03b00000 /* link, symlink, ... */
>> +#define P9_CREATE_PERM_DIR_MASK 0777
>> +#define P9_CREATE_PERM_FILE_MASK 0666
>> +
>> #define P9_MIN_MSIZE 2048
>> #define P9_VERSION "9P2000.u"
>> #define P9_WALK_MAXELEM 16
>> @@ -861,6 +868,128 @@ static void p9_open(device *device, struct p9_header *hdr)
>> fill_buffer(device, hdr->cmd + 1, hdr->tag, "QU", &qid, &iounit);
>> }
>>
>> +static void p9_create(device *device, struct p9_header *hdr)
>> +{
>> + uint32_t fid;
>> + unsigned int name_off;
>> + uint32_t perm;
>> + uint8_t mode;
>> + unsigned int ext_off;
>> + struct p9_fid *fidp;
>> + struct p9_fid *new_fidp;
>> + char *path;
>> + struct stat st;
>> + struct p9_qid qid;
>> + uint32_t iounit;
>> + int flags;
>> + int ret;
>> +
>> + ret = fill_data(device, "USUbS", &fid, &name_off, &perm, &mode, &ext_off);
>> + if ( ret != 5 )
>> + {
>> + p9_error(device, hdr->tag, EINVAL);
>> + return;
>> + }
>> +
>> + if ( !name_ok(device->str + name_off) )
>> + {
>> + p9_error(device, hdr->tag, ENOENT);
>> + return;
>> + }
>> +
>> + if ( perm & P9_CREATE_PERM_NOTSUPP )
>> + {
>> + p9_error(device, hdr->tag, EINVAL);
>> + return;
>> + }
>> +
>> + fidp = find_fid(device, fid);
>> + if ( !fidp || fidp->opened )
>> + {
>> + p9_error(device, hdr->tag, EINVAL);
>> + return;
>> + }
>> +
>> + path = malloc(strlen(fidp->path) + strlen(device->str + name_off) + 2 -
>> + strlen(device->host_path));
>> + if ( !path )
>> + {
>> + p9_error(device, hdr->tag, ENOMEM);
>> + return;
>> + }
>> + sprintf(path, "%s/%s", fidp->path + strlen(device->host_path),
>> + device->str + name_off);
>> + new_fidp = alloc_fid_mem(device, fid, path);
>> + free(path);
>> + if ( !new_fidp )
>> + {
>> + p9_error(device, hdr->tag, ENOMEM);
>> + return;
>> + }
>> +
>> + if ( perm & P9_CREATE_PERM_DIR )
>> + {
>> + if ( mode != P9_OREAD )
>> + {
>> + p9_error(device, hdr->tag, EINVAL);
>> + free(new_fidp);
>> + return;
>> + }
>> + if ( mkdir(new_fidp->path, perm & P9_CREATE_PERM_DIR_MASK) < 0 )
>> + {
>> + p9_error(device, hdr->tag, errno);
>> + free(new_fidp);
>> + return;
>> + }
>> +
>> + XEN_TAILQ_REMOVE(&device->fids, fidp, list);
>> + XEN_TAILQ_INSERT_HEAD(&device->fids, new_fidp, list);
>> + free(fidp);
>> + fidp = new_fidp;
>> +
>> + fidp->data = opendir(fidp->path);
>> + if ( !fidp->data )
>> + {
>> + p9_error(device, hdr->tag, errno);
>> + return;
>> + }
>> + fidp->fd = dirfd(fidp->data);
>> + }
>> + else
>> + {
>> + flags = open_flags_from_mode(mode);
>> + if ( flags < 0 )
>> + {
>> + p9_error(device, hdr->tag, EINVAL);
>> + free(new_fidp);
>> + return;
>> + }
>> +
>> + XEN_TAILQ_REMOVE(&device->fids, """fidp, list);
>> + XEN_TAILQ_INSERT_HEAD(&device->fids, new_fidp, list);
>> + free(fidp);
>> + fidp = new_fidp;
>> +
>> + fidp->fd = creat(fidp->path, flags);
>
> https://ericvh.github.io/9p-rfc/rfc9p2000.html#anchor29
> """
> The create request asks the file server to create a new file with the
> name supplied, in the directory (dir) represented by fid, and requires
> write permission in the directory. The owner of the file is the
> implied user id of the request, the group of the file is the same as
> dir, and the permissions are the value of
>
> perm & (~0666 | (dir.perm & 0666))
>
> if a regular file is being created and
>
> perm & (~0777 | (dir.perm & 0777))
>
> if a directory is being created. This means, for example, that if the
> create allows read permission to others, but the containing directory
> does not, then the created file will not allow others to read the
> file.
> """
>
> So P9_CREATE_PERM_FILE_MASK (which is otherwise unused) should be
> incorporated. Also the mode and the permissions are handled
> independently:
> """
> Finally, the newly created file is opened according to mode, and fid
> will represent the newly opened file. Mode is not checked against the
> permissions in perm.
> """
>
> I think fidp->mode should be set in here somewhere based on mode. And
> `flags` for creat should be derived from the incoming perms.
Yes, I agree.
Juergen
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3149 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]
^ permalink raw reply [flat|nested] 81+ messages in thread
* [PATCH 12/29] tools/xenlogd: add 9pfs stat request support
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
` (10 preceding siblings ...)
2023-11-01 9:33 ` [PATCH 11/29] tools/xenlogd: add 9pfs create " Juergen Gross
@ 2023-11-01 9:33 ` Juergen Gross
2023-11-07 14:04 ` Jason Andryuk
2023-11-01 9:33 ` [PATCH 13/29] tools/xenlogd: add 9pfs write " Juergen Gross
` (16 subsequent siblings)
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:33 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Anthony PERARD
Add the stat request of the 9pfs protocol.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/xenlogd/io.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 89 insertions(+)
diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
index 34f137be1b..6e92667fab 100644
--- a/tools/xenlogd/io.c
+++ b/tools/xenlogd/io.c
@@ -33,6 +33,7 @@
#define P9_CMD_OPEN 112
#define P9_CMD_CREATE 114
#define P9_CMD_CLUNK 120
+#define P9_CMD_STAT 124
/* P9 protocol open flags. */
#define P9_OREAD 0 /* read */
@@ -59,6 +60,25 @@ struct p9_qid {
uint64_t path;
};
+struct p9_stat {
+ uint16_t size;
+ uint16_t type;
+ uint32_t dev;
+ struct p9_qid qid;
+ uint32_t mode;
+ uint32_t atime;
+ uint32_t mtime;
+ uint64_t length;
+ const char *name;
+ const char *uid;
+ const char *gid;
+ const char *muid;
+ const char *extension;
+ uint32_t n_uid;
+ uint32_t n_gid;
+ uint32_t n_muid;
+};
+
/*
* Note that the ring names "in" and "out" are from the frontend's
* perspective, so the "in" ring will be used for responses to the frontend,
@@ -1022,6 +1042,71 @@ static void p9_clunk(device *device, struct p9_header *hdr)
fill_buffer(device, hdr->cmd + 1, hdr->tag, "");
}
+static void fill_p9_stat(struct p9_stat *p9s, struct stat *st, const char *name)
+{
+ memset(p9s, 0, sizeof(*p9s));
+ fill_qid(NULL, &p9s->qid, st);
+ p9s->mode = st->st_mode & 0777;
+ if ( S_ISDIR(st->st_mode) )
+ p9s->mode |= P9_CREATE_PERM_DIR;
+ p9s->atime = st->st_atime;
+ p9s->mtime = st->st_mtime;
+ p9s->length = st->st_size;
+ p9s->name = name;
+ p9s->uid = "";
+ p9s->gid = "";
+ p9s->muid = "";
+ p9s->extension = "";
+ p9s->n_uid = 0;
+ p9s->n_gid = 0;
+ p9s->n_muid = 0;
+
+ /*
+ * Size of individual fields without the size field, including 5 2-byte
+ * string length fields.
+ */
+ p9s->size = 71 + strlen(p9s->name);
+}
+
+static void p9_stat(device *device, struct p9_header *hdr)
+{
+ uint32_t fid;
+ struct p9_fid *fidp;
+ struct p9_stat p9s;
+ struct stat st;
+ uint16_t total_length;
+ int ret;
+
+ ret = fill_data(device, "U", &fid);
+ if ( ret != 1 )
+ {
+ p9_error(device, hdr->tag, EINVAL);
+ return;
+ }
+
+ fidp = find_fid(device, fid);
+ if ( !fidp )
+ {
+ p9_error(device, hdr->tag, ENOENT);
+ return;
+ }
+
+ if ( stat(fidp->path, &st) < 0 )
+ {
+ p9_error(device, hdr->tag, errno);
+ return;
+ }
+ fill_p9_stat(&p9s, &st, strrchr(fidp->path, '/') + 1);
+
+ total_length = p9s.size + sizeof(p9s.size);
+ fill_buffer(device, hdr->cmd + 1, hdr->tag, "uuuUQUUULSSSSSUUU",
+ &total_length, &p9s.size, &p9s.type, &p9s.dev, &p9s.qid,
+ &p9s.mode, &p9s.atime, &p9s.mtime, &p9s.length, p9s.name,
+ p9s.uid, p9s.gid, p9s.muid, p9s.extension, &p9s.n_uid,
+ &p9s.n_gid, &p9s.n_muid);
+
+}
+
void *io_thread(void *arg)
{
device *device = arg;
@@ -1101,6 +1186,10 @@ void *io_thread(void *arg)
p9_clunk(device, &hdr);
break;
+ case P9_CMD_STAT:
+ p9_stat(device, &hdr);
+ break;
+
default:
syslog(LOG_DEBUG, "%u.%u sent unhandled command %u\n",
device->domid, device->devid, hdr.cmd);
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* Re: [PATCH 12/29] tools/xenlogd: add 9pfs stat request support
2023-11-01 9:33 ` [PATCH 12/29] tools/xenlogd: add 9pfs stat " Juergen Gross
@ 2023-11-07 14:04 ` Jason Andryuk
2023-11-07 14:42 ` Juergen Gross
0 siblings, 1 reply; 81+ messages in thread
From: Jason Andryuk @ 2023-11-07 14:04 UTC (permalink / raw)
To: Juergen Gross; +Cc: xen-devel, Wei Liu, Anthony PERARD
On Wed, Nov 1, 2023 at 5:34 AM Juergen Gross <jgross@suse.com> wrote:
>
> Add the stat request of the 9pfs protocol.
>
> Signed-off-by: Juergen Gross <jgross@suse.com>
> ---
> tools/xenlogd/io.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 89 insertions(+)
>
> diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
> index 34f137be1b..6e92667fab 100644
> --- a/tools/xenlogd/io.c
> +++ b/tools/xenlogd/io.c
> @@ -33,6 +33,7 @@
> +static void fill_p9_stat(struct p9_stat *p9s, struct stat *st, const char *name)
> +{
> + memset(p9s, 0, sizeof(*p9s));
> + fill_qid(NULL, &p9s->qid, st);
> + p9s->mode = st->st_mode & 0777;
> + if ( S_ISDIR(st->st_mode) )
> + p9s->mode |= P9_CREATE_PERM_DIR;
> + p9s->atime = st->st_atime;
> + p9s->mtime = st->st_mtime;
> + p9s->length = st->st_size;
> + p9s->name = name;
> + p9s->uid = "";
> + p9s->gid = "";
> + p9s->muid = "";
> + p9s->extension = "";
> + p9s->n_uid = 0;
> + p9s->n_gid = 0;
If the daemon is running as root and managing the directories, these
probably match. Still, do we want uid & gid to be populated from the
stat struct?
> + p9s->n_muid = 0;
> +
> + /*
> + * Size of individual fields without the size field, including 5 2-byte
> + * string length fields.
> + */
> + p9s->size = 71 + strlen(p9s->name);
> +}
> +
> +static void p9_stat(device *device, struct p9_header *hdr)
> +{
> + uint32_t fid;
> + struct p9_fid *fidp;
> + struct p9_stat p9s;
> + struct stat st;
> + uint16_t total_length;
total_length = 0;
Otherwise it is used uninitialized.
Regards,
Jason
^ permalink raw reply [flat|nested] 81+ messages in thread* Re: [PATCH 12/29] tools/xenlogd: add 9pfs stat request support
2023-11-07 14:04 ` Jason Andryuk
@ 2023-11-07 14:42 ` Juergen Gross
2023-11-07 14:48 ` Jason Andryuk
0 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-07 14:42 UTC (permalink / raw)
To: Jason Andryuk; +Cc: xen-devel, Wei Liu, Anthony PERARD
[-- Attachment #1.1.1: Type: text/plain, Size: 2079 bytes --]
On 07.11.23 15:04, Jason Andryuk wrote:
> On Wed, Nov 1, 2023 at 5:34 AM Juergen Gross <jgross@suse.com> wrote:
>>
>> Add the stat request of the 9pfs protocol.
>>
>> Signed-off-by: Juergen Gross <jgross@suse.com>
>> ---
>> tools/xenlogd/io.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 89 insertions(+)
>>
>> diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
>> index 34f137be1b..6e92667fab 100644
>> --- a/tools/xenlogd/io.c
>> +++ b/tools/xenlogd/io.c
>> @@ -33,6 +33,7 @@
>
>> +static void fill_p9_stat(struct p9_stat *p9s, struct stat *st, const char *name)
>> +{
>> + memset(p9s, 0, sizeof(*p9s));
>> + fill_qid(NULL, &p9s->qid, st);
>> + p9s->mode = st->st_mode & 0777;
>> + if ( S_ISDIR(st->st_mode) )
>> + p9s->mode |= P9_CREATE_PERM_DIR;
>> + p9s->atime = st->st_atime;
>> + p9s->mtime = st->st_mtime;
>> + p9s->length = st->st_size;
>> + p9s->name = name;
>> + p9s->uid = "";
>> + p9s->gid = "";
>> + p9s->muid = "";
>> + p9s->extension = "";
>> + p9s->n_uid = 0;
>> + p9s->n_gid = 0;
>
> If the daemon is running as root and managing the directories, these
> probably match. Still, do we want uid & gid to be populated from the
> stat struct?
I wouldn't want to do that. In the end the permissions of the daemon are
relevant for being able to access the files. There is no need to leak any
uids and gids from the host to the guests.
>
>> + p9s->n_muid = 0;
>> +
>> + /*
>> + * Size of individual fields without the size field, including 5 2-byte
>> + * string length fields.
>> + */
>> + p9s->size = 71 + strlen(p9s->name);
>> +}
>> +
>> +static void p9_stat(device *device, struct p9_header *hdr)
>> +{
>> + uint32_t fid;
>> + struct p9_fid *fidp;
>> + struct p9_stat p9s;
>> + struct stat st;
>> + uint16_t total_length;
>
> total_length = 0;
>
> Otherwise it is used uninitialized.
I don't think so. There is a single user just after setting the variable.
Juergen
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3149 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]
^ permalink raw reply [flat|nested] 81+ messages in thread* Re: [PATCH 12/29] tools/xenlogd: add 9pfs stat request support
2023-11-07 14:42 ` Juergen Gross
@ 2023-11-07 14:48 ` Jason Andryuk
2023-11-07 15:20 ` Jason Andryuk
0 siblings, 1 reply; 81+ messages in thread
From: Jason Andryuk @ 2023-11-07 14:48 UTC (permalink / raw)
To: Juergen Gross; +Cc: xen-devel, Wei Liu, Anthony PERARD
On Tue, Nov 7, 2023 at 9:42 AM Juergen Gross <jgross@suse.com> wrote:
>
> On 07.11.23 15:04, Jason Andryuk wrote:
> > On Wed, Nov 1, 2023 at 5:34 AM Juergen Gross <jgross@suse.com> wrote:
> >>
> >> Add the stat request of the 9pfs protocol.
> >>
> >> Signed-off-by: Juergen Gross <jgross@suse.com>
> >> ---
> >> tools/xenlogd/io.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++
> >> 1 file changed, 89 insertions(+)
> >>
> >> diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
> >> index 34f137be1b..6e92667fab 100644
> >> --- a/tools/xenlogd/io.c
> >> +++ b/tools/xenlogd/io.c
> >> @@ -33,6 +33,7 @@
> >
> >> +static void fill_p9_stat(struct p9_stat *p9s, struct stat *st, const char *name)
> >> +{
> >> + memset(p9s, 0, sizeof(*p9s));
> >> + fill_qid(NULL, &p9s->qid, st);
> >> + p9s->mode = st->st_mode & 0777;
> >> + if ( S_ISDIR(st->st_mode) )
> >> + p9s->mode |= P9_CREATE_PERM_DIR;
> >> + p9s->atime = st->st_atime;
> >> + p9s->mtime = st->st_mtime;
> >> + p9s->length = st->st_size;
> >> + p9s->name = name;
> >> + p9s->uid = "";
> >> + p9s->gid = "";
> >> + p9s->muid = "";
> >> + p9s->extension = "";
> >> + p9s->n_uid = 0;
> >> + p9s->n_gid = 0;
> >
> > If the daemon is running as root and managing the directories, these
> > probably match. Still, do we want uid & gid to be populated from the
> > stat struct?
>
> I wouldn't want to do that. In the end the permissions of the daemon are
> relevant for being able to access the files. There is no need to leak any
> uids and gids from the host to the guests.
Ok.
> >
> >> + p9s->n_muid = 0;
> >> +
> >> + /*
> >> + * Size of individual fields without the size field, including 5 2-byte
> >> + * string length fields.
> >> + */
> >> + p9s->size = 71 + strlen(p9s->name);
> >> +}
> >> +
> >> +static void p9_stat(device *device, struct p9_header *hdr)
> >> +{
> >> + uint32_t fid;
> >> + struct p9_fid *fidp;
> >> + struct p9_stat p9s;
> >> + struct stat st;
> >> + uint16_t total_length;
> >
> > total_length = 0;
> >
> > Otherwise it is used uninitialized.
>
> I don't think so. There is a single user just after setting the variable.
Whoops - you are right. Sorry for the noise.
Regards,
Jason
^ permalink raw reply [flat|nested] 81+ messages in thread* Re: [PATCH 12/29] tools/xenlogd: add 9pfs stat request support
2023-11-07 14:48 ` Jason Andryuk
@ 2023-11-07 15:20 ` Jason Andryuk
0 siblings, 0 replies; 81+ messages in thread
From: Jason Andryuk @ 2023-11-07 15:20 UTC (permalink / raw)
To: Juergen Gross; +Cc: xen-devel, Wei Liu, Anthony PERARD
On Tue, Nov 7, 2023 at 9:48 AM Jason Andryuk <jandryuk@gmail.com> wrote:
>
> On Tue, Nov 7, 2023 at 9:42 AM Juergen Gross <jgross@suse.com> wrote:
> >
> > On 07.11.23 15:04, Jason Andryuk wrote:
> > > On Wed, Nov 1, 2023 at 5:34 AM Juergen Gross <jgross@suse.com> wrote:
> > >>
> > >> Add the stat request of the 9pfs protocol.
> > >>
> > >> Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Jason Andryuk <jandryuk@gmail.com>
^ permalink raw reply [flat|nested] 81+ messages in thread
* [PATCH 13/29] tools/xenlogd: add 9pfs write request support
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
` (11 preceding siblings ...)
2023-11-01 9:33 ` [PATCH 12/29] tools/xenlogd: add 9pfs stat " Juergen Gross
@ 2023-11-01 9:33 ` Juergen Gross
2023-11-07 14:10 ` Jason Andryuk
2023-11-01 9:33 ` [PATCH 14/29] tools/xenlogd: add 9pfs read " Juergen Gross
` (15 subsequent siblings)
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:33 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Anthony PERARD
Add the write request of the 9pfs protocol.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/xenlogd/io.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
index 6e92667fab..6b4692ca67 100644
--- a/tools/xenlogd/io.c
+++ b/tools/xenlogd/io.c
@@ -32,6 +32,7 @@
#define P9_CMD_WALK 110
#define P9_CMD_OPEN 112
#define P9_CMD_CREATE 114
+#define P9_CMD_WRITE 118
#define P9_CMD_CLUNK 120
#define P9_CMD_STAT 124
@@ -1010,6 +1011,51 @@ static void p9_create(device *device, struct p9_header *hdr)
fill_buffer(device, hdr->cmd + 1, hdr->tag, "QU", &qid, &iounit);
}
+static void p9_write(device *device, struct p9_header *hdr)
+{
+ uint32_t fid;
+ uint64_t off;
+ unsigned int len;
+ uint32_t written;
+ void *buf;
+ struct p9_fid *fidp;
+ int ret;
+
+ ret = fill_data(device, "ULD", &fid, &off, &len, device->buffer);
+ if ( ret != 3 )
+ {
+ p9_error(device, hdr->tag, EINVAL);
+ return;
+ }
+
+ fidp = find_fid(device, fid);
+ if ( !fidp || !fidp->opened || fidp->isdir )
+ {
+ p9_error(device, hdr->tag, EBADF);
+ return;
+ }
+
+ buf = device->buffer;
+
+ while ( len != 0 )
+ {
+ ret = pwrite(fidp->fd, buf, len, off);
+ if ( ret < 0 )
+ break;
+ len -= ret;
+ buf += ret;
+ off += ret;
+ }
+
+ written = buf - device->buffer;
+ if ( written == 0 )
+ {
+ p9_error(device, hdr->tag, errno);
+ return;
+ }
+ fill_buffer(device, hdr->cmd + 1, hdr->tag, "U", &written);
+}
+
static void p9_clunk(device *device, struct p9_header *hdr)
{
uint32_t fid;
@@ -1182,6 +1228,10 @@ void *io_thread(void *arg)
p9_create(device, &hdr);
break;
+ case P9_CMD_WRITE:
+ p9_write(device, &hdr);
+ break;
+
case P9_CMD_CLUNK:
p9_clunk(device, &hdr);
break;
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* Re: [PATCH 13/29] tools/xenlogd: add 9pfs write request support
2023-11-01 9:33 ` [PATCH 13/29] tools/xenlogd: add 9pfs write " Juergen Gross
@ 2023-11-07 14:10 ` Jason Andryuk
2023-11-07 14:43 ` Juergen Gross
0 siblings, 1 reply; 81+ messages in thread
From: Jason Andryuk @ 2023-11-07 14:10 UTC (permalink / raw)
To: Juergen Gross; +Cc: xen-devel, Wei Liu, Anthony PERARD
On Wed, Nov 1, 2023 at 5:54 AM Juergen Gross <jgross@suse.com> wrote:
>
> Add the write request of the 9pfs protocol.
>
> Signed-off-by: Juergen Gross <jgross@suse.com>
> ---
> tools/xenlogd/io.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 50 insertions(+)
>
> diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
> index 6e92667fab..6b4692ca67 100644
> --- a/tools/xenlogd/io.c
> +++ b/tools/xenlogd/io.c
> @@ -1010,6 +1011,51 @@ static void p9_create(device *device, struct p9_header *hdr)
> fill_buffer(device, hdr->cmd + 1, hdr->tag, "QU", &qid, &iounit);
> }
>
> +static void p9_write(device *device, struct p9_header *hdr)
> +{
> + uint32_t fid;
> + uint64_t off;
> + unsigned int len;
> + uint32_t written;
> + void *buf;
> + struct p9_fid *fidp;
> + int ret;
> +
> + ret = fill_data(device, "ULD", &fid, &off, &len, device->buffer);
> + if ( ret != 3 )
> + {
> + p9_error(device, hdr->tag, EINVAL);
> + return;
> + }
> +
> + fidp = find_fid(device, fid);
> + if ( !fidp || !fidp->opened || fidp->isdir )
I think you want an additional check that the fidp is writable.
Regards,
Jason
^ permalink raw reply [flat|nested] 81+ messages in thread* Re: [PATCH 13/29] tools/xenlogd: add 9pfs write request support
2023-11-07 14:10 ` Jason Andryuk
@ 2023-11-07 14:43 ` Juergen Gross
2023-11-07 15:21 ` Jason Andryuk
0 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-07 14:43 UTC (permalink / raw)
To: Jason Andryuk; +Cc: xen-devel, Wei Liu, Anthony PERARD
[-- Attachment #1.1.1: Type: text/plain, Size: 1424 bytes --]
On 07.11.23 15:10, Jason Andryuk wrote:
> On Wed, Nov 1, 2023 at 5:54 AM Juergen Gross <jgross@suse.com> wrote:
>>
>> Add the write request of the 9pfs protocol.
>>
>> Signed-off-by: Juergen Gross <jgross@suse.com>
>> ---
>> tools/xenlogd/io.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 50 insertions(+)
>>
>> diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
>> index 6e92667fab..6b4692ca67 100644
>> --- a/tools/xenlogd/io.c
>> +++ b/tools/xenlogd/io.c
>
>> @@ -1010,6 +1011,51 @@ static void p9_create(device *device, struct p9_header *hdr)
>> fill_buffer(device, hdr->cmd + 1, hdr->tag, "QU", &qid, &iounit);
>> }
>>
>> +static void p9_write(device *device, struct p9_header *hdr)
>> +{
>> + uint32_t fid;
>> + uint64_t off;
>> + unsigned int len;
>> + uint32_t written;
>> + void *buf;
>> + struct p9_fid *fidp;
>> + int ret;
>> +
>> + ret = fill_data(device, "ULD", &fid, &off, &len, device->buffer);
>> + if ( ret != 3 )
>> + {
>> + p9_error(device, hdr->tag, EINVAL);
>> + return;
>> + }
>> +
>> + fidp = find_fid(device, fid);
>> + if ( !fidp || !fidp->opened || fidp->isdir )
>
> I think you want an additional check that the fidp is writable.
The open was done with the correct mode. If fidp isn't writable, the write()
will fail with the correct errno.
Juergen
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3149 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]
^ permalink raw reply [flat|nested] 81+ messages in thread* Re: [PATCH 13/29] tools/xenlogd: add 9pfs write request support
2023-11-07 14:43 ` Juergen Gross
@ 2023-11-07 15:21 ` Jason Andryuk
0 siblings, 0 replies; 81+ messages in thread
From: Jason Andryuk @ 2023-11-07 15:21 UTC (permalink / raw)
To: Juergen Gross; +Cc: xen-devel, Wei Liu, Anthony PERARD
On Tue, Nov 7, 2023 at 9:43 AM Juergen Gross <jgross@suse.com> wrote:
>
> On 07.11.23 15:10, Jason Andryuk wrote:
> > On Wed, Nov 1, 2023 at 5:54 AM Juergen Gross <jgross@suse.com> wrote:
> >>
> >> Add the write request of the 9pfs protocol.
> >>
> >> Signed-off-by: Juergen Gross <jgross@suse.com>
> >> ---
> >> tools/xenlogd/io.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++
> >> 1 file changed, 50 insertions(+)
> >>
> >> diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
> >> index 6e92667fab..6b4692ca67 100644
> >> --- a/tools/xenlogd/io.c
> >> +++ b/tools/xenlogd/io.c
> >
> >> @@ -1010,6 +1011,51 @@ static void p9_create(device *device, struct p9_header *hdr)
> >> fill_buffer(device, hdr->cmd + 1, hdr->tag, "QU", &qid, &iounit);
> >> }
> >>
> >> +static void p9_write(device *device, struct p9_header *hdr)
> >> +{
> >> + uint32_t fid;
> >> + uint64_t off;
> >> + unsigned int len;
> >> + uint32_t written;
> >> + void *buf;
> >> + struct p9_fid *fidp;
> >> + int ret;
> >> +
> >> + ret = fill_data(device, "ULD", &fid, &off, &len, device->buffer);
> >> + if ( ret != 3 )
> >> + {
> >> + p9_error(device, hdr->tag, EINVAL);
> >> + return;
> >> + }
> >> +
> >> + fidp = find_fid(device, fid);
> >> + if ( !fidp || !fidp->opened || fidp->isdir )
> >
> > I think you want an additional check that the fidp is writable.
>
> The open was done with the correct mode. If fidp isn't writable, the write()
> will fail with the correct errno.
Oh, right.
Reviewed-by: Jason Andryuk <jandryuk@gmail.com>
^ permalink raw reply [flat|nested] 81+ messages in thread
* [PATCH 14/29] tools/xenlogd: add 9pfs read request support
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
` (12 preceding siblings ...)
2023-11-01 9:33 ` [PATCH 13/29] tools/xenlogd: add 9pfs write " Juergen Gross
@ 2023-11-01 9:33 ` Juergen Gross
2023-11-07 14:31 ` Jason Andryuk
2023-11-01 9:33 ` [PATCH 15/29] tools/libs/light: add backend type for 9pfs PV devices Juergen Gross
` (14 subsequent siblings)
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:33 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Anthony PERARD
Add the read request of the 9pfs protocol.
For now support only reading plain files (no directories).
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/xenlogd/io.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 60 insertions(+)
diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
index 6b4692ca67..b3f9f96bcc 100644
--- a/tools/xenlogd/io.c
+++ b/tools/xenlogd/io.c
@@ -32,6 +32,7 @@
#define P9_CMD_WALK 110
#define P9_CMD_OPEN 112
#define P9_CMD_CREATE 114
+#define P9_CMD_READ 116
#define P9_CMD_WRITE 118
#define P9_CMD_CLUNK 120
#define P9_CMD_STAT 124
@@ -1011,6 +1012,61 @@ static void p9_create(device *device, struct p9_header *hdr)
fill_buffer(device, hdr->cmd + 1, hdr->tag, "QU", &qid, &iounit);
}
+static void p9_read(device *device, struct p9_header *hdr)
+{
+ uint32_t fid;
+ uint64_t off;
+ unsigned int len;
+ uint32_t count;
+ void *buf;
+ struct p9_fid *fidp;
+ int ret;
+
+ ret = fill_data(device, "ULU", &fid, &off, &count);
+ if ( ret != 3 )
+ {
+ p9_error(device, hdr->tag, EINVAL);
+ return;
+ }
+
+ fidp = find_fid(device, fid);
+ if ( !fidp || !fidp->opened )
+ {
+ p9_error(device, hdr->tag, EBADF);
+ return;
+ }
+
+ if ( fidp->isdir )
+ {
+ p9_error(device, hdr->tag, EOPNOTSUPP);
+ return;
+ }
+ else
+ {
+ len = count;
+ buf = device->buffer + sizeof(*hdr) + sizeof(uint32_t);
+
+ while ( len != 0 )
+ {
+ ret = pread(fidp->fd, buf, len, off);
+ if ( ret <= 0 )
+ break;
+ len -= ret;
+ buf += ret;
+ off += ret;
+ }
+ if ( ret && len == count )
+ {
+ p9_error(device, hdr->tag, errno);
+ return;
+ }
+
+ buf = device->buffer + sizeof(*hdr) + sizeof(uint32_t);
+ len = count - len;
+ fill_buffer(device, hdr->cmd + 1, hdr->tag, "D", &len, buf);
+ }
+}
+
static void p9_write(device *device, struct p9_header *hdr)
{
uint32_t fid;
@@ -1228,6 +1284,10 @@ void *io_thread(void *arg)
p9_create(device, &hdr);
break;
+ case P9_CMD_READ:
+ p9_read(device, &hdr);
+ break;
+
case P9_CMD_WRITE:
p9_write(device, &hdr);
break;
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* Re: [PATCH 14/29] tools/xenlogd: add 9pfs read request support
2023-11-01 9:33 ` [PATCH 14/29] tools/xenlogd: add 9pfs read " Juergen Gross
@ 2023-11-07 14:31 ` Jason Andryuk
2023-11-07 14:49 ` Juergen Gross
0 siblings, 1 reply; 81+ messages in thread
From: Jason Andryuk @ 2023-11-07 14:31 UTC (permalink / raw)
To: Juergen Gross; +Cc: xen-devel, Wei Liu, Anthony PERARD
On Wed, Nov 1, 2023 at 5:35 AM Juergen Gross <jgross@suse.com> wrote:
>
> Add the read request of the 9pfs protocol.
>
> For now support only reading plain files (no directories).
>
> Signed-off-by: Juergen Gross <jgross@suse.com>
> ---
> tools/xenlogd/io.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 60 insertions(+)
>
> diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
> index 6b4692ca67..b3f9f96bcc 100644
> --- a/tools/xenlogd/io.c
> +++ b/tools/xenlogd/io.c
> @@ -1011,6 +1012,61 @@ static void p9_create(device *device, struct p9_header *hdr)
> fill_buffer(device, hdr->cmd + 1, hdr->tag, "QU", &qid, &iounit);
> }
>
> +static void p9_read(device *device, struct p9_header *hdr)
> +{
> + uint32_t fid;
> + uint64_t off;
> + unsigned int len;
> + uint32_t count;
> + void *buf;
> + struct p9_fid *fidp;
> + int ret;
> +
> + ret = fill_data(device, "ULU", &fid, &off, &count);
> + if ( ret != 3 )
> + {
> + p9_error(device, hdr->tag, EINVAL);
> + return;
> + }
> +
> + fidp = find_fid(device, fid);
> + if ( !fidp || !fidp->opened )
> + {
> + p9_error(device, hdr->tag, EBADF);
> + return;
> + }
> +
I think you want to mode check here for readability.
> + if ( fidp->isdir )
> + {
> + p9_error(device, hdr->tag, EOPNOTSUPP);
> + return;
Hmmm, 9P2000.u supports read on a dir.
https://ericvh.github.io/9p-rfc/rfc9p2000.html#anchor30
"""
For directories, read returns an integral number of direc- tory
entries exactly as in stat (see stat(5)), one for each member of the
directory. The read request message must have offset equal to zero or
the value of offset in the previous read on the directory, plus the
number of bytes returned in the previous read. In other words, seeking
other than to the beginning is illegal in a directory (see seek(2)).
"""
> + }
> + else
Since the above is a return, maybe remove the else and un-indent?
Though maybe you don't want to do that if you want to implement read
on a dir.
> + {
> + len = count;
> + buf = device->buffer + sizeof(*hdr) + sizeof(uint32_t);
> +
> + while ( len != 0 )
> + {
> + ret = pread(fidp->fd, buf, len, off);
> + if ( ret <= 0 )
> + break;
> + len -= ret;
> + buf += ret;
> + off += ret;
> + }
> + if ( ret && len == count )
This seems wrong to me - should this be ( ret < 0 && len == count ) to
indicate an error on the first pread? Any partial reads would still
return their data?
Regards,
Jason
> + {
> + p9_error(device, hdr->tag, errno);
> + return;
> + }
> +
> + buf = device->buffer + sizeof(*hdr) + sizeof(uint32_t);
> + len = count - len;
> + fill_buffer(device, hdr->cmd + 1, hdr->tag, "D", &len, buf);
> + }
> +}
> +
> static void p9_write(device *device, struct p9_header *hdr)
> {
> uint32_t fid;
^ permalink raw reply [flat|nested] 81+ messages in thread* Re: [PATCH 14/29] tools/xenlogd: add 9pfs read request support
2023-11-07 14:31 ` Jason Andryuk
@ 2023-11-07 14:49 ` Juergen Gross
2023-11-07 15:23 ` Jason Andryuk
0 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-07 14:49 UTC (permalink / raw)
To: Jason Andryuk; +Cc: xen-devel, Wei Liu, Anthony PERARD
[-- Attachment #1.1.1: Type: text/plain, Size: 3209 bytes --]
On 07.11.23 15:31, Jason Andryuk wrote:
> On Wed, Nov 1, 2023 at 5:35 AM Juergen Gross <jgross@suse.com> wrote:
>>
>> Add the read request of the 9pfs protocol.
>>
>> For now support only reading plain files (no directories).
>>
>> Signed-off-by: Juergen Gross <jgross@suse.com>
>> ---
>> tools/xenlogd/io.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 60 insertions(+)
>>
>> diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
>> index 6b4692ca67..b3f9f96bcc 100644
>> --- a/tools/xenlogd/io.c
>> +++ b/tools/xenlogd/io.c
>
>> @@ -1011,6 +1012,61 @@ static void p9_create(device *device, struct p9_header *hdr)
>> fill_buffer(device, hdr->cmd + 1, hdr->tag, "QU", &qid, &iounit);
>> }
>>
>> +static void p9_read(device *device, struct p9_header *hdr)
>> +{
>> + uint32_t fid;
>> + uint64_t off;
>> + unsigned int len;
>> + uint32_t count;
>> + void *buf;
>> + struct p9_fid *fidp;
>> + int ret;
>> +
>> + ret = fill_data(device, "ULU", &fid, &off, &count);
>> + if ( ret != 3 )
>> + {
>> + p9_error(device, hdr->tag, EINVAL);
>> + return;
>> + }
>> +
>> + fidp = find_fid(device, fid);
>> + if ( !fidp || !fidp->opened )
>> + {
>> + p9_error(device, hdr->tag, EBADF);
>> + return;
>> + }
>> +
>
> I think you want to mode check here for readability.
Same reasoning as for the write case: read() will do it for me.
>
>> + if ( fidp->isdir )
>> + {
>> + p9_error(device, hdr->tag, EOPNOTSUPP);
>> + return;
>
> Hmmm, 9P2000.u supports read on a dir.
> https://ericvh.github.io/9p-rfc/rfc9p2000.html#anchor30
> """
> For directories, read returns an integral number of direc- tory
> entries exactly as in stat (see stat(5)), one for each member of the
> directory. The read request message must have offset equal to zero or
> the value of offset in the previous read on the directory, plus the
> number of bytes returned in the previous read. In other words, seeking
> other than to the beginning is illegal in a directory (see seek(2)).
> """
This is part of "only operations needed for Xenstore-stubdom are implemented."
For supporting Linux guests or other stubdoms directory reading must be added,
of course.
>
>> + }
>> + else
>
> Since the above is a return, maybe remove the else and un-indent?
> Though maybe you don't want to do that if you want to implement read
> on a dir.
Correct.
>
>> + {
>> + len = count;
>> + buf = device->buffer + sizeof(*hdr) + sizeof(uint32_t);
>> +
>> + while ( len != 0 )
>> + {
>> + ret = pread(fidp->fd, buf, len, off);
>> + if ( ret <= 0 )
>> + break;
>> + len -= ret;
>> + buf += ret;
>> + off += ret;
>> + }
>> + if ( ret && len == count )
>
> This seems wrong to me - should this be ( ret < 0 && len == count ) to
> indicate an error on the first pread? Any partial reads would still
> return their data?
If len == count there was no partial read, as this would have reduced len.
Juergen
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3149 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]
^ permalink raw reply [flat|nested] 81+ messages in thread* Re: [PATCH 14/29] tools/xenlogd: add 9pfs read request support
2023-11-07 14:49 ` Juergen Gross
@ 2023-11-07 15:23 ` Jason Andryuk
0 siblings, 0 replies; 81+ messages in thread
From: Jason Andryuk @ 2023-11-07 15:23 UTC (permalink / raw)
To: Juergen Gross; +Cc: xen-devel, Wei Liu, Anthony PERARD
On Tue, Nov 7, 2023 at 9:49 AM Juergen Gross <jgross@suse.com> wrote:
>
> On 07.11.23 15:31, Jason Andryuk wrote:
> > On Wed, Nov 1, 2023 at 5:35 AM Juergen Gross <jgross@suse.com> wrote:
> >>
> >> Add the read request of the 9pfs protocol.
> >>
> >> For now support only reading plain files (no directories).
> >>
> >> Signed-off-by: Juergen Gross <jgross@suse.com>
> >> ---
> >> tools/xenlogd/io.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++
> >> 1 file changed, 60 insertions(+)
> >>
> >> diff --git a/tools/xenlogd/io.c b/tools/xenlogd/io.c
> >> index 6b4692ca67..b3f9f96bcc 100644
> >> --- a/tools/xenlogd/io.c
> >> +++ b/tools/xenlogd/io.c
> >
> >> @@ -1011,6 +1012,61 @@ static void p9_create(device *device, struct p9_header *hdr)
> >> fill_buffer(device, hdr->cmd + 1, hdr->tag, "QU", &qid, &iounit);
> >> }
> >>
> >> +static void p9_read(device *device, struct p9_header *hdr)
> >> +{
> >> + uint32_t fid;
> >> + uint64_t off;
> >> + unsigned int len;
> >> + uint32_t count;
> >> + void *buf;
> >> + struct p9_fid *fidp;
> >> + int ret;
> >> +
> >> + ret = fill_data(device, "ULU", &fid, &off, &count);
> >> + if ( ret != 3 )
> >> + {
> >> + p9_error(device, hdr->tag, EINVAL);
> >> + return;
> >> + }
> >> +
> >> + fidp = find_fid(device, fid);
> >> + if ( !fidp || !fidp->opened )
> >> + {
> >> + p9_error(device, hdr->tag, EBADF);
> >> + return;
> >> + }
> >> +
> >
> > I think you want to mode check here for readability.
>
> Same reasoning as for the write case: read() will do it for me.
>
> >
> >> + if ( fidp->isdir )
> >> + {
> >> + p9_error(device, hdr->tag, EOPNOTSUPP);
> >> + return;
> >
> > Hmmm, 9P2000.u supports read on a dir.
> > https://ericvh.github.io/9p-rfc/rfc9p2000.html#anchor30
> > """
> > For directories, read returns an integral number of direc- tory
> > entries exactly as in stat (see stat(5)), one for each member of the
> > directory. The read request message must have offset equal to zero or
> > the value of offset in the previous read on the directory, plus the
> > number of bytes returned in the previous read. In other words, seeking
> > other than to the beginning is illegal in a directory (see seek(2)).
> > """
>
> This is part of "only operations needed for Xenstore-stubdom are implemented."
> For supporting Linux guests or other stubdoms directory reading must be added,
> of course.
>
> >
> >> + }
> >> + else
> >
> > Since the above is a return, maybe remove the else and un-indent?
> > Though maybe you don't want to do that if you want to implement read
> > on a dir.
>
> Correct.
>
> >
> >> + {
> >> + len = count;
> >> + buf = device->buffer + sizeof(*hdr) + sizeof(uint32_t);
> >> +
> >> + while ( len != 0 )
> >> + {
> >> + ret = pread(fidp->fd, buf, len, off);
> >> + if ( ret <= 0 )
> >> + break;
> >> + len -= ret;
> >> + buf += ret;
> >> + off += ret;
> >> + }
> >> + if ( ret && len == count )
> >
> > This seems wrong to me - should this be ( ret < 0 && len == count ) to
> > indicate an error on the first pread? Any partial reads would still
> > return their data?
>
> If len == count there was no partial read, as this would have reduced len.
Right. I found it confusing since ret > 0 is not an error. As you
wrote, len != count in that case though.
Preferably with ret < 0:
Reviewed-by: Jason Andryuk <jandryuk@gmail.com>
Regards,
Jason
^ permalink raw reply [flat|nested] 81+ messages in thread
* [PATCH 15/29] tools/libs/light: add backend type for 9pfs PV devices
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
` (13 preceding siblings ...)
2023-11-01 9:33 ` [PATCH 14/29] tools/xenlogd: add 9pfs read " Juergen Gross
@ 2023-11-01 9:33 ` Juergen Gross
2023-11-07 15:46 ` Jason Andryuk
2023-11-01 9:33 ` [PATCH 16/29] tools/xl: support new 9pfs backend xenlogd Juergen Gross
` (13 subsequent siblings)
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:33 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Anthony PERARD
Make the backend type of 9pfs PV devices configurable. The default is
"qemu" with the related Xenstore backend-side directory being "9pfs".
Add another type "xenlogd" with the related Xenstore backend-side
directory "xen_9pfs".
As additional security features it is possible to specify:
- "max-space" for limiting the maximum space consumed on the filesystem
in MBs
- "max-files" for limiting the maximum number of files in the
filesystem
- "max-open-files" for limiting the maximum number of concurrent open
files
For convenience "auto-delete" is available to let the backend delete the
oldest file of the guest in case otherwise "max-space" or "max-files"
would be violated.
The xenlogd daemon will be started by libxenlight automatically when
the first "xen_9pfs" device is being created.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/libs/light/libxl_9pfs.c | 143 +++++++++++++++++++++-
tools/libs/light/libxl_create.c | 4 +-
tools/libs/light/libxl_dm.c | 2 +-
tools/libs/light/libxl_types.idl | 11 ++
tools/libs/light/libxl_types_internal.idl | 1 +
5 files changed, 154 insertions(+), 7 deletions(-)
diff --git a/tools/libs/light/libxl_9pfs.c b/tools/libs/light/libxl_9pfs.c
index 5ab0d3aa21..0b9d84dce9 100644
--- a/tools/libs/light/libxl_9pfs.c
+++ b/tools/libs/light/libxl_9pfs.c
@@ -33,20 +33,157 @@ static int libxl__set_xenstore_p9(libxl__gc *gc, uint32_t domid,
flexarray_append_pair(front, "tag", p9->tag);
+ if (p9->type == LIBXL_P9_TYPE_XENLOGD) {
+ flexarray_append_pair(back, "max-space",
+ GCSPRINTF("%u", p9->max_space));
+ flexarray_append_pair(back, "max-files",
+ GCSPRINTF("%u", p9->max_files));
+ flexarray_append_pair(back, "max-open-files",
+ GCSPRINTF("%u", p9->max_open_files));
+ flexarray_append_pair(back, "auto-delete",
+ p9->auto_delete ? "1" : "0");
+ }
+
+ return 0;
+}
+
+static int libxl__device_from_p9(libxl__gc *gc, uint32_t domid,
+ libxl_device_p9 *type, libxl__device *device)
+{
+ device->backend_devid = type->devid;
+ device->backend_domid = type->backend_domid;
+ device->backend_kind = type->type == LIBXL_P9_TYPE_QEMU
+ ? LIBXL__DEVICE_KIND_9PFS
+ : LIBXL__DEVICE_KIND_XEN_9PFS;
+ device->devid = type->devid;
+ device->domid = domid;
+ device->kind = LIBXL__DEVICE_KIND_9PFS;
+
return 0;
}
-#define libxl__add_p9s NULL
+static int libxl_device_p9_dm_needed(void *e, unsigned domid)
+{
+ libxl_device_p9 *elem = e;
+
+ return elem->type == LIBXL_P9_TYPE_QEMU && elem->backend_domid == domid;
+}
+
+typedef struct libxl__aop9_state libxl__aop9_state;
+
+struct libxl__aop9_state {
+ libxl__spawn_state spawn;
+ libxl__ao_device *aodev;
+ libxl_device_p9 *p9;
+ uint32_t domid;
+ void (*callback)(libxl__egc *, libxl__aop9_state *, int);
+};
+
+static void xenlogd_spawn_outcome(libxl__egc *egc, libxl__aop9_state *aop9,
+ int rc)
+{
+ aop9->aodev->rc = rc;
+ if (rc)
+ aop9->aodev->callback(egc, aop9->aodev);
+ else
+ libxl__device_add_async(egc, aop9->domid, &libxl__p9_devtype,
+ aop9->p9, aop9->aodev);
+}
+
+static void xenlogd_confirm(libxl__egc *egc, libxl__spawn_state *spawn,
+ const char *xsdata)
+{
+ STATE_AO_GC(spawn->ao);
+
+ if (!xsdata)
+ return;
+
+ if (strcmp(xsdata, "running"))
+ return;
+
+ libxl__spawn_initiate_detach(gc, spawn);
+}
+
+static void xenlogd_failed(libxl__egc *egc, libxl__spawn_state *spawn, int rc)
+{
+ libxl__aop9_state *aop9 = CONTAINER_OF(spawn, *aop9, spawn);
+
+ xenlogd_spawn_outcome(egc, aop9, rc);
+}
+
+static void xenlogd_detached(libxl__egc *egc, libxl__spawn_state *spawn)
+{
+ libxl__aop9_state *aop9 = CONTAINER_OF(spawn, *aop9, spawn);
+
+ xenlogd_spawn_outcome(egc, aop9, 0);
+}
+
+static int xenlogd_spawn(libxl__egc *egc, uint32_t domid, libxl_device_p9 *p9,
+ libxl__ao_device *aodev)
+{
+ STATE_AO_GC(aodev->ao);
+ struct libxl__aop9_state *aop9;
+ int rc;
+ char *args[] = { "xenlogd", NULL };
+
+ if (p9->type != LIBXL_P9_TYPE_XENLOGD ||
+ libxl__xs_read(gc, XBT_NULL, "/tool/xenlog/state"))
+ return 0;
+
+ GCNEW(aop9);
+ aop9->aodev = aodev;
+ aop9->p9 = p9;
+ aop9->domid = domid;
+ aop9->callback = xenlogd_spawn_outcome;
+
+ aop9->spawn.ao = aodev->ao;
+ aop9->spawn.what = "xenlog daemon";
+ aop9->spawn.xspath = "/tool/xenlog/state";
+ aop9->spawn.timeout_ms = LIBXL_DEVICE_MODEL_START_TIMEOUT * 1000;
+ aop9->spawn.pidpath = "/tool/xenlog/pid";
+ aop9->spawn.midproc_cb = libxl__spawn_record_pid;
+ aop9->spawn.confirm_cb = xenlogd_confirm;
+ aop9->spawn.failure_cb = xenlogd_failed;
+ aop9->spawn.detached_cb = xenlogd_detached;
+ rc = libxl__spawn_spawn(egc, &aop9->spawn);
+ if (rc < 0)
+ return rc;
+ if (!rc) {
+ setsid();
+ libxl__exec(gc, -1, -1, -1, LIBEXEC_BIN "/xenlogd", args, NULL);
+ }
+
+ return 1;
+}
+
+static void libxl__device_p9_add(libxl__egc *egc, uint32_t domid,
+ libxl_device_p9 *p9,
+ libxl__ao_device *aodev)
+{
+ int rc;
+
+ rc = xenlogd_spawn(egc, domid, p9, aodev);
+ if (rc == 1)
+ return;
+
+ if (rc == 0)
+ libxl__device_add_async(egc, domid, &libxl__p9_devtype, p9, aodev);
+
+ aodev->rc = rc;
+ if (rc)
+ aodev->callback(egc, aodev);
+}
+
#define libxl_device_p9_list NULL
#define libxl_device_p9_compare NULL
static LIBXL_DEFINE_UPDATE_DEVID(p9)
-static LIBXL_DEFINE_DEVICE_FROM_TYPE(p9)
+static LIBXL_DEFINE_DEVICES_ADD(p9)
LIBXL_DEFINE_DEVICE_REMOVE(p9)
DEFINE_DEVICE_TYPE_STRUCT(p9, 9PFS, p9s,
- .skip_attach = 1,
.set_xenstore_config = (device_set_xenstore_config_fn_t)
libxl__set_xenstore_p9,
+ .dm_needed = libxl_device_p9_dm_needed,
);
diff --git a/tools/libs/light/libxl_create.c b/tools/libs/light/libxl_create.c
index ce1d431103..b19e9379b6 100644
--- a/tools/libs/light/libxl_create.c
+++ b/tools/libs/light/libxl_create.c
@@ -1760,9 +1760,6 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *multidev,
libxl__device_console_dispose(&console);
}
- for (i = 0; i < d_config->num_p9s; i++)
- libxl__device_add(gc, domid, &libxl__p9_devtype, &d_config->p9s[i]);
-
for (i = 0; i < d_config->num_pvcallsifs; i++)
libxl__device_add(gc, domid, &libxl__pvcallsif_devtype,
&d_config->pvcallsifs[i]);
@@ -1899,6 +1896,7 @@ const libxl__device_type *device_type_tbl[] = {
&libxl__vdispl_devtype,
&libxl__vsnd_devtype,
&libxl__virtio_devtype,
+ &libxl__p9_devtype,
NULL
};
diff --git a/tools/libs/light/libxl_dm.c b/tools/libs/light/libxl_dm.c
index 14b593110f..2aaaeb5aa7 100644
--- a/tools/libs/light/libxl_dm.c
+++ b/tools/libs/light/libxl_dm.c
@@ -3761,7 +3761,7 @@ int libxl__need_xenpv_qemu(libxl__gc *gc, libxl_domain_config *d_config)
goto out;
}
- if (d_config->num_vfbs > 0 || d_config->num_p9s > 0) {
+ if (d_config->num_vfbs > 0) {
ret = 1;
goto out;
}
diff --git a/tools/libs/light/libxl_types.idl b/tools/libs/light/libxl_types.idl
index 7d8bd5d216..e910bf1621 100644
--- a/tools/libs/light/libxl_types.idl
+++ b/tools/libs/light/libxl_types.idl
@@ -150,6 +150,12 @@ libxl_nic_type = Enumeration("nic_type", [
(2, "VIF"),
])
+libxl_p9_type = Enumeration("p9_type", [
+ (0, "unknown"),
+ (1, "qemu"),
+ (2, "xenlogd"),
+ ])
+
libxl_action_on_shutdown = Enumeration("action_on_shutdown", [
(1, "DESTROY"),
@@ -942,6 +948,11 @@ libxl_device_p9 = Struct("device_p9", [
("path", string),
("security_model", string),
("devid", libxl_devid),
+ ("type", libxl_p9_type),
+ ("max_space", integer),
+ ("max_files", integer),
+ ("max_open_files", integer),
+ ("auto_delete", bool),
])
libxl_device_pvcallsif = Struct("device_pvcallsif", [
diff --git a/tools/libs/light/libxl_types_internal.idl b/tools/libs/light/libxl_types_internal.idl
index e24288f1a5..39da71cef5 100644
--- a/tools/libs/light/libxl_types_internal.idl
+++ b/tools/libs/light/libxl_types_internal.idl
@@ -34,6 +34,7 @@ libxl__device_kind = Enumeration("device_kind", [
(16, "VINPUT"),
(17, "VIRTIO_DISK"),
(18, "VIRTIO"),
+ (19, "XEN_9PFS"),
])
libxl__console_backend = Enumeration("console_backend", [
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* Re: [PATCH 15/29] tools/libs/light: add backend type for 9pfs PV devices
2023-11-01 9:33 ` [PATCH 15/29] tools/libs/light: add backend type for 9pfs PV devices Juergen Gross
@ 2023-11-07 15:46 ` Jason Andryuk
0 siblings, 0 replies; 81+ messages in thread
From: Jason Andryuk @ 2023-11-07 15:46 UTC (permalink / raw)
To: Juergen Gross; +Cc: xen-devel, Wei Liu, Anthony PERARD
On Wed, Nov 1, 2023 at 5:51 AM Juergen Gross <jgross@suse.com> wrote:
>
> Make the backend type of 9pfs PV devices configurable. The default is
> "qemu" with the related Xenstore backend-side directory being "9pfs".
>
> Add another type "xenlogd" with the related Xenstore backend-side
> directory "xen_9pfs".
>
> As additional security features it is possible to specify:
> - "max-space" for limiting the maximum space consumed on the filesystem
> in MBs
> - "max-files" for limiting the maximum number of files in the
> filesystem
> - "max-open-files" for limiting the maximum number of concurrent open
> files
>
> For convenience "auto-delete" is available to let the backend delete the
> oldest file of the guest in case otherwise "max-space" or "max-files"
> would be violated.
>
> The xenlogd daemon will be started by libxenlight automatically when
> the first "xen_9pfs" device is being created.
>
> Signed-off-by: Juergen Gross <jgross@suse.com>
With Xentore paths updated to "libxl/..." as mentioned elsewhere:
Reviewed-by: Jason Andryuk <jandryuk@gmail.com>
^ permalink raw reply [flat|nested] 81+ messages in thread
* [PATCH 16/29] tools/xl: support new 9pfs backend xenlogd
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
` (14 preceding siblings ...)
2023-11-01 9:33 ` [PATCH 15/29] tools/libs/light: add backend type for 9pfs PV devices Juergen Gross
@ 2023-11-01 9:33 ` Juergen Gross
2023-11-07 16:55 ` Jason Andryuk
2023-11-01 9:33 ` [PATCH 17/29] tools/helpers: allocate xenstore event channel for xenstore stubdom Juergen Gross
` (12 subsequent siblings)
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:33 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Anthony PERARD
Add support for the new 9pfs backend "xenlogd". For this backend type
the tag defaults to "Xen" and the host side path to
"/var/log/xen/guests/<dom-name>".
Signed-off-by: Juergen Gross <jgross@suse.com>
---
docs/man/xl.cfg.5.pod.in | 36 ++++++++++++++++++++++++++++++++++--
tools/xl/xl_parse.c | 35 +++++++++++++++++++++++++++++++++++
2 files changed, 69 insertions(+), 2 deletions(-)
diff --git a/docs/man/xl.cfg.5.pod.in b/docs/man/xl.cfg.5.pod.in
index 2e234b450e..be82d35eed 100644
--- a/docs/man/xl.cfg.5.pod.in
+++ b/docs/man/xl.cfg.5.pod.in
@@ -772,10 +772,16 @@ settings, from the following list:
=over 4
+=item B<type=TYPE>
+
+The backendtype for the PV device. Supported values are B<qemu> and B<xenlogd>.
+The default is B<qemu>.
+
=item B<tag=STRING>
9pfs tag to identify the filesystem share. The tag is needed on the
-guest side to mount it.
+guest side to mount it. For the backendtype of B<xenlogd> the tag defaults to
+"Xen".
=item B<security_model="none">
@@ -785,12 +791,38 @@ squash or remap).
=item B<path=STRING>
-Filesystem path on the backend to export.
+Filesystem path on the backend to export. For the backendtype of B<xenlogd>
+the path defaults to "@XEN_LOG_DIR@/guests/<guest-name>".
=item B<backend=domain-id>
Specify the backend domain name or id, defaults to dom0.
+=item B<max-files=NUMBER>
+
+Specify the maximum number of files below B<path>. A value of 0 (which
+is the default) doesn't limit the number of files. Only valid for
+B<type=xenlogd>.
+
+=item B<max-open-files=NUMBER>
+
+Specify the maximum number of concurrently opened files below B<path>.
+Multiple opens of the same file are counted individually. Only valid for
+B<type=xenlogd>, which has a default of B<max-open-files=5>.
+
+=item B<max-space=NUMBER>
+
+Specify the maximum used disk space in MiB below B<path>. A value of 0 (which
+is the default) doesn't limit the usable disk space. Only valid for
+B<type=xenlogd>.
+
+=item B<auto-delete=BOOLEAN>
+
+When set the backend will delete the oldest file which is currently not
+opened by the guest in case the disk space limit set via B<max-space> or the
+file limit set via B<max-files> is being reached. Only valid for
+B<type=xenlogd>.
+
=back
=item B<pvcalls=[ "backend=domain-id", ... ]>
diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c
index ed983200c3..346532e117 100644
--- a/tools/xl/xl_parse.c
+++ b/tools/xl/xl_parse.c
@@ -2232,6 +2232,20 @@ void parse_config_data(const char *config_source,
replace_string(&p9->tag, value);
} else if (!strcmp(key, "backend")) {
replace_string(&p9->backend_domname, value);
+ } else if (!strcmp(key, "type")) {
+ if (libxl_p9_type_from_string(value, &p9->type)) {
+ fprintf(stderr, "failed to parse 9pfs type: %s\n",
+ value);
+ exit(1);
+ }
+ } else if (!strcmp(key, "max-files")) {
+ p9->max_files = parse_ulong(value);
+ } else if (!strcmp(key, "max-open-files")) {
+ p9->max_open_files = parse_ulong(value);
+ } else if (!strcmp(key, "max-space")) {
+ p9->max_space = parse_ulong(value);
+ } else if (!strcmp(key, "auto-delete")) {
+ p9->auto_delete = strtoul(value, NULL, 0);
} else {
fprintf(stderr, "Unknown 9pfs parameter '%s'\n", key);
exit(1);
@@ -2242,6 +2256,27 @@ void parse_config_data(const char *config_source,
libxl_string_list_dispose(&pairs);
+ if (p9->type == LIBXL_P9_TYPE_UNKNOWN) {
+ p9->type = LIBXL_P9_TYPE_QEMU;
+ }
+ if (p9->type == LIBXL_P9_TYPE_QEMU &&
+ (p9->max_space || p9->auto_delete)) {
+ fprintf(stderr, "Illegal 9pfs parameter combination\n");
+ exit(1);
+ }
+ if (p9->type == LIBXL_P9_TYPE_XENLOGD) {
+ if (!p9->tag) {
+ replace_string(&p9->tag, "Xen");
+ }
+ if (!p9->path) {
+ char *path;
+
+ xasprintf(&path, XEN_LOG_DIR "/guests/%s", c_info->name);
+ replace_string(&p9->path, path);
+ free(path);
+ }
+ }
+
if (!p9->path || !p9->security_model || !p9->tag) {
fprintf(stderr, "9pfs spec missing required field!\n");
exit(1);
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* Re: [PATCH 16/29] tools/xl: support new 9pfs backend xenlogd
2023-11-01 9:33 ` [PATCH 16/29] tools/xl: support new 9pfs backend xenlogd Juergen Gross
@ 2023-11-07 16:55 ` Jason Andryuk
2023-11-08 6:54 ` Juergen Gross
0 siblings, 1 reply; 81+ messages in thread
From: Jason Andryuk @ 2023-11-07 16:55 UTC (permalink / raw)
To: Juergen Gross; +Cc: xen-devel, Wei Liu, Anthony PERARD
On Wed, Nov 1, 2023 at 6:41 AM Juergen Gross <jgross@suse.com> wrote:
>
> Add support for the new 9pfs backend "xenlogd". For this backend type
> the tag defaults to "Xen" and the host side path to
> "/var/log/xen/guests/<dom-name>".
>
> Signed-off-by: Juergen Gross <jgross@suse.com>
> diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c
> index ed983200c3..346532e117 100644
> --- a/tools/xl/xl_parse.c
> +++ b/tools/xl/xl_parse.c
> @@ -2242,6 +2256,27 @@ void parse_config_data(const char *config_source,
>
> libxl_string_list_dispose(&pairs);
>
> + if (p9->type == LIBXL_P9_TYPE_UNKNOWN) {
> + p9->type = LIBXL_P9_TYPE_QEMU;
> + }
> + if (p9->type == LIBXL_P9_TYPE_QEMU &&
> + (p9->max_space || p9->auto_delete)) {
Also check p9->max_open_files and p9->max_files?
Regards,
Jason
^ permalink raw reply [flat|nested] 81+ messages in thread* Re: [PATCH 16/29] tools/xl: support new 9pfs backend xenlogd
2023-11-07 16:55 ` Jason Andryuk
@ 2023-11-08 6:54 ` Juergen Gross
0 siblings, 0 replies; 81+ messages in thread
From: Juergen Gross @ 2023-11-08 6:54 UTC (permalink / raw)
To: Jason Andryuk; +Cc: xen-devel, Wei Liu, Anthony PERARD
[-- Attachment #1.1.1: Type: text/plain, Size: 1026 bytes --]
On 07.11.23 17:55, Jason Andryuk wrote:
> On Wed, Nov 1, 2023 at 6:41 AM Juergen Gross <jgross@suse.com> wrote:
>>
>> Add support for the new 9pfs backend "xenlogd". For this backend type
>> the tag defaults to "Xen" and the host side path to
>> "/var/log/xen/guests/<dom-name>".
>>
>> Signed-off-by: Juergen Gross <jgross@suse.com>
>
>> diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c
>> index ed983200c3..346532e117 100644
>> --- a/tools/xl/xl_parse.c
>> +++ b/tools/xl/xl_parse.c
>
>> @@ -2242,6 +2256,27 @@ void parse_config_data(const char *config_source,
>>
>> libxl_string_list_dispose(&pairs);
>>
>> + if (p9->type == LIBXL_P9_TYPE_UNKNOWN) {
>> + p9->type = LIBXL_P9_TYPE_QEMU;
>> + }
>> + if (p9->type == LIBXL_P9_TYPE_QEMU &&
>> + (p9->max_space || p9->auto_delete)) {
>
> Also check p9->max_open_files and p9->max_files?
Ah, yes, I added those later and forgot to adapt this check.
Juergen
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3149 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]
^ permalink raw reply [flat|nested] 81+ messages in thread
* [PATCH 17/29] tools/helpers: allocate xenstore event channel for xenstore stubdom
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
` (15 preceding siblings ...)
2023-11-01 9:33 ` [PATCH 16/29] tools/xl: support new 9pfs backend xenlogd Juergen Gross
@ 2023-11-01 9:33 ` Juergen Gross
2023-11-07 18:23 ` Jason Andryuk
2023-11-01 9:33 ` [PATCH 18/29] tools/xenstored: rename xenbus_evtchn() Juergen Gross
` (11 subsequent siblings)
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:33 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Julien Grall, Anthony PERARD
In order to prepare support of PV frontends in xenstore-stubdom, add
allocation of a Xenstore event channel to init-xenstore-domain.c.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/helpers/init-xenstore-domain.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/tools/helpers/init-xenstore-domain.c b/tools/helpers/init-xenstore-domain.c
index b2d5df8ba5..140ed610ae 100644
--- a/tools/helpers/init-xenstore-domain.c
+++ b/tools/helpers/init-xenstore-domain.c
@@ -248,6 +248,13 @@ static int build(xc_interface *xch)
dom->cmdline = xc_dom_strdup(dom, cmdline);
dom->xenstore_domid = domid;
dom->console_evtchn = console_evtchn;
+ rv = xc_evtchn_alloc_unbound(xch, domid, domid);
+ if ( rv < 0 )
+ {
+ fprintf(stderr, "xc_evtchn_alloc_unbound failed\n");
+ goto err;
+ }
+ dom->xenstore_evtchn = rv;
rv = xc_dom_mem_init(dom, memory);
if ( rv )
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH 18/29] tools/xenstored: rename xenbus_evtchn()
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
` (16 preceding siblings ...)
2023-11-01 9:33 ` [PATCH 17/29] tools/helpers: allocate xenstore event channel for xenstore stubdom Juergen Gross
@ 2023-11-01 9:33 ` Juergen Gross
2023-11-01 10:44 ` Julien Grall
2023-11-01 9:33 ` [PATCH 19/29] stubdom: extend xenstore stubdom configs Juergen Gross
` (10 subsequent siblings)
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:33 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Julien Grall, Anthony PERARD
Rename the xenbus_evtchn() function to get_xenbus_evtchn() in order to
avoid two externally visible symbols with the same name when Xenstore-
stubdom is being built with a Mini-OS with CONFIG_XENBUS set.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/xenstored/core.h | 2 +-
tools/xenstored/domain.c | 2 +-
tools/xenstored/minios.c | 2 +-
tools/xenstored/posix.c | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/tools/xenstored/core.h b/tools/xenstored/core.h
index ad87199042..480b0f5f7b 100644
--- a/tools/xenstored/core.h
+++ b/tools/xenstored/core.h
@@ -383,7 +383,7 @@ static inline bool domain_is_unprivileged(const struct connection *conn)
}
/* Return the event channel used by xenbus. */
-evtchn_port_t xenbus_evtchn(void);
+evtchn_port_t get_xenbus_evtchn(void);
/* Write out the pidfile */
void write_pidfile(const char *pidfile);
diff --git a/tools/xenstored/domain.c b/tools/xenstored/domain.c
index 409b53acf9..6ef136e01f 100644
--- a/tools/xenstored/domain.c
+++ b/tools/xenstored/domain.c
@@ -1208,7 +1208,7 @@ void dom0_init(void)
evtchn_port_t port;
struct domain *dom0;
- port = xenbus_evtchn();
+ port = get_xenbus_evtchn();
if (port == -1)
barf_perror("Failed to initialize dom0 port");
diff --git a/tools/xenstored/minios.c b/tools/xenstored/minios.c
index b5c3a205e6..0779efbf91 100644
--- a/tools/xenstored/minios.c
+++ b/tools/xenstored/minios.c
@@ -38,7 +38,7 @@ void init_pipe(int reopen_log_pipe[2])
reopen_log_pipe[1] = -1;
}
-evtchn_port_t xenbus_evtchn(void)
+evtchn_port_t get_xenbus_evtchn(void)
{
return dom0_event;
}
diff --git a/tools/xenstored/posix.c b/tools/xenstored/posix.c
index 6ac45fdb45..7e03dd982d 100644
--- a/tools/xenstored/posix.c
+++ b/tools/xenstored/posix.c
@@ -111,7 +111,7 @@ void unmap_xenbus(void *interface)
munmap(interface, getpagesize());
}
-evtchn_port_t xenbus_evtchn(void)
+evtchn_port_t get_xenbus_evtchn(void)
{
int fd;
int rc;
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* Re: [PATCH 18/29] tools/xenstored: rename xenbus_evtchn()
2023-11-01 9:33 ` [PATCH 18/29] tools/xenstored: rename xenbus_evtchn() Juergen Gross
@ 2023-11-01 10:44 ` Julien Grall
2023-11-01 11:08 ` Juergen Gross
0 siblings, 1 reply; 81+ messages in thread
From: Julien Grall @ 2023-11-01 10:44 UTC (permalink / raw)
To: Juergen Gross, xen-devel; +Cc: Wei Liu, Anthony PERARD
Hi Juergen,
On 01/11/2023 09:33, Juergen Gross wrote:
> Rename the xenbus_evtchn() function to get_xenbus_evtchn() in order to
> avoid two externally visible symbols with the same name when Xenstore-
> stubdom is being built with a Mini-OS with CONFIG_XENBUS set.
This works right now, but what guarantee us that Mini-OS will not change
other symbols and clash with the one provided by Xenstored again?
Furthermore, technically, this is a problem for all the other software
linked with Mini-OS. So wouldn't it be better to modify the Mini-OS
build system to prefix all the symbols of the linked binary (here
Xenstored)?
Cheers,
--
Julien Grall
^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: [PATCH 18/29] tools/xenstored: rename xenbus_evtchn()
2023-11-01 10:44 ` Julien Grall
@ 2023-11-01 11:08 ` Juergen Gross
2023-11-01 11:14 ` Julien Grall
0 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 11:08 UTC (permalink / raw)
To: Julien Grall, xen-devel; +Cc: Wei Liu, Anthony PERARD
[-- Attachment #1.1.1: Type: text/plain, Size: 1319 bytes --]
On 01.11.23 11:44, Julien Grall wrote:
> Hi Juergen,
>
> On 01/11/2023 09:33, Juergen Gross wrote:
>> Rename the xenbus_evtchn() function to get_xenbus_evtchn() in order to
>> avoid two externally visible symbols with the same name when Xenstore-
>> stubdom is being built with a Mini-OS with CONFIG_XENBUS set.
> This works right now, but what guarantee us that Mini-OS will not change other
> symbols and clash with the one provided by Xenstored again?
>
> Furthermore, technically, this is a problem for all the other software linked
> with Mini-OS. So wouldn't it be better to modify the Mini-OS build system to
> prefix all the symbols of the linked binary (here Xenstored)?
How would that work?
From Mini-OS point of view libraries are not distinguishable from the
linked application. This would mean the build system would prefix the
library symbols as well, while the application would try to reference
the the un-prefixed library symbols.
I think the only way to avoid this kind of problem would be to have a
positive list of exported Mini-OS symbols and to hide all other symbols
from linked libraries and the app.
I can look into this, but I'd like to do this work outside of this
series in order not to block its development for an unknown amount of
time.
Juergen
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3149 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]
^ permalink raw reply [flat|nested] 81+ messages in thread
* Re: [PATCH 18/29] tools/xenstored: rename xenbus_evtchn()
2023-11-01 11:08 ` Juergen Gross
@ 2023-11-01 11:14 ` Julien Grall
0 siblings, 0 replies; 81+ messages in thread
From: Julien Grall @ 2023-11-01 11:14 UTC (permalink / raw)
To: Juergen Gross, xen-devel; +Cc: Wei Liu, Anthony PERARD
Hi Juergen,
On 01/11/2023 11:08, Juergen Gross wrote:
> On 01.11.23 11:44, Julien Grall wrote:
>> Hi Juergen,
>>
>> On 01/11/2023 09:33, Juergen Gross wrote:
>>> Rename the xenbus_evtchn() function to get_xenbus_evtchn() in order to
>>> avoid two externally visible symbols with the same name when Xenstore-
>>> stubdom is being built with a Mini-OS with CONFIG_XENBUS set.
>> This works right now, but what guarantee us that Mini-OS will not
>> change other symbols and clash with the one provided by Xenstored again?
>>
>> Furthermore, technically, this is a problem for all the other software
>> linked with Mini-OS. So wouldn't it be better to modify the Mini-OS
>> build system to prefix all the symbols of the linked binary (here
>> Xenstored)?
>
> How would that work?
>
> From Mini-OS point of view libraries are not distinguishable from the
> linked application. This would mean the build system would prefix the
> library symbols as well, while the application would try to reference
> the the un-prefixed library symbols.
AFAICT, objcopy could rename symbols. So if you pre-process the
libraries and application before hand, then you should still be able to
link.
>
> I think the only way to avoid this kind of problem would be to have a
> positive list of exported Mini-OS symbols and to hide all other symbols
> from linked libraries and the app.
>
> I can look into this, but I'd like to do this work outside of this
> series in order not to block its development for an unknown amount of
> time.
I am ok with that:
Reviewed-by: Julien Grall <jgrall@amazon.com>
Cheers,
--
Julien Grall
^ permalink raw reply [flat|nested] 81+ messages in thread
* [PATCH 19/29] stubdom: extend xenstore stubdom configs
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
` (17 preceding siblings ...)
2023-11-01 9:33 ` [PATCH 18/29] tools/xenstored: rename xenbus_evtchn() Juergen Gross
@ 2023-11-01 9:33 ` Juergen Gross
2023-11-07 18:24 ` Jason Andryuk
2023-11-01 9:33 ` [PATCH 20/29] tools: add 9pfs device to xenstore-stubdom Juergen Gross
` (9 subsequent siblings)
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:33 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Samuel Thibault
Extend the config files of the Xenstore stubdoms to include XENBUS
and 9PFRONT items in order to support file based logging.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
stubdom/xenstore-minios.cfg | 2 +-
stubdom/xenstorepvh-minios.cfg | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/stubdom/xenstore-minios.cfg b/stubdom/xenstore-minios.cfg
index a41704bb6b..239da519b9 100644
--- a/stubdom/xenstore-minios.cfg
+++ b/stubdom/xenstore-minios.cfg
@@ -3,7 +3,7 @@ CONFIG_NETFRONT=n
CONFIG_FBFRONT=n
CONFIG_KBDFRONT=n
CONFIG_CONSFRONT=n
-CONFIG_XENBUS=n
CONFIG_LWIP=n
+CONFIG_9PFRONT=y
CONFIG_BALLOON=y
XEN_INTERFACE_VERSION=__XEN_LATEST_INTERFACE_VERSION__
diff --git a/stubdom/xenstorepvh-minios.cfg b/stubdom/xenstorepvh-minios.cfg
index 6af51f5753..752b90d7d3 100644
--- a/stubdom/xenstorepvh-minios.cfg
+++ b/stubdom/xenstorepvh-minios.cfg
@@ -4,7 +4,7 @@ CONFIG_NETFRONT=n
CONFIG_FBFRONT=n
CONFIG_KBDFRONT=n
CONFIG_CONSFRONT=n
-CONFIG_XENBUS=n
CONFIG_LWIP=n
+CONFIG_9PFRONT=y
CONFIG_BALLOON=y
XEN_INTERFACE_VERSION=__XEN_LATEST_INTERFACE_VERSION__
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH 20/29] tools: add 9pfs device to xenstore-stubdom
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
` (18 preceding siblings ...)
2023-11-01 9:33 ` [PATCH 19/29] stubdom: extend xenstore stubdom configs Juergen Gross
@ 2023-11-01 9:33 ` Juergen Gross
2023-11-07 19:18 ` Jason Andryuk
2023-11-01 9:33 ` [PATCH 21/29] tools: tell xenstore-stubdom its own domid Juergen Gross
` (8 subsequent siblings)
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:33 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Julien Grall, Anthony PERARD
Add a 9pfs device to Xenstore stubdom in order to allow it to do e.g.
logging into a dom0 file.
Use the following parameters for the new device:
- tag = "xen"
- type = "xenlogd"
- path = "/var/lib/xen/xenstore"
For now don't limit allowed file space or number of files.
Add a new libxl function for adding it similar to the function for
adding the console device.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/helpers/init-xenstore-domain.c | 2 ++
tools/include/libxl.h | 17 ++++++++++++++++
tools/libs/light/libxl_9pfs.c | 29 ++++++++++++++++++++++++++++
3 files changed, 48 insertions(+)
diff --git a/tools/helpers/init-xenstore-domain.c b/tools/helpers/init-xenstore-domain.c
index 140ed610ae..a65abae2ac 100644
--- a/tools/helpers/init-xenstore-domain.c
+++ b/tools/helpers/init-xenstore-domain.c
@@ -543,6 +543,8 @@ int main(int argc, char** argv)
}
libxl_console_add_xenstore(ctx, domid, 0, console_evtchn, console_gfn,
NULL);
+ libxl_p9_add_xenstore(ctx, domid, 0, LIBXL_P9_TYPE_XENLOGD, "xen",
+ XEN_LIB_DIR"/xenstore", 0, 0, 0, 0, NULL);
libxl_ctx_free(ctx);
fd = creat(XEN_RUN_DIR "/xenstored.pid", 0666);
diff --git a/tools/include/libxl.h b/tools/include/libxl.h
index 907aa0a330..ab8a67f50a 100644
--- a/tools/include/libxl.h
+++ b/tools/include/libxl.h
@@ -583,6 +583,13 @@
* libxl_console_add_xenstore() in libxl.
*/
#define LIBXL_HAVE_CONSOLE_ADD_XENSTORE 1
+
+/*
+ * LIBXL_HAVE_P9_ADD_XENSTORE indicates presence of the function
+ * libxl_p9_add_xenstore() in libxl.
+ */
+#define LIBXL_HAVE_P9_ADD_XENSTORE 1
+
/*
* libxl ABI compatibility
*
@@ -2060,6 +2067,16 @@ int libxl_console_add_xenstore(libxl_ctx *ctx, uint32_t domid, uint32_t backend,
const libxl_asyncop_how *ao_how)
LIBXL_EXTERNAL_CALLERS_ONLY;
+/* libxl_p9_add_xenstore writes the Xenstore entries for a domain's
+ * primary 9pfs device based on domid, backend type and device parameters.
+ */
+int libxl_p9_add_xenstore(libxl_ctx *ctx, uint32_t domid, uint32_t backend,
+ libxl_p9_type type, char *tag, char *path,
+ unsigned int max_space, unsigned int max_files,
+ unsigned int max_open_files, bool auto_delete,
+ const libxl_asyncop_how *ao_how)
+ LIBXL_EXTERNAL_CALLERS_ONLY;
+
/* May be called with info_r == NULL to check for domain's existence.
* Returns ERROR_DOMAIN_NOTFOUND if domain does not exist (used to return
* ERROR_INVAL for this scenario). */
diff --git a/tools/libs/light/libxl_9pfs.c b/tools/libs/light/libxl_9pfs.c
index 0b9d84dce9..3297389493 100644
--- a/tools/libs/light/libxl_9pfs.c
+++ b/tools/libs/light/libxl_9pfs.c
@@ -174,6 +174,35 @@ static void libxl__device_p9_add(libxl__egc *egc, uint32_t domid,
aodev->callback(egc, aodev);
}
+int libxl_p9_add_xenstore(libxl_ctx *ctx, uint32_t domid, uint32_t backend,
+ libxl_p9_type type, char *tag, char *path,
+ unsigned int max_space, unsigned int max_files,
+ unsigned int max_open_files, bool auto_delete,
+ const libxl_asyncop_how *ao_how)
+{
+ AO_CREATE(ctx, domid, ao_how);
+ libxl__ao_device *aodev;
+ libxl_device_p9 p9 = { .backend_domid = backend,
+ .tag = tag,
+ .path = path,
+ .security_model = "none",
+ .type = type,
+ .max_space = max_space,
+ .max_files = max_files,
+ .max_open_files = max_open_files,
+ .auto_delete = auto_delete,
+ };
+
+ GCNEW(aodev);
+ libxl__prepare_ao_device(ao, aodev);
+ aodev->action = LIBXL__DEVICE_ACTION_ADD;
+ aodev->callback = device_addrm_aocomplete;
+
+ libxl__device_p9_add(egc, domid, &p9, aodev);
+
+ return AO_INPROGRESS;
+}
+
#define libxl_device_p9_list NULL
#define libxl_device_p9_compare NULL
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* Re: [PATCH 20/29] tools: add 9pfs device to xenstore-stubdom
2023-11-01 9:33 ` [PATCH 20/29] tools: add 9pfs device to xenstore-stubdom Juergen Gross
@ 2023-11-07 19:18 ` Jason Andryuk
2023-11-08 6:54 ` Juergen Gross
0 siblings, 1 reply; 81+ messages in thread
From: Jason Andryuk @ 2023-11-07 19:18 UTC (permalink / raw)
To: Juergen Gross; +Cc: xen-devel, Wei Liu, Julien Grall, Anthony PERARD
On Wed, Nov 1, 2023 at 8:23 AM Juergen Gross <jgross@suse.com> wrote:
>
> Add a 9pfs device to Xenstore stubdom in order to allow it to do e.g.
> logging into a dom0 file.
>
> Use the following parameters for the new device:
>
> - tag = "xen"
> - type = "xenlogd"
> - path = "/var/lib/xen/xenstore"
>
> For now don't limit allowed file space or number of files.
>
> Add a new libxl function for adding it similar to the function for
> adding the console device.
>
> Signed-off-by: Juergen Gross <jgross@suse.com>
> diff --git a/tools/libs/light/libxl_9pfs.c b/tools/libs/light/libxl_9pfs.c
> index 0b9d84dce9..3297389493 100644
> --- a/tools/libs/light/libxl_9pfs.c
> +++ b/tools/libs/light/libxl_9pfs.c
> @@ -174,6 +174,35 @@ static void libxl__device_p9_add(libxl__egc *egc, uint32_t domid,
> aodev->callback(egc, aodev);
> }
>
> +int libxl_p9_add_xenstore(libxl_ctx *ctx, uint32_t domid, uint32_t backend,
> + libxl_p9_type type, char *tag, char *path,
> + unsigned int max_space, unsigned int max_files,
> + unsigned int max_open_files, bool auto_delete,
> + const libxl_asyncop_how *ao_how)
> +{
> + AO_CREATE(ctx, domid, ao_how);
> + libxl__ao_device *aodev;
> + libxl_device_p9 p9 = { .backend_domid = backend,
> + .tag = tag,
> + .path = path,
> + .security_model = "none",
While the xl.cfg man page states that only security_model="none" is
supported, it is possible to use other ones. The value isn't
inspected and it is just passed through Xenstore to QEMU. QEMU can
then operate however it operates. I just tested mapped-xattr and it's
working from some quick testing. So maybe libxl_p9_add_xenstore()
should take security_model as an argument, and then
init-xenstore-domain can pass in "none"?
Everything else looks good, so either way:
Reviewed-by: Jason Andryuk <jandryuk@gmail.com>
^ permalink raw reply [flat|nested] 81+ messages in thread* Re: [PATCH 20/29] tools: add 9pfs device to xenstore-stubdom
2023-11-07 19:18 ` Jason Andryuk
@ 2023-11-08 6:54 ` Juergen Gross
0 siblings, 0 replies; 81+ messages in thread
From: Juergen Gross @ 2023-11-08 6:54 UTC (permalink / raw)
To: Jason Andryuk; +Cc: xen-devel, Wei Liu, Julien Grall, Anthony PERARD
[-- Attachment #1.1.1: Type: text/plain, Size: 2203 bytes --]
On 07.11.23 20:18, Jason Andryuk wrote:
> On Wed, Nov 1, 2023 at 8:23 AM Juergen Gross <jgross@suse.com> wrote:
>>
>> Add a 9pfs device to Xenstore stubdom in order to allow it to do e.g.
>> logging into a dom0 file.
>>
>> Use the following parameters for the new device:
>>
>> - tag = "xen"
>> - type = "xenlogd"
>> - path = "/var/lib/xen/xenstore"
>>
>> For now don't limit allowed file space or number of files.
>>
>> Add a new libxl function for adding it similar to the function for
>> adding the console device.
>>
>> Signed-off-by: Juergen Gross <jgross@suse.com>
>
>> diff --git a/tools/libs/light/libxl_9pfs.c b/tools/libs/light/libxl_9pfs.c
>> index 0b9d84dce9..3297389493 100644
>> --- a/tools/libs/light/libxl_9pfs.c
>> +++ b/tools/libs/light/libxl_9pfs.c
>> @@ -174,6 +174,35 @@ static void libxl__device_p9_add(libxl__egc *egc, uint32_t domid,
>> aodev->callback(egc, aodev);
>> }
>>
>> +int libxl_p9_add_xenstore(libxl_ctx *ctx, uint32_t domid, uint32_t backend,
>> + libxl_p9_type type, char *tag, char *path,
>> + unsigned int max_space, unsigned int max_files,
>> + unsigned int max_open_files, bool auto_delete,
>> + const libxl_asyncop_how *ao_how)
>> +{
>> + AO_CREATE(ctx, domid, ao_how);
>> + libxl__ao_device *aodev;
>> + libxl_device_p9 p9 = { .backend_domid = backend,
>> + .tag = tag,
>> + .path = path,
>> + .security_model = "none",
>
> While the xl.cfg man page states that only security_model="none" is
> supported, it is possible to use other ones. The value isn't
> inspected and it is just passed through Xenstore to QEMU. QEMU can
> then operate however it operates. I just tested mapped-xattr and it's
> working from some quick testing. So maybe libxl_p9_add_xenstore()
> should take security_model as an argument, and then
> init-xenstore-domain can pass in "none"?
Yes, good idea.
>
> Everything else looks good, so either way:
> Reviewed-by: Jason Andryuk <jandryuk@gmail.com>
Thanks,
Juergen
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3149 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]
^ permalink raw reply [flat|nested] 81+ messages in thread
* [PATCH 21/29] tools: tell xenstore-stubdom its own domid
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
` (19 preceding siblings ...)
2023-11-01 9:33 ` [PATCH 20/29] tools: add 9pfs device to xenstore-stubdom Juergen Gross
@ 2023-11-01 9:33 ` Juergen Gross
2023-11-01 16:51 ` Andrew Cooper
2023-11-01 9:33 ` [PATCH 22/29] tools/xenstored: Juergen Gross
` (7 subsequent siblings)
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:33 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Julien Grall, Anthony PERARD
Pass the domid as a boot parameter when starting xenstore-stubdom.
It will be needed to administrate its own Xenstore entries.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/helpers/init-xenstore-domain.c | 4 ++--
tools/xenstored/core.c | 9 +++++++++
tools/xenstored/core.h | 1 +
3 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/tools/helpers/init-xenstore-domain.c b/tools/helpers/init-xenstore-domain.c
index a65abae2ac..718cb3ba4e 100644
--- a/tools/helpers/init-xenstore-domain.c
+++ b/tools/helpers/init-xenstore-domain.c
@@ -240,9 +240,9 @@ static int build(xc_interface *xch)
}
if ( param )
- snprintf(cmdline, 512, "--event %d %s", rv, param);
+ snprintf(cmdline, 512, "--event %d --domid %u %s", rv, domid, param);
else
- snprintf(cmdline, 512, "--event %d", rv);
+ snprintf(cmdline, 512, "--event %d --domid %u", rv, domid);
dom->guest_domid = domid;
dom->cmdline = xc_dom_strdup(dom, cmdline);
diff --git a/tools/xenstored/core.c b/tools/xenstored/core.c
index edd07711db..bb4612455d 100644
--- a/tools/xenstored/core.c
+++ b/tools/xenstored/core.c
@@ -2732,12 +2732,16 @@ static struct option options[] = {
{ "watch-nb", 1, NULL, 'W' },
#ifndef NO_LIVE_UPDATE
{ "live-update", 0, NULL, 'U' },
+#endif
+#ifdef __MINIOS__
+ { "domid", 1, NULL, 2 },
#endif
{ NULL, 0, NULL, 0 } };
int dom0_domid = 0;
int dom0_event = 0;
int priv_domid = 0;
+int stub_domid = -1;
static unsigned int get_optval_uint(const char *arg)
{
@@ -2927,6 +2931,11 @@ int main(int argc, char *argv[])
case 'U':
live_update = true;
break;
+#endif
+#ifdef __MINIOS__
+ case 2:
+ stub_domid = get_optval_uint(optarg);
+ break;
#endif
}
}
diff --git a/tools/xenstored/core.h b/tools/xenstored/core.h
index 480b0f5f7b..f7a27a4131 100644
--- a/tools/xenstored/core.h
+++ b/tools/xenstored/core.h
@@ -359,6 +359,7 @@ do { \
extern int dom0_domid;
extern int dom0_event;
extern int priv_domid;
+extern int stub_domid;
extern bool keep_orphans;
extern unsigned int timeout_watch_event_msec;
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* Re: [PATCH 21/29] tools: tell xenstore-stubdom its own domid
2023-11-01 9:33 ` [PATCH 21/29] tools: tell xenstore-stubdom its own domid Juergen Gross
@ 2023-11-01 16:51 ` Andrew Cooper
0 siblings, 0 replies; 81+ messages in thread
From: Andrew Cooper @ 2023-11-01 16:51 UTC (permalink / raw)
To: Juergen Gross, xen-devel; +Cc: Wei Liu, Julien Grall, Anthony PERARD
On 01/11/2023 9:33 am, Juergen Gross wrote:
> Pass the domid as a boot parameter when starting xenstore-stubdom.
> It will be needed to administrate its own Xenstore entries.
>
> Signed-off-by: Juergen Gross <jgross@suse.com>
I'm going to fix this differently.
Because I'm utterly sick and tired of the absurd position at the moment
where HVM guests can ask the hypervisor for their domid but PV cant.
(Despite both being able to figure it out anyway through other
information leaks in hypercalls.)
The only reason I didn't nack the patch which created this problem to
begin with was because it was part of the original Spectre/Meltdown work.
~Andrew
^ permalink raw reply [flat|nested] 81+ messages in thread
* [PATCH 22/29] tools/xenstored:
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
` (20 preceding siblings ...)
2023-11-01 9:33 ` [PATCH 21/29] tools: tell xenstore-stubdom its own domid Juergen Gross
@ 2023-11-01 9:33 ` Juergen Gross
2023-11-07 19:23 ` Jason Andryuk
2023-11-01 9:33 ` [PATCH 23/29] tools/xenstored: split domain_init() Juergen Gross
` (6 subsequent siblings)
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:33 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Julien Grall, Anthony PERARD
When [un]mapping the ring page of a Xenstore client, different actions
are required for "normal" guests and dom0. Today this distinction is
made at call site.
Move this distinction into [un]map_interface() instead, avoiding code
duplication and preparing special handling for [un]mapping the stub
domain's ring page.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/xenstored/domain.c | 31 +++++++++++++------------------
1 file changed, 13 insertions(+), 18 deletions(-)
diff --git a/tools/xenstored/domain.c b/tools/xenstored/domain.c
index 6ef136e01f..58b0942043 100644
--- a/tools/xenstored/domain.c
+++ b/tools/xenstored/domain.c
@@ -497,14 +497,20 @@ static const struct interface_funcs domain_funcs = {
static void *map_interface(domid_t domid)
{
+ if (domid == xenbus_master_domid())
+ return xenbus_map();
+
return xengnttab_map_grant_ref(*xgt_handle, domid,
GNTTAB_RESERVED_XENSTORE,
PROT_READ|PROT_WRITE);
}
-static void unmap_interface(void *interface)
+static void unmap_interface(domid_t domid, void *interface)
{
- xengnttab_unmap(*xgt_handle, interface, 1);
+ if (domid == xenbus_master_domid())
+ unmap_xenbus(interface);
+ else
+ xengnttab_unmap(*xgt_handle, interface, 1);
}
static int domain_tree_remove_sub(const void *ctx, struct connection *conn,
@@ -594,14 +600,8 @@ static int destroy_domain(void *_domain)
eprintf("> Unbinding port %i failed!\n", domain->port);
}
- if (domain->interface) {
- /* Domain 0 was mapped by dom0_init, so it must be unmapped
- using munmap() and not the grant unmap call. */
- if (domain->domid == dom0_domid)
- unmap_xenbus(domain->interface);
- else
- unmap_interface(domain->interface);
- }
+ if (domain->interface)
+ unmap_interface(domain->domid, domain->interface);
fire_special_watches("@releaseDomain");
@@ -966,18 +966,13 @@ static struct domain *introduce_domain(const void *ctx,
return NULL;
if (!domain->introduced) {
- interface = is_master_domain ? xenbus_map()
- : map_interface(domid);
+ interface = map_interface(domid);
if (!interface && !restore)
return NULL;
if (new_domain(domain, port, restore)) {
rc = errno;
- if (interface) {
- if (is_master_domain)
- unmap_xenbus(interface);
- else
- unmap_interface(interface);
- }
+ if (interface)
+ unmap_interface(domid, interface);
errno = rc;
return NULL;
}
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* Re: [PATCH 22/29] tools/xenstored:
2023-11-01 9:33 ` [PATCH 22/29] tools/xenstored: Juergen Gross
@ 2023-11-07 19:23 ` Jason Andryuk
0 siblings, 0 replies; 81+ messages in thread
From: Jason Andryuk @ 2023-11-07 19:23 UTC (permalink / raw)
To: Juergen Gross; +Cc: xen-devel, Wei Liu, Julien Grall, Anthony PERARD
On Wed, Nov 1, 2023 at 7:15 AM Juergen Gross <jgross@suse.com> wrote:
>
> When [un]mapping the ring page of a Xenstore client, different actions
> are required for "normal" guests and dom0. Today this distinction is
> made at call site.
>
> Move this distinction into [un]map_interface() instead, avoiding code
> duplication and preparing special handling for [un]mapping the stub
> domain's ring page.
>
> Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Jason Andryuk <jandryuk@gmail.com>
^ permalink raw reply [flat|nested] 81+ messages in thread
* [PATCH 23/29] tools/xenstored: split domain_init()
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
` (21 preceding siblings ...)
2023-11-01 9:33 ` [PATCH 22/29] tools/xenstored: Juergen Gross
@ 2023-11-01 9:33 ` Juergen Gross
2023-11-01 9:33 ` [PATCH 24/29] tools/xenstored: map stubdom interface Juergen Gross
` (5 subsequent siblings)
28 siblings, 0 replies; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:33 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Julien Grall, Anthony PERARD
Today domain_init() is called either just before calling dom0_init()
in case no live update is being performed, or it is called after
reading the global state from read_state_global(), as the event
channel fd is needed.
Split up domain_init() into a preparation part which can be called
unconditionally, and in a part setting up the event channel handle.
Note that there is no chance that chk_domain_generation() can be
called now before xc_handle has been setup, so there is no need for
the related special case anymore.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/xenstored/core.c | 2 ++
tools/xenstored/domain.c | 12 ++++++------
tools/xenstored/domain.h | 1 +
3 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/tools/xenstored/core.c b/tools/xenstored/core.c
index bb4612455d..42a848e098 100644
--- a/tools/xenstored/core.c
+++ b/tools/xenstored/core.c
@@ -2972,6 +2972,8 @@ int main(int argc, char *argv[])
init_pipe(reopen_log_pipe);
+ domain_static_init();
+
/* Listen to hypervisor. */
if (!no_domain_init && !live_update) {
domain_init(-1);
diff --git a/tools/xenstored/domain.c b/tools/xenstored/domain.c
index 58b0942043..fa17f68618 100644
--- a/tools/xenstored/domain.c
+++ b/tools/xenstored/domain.c
@@ -1224,10 +1224,8 @@ static int domeq_fn(const void *key1, const void *key2)
return *(const unsigned int *)key1 == *(const unsigned int *)key2;
}
-void domain_init(int evtfd)
+void domain_static_init(void)
{
- int rc;
-
/* Start with a random rather low domain count for the hashtable. */
domhash = create_hashtable(NULL, "domains", domhash_fn, domeq_fn, 0);
if (!domhash)
@@ -1258,6 +1256,11 @@ void domain_init(int evtfd)
xengnttab_set_max_grants(*xgt_handle, DOMID_FIRST_RESERVED);
talloc_set_destructor(xgt_handle, close_xgt_handle);
+}
+
+void domain_init(int evtfd)
+{
+ int rc;
if (evtfd < 0)
xce_handle = xenevtchn_open(NULL, XENEVTCHN_NO_CLOEXEC);
@@ -1291,9 +1294,6 @@ static bool chk_domain_generation(unsigned int domid, uint64_t gen)
{
struct domain *d;
- if (!xc_handle && domid == dom0_domid)
- return true;
-
d = find_domain_struct(domid);
return d && d->generation <= gen;
diff --git a/tools/xenstored/domain.h b/tools/xenstored/domain.h
index 7625dca8cd..6c00540311 100644
--- a/tools/xenstored/domain.h
+++ b/tools/xenstored/domain.h
@@ -82,6 +82,7 @@ int do_get_domain_path(const void *ctx, struct connection *conn,
int do_reset_watches(const void *ctx, struct connection *conn,
struct buffered_data *in);
+void domain_static_init(void);
void domain_init(int evtfd);
void dom0_init(void);
void domain_deinit(void);
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH 24/29] tools/xenstored: map stubdom interface
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
` (22 preceding siblings ...)
2023-11-01 9:33 ` [PATCH 23/29] tools/xenstored: split domain_init() Juergen Gross
@ 2023-11-01 9:33 ` Juergen Gross
2023-11-01 9:33 ` [PATCH 25/29] tools/xenstored: mount 9pfs device in stubdom Juergen Gross
` (4 subsequent siblings)
28 siblings, 0 replies; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:33 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Julien Grall, Anthony PERARD
When running as stubdom, map the stubdom's Xenstore ring page in order
to support using the 9pfs frontend.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/xenstored/core.c | 2 ++
tools/xenstored/domain.c | 27 ++++++++++++++++++++++++++-
tools/xenstored/domain.h | 1 +
3 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/tools/xenstored/core.c b/tools/xenstored/core.c
index 42a848e098..1764b1af4e 100644
--- a/tools/xenstored/core.c
+++ b/tools/xenstored/core.c
@@ -3003,6 +3003,8 @@ int main(int argc, char *argv[])
lu_read_state();
#endif
+ stubdom_init();
+
check_store();
/* Get ready to listen to the tools. */
diff --git a/tools/xenstored/domain.c b/tools/xenstored/domain.c
index fa17f68618..162b87b460 100644
--- a/tools/xenstored/domain.c
+++ b/tools/xenstored/domain.c
@@ -37,6 +37,10 @@
#include <xenctrl.h>
#include <xen/grant_table.h>
+#ifdef __MINIOS__
+#include <mini-os/xenbus.h>
+#endif
+
static xc_interface **xc_handle;
xengnttab_handle **xgt_handle;
static evtchn_port_t virq_port;
@@ -500,6 +504,11 @@ static void *map_interface(domid_t domid)
if (domid == xenbus_master_domid())
return xenbus_map();
+#ifdef __MINIOS__
+ if (domid == stub_domid)
+ return xenstore_buf;
+#endif
+
return xengnttab_map_grant_ref(*xgt_handle, domid,
GNTTAB_RESERVED_XENSTORE,
PROT_READ|PROT_WRITE);
@@ -509,7 +518,7 @@ static void unmap_interface(domid_t domid, void *interface)
{
if (domid == xenbus_master_domid())
unmap_xenbus(interface);
- else
+ else if (domid != stub_domid)
xengnttab_unmap(*xgt_handle, interface, 1);
}
@@ -1214,6 +1223,22 @@ void dom0_init(void)
xenevtchn_notify(xce_handle, dom0->port);
}
+void stubdom_init(void)
+{
+#ifdef __MINIOS__
+ struct domain *stubdom;
+
+ if (stub_domid < 0)
+ return;
+
+ stubdom = introduce_domain(NULL, stub_domid, xenbus_evtchn, false);
+ if (!stubdom)
+ barf_perror("Failed to initialize stubdom");
+
+ xenevtchn_notify(xce_handle, stubdom->port);
+#endif
+}
+
static unsigned int domhash_fn(const void *k)
{
return *(const unsigned int *)k;
diff --git a/tools/xenstored/domain.h b/tools/xenstored/domain.h
index 6c00540311..49c60c56bf 100644
--- a/tools/xenstored/domain.h
+++ b/tools/xenstored/domain.h
@@ -85,6 +85,7 @@ int do_reset_watches(const void *ctx, struct connection *conn,
void domain_static_init(void);
void domain_init(int evtfd);
void dom0_init(void);
+void stubdom_init(void);
void domain_deinit(void);
void ignore_connection(struct connection *conn, unsigned int err);
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH 25/29] tools/xenstored: mount 9pfs device in stubdom
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
` (23 preceding siblings ...)
2023-11-01 9:33 ` [PATCH 24/29] tools/xenstored: map stubdom interface Juergen Gross
@ 2023-11-01 9:33 ` Juergen Gross
2023-11-07 20:32 ` Jason Andryuk
2023-11-01 9:33 ` [PATCH 26/29] tools/xenstored: add helpers for filename handling Juergen Gross
` (3 subsequent siblings)
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:33 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Julien Grall, Anthony PERARD
Mount the 9pfs device in stubdom enabling it to use files.
This has to happen in a worker thread in order to allow the main thread
handling the required Xenstore accesses in parallel.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/xenstored/core.h | 5 +++++
tools/xenstored/domain.c | 2 ++
tools/xenstored/minios.c | 35 +++++++++++++++++++++++++++++++++++
3 files changed, 42 insertions(+)
diff --git a/tools/xenstored/core.h b/tools/xenstored/core.h
index f7a27a4131..48ff659ec5 100644
--- a/tools/xenstored/core.h
+++ b/tools/xenstored/core.h
@@ -35,6 +35,8 @@
#include "list.h"
#include "hashtable.h"
+#define XENSTORE_LIB_DIR XEN_LIB_DIR "/xenstore"
+
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
/* O_CLOEXEC support is needed for Live Update in the daemon case. */
@@ -385,6 +387,9 @@ static inline bool domain_is_unprivileged(const struct connection *conn)
/* Return the event channel used by xenbus. */
evtchn_port_t get_xenbus_evtchn(void);
+#ifdef __MINIOS__
+void mount_9pfs(void);
+#endif
/* Write out the pidfile */
void write_pidfile(const char *pidfile);
diff --git a/tools/xenstored/domain.c b/tools/xenstored/domain.c
index 162b87b460..4263c1360f 100644
--- a/tools/xenstored/domain.c
+++ b/tools/xenstored/domain.c
@@ -1236,6 +1236,8 @@ void stubdom_init(void)
barf_perror("Failed to initialize stubdom");
xenevtchn_notify(xce_handle, stubdom->port);
+
+ mount_9pfs();
#endif
}
diff --git a/tools/xenstored/minios.c b/tools/xenstored/minios.c
index 0779efbf91..e5a3684df6 100644
--- a/tools/xenstored/minios.c
+++ b/tools/xenstored/minios.c
@@ -19,6 +19,14 @@
#include <sys/mman.h>
#include "core.h"
#include <xen/grant_table.h>
+#include <mini-os/9pfront.h>
+#include <mini-os/sched.h>
+#include <mini-os/xenbus.h>
+#include <mini-os/xmalloc.h>
+
+#define P9_STATE_PATH "device/9pfs/0/state"
+
+static void *p9_device;
void write_pidfile(const char *pidfile)
{
@@ -54,3 +62,30 @@ void unmap_xenbus(void *interface)
xengnttab_unmap(*xgt_handle, interface, 1);
}
+static void mount_thread(void *p)
+{
+ xenbus_event_queue events = NULL;
+ char *err;
+ char *dummy;
+
+ free(xenbus_watch_path_token(XBT_NIL, P9_STATE_PATH, "9pfs", &events));
+
+ for (;;) {
+ xenbus_wait_for_watch(&events);
+ err = xenbus_read(XBT_NIL, P9_STATE_PATH, &dummy);
+ if (!err)
+ break;
+ free(err);
+ }
+
+ free(dummy);
+
+ free(xenbus_unwatch_path_token(XBT_NIL, P9_STATE_PATH, "9pfs"));
+
+ p9_device = init_9pfront(0, XENSTORE_LIB_DIR);
+}
+
+void mount_9pfs(void)
+{
+ create_thread("mount-9pfs", mount_thread, NULL);
+}
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH 26/29] tools/xenstored: add helpers for filename handling
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
` (24 preceding siblings ...)
2023-11-01 9:33 ` [PATCH 25/29] tools/xenstored: mount 9pfs device in stubdom Juergen Gross
@ 2023-11-01 9:33 ` Juergen Gross
2023-11-07 20:34 ` Jason Andryuk
2023-11-01 9:33 ` [PATCH 27/29] tools/xenstored: add daemon_init() function Juergen Gross
` (2 subsequent siblings)
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:33 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Julien Grall, Anthony PERARD
Add some helpers for handling filenames which might need different
implementations between stubdom and daemon environments:
- expansion of relative filenames (those are not really defined today,
just expand them to be relative to /var/lib/xen/xenstore)
- expansion of xenstore_daemon_rundir() (used e.g. for saving the state
file in case of live update - needs to be unchanged in the daemon
case, but should result in /var/lib/xen/xenstore for stubdom)
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/xenstored/core.c | 9 ++++++++-
tools/xenstored/core.h | 3 +++
tools/xenstored/lu_daemon.c | 4 ++--
tools/xenstored/minios.c | 5 +++++
tools/xenstored/posix.c | 6 ++++++
5 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/tools/xenstored/core.c b/tools/xenstored/core.c
index 1764b1af4e..9f48d91027 100644
--- a/tools/xenstored/core.c
+++ b/tools/xenstored/core.c
@@ -158,6 +158,13 @@ void trace_destroy(const void *data, const char *type)
trace("obj: DESTROY %s %p\n", type, data);
}
+char *absolute_filename(const void *ctx, const char *filename)
+{
+ if (filename[0] != '/')
+ return talloc_asprintf(ctx, XENSTORE_LIB_DIR "/%s", filename);
+ return talloc_strdup(ctx, filename);
+}
+
/**
* Signal handler for SIGHUP, which requests that the trace log is reopened
* (in the main loop). A single byte is written to reopen_log_pipe, to awaken
@@ -2995,7 +3002,7 @@ int main(int argc, char *argv[])
signal(SIGHUP, trigger_reopen_log);
if (tracefile)
- tracefile = talloc_strdup(NULL, tracefile);
+ tracefile = absolute_filename(NULL, tracefile);
#ifndef NO_LIVE_UPDATE
/* Read state in case of live update. */
diff --git a/tools/xenstored/core.h b/tools/xenstored/core.h
index 48ff659ec5..d3cd4a4c8a 100644
--- a/tools/xenstored/core.h
+++ b/tools/xenstored/core.h
@@ -391,6 +391,9 @@ evtchn_port_t get_xenbus_evtchn(void);
void mount_9pfs(void);
#endif
+const char *xenstore_rundir(void);
+char *absolute_filename(const void *ctx, const char *filename);
+
/* Write out the pidfile */
void write_pidfile(const char *pidfile);
diff --git a/tools/xenstored/lu_daemon.c b/tools/xenstored/lu_daemon.c
index 71bcabadd3..6351111ab0 100644
--- a/tools/xenstored/lu_daemon.c
+++ b/tools/xenstored/lu_daemon.c
@@ -24,7 +24,7 @@ void lu_get_dump_state(struct lu_dump_state *state)
state->size = 0;
state->filename = talloc_asprintf(NULL, "%s/state_dump",
- xenstore_daemon_rundir());
+ xenstore_rundir());
if (!state->filename)
barf("Allocation failure");
@@ -65,7 +65,7 @@ FILE *lu_dump_open(const void *ctx)
int fd;
filename = talloc_asprintf(ctx, "%s/state_dump",
- xenstore_daemon_rundir());
+ xenstore_rundir());
if (!filename)
return NULL;
diff --git a/tools/xenstored/minios.c b/tools/xenstored/minios.c
index e5a3684df6..104f37587b 100644
--- a/tools/xenstored/minios.c
+++ b/tools/xenstored/minios.c
@@ -89,3 +89,8 @@ void mount_9pfs(void)
{
create_thread("mount-9pfs", mount_thread, NULL);
}
+
+const char *xenstore_rundir(void)
+{
+ return XENSTORE_LIB_DIR;
+}
diff --git a/tools/xenstored/posix.c b/tools/xenstored/posix.c
index 7e03dd982d..d02d0e446f 100644
--- a/tools/xenstored/posix.c
+++ b/tools/xenstored/posix.c
@@ -22,6 +22,7 @@
#include <fcntl.h>
#include <stdlib.h>
#include <sys/mman.h>
+#include <xen-tools/xenstore-common.h>
#include "utils.h"
#include "core.h"
@@ -157,3 +158,8 @@ void *xenbus_map(void)
return addr;
}
+
+const char *xenstore_rundir(void)
+{
+ return xenstore_daemon_rundir();
+}
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* Re: [PATCH 26/29] tools/xenstored: add helpers for filename handling
2023-11-01 9:33 ` [PATCH 26/29] tools/xenstored: add helpers for filename handling Juergen Gross
@ 2023-11-07 20:34 ` Jason Andryuk
0 siblings, 0 replies; 81+ messages in thread
From: Jason Andryuk @ 2023-11-07 20:34 UTC (permalink / raw)
To: Juergen Gross; +Cc: xen-devel, Wei Liu, Julien Grall, Anthony PERARD
On Wed, Nov 1, 2023 at 7:29 AM Juergen Gross <jgross@suse.com> wrote:
>
> Add some helpers for handling filenames which might need different
> implementations between stubdom and daemon environments:
>
> - expansion of relative filenames (those are not really defined today,
> just expand them to be relative to /var/lib/xen/xenstore)
> - expansion of xenstore_daemon_rundir() (used e.g. for saving the state
> file in case of live update - needs to be unchanged in the daemon
> case, but should result in /var/lib/xen/xenstore for stubdom)
>
> Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Jason Andryuk <jandryuk@gmail.com>
^ permalink raw reply [flat|nested] 81+ messages in thread
* [PATCH 27/29] tools/xenstored: add daemon_init() function
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
` (25 preceding siblings ...)
2023-11-01 9:33 ` [PATCH 26/29] tools/xenstored: add helpers for filename handling Juergen Gross
@ 2023-11-01 9:33 ` Juergen Gross
2023-11-07 20:34 ` Jason Andryuk
2023-11-01 9:33 ` [PATCH 28/29] tools/xenstored: support complete log capabilities in stubdom Juergen Gross
2023-11-01 9:33 ` [PATCH 29/29] tools/xenstored: have a single do_control_memreport() Juergen Gross
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:33 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Julien Grall, Anthony PERARD
Some xenstored initialization needs to be done in the daemon case only,
so split it out into a new daemon_init() function being a stub in the
stubdom case.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/xenstored/core.c | 6 +-----
tools/xenstored/core.h | 1 +
tools/xenstored/minios.c | 4 ++++
tools/xenstored/posix.c | 10 ++++++++++
4 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/tools/xenstored/core.c b/tools/xenstored/core.c
index 9f48d91027..204b932ca9 100644
--- a/tools/xenstored/core.c
+++ b/tools/xenstored/core.c
@@ -2949,11 +2949,7 @@ int main(int argc, char *argv[])
if (optind != argc)
barf("%s: No arguments desired", argv[0]);
- reopen_log();
-
- /* Make sure xenstored directory exists. */
- /* Errors ignored here, will be reported when we open files */
- mkdir(xenstore_daemon_rundir(), 0755);
+ daemon_init();
if (dofork) {
openlog("xenstored", 0, LOG_DAEMON);
diff --git a/tools/xenstored/core.h b/tools/xenstored/core.h
index d3cd4a4c8a..a15d5b0d67 100644
--- a/tools/xenstored/core.h
+++ b/tools/xenstored/core.h
@@ -391,6 +391,7 @@ evtchn_port_t get_xenbus_evtchn(void);
void mount_9pfs(void);
#endif
+void daemon_init(void);
const char *xenstore_rundir(void);
char *absolute_filename(const void *ctx, const char *filename);
diff --git a/tools/xenstored/minios.c b/tools/xenstored/minios.c
index 104f37587b..cd6e288f2a 100644
--- a/tools/xenstored/minios.c
+++ b/tools/xenstored/minios.c
@@ -62,6 +62,10 @@ void unmap_xenbus(void *interface)
xengnttab_unmap(*xgt_handle, interface, 1);
}
+void daemon_init(void)
+{
+}
+
static void mount_thread(void *p)
{
xenbus_event_queue events = NULL;
diff --git a/tools/xenstored/posix.c b/tools/xenstored/posix.c
index d02d0e446f..c84e7ef3a8 100644
--- a/tools/xenstored/posix.c
+++ b/tools/xenstored/posix.c
@@ -163,3 +163,13 @@ const char *xenstore_rundir(void)
{
return xenstore_daemon_rundir();
}
+
+void daemon_init(void)
+{
+ reopen_log();
+
+ /* Make sure xenstored directories exist. */
+ /* Errors ignored here, will be reported when we open files */
+ mkdir(xenstore_daemon_rundir(), 0755);
+ mkdir(XENSTORE_LIB_DIR, 0755);
+}
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH 28/29] tools/xenstored: support complete log capabilities in stubdom
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
` (26 preceding siblings ...)
2023-11-01 9:33 ` [PATCH 27/29] tools/xenstored: add daemon_init() function Juergen Gross
@ 2023-11-01 9:33 ` Juergen Gross
2023-11-07 20:36 ` Jason Andryuk
2023-11-01 9:33 ` [PATCH 29/29] tools/xenstored: have a single do_control_memreport() Juergen Gross
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:33 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Anthony PERARD, Julien Grall
With 9pfs being fully available in Xenstore-stubdom now, there is no
reason to not fully support all logging capabilities in stubdom.
Open the logfile on stubdom only after the 9pfs file system has been
mounted.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/hotplug/Linux/launch-xenstore.in | 1 +
tools/xenstored/control.c | 30 +++++++++++++-------------
tools/xenstored/minios.c | 3 +++
3 files changed, 19 insertions(+), 15 deletions(-)
diff --git a/tools/hotplug/Linux/launch-xenstore.in b/tools/hotplug/Linux/launch-xenstore.in
index e854ca1eb8..da4eeca7c5 100644
--- a/tools/hotplug/Linux/launch-xenstore.in
+++ b/tools/hotplug/Linux/launch-xenstore.in
@@ -98,6 +98,7 @@ test -f @CONFIG_DIR@/@CONFIG_LEAF_DIR@/xencommons && . @CONFIG_DIR@/@CONFIG_LEAF
[ -z "$XENSTORE_DOMAIN_SIZE" ] && XENSTORE_DOMAIN_SIZE=8
XENSTORE_DOMAIN_ARGS="$XENSTORE_DOMAIN_ARGS --memory $XENSTORE_DOMAIN_SIZE"
[ -z "$XENSTORE_MAX_DOMAIN_SIZE" ] || XENSTORE_DOMAIN_ARGS="$XENSTORE_DOMAIN_ARGS --maxmem $XENSTORE_MAX_DOMAIN_SIZE"
+ [ -z "$XENSTORED_TRACE" ] || XENSTORE_DOMAIN_ARGS="$XENSTORE_DOMAIN_ARGS -T xenstored-trace.log"
echo -n Starting $XENSTORE_DOMAIN_KERNEL...
${LIBEXEC_BIN}/init-xenstore-domain $XENSTORE_DOMAIN_ARGS || exit 1
diff --git a/tools/xenstored/control.c b/tools/xenstored/control.c
index b2f64d674f..dae23a5ac0 100644
--- a/tools/xenstored/control.c
+++ b/tools/xenstored/control.c
@@ -201,19 +201,6 @@ static int do_control_quota_s(const void *ctx, struct connection *conn,
return EINVAL;
}
-#ifdef __MINIOS__
-static int do_control_memreport(const void *ctx, struct connection *conn,
- const char **vec, int num)
-{
- if (num)
- return EINVAL;
-
- talloc_report_full(NULL, stdout);
-
- send_ack(conn, XS_CONTROL);
- return 0;
-}
-#else
static int do_control_logfile(const void *ctx, struct connection *conn,
const char **vec, int num)
{
@@ -222,13 +209,26 @@ static int do_control_logfile(const void *ctx, struct connection *conn,
close_log();
talloc_free(tracefile);
- tracefile = talloc_strdup(NULL, vec[0]);
+ tracefile = absolute_filename(NULL, vec[0]);
reopen_log();
send_ack(conn, XS_CONTROL);
return 0;
}
+#ifdef __MINIOS__
+static int do_control_memreport(const void *ctx, struct connection *conn,
+ const char **vec, int num)
+{
+ if (num)
+ return EINVAL;
+
+ talloc_report_full(NULL, stdout);
+
+ send_ack(conn, XS_CONTROL);
+ return 0;
+}
+#else
static int do_control_memreport(const void *ctx, struct connection *conn,
const char **vec, int num)
{
@@ -309,10 +309,10 @@ static struct cmd_s cmds[] = {
"[-c <cmdline>] [-F] [-t <timeout>] <file>\n"
" Default timeout is 60 seconds.", 5 },
#endif
+ { "logfile", do_control_logfile, "<file>" },
#ifdef __MINIOS__
{ "memreport", do_control_memreport, "" },
#else
- { "logfile", do_control_logfile, "<file>" },
{ "memreport", do_control_memreport, "[<file>]" },
#endif
{ "print", do_control_print, "<string>" },
diff --git a/tools/xenstored/minios.c b/tools/xenstored/minios.c
index cd6e288f2a..c02a263d9d 100644
--- a/tools/xenstored/minios.c
+++ b/tools/xenstored/minios.c
@@ -87,6 +87,9 @@ static void mount_thread(void *p)
free(xenbus_unwatch_path_token(XBT_NIL, P9_STATE_PATH, "9pfs"));
p9_device = init_9pfront(0, XENSTORE_LIB_DIR);
+
+ /* Start logging if selected. */
+ reopen_log();
}
void mount_9pfs(void)
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH 29/29] tools/xenstored: have a single do_control_memreport()
2023-11-01 9:32 [PATCH 00/29] tools: enable xenstore-stubdom to use 9pfs Juergen Gross
` (27 preceding siblings ...)
2023-11-01 9:33 ` [PATCH 28/29] tools/xenstored: support complete log capabilities in stubdom Juergen Gross
@ 2023-11-01 9:33 ` Juergen Gross
2023-11-07 20:40 ` Jason Andryuk
28 siblings, 1 reply; 81+ messages in thread
From: Juergen Gross @ 2023-11-01 9:33 UTC (permalink / raw)
To: xen-devel; +Cc: Juergen Gross, Wei Liu, Julien Grall, Anthony PERARD
With 9pfs now available in Xenstore-stubdom, there is no reason to
have distinct do_control_memreport() variants for the daemon and the
stubdom implementations.
Signed-off-by: Juergen Gross <jgross@suse.com>
---
tools/xenstored/control.c | 27 +++++++--------------------
1 file changed, 7 insertions(+), 20 deletions(-)
diff --git a/tools/xenstored/control.c b/tools/xenstored/control.c
index dae23a5ac0..7db2c4703b 100644
--- a/tools/xenstored/control.c
+++ b/tools/xenstored/control.c
@@ -216,23 +216,11 @@ static int do_control_logfile(const void *ctx, struct connection *conn,
return 0;
}
-#ifdef __MINIOS__
-static int do_control_memreport(const void *ctx, struct connection *conn,
- const char **vec, int num)
-{
- if (num)
- return EINVAL;
-
- talloc_report_full(NULL, stdout);
-
- send_ack(conn, XS_CONTROL);
- return 0;
-}
-#else
static int do_control_memreport(const void *ctx, struct connection *conn,
const char **vec, int num)
{
FILE *fp;
+ char *filename;
int fd;
if (num > 1)
@@ -255,8 +243,12 @@ static int do_control_memreport(const void *ctx, struct connection *conn,
if (!fp)
close(fd);
}
- } else
- fp = fopen(vec[0], "a");
+ } else {
+ filename = absolute_filename(ctx, vec[0]);
+ if (!filename)
+ return ENOMEM;
+ fp = fopen(filename, "a");
+ }
if (!fp)
return EBADF;
@@ -267,7 +259,6 @@ static int do_control_memreport(const void *ctx, struct connection *conn,
send_ack(conn, XS_CONTROL);
return 0;
}
-#endif
static int do_control_print(const void *ctx, struct connection *conn,
const char **vec, int num)
@@ -310,11 +301,7 @@ static struct cmd_s cmds[] = {
" Default timeout is 60 seconds.", 5 },
#endif
{ "logfile", do_control_logfile, "<file>" },
-#ifdef __MINIOS__
- { "memreport", do_control_memreport, "" },
-#else
{ "memreport", do_control_memreport, "[<file>]" },
-#endif
{ "print", do_control_print, "<string>" },
{ "quota", do_control_quota,
"[set <name> <val>|<domid>|max [-r]]" },
--
2.35.3
^ permalink raw reply related [flat|nested] 81+ messages in thread