diff mbox series

[09/29] tools/xenlogd: add 9pfs open request support

Message ID 20231101093325.30302-10-jgross@suse.com (mailing list archive)
State Superseded
Headers show
Series tools: enable xenstore-stubdom to use 9pfs | expand

Commit Message

Jürgen Groß Nov. 1, 2023, 9:33 a.m. UTC
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(+)

Comments

Jason Andryuk Nov. 6, 2023, 7:33 p.m. UTC | #1
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
Jürgen Groß Nov. 7, 2023, 7:03 a.m. UTC | #2
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
diff mbox series

Patch

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[];
 };