All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 1/7] tests/9pfs: walk to non-existent dir
  2022-03-15 10:10 [PATCH v4 0/7] 9pfs: fix 'Twalk' protocol violation Christian Schoenebeck
@ 2022-03-15 10:08 ` Christian Schoenebeck
  2022-03-15 10:08 ` [PATCH v4 2/7] tests/9pfs: Twalk with nwname=0 Christian Schoenebeck
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Christian Schoenebeck @ 2022-03-15 10:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Greg Kurz

Expect ENOENT Rlerror response when trying to walk to a
non-existent directory.

Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
Based-on: <E1nTpyU-0000yR-9o@lizzy.crudebyte.com>
---
 tests/qtest/virtio-9p-test.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/tests/qtest/virtio-9p-test.c b/tests/qtest/virtio-9p-test.c
index 01ca076afe..22bdd74bc1 100644
--- a/tests/qtest/virtio-9p-test.c
+++ b/tests/qtest/virtio-9p-test.c
@@ -606,6 +606,25 @@ static uint32_t do_walk(QVirtio9P *v9p, const char *path)
     return fid;
 }
 
+/* utility function: walk to requested dir and expect passed error response */
+static void do_walk_expect_error(QVirtio9P *v9p, const char *path, uint32_t err)
+{
+    char **wnames;
+    P9Req *req;
+    uint32_t _err;
+    const uint32_t fid = genfid();
+
+    int nwnames = split(path, "/", &wnames);
+
+    req = v9fs_twalk(v9p, 0, fid, nwnames, wnames, 0);
+    v9fs_req_wait_for_reply(req, NULL);
+    v9fs_rlerror(req, &_err);
+
+    g_assert_cmpint(_err, ==, err);
+
+    split_free(&wnames);
+}
+
 static void fs_version(void *obj, void *data, QGuestAllocator *t_alloc)
 {
     alloc = t_alloc;
@@ -974,6 +993,15 @@ static void fs_walk_no_slash(void *obj, void *data, QGuestAllocator *t_alloc)
     g_free(wnames[0]);
 }
 
+static void fs_walk_nonexistent(void *obj, void *data, QGuestAllocator *t_alloc)
+{
+    QVirtio9P *v9p = obj;
+    alloc = t_alloc;
+
+    do_attach(v9p);
+    do_walk_expect_error(v9p, "non-existent", ENOENT);
+}
+
 static void fs_walk_dotdot(void *obj, void *data, QGuestAllocator *t_alloc)
 {
     QVirtio9P *v9p = obj;
@@ -1409,6 +1437,8 @@ static void register_virtio_9p_test(void)
                   &opts);
     qos_add_test("synth/walk/dotdot_from_root", "virtio-9p",
                  fs_walk_dotdot,  &opts);
+    qos_add_test("synth/walk/non_existent", "virtio-9p", fs_walk_nonexistent,
+                  &opts);
     qos_add_test("synth/lopen/basic", "virtio-9p", fs_lopen,  &opts);
     qos_add_test("synth/write/basic", "virtio-9p", fs_write,  &opts);
     qos_add_test("synth/flush/success", "virtio-9p", fs_flush_success,
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v4 2/7] tests/9pfs: Twalk with nwname=0
  2022-03-15 10:10 [PATCH v4 0/7] 9pfs: fix 'Twalk' protocol violation Christian Schoenebeck
  2022-03-15 10:08 ` [PATCH v4 1/7] tests/9pfs: walk to non-existent dir Christian Schoenebeck
@ 2022-03-15 10:08 ` Christian Schoenebeck
  2022-03-15 10:08 ` [PATCH v4 3/7] tests/9pfs: compare QIDs in fs_walk_none() test Christian Schoenebeck
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Christian Schoenebeck @ 2022-03-15 10:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Greg Kurz

Send Twalk request with nwname=0. In this case no QIDs should
be returned by 9p server; this is equivalent to walking to dot.

Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
---
 tests/qtest/virtio-9p-test.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/tests/qtest/virtio-9p-test.c b/tests/qtest/virtio-9p-test.c
index 22bdd74bc1..6c00da03f4 100644
--- a/tests/qtest/virtio-9p-test.c
+++ b/tests/qtest/virtio-9p-test.c
@@ -1002,6 +1002,27 @@ static void fs_walk_nonexistent(void *obj, void *data, QGuestAllocator *t_alloc)
     do_walk_expect_error(v9p, "non-existent", ENOENT);
 }
 
+static void fs_walk_none(void *obj, void *data, QGuestAllocator *t_alloc)
+{
+    QVirtio9P *v9p = obj;
+    alloc = t_alloc;
+    v9fs_qid root_qid;
+    g_autofree v9fs_qid *wqid = NULL;
+    P9Req *req;
+
+    do_version(v9p);
+    req = v9fs_tattach(v9p, 0, getuid(), 0);
+    v9fs_req_wait_for_reply(req, NULL);
+    v9fs_rattach(req, &root_qid);
+
+    req = v9fs_twalk(v9p, 0, 1, 0, NULL, 0);
+    v9fs_req_wait_for_reply(req, NULL);
+    v9fs_rwalk(req, NULL, &wqid);
+
+    /* special case: no QID is returned if nwname=0 was sent */
+    g_assert(wqid == NULL);
+}
+
 static void fs_walk_dotdot(void *obj, void *data, QGuestAllocator *t_alloc)
 {
     QVirtio9P *v9p = obj;
@@ -1435,6 +1456,7 @@ static void register_virtio_9p_test(void)
     qos_add_test("synth/walk/basic", "virtio-9p", fs_walk,  &opts);
     qos_add_test("synth/walk/no_slash", "virtio-9p", fs_walk_no_slash,
                   &opts);
+    qos_add_test("synth/walk/none", "virtio-9p", fs_walk_none, &opts);
     qos_add_test("synth/walk/dotdot_from_root", "virtio-9p",
                  fs_walk_dotdot,  &opts);
     qos_add_test("synth/walk/non_existent", "virtio-9p", fs_walk_nonexistent,
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v4 3/7] tests/9pfs: compare QIDs in fs_walk_none() test
  2022-03-15 10:10 [PATCH v4 0/7] 9pfs: fix 'Twalk' protocol violation Christian Schoenebeck
  2022-03-15 10:08 ` [PATCH v4 1/7] tests/9pfs: walk to non-existent dir Christian Schoenebeck
  2022-03-15 10:08 ` [PATCH v4 2/7] tests/9pfs: Twalk with nwname=0 Christian Schoenebeck
@ 2022-03-15 10:08 ` Christian Schoenebeck
  2022-06-15 15:08   ` Greg Kurz
  2022-03-15 10:08 ` [PATCH v4 4/7] 9pfs: refactor 'name_idx' -> 'nwalked' in v9fs_walk() Christian Schoenebeck
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 16+ messages in thread
From: Christian Schoenebeck @ 2022-03-15 10:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Greg Kurz

Extend previously added fs_walk_none() test by comparing the QID
of the root fid with the QID of the cloned fid. They should be
equal.

Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
---
 tests/qtest/virtio-9p-test.c | 87 ++++++++++++++++++++++++++++++++++++
 1 file changed, 87 insertions(+)

diff --git a/tests/qtest/virtio-9p-test.c b/tests/qtest/virtio-9p-test.c
index 6c00da03f4..a1160f4659 100644
--- a/tests/qtest/virtio-9p-test.c
+++ b/tests/qtest/virtio-9p-test.c
@@ -371,8 +371,15 @@ static P9Req *v9fs_tattach(QVirtio9P *v9p, uint32_t fid, uint32_t n_uname,
     return req;
 }
 
+/* type[1] version[4] path[8] */
 typedef char v9fs_qid[13];
 
+static inline bool is_same_qid(v9fs_qid a, v9fs_qid b)
+{
+    /* don't compare QID version for checking for file ID equalness */
+    return a[0] == b[0] && memcmp(&a[5], &b[5], 8) == 0;
+}
+
 /* size[4] Rattach tag[2] qid[13] */
 static void v9fs_rattach(P9Req *req, v9fs_qid *qid)
 {
@@ -425,6 +432,79 @@ static void v9fs_rwalk(P9Req *req, uint16_t *nwqid, v9fs_qid **wqid)
     v9fs_req_free(req);
 }
 
+/* size[4] Tgetattr tag[2] fid[4] request_mask[8] */
+static P9Req *v9fs_tgetattr(QVirtio9P *v9p, uint32_t fid, uint64_t request_mask,
+                            uint16_t tag)
+{
+    P9Req *req;
+
+    req = v9fs_req_init(v9p, 4 + 8, P9_TGETATTR, tag);
+    v9fs_uint32_write(req, fid);
+    v9fs_uint64_write(req, request_mask);
+    v9fs_req_send(req);
+    return req;
+}
+
+typedef struct v9fs_attr {
+    uint64_t valid;
+    v9fs_qid qid;
+    uint32_t mode;
+    uint32_t uid;
+    uint32_t gid;
+    uint64_t nlink;
+    uint64_t rdev;
+    uint64_t size;
+    uint64_t blksize;
+    uint64_t blocks;
+    uint64_t atime_sec;
+    uint64_t atime_nsec;
+    uint64_t mtime_sec;
+    uint64_t mtime_nsec;
+    uint64_t ctime_sec;
+    uint64_t ctime_nsec;
+    uint64_t btime_sec;
+    uint64_t btime_nsec;
+    uint64_t gen;
+    uint64_t data_version;
+} v9fs_attr;
+
+#define P9_GETATTR_BASIC    0x000007ffULL /* Mask for fields up to BLOCKS */
+
+/*
+ * size[4] Rgetattr tag[2] valid[8] qid[13] mode[4] uid[4] gid[4] nlink[8]
+ *                  rdev[8] size[8] blksize[8] blocks[8]
+ *                  atime_sec[8] atime_nsec[8] mtime_sec[8] mtime_nsec[8]
+ *                  ctime_sec[8] ctime_nsec[8] btime_sec[8] btime_nsec[8]
+ *                  gen[8] data_version[8]
+ */
+static void v9fs_rgetattr(P9Req *req, v9fs_attr *attr)
+{
+    v9fs_req_recv(req, P9_RGETATTR);
+
+    v9fs_uint64_read(req, &attr->valid);
+    v9fs_memread(req, &attr->qid, 13);
+    v9fs_uint32_read(req, &attr->mode);
+    v9fs_uint32_read(req, &attr->uid);
+    v9fs_uint32_read(req, &attr->gid);
+    v9fs_uint64_read(req, &attr->nlink);
+    v9fs_uint64_read(req, &attr->rdev);
+    v9fs_uint64_read(req, &attr->size);
+    v9fs_uint64_read(req, &attr->blksize);
+    v9fs_uint64_read(req, &attr->blocks);
+    v9fs_uint64_read(req, &attr->atime_sec);
+    v9fs_uint64_read(req, &attr->atime_nsec);
+    v9fs_uint64_read(req, &attr->mtime_sec);
+    v9fs_uint64_read(req, &attr->mtime_nsec);
+    v9fs_uint64_read(req, &attr->ctime_sec);
+    v9fs_uint64_read(req, &attr->ctime_nsec);
+    v9fs_uint64_read(req, &attr->btime_sec);
+    v9fs_uint64_read(req, &attr->btime_nsec);
+    v9fs_uint64_read(req, &attr->gen);
+    v9fs_uint64_read(req, &attr->data_version);
+
+    v9fs_req_free(req);
+}
+
 /* size[4] Treaddir tag[2] fid[4] offset[8] count[4] */
 static P9Req *v9fs_treaddir(QVirtio9P *v9p, uint32_t fid, uint64_t offset,
                             uint32_t count, uint16_t tag)
@@ -1009,6 +1089,7 @@ static void fs_walk_none(void *obj, void *data, QGuestAllocator *t_alloc)
     v9fs_qid root_qid;
     g_autofree v9fs_qid *wqid = NULL;
     P9Req *req;
+    struct v9fs_attr attr;
 
     do_version(v9p);
     req = v9fs_tattach(v9p, 0, getuid(), 0);
@@ -1021,6 +1102,12 @@ static void fs_walk_none(void *obj, void *data, QGuestAllocator *t_alloc)
 
     /* special case: no QID is returned if nwname=0 was sent */
     g_assert(wqid == NULL);
+
+    req = v9fs_tgetattr(v9p, 1, P9_GETATTR_BASIC, 0);
+    v9fs_req_wait_for_reply(req, NULL);
+    v9fs_rgetattr(req, &attr);
+
+    g_assert(is_same_qid(root_qid, attr.qid));
 }
 
 static void fs_walk_dotdot(void *obj, void *data, QGuestAllocator *t_alloc)
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v4 4/7] 9pfs: refactor 'name_idx' -> 'nwalked' in v9fs_walk()
  2022-03-15 10:10 [PATCH v4 0/7] 9pfs: fix 'Twalk' protocol violation Christian Schoenebeck
                   ` (2 preceding siblings ...)
  2022-03-15 10:08 ` [PATCH v4 3/7] tests/9pfs: compare QIDs in fs_walk_none() test Christian Schoenebeck
@ 2022-03-15 10:08 ` Christian Schoenebeck
  2022-03-15 10:08 ` [PATCH v4 5/7] 9pfs: fix 'Twalk' to only send error if no component walked Christian Schoenebeck
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Christian Schoenebeck @ 2022-03-15 10:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Greg Kurz

The local variable 'name_idx' is used in two loops in function v9fs_walk().
Let the first loop use its own variable 'nwalked' instead, which we will
use in subsequent patch as the number of (requested) path components
successfully walked by background I/O thread.

Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
---
 hw/9pfs/9p.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index a6d6b3f835..298f4e6548 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -1764,7 +1764,7 @@ static bool same_stat_id(const struct stat *a, const struct stat *b)
 
 static void coroutine_fn v9fs_walk(void *opaque)
 {
-    int name_idx;
+    int name_idx, nwalked;
     g_autofree V9fsQID *qids = NULL;
     int i, err = 0;
     V9fsPath dpath, path;
@@ -1842,17 +1842,17 @@ static void coroutine_fn v9fs_walk(void *opaque)
             break;
         }
         stbuf = fidst;
-        for (name_idx = 0; name_idx < nwnames; name_idx++) {
+        for (nwalked = 0; nwalked < nwnames; nwalked++) {
             if (v9fs_request_cancelled(pdu)) {
                 err = -EINTR;
                 break;
             }
             if (!same_stat_id(&pdu->s->root_st, &stbuf) ||
-                strcmp("..", wnames[name_idx].data))
+                strcmp("..", wnames[nwalked].data))
             {
                 err = s->ops->name_to_path(&s->ctx, &dpath,
-                                           wnames[name_idx].data,
-                                           &pathes[name_idx]);
+                                           wnames[nwalked].data,
+                                           &pathes[nwalked]);
                 if (err < 0) {
                     err = -errno;
                     break;
@@ -1861,13 +1861,13 @@ static void coroutine_fn v9fs_walk(void *opaque)
                     err = -EINTR;
                     break;
                 }
-                err = s->ops->lstat(&s->ctx, &pathes[name_idx], &stbuf);
+                err = s->ops->lstat(&s->ctx, &pathes[nwalked], &stbuf);
                 if (err < 0) {
                     err = -errno;
                     break;
                 }
-                stbufs[name_idx] = stbuf;
-                v9fs_path_copy(&dpath, &pathes[name_idx]);
+                stbufs[nwalked] = stbuf;
+                v9fs_path_copy(&dpath, &pathes[nwalked]);
             }
         }
     });
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v4 5/7] 9pfs: fix 'Twalk' to only send error if no component walked
  2022-03-15 10:10 [PATCH v4 0/7] 9pfs: fix 'Twalk' protocol violation Christian Schoenebeck
                   ` (3 preceding siblings ...)
  2022-03-15 10:08 ` [PATCH v4 4/7] 9pfs: refactor 'name_idx' -> 'nwalked' in v9fs_walk() Christian Schoenebeck
@ 2022-03-15 10:08 ` Christian Schoenebeck
  2022-06-15 15:52   ` Greg Kurz
  2022-03-15 10:08 ` [PATCH v4 6/7] tests/9pfs: guard recent 'Twalk' behaviour fix Christian Schoenebeck
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 16+ messages in thread
From: Christian Schoenebeck @ 2022-03-15 10:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Greg Kurz

Current implementation of 'Twalk' request handling always sends an 'Rerror'
response if any error occured. The 9p2000 protocol spec says though:

  "
  If the first element cannot be walked for any reason, Rerror is returned.
  Otherwise, the walk will return an Rwalk message containing nwqid qids
  corresponding, in order, to the files that are visited by the nwqid
  successful elementwise walks; nwqid is therefore either nwname or the index
  of the first elementwise walk that failed.
  "

  http://ericvh.github.io/9p-rfc/rfc9p2000.html#anchor33

For that reason we are no longer leaving from an error path in function
v9fs_walk(), unless really no path component could be walked successfully or
if the request has been interrupted.

Local variable 'nwalked' counts and reflects the number of path components
successfully processed by background I/O thread, whereas local variable
'name_idx' subsequently counts and reflects the number of path components
eventually accepted successfully by 9p server controller portion.

New local variable 'any_err' is an aggregate variable reflecting whether any
error occurred at all, while already existing variable 'err' only reflects
the last error.

Despite QIDs being delivered to client in a more relaxed way now, it is
important to note though that fid still must remain unaffected if any error
occurred.

Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
---
 hw/9pfs/9p.c | 43 +++++++++++++++++++++++++++----------------
 1 file changed, 27 insertions(+), 16 deletions(-)

diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 298f4e6548..e770972a71 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -1766,7 +1766,7 @@ static void coroutine_fn v9fs_walk(void *opaque)
 {
     int name_idx, nwalked;
     g_autofree V9fsQID *qids = NULL;
-    int i, err = 0;
+    int i, err = 0, any_err = 0;
     V9fsPath dpath, path;
     P9ARRAY_REF(V9fsPath) pathes = NULL;
     uint16_t nwnames;
@@ -1832,19 +1832,20 @@ static void coroutine_fn v9fs_walk(void *opaque)
      * driver code altogether inside the following block.
      */
     v9fs_co_run_in_worker({
+        nwalked = 0;
         if (v9fs_request_cancelled(pdu)) {
-            err = -EINTR;
+            any_err |= err = -EINTR;
             break;
         }
         err = s->ops->lstat(&s->ctx, &dpath, &fidst);
         if (err < 0) {
-            err = -errno;
+            any_err |= err = -errno;
             break;
         }
         stbuf = fidst;
-        for (nwalked = 0; nwalked < nwnames; nwalked++) {
+        for (; nwalked < nwnames; nwalked++) {
             if (v9fs_request_cancelled(pdu)) {
-                err = -EINTR;
+                any_err |= err = -EINTR;
                 break;
             }
             if (!same_stat_id(&pdu->s->root_st, &stbuf) ||
@@ -1854,16 +1855,16 @@ static void coroutine_fn v9fs_walk(void *opaque)
                                            wnames[nwalked].data,
                                            &pathes[nwalked]);
                 if (err < 0) {
-                    err = -errno;
+                    any_err |= err = -errno;
                     break;
                 }
                 if (v9fs_request_cancelled(pdu)) {
-                    err = -EINTR;
+                    any_err |= err = -EINTR;
                     break;
                 }
                 err = s->ops->lstat(&s->ctx, &pathes[nwalked], &stbuf);
                 if (err < 0) {
-                    err = -errno;
+                    any_err |= err = -errno;
                     break;
                 }
                 stbufs[nwalked] = stbuf;
@@ -1874,12 +1875,12 @@ static void coroutine_fn v9fs_walk(void *opaque)
     /*
      * Handle all the rest of this Twalk request on main thread ...
      */
-    if (err < 0) {
+    if ((err < 0 && !nwalked) || err == -EINTR) {
         goto out;
     }
 
-    err = stat_to_qid(pdu, &fidst, &qid);
-    if (err < 0) {
+    any_err |= err = stat_to_qid(pdu, &fidst, &qid);
+    if (err < 0 && !nwalked) {
         goto out;
     }
     stbuf = fidst;
@@ -1888,20 +1889,29 @@ static void coroutine_fn v9fs_walk(void *opaque)
     v9fs_path_copy(&dpath, &fidp->path);
     v9fs_path_copy(&path, &fidp->path);
 
-    for (name_idx = 0; name_idx < nwnames; name_idx++) {
+    for (name_idx = 0; name_idx < nwalked; name_idx++) {
         if (!same_stat_id(&pdu->s->root_st, &stbuf) ||
             strcmp("..", wnames[name_idx].data))
         {
             stbuf = stbufs[name_idx];
-            err = stat_to_qid(pdu, &stbuf, &qid);
+            any_err |= err = stat_to_qid(pdu, &stbuf, &qid);
             if (err < 0) {
-                goto out;
+                break;
             }
             v9fs_path_copy(&path, &pathes[name_idx]);
             v9fs_path_copy(&dpath, &path);
         }
         memcpy(&qids[name_idx], &qid, sizeof(qid));
     }
+    if (any_err < 0) {
+        if (!name_idx) {
+            /* don't send any QIDs, send Rlerror instead */
+            goto out;
+        } else {
+            /* send QIDs (not Rlerror), but fid MUST remain unaffected */
+            goto send_qids;
+        }
+    }
     if (fid == newfid) {
         if (fidp->fid_type != P9_FID_NONE) {
             err = -EINVAL;
@@ -1919,8 +1929,9 @@ static void coroutine_fn v9fs_walk(void *opaque)
         newfidp->uid = fidp->uid;
         v9fs_path_copy(&newfidp->path, &path);
     }
-    err = v9fs_walk_marshal(pdu, nwnames, qids);
-    trace_v9fs_walk_return(pdu->tag, pdu->id, nwnames, qids);
+send_qids:
+    err = v9fs_walk_marshal(pdu, name_idx, qids);
+    trace_v9fs_walk_return(pdu->tag, pdu->id, name_idx, qids);
 out:
     put_fid(pdu, fidp);
     if (newfidp) {
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v4 6/7] tests/9pfs: guard recent 'Twalk' behaviour fix
  2022-03-15 10:10 [PATCH v4 0/7] 9pfs: fix 'Twalk' protocol violation Christian Schoenebeck
                   ` (4 preceding siblings ...)
  2022-03-15 10:08 ` [PATCH v4 5/7] 9pfs: fix 'Twalk' to only send error if no component walked Christian Schoenebeck
@ 2022-03-15 10:08 ` Christian Schoenebeck
  2022-03-15 10:08 ` [PATCH v4 7/7] tests/9pfs: check fid being unaffected in fs_walk_2nd_nonexistent Christian Schoenebeck
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 16+ messages in thread
From: Christian Schoenebeck @ 2022-03-15 10:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Greg Kurz

Previous 9p patch fixed 'Twalk' request handling, which was previously not
behaving as specified by the 9p2000 protocol spec. This patch adds a new test
case which guards the new 'Twalk' behaviour in question.

More specifically: it sends a 'Twalk' request where the 1st path component
is valid, whereas the 2nd path component transmitted to server does not
exist. The expected behaviour is that 9p server would respond by sending
a 'Rwalk' response with exactly 1 QID (instead of 'Rlerror' response).

Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
---
 tests/qtest/virtio-9p-test.c | 42 +++++++++++++++++++++++++++++++++---
 1 file changed, 39 insertions(+), 3 deletions(-)

diff --git a/tests/qtest/virtio-9p-test.c b/tests/qtest/virtio-9p-test.c
index a1160f4659..f6e78d388e 100644
--- a/tests/qtest/virtio-9p-test.c
+++ b/tests/qtest/virtio-9p-test.c
@@ -669,8 +669,12 @@ static void do_version(QVirtio9P *v9p)
     g_assert_cmpmem(server_version, server_len, version, strlen(version));
 }
 
-/* utility function: walk to requested dir and return fid for that dir */
-static uint32_t do_walk(QVirtio9P *v9p, const char *path)
+/*
+ * utility function: walk to requested dir and return fid for that dir and
+ * the QIDs of server response
+ */
+static uint32_t do_walk_rqids(QVirtio9P *v9p, const char *path, uint16_t *nwqid,
+                              v9fs_qid **wqid)
 {
     char **wnames;
     P9Req *req;
@@ -680,12 +684,18 @@ static uint32_t do_walk(QVirtio9P *v9p, const char *path)
 
     req = v9fs_twalk(v9p, 0, fid, nwnames, wnames, 0);
     v9fs_req_wait_for_reply(req, NULL);
-    v9fs_rwalk(req, NULL, NULL);
+    v9fs_rwalk(req, nwqid, wqid);
 
     split_free(&wnames);
     return fid;
 }
 
+/* utility function: walk to requested dir and return fid for that dir */
+static uint32_t do_walk(QVirtio9P *v9p, const char *path)
+{
+    return do_walk_rqids(v9p, path, NULL, NULL);
+}
+
 /* utility function: walk to requested dir and expect passed error response */
 static void do_walk_expect_error(QVirtio9P *v9p, const char *path, uint32_t err)
 {
@@ -1079,9 +1089,33 @@ static void fs_walk_nonexistent(void *obj, void *data, QGuestAllocator *t_alloc)
     alloc = t_alloc;
 
     do_attach(v9p);
+    /*
+     * The 9p2000 protocol spec says: "If the first element cannot be walked
+     * for any reason, Rerror is returned."
+     */
     do_walk_expect_error(v9p, "non-existent", ENOENT);
 }
 
+static void fs_walk_2nd_nonexistent(void *obj, void *data,
+                                    QGuestAllocator *t_alloc)
+{
+    QVirtio9P *v9p = obj;
+    alloc = t_alloc;
+    uint16_t nwqid;
+    g_autofree v9fs_qid *wqid = NULL;
+    g_autofree char *path = g_strdup_printf(
+        QTEST_V9FS_SYNTH_WALK_FILE "/non-existent", 0
+    );
+
+    do_attach(v9p);
+    do_walk_rqids(v9p, path, &nwqid, &wqid);
+    /*
+     * The 9p2000 protocol spec says: "nwqid is therefore either nwname or the
+     * index of the first elementwise walk that failed."
+     */
+    assert(nwqid == 1);
+}
+
 static void fs_walk_none(void *obj, void *data, QGuestAllocator *t_alloc)
 {
     QVirtio9P *v9p = obj;
@@ -1548,6 +1582,8 @@ static void register_virtio_9p_test(void)
                  fs_walk_dotdot,  &opts);
     qos_add_test("synth/walk/non_existent", "virtio-9p", fs_walk_nonexistent,
                   &opts);
+    qos_add_test("synth/walk/2nd_non_existent", "virtio-9p",
+                 fs_walk_2nd_nonexistent, &opts);
     qos_add_test("synth/lopen/basic", "virtio-9p", fs_lopen,  &opts);
     qos_add_test("synth/write/basic", "virtio-9p", fs_write,  &opts);
     qos_add_test("synth/flush/success", "virtio-9p", fs_flush_success,
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v4 7/7] tests/9pfs: check fid being unaffected in fs_walk_2nd_nonexistent
  2022-03-15 10:10 [PATCH v4 0/7] 9pfs: fix 'Twalk' protocol violation Christian Schoenebeck
                   ` (5 preceding siblings ...)
  2022-03-15 10:08 ` [PATCH v4 6/7] tests/9pfs: guard recent 'Twalk' behaviour fix Christian Schoenebeck
@ 2022-03-15 10:08 ` Christian Schoenebeck
  2022-06-15 15:57   ` Greg Kurz
  2022-03-29 10:21 ` [PATCH v4 0/7] 9pfs: fix 'Twalk' protocol violation Christian Schoenebeck
  2022-06-16 10:53 ` Christian Schoenebeck
  8 siblings, 1 reply; 16+ messages in thread
From: Christian Schoenebeck @ 2022-03-15 10:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Greg Kurz

Extend previously added test case by checking that fid was unaffected
by 'Twalk' request (i.e. when 2nd path component of request being
invalid). Do that by subsequently sending a 'Tgetattr' request with
the fid previously used for 'Twalk'; that 'Tgetattr' request should
return an 'Rlerror' response by 9p server with error code ENOENT as
that fid is basically invalid.

And as we are at it, also check that the QID returned by 'Twalk' is
not identical to the root node's QID.

Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
---
 tests/qtest/virtio-9p-test.c | 26 ++++++++++++++++++++++----
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/tests/qtest/virtio-9p-test.c b/tests/qtest/virtio-9p-test.c
index f6e78d388e..2784ee4b2d 100644
--- a/tests/qtest/virtio-9p-test.c
+++ b/tests/qtest/virtio-9p-test.c
@@ -721,14 +721,19 @@ static void fs_version(void *obj, void *data, QGuestAllocator *t_alloc)
     do_version(obj);
 }
 
-static void do_attach(QVirtio9P *v9p)
+static void do_attach_rqid(QVirtio9P *v9p, v9fs_qid *qid)
 {
     P9Req *req;
 
     do_version(v9p);
     req = v9fs_tattach(v9p, 0, getuid(), 0);
     v9fs_req_wait_for_reply(req, NULL);
-    v9fs_rattach(req, NULL);
+    v9fs_rattach(req, qid);
+}
+
+static void do_attach(QVirtio9P *v9p)
+{
+    do_attach_rqid(v9p, NULL);
 }
 
 static void fs_attach(void *obj, void *data, QGuestAllocator *t_alloc)
@@ -1101,19 +1106,32 @@ static void fs_walk_2nd_nonexistent(void *obj, void *data,
 {
     QVirtio9P *v9p = obj;
     alloc = t_alloc;
+    v9fs_qid root_qid;
     uint16_t nwqid;
+    uint32_t fid, err;
+    P9Req *req;
     g_autofree v9fs_qid *wqid = NULL;
     g_autofree char *path = g_strdup_printf(
         QTEST_V9FS_SYNTH_WALK_FILE "/non-existent", 0
     );
 
-    do_attach(v9p);
-    do_walk_rqids(v9p, path, &nwqid, &wqid);
+    do_attach_rqid(v9p, &root_qid);
+    fid = do_walk_rqids(v9p, path, &nwqid, &wqid);
     /*
      * The 9p2000 protocol spec says: "nwqid is therefore either nwname or the
      * index of the first elementwise walk that failed."
      */
     assert(nwqid == 1);
+
+    /* returned QID wqid[0] is file ID of 1st subdir */
+    g_assert(wqid && wqid[0] && !is_same_qid(root_qid, wqid[0]));
+
+    /* expect fid being unaffected by walk above */
+    req = v9fs_tgetattr(v9p, fid, P9_GETATTR_BASIC, 0);
+    v9fs_req_wait_for_reply(req, NULL);
+    v9fs_rlerror(req, &err);
+
+    g_assert_cmpint(err, ==, ENOENT);
 }
 
 static void fs_walk_none(void *obj, void *data, QGuestAllocator *t_alloc)
-- 
2.30.2



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v4 0/7] 9pfs: fix 'Twalk' protocol violation
@ 2022-03-15 10:10 Christian Schoenebeck
  2022-03-15 10:08 ` [PATCH v4 1/7] tests/9pfs: walk to non-existent dir Christian Schoenebeck
                   ` (8 more replies)
  0 siblings, 9 replies; 16+ messages in thread
From: Christian Schoenebeck @ 2022-03-15 10:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: Greg Kurz

Currently the implementation of 'Twalk' does not behave exactly as specified
by the 9p2000 protocol specification. Actual fix is patch 5; see the
description of that patch for details of what this overall fix and series is
about.

PREREQUISITES
=============

This series requires the following additional patch to work correctly:
https://lore.kernel.org/qemu-devel/E1nTpyU-0000yR-9o@lizzy.crudebyte.com/

OVERVIEW OF PATCHES
===================

Patch 4 is a preparatory (pure) refactoring change to make actual 'Twalk' fix
patch 5 better readable.

All the other patches are just additional test cases for guarding 'Twalk'
behaviour.

v3 -> v4:

  * QID returned by Twalk request in fs_walk_2nd_nonexistent() test should NOT
    be identical to root node's QID. [patch 7]

  * Fix actual 'fid unaffected' check in fs_walk_2nd_nonexistent() test by
    sending a subsequent 'Tgetattr' request. [patch 7]

Christian Schoenebeck (7):
  tests/9pfs: walk to non-existent dir
  tests/9pfs: Twalk with nwname=0
  tests/9pfs: compare QIDs in fs_walk_none() test
  9pfs: refactor 'name_idx' -> 'nwalked' in v9fs_walk()
  9pfs: fix 'Twalk' to only send error if no component walked
  tests/9pfs: guard recent 'Twalk' behaviour fix
  tests/9pfs: check fid being unaffected in fs_walk_2nd_nonexistent

 hw/9pfs/9p.c                 |  57 ++++++----
 tests/qtest/virtio-9p-test.c | 201 ++++++++++++++++++++++++++++++++++-
 2 files changed, 231 insertions(+), 27 deletions(-)

-- 
2.30.2



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v4 0/7] 9pfs: fix 'Twalk' protocol violation
  2022-03-15 10:10 [PATCH v4 0/7] 9pfs: fix 'Twalk' protocol violation Christian Schoenebeck
                   ` (6 preceding siblings ...)
  2022-03-15 10:08 ` [PATCH v4 7/7] tests/9pfs: check fid being unaffected in fs_walk_2nd_nonexistent Christian Schoenebeck
@ 2022-03-29 10:21 ` Christian Schoenebeck
  2022-03-29 10:59   ` Greg Kurz
  2022-06-16 10:53 ` Christian Schoenebeck
  8 siblings, 1 reply; 16+ messages in thread
From: Christian Schoenebeck @ 2022-03-29 10:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: Greg Kurz

On Dienstag, 15. März 2022 11:10:25 CEST Christian Schoenebeck wrote:
> Currently the implementation of 'Twalk' does not behave exactly as specified
> by the 9p2000 protocol specification. Actual fix is patch 5; see the
> description of that patch for details of what this overall fix and series
> is about.
> 
> PREREQUISITES
> =============
> 
> This series requires the following additional patch to work correctly:
> https://lore.kernel.org/qemu-devel/E1nTpyU-0000yR-9o@lizzy.crudebyte.com/
> 
> OVERVIEW OF PATCHES
> ===================
> 
> Patch 4 is a preparatory (pure) refactoring change to make actual 'Twalk'
> fix patch 5 better readable.
> 
> All the other patches are just additional test cases for guarding 'Twalk'
> behaviour.
> 
> v3 -> v4:
> 
>   * QID returned by Twalk request in fs_walk_2nd_nonexistent() test should
> NOT be identical to root node's QID. [patch 7]
> 
>   * Fix actual 'fid unaffected' check in fs_walk_2nd_nonexistent() test by
>     sending a subsequent 'Tgetattr' request. [patch 7]
> 
> Christian Schoenebeck (7):
>   tests/9pfs: walk to non-existent dir
>   tests/9pfs: Twalk with nwname=0
>   tests/9pfs: compare QIDs in fs_walk_none() test
>   9pfs: refactor 'name_idx' -> 'nwalked' in v9fs_walk()
>   9pfs: fix 'Twalk' to only send error if no component walked
>   tests/9pfs: guard recent 'Twalk' behaviour fix
>   tests/9pfs: check fid being unaffected in fs_walk_2nd_nonexistent
> 
>  hw/9pfs/9p.c                 |  57 ++++++----
>  tests/qtest/virtio-9p-test.c | 201 ++++++++++++++++++++++++++++++++++-
>  2 files changed, 231 insertions(+), 27 deletions(-)

ping

No hurry, as this is something for the subsequent QEMU release cycle, but 
would be good to know whether you will be able to look at this at all.

Best regards,
Christian Schoenebeck




^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v4 0/7] 9pfs: fix 'Twalk' protocol violation
  2022-03-29 10:21 ` [PATCH v4 0/7] 9pfs: fix 'Twalk' protocol violation Christian Schoenebeck
@ 2022-03-29 10:59   ` Greg Kurz
  0 siblings, 0 replies; 16+ messages in thread
From: Greg Kurz @ 2022-03-29 10:59 UTC (permalink / raw)
  To: Christian Schoenebeck; +Cc: qemu-devel

On Tue, 29 Mar 2022 12:21:13 +0200
Christian Schoenebeck <qemu_oss@crudebyte.com> wrote:

> On Dienstag, 15. März 2022 11:10:25 CEST Christian Schoenebeck wrote:
> > Currently the implementation of 'Twalk' does not behave exactly as specified
> > by the 9p2000 protocol specification. Actual fix is patch 5; see the
> > description of that patch for details of what this overall fix and series
> > is about.
> > 
> > PREREQUISITES
> > =============
> > 
> > This series requires the following additional patch to work correctly:
> > https://lore.kernel.org/qemu-devel/E1nTpyU-0000yR-9o@lizzy.crudebyte.com/
> > 
> > OVERVIEW OF PATCHES
> > ===================
> > 
> > Patch 4 is a preparatory (pure) refactoring change to make actual 'Twalk'
> > fix patch 5 better readable.
> > 
> > All the other patches are just additional test cases for guarding 'Twalk'
> > behaviour.
> > 
> > v3 -> v4:
> > 
> >   * QID returned by Twalk request in fs_walk_2nd_nonexistent() test should
> > NOT be identical to root node's QID. [patch 7]
> > 
> >   * Fix actual 'fid unaffected' check in fs_walk_2nd_nonexistent() test by
> >     sending a subsequent 'Tgetattr' request. [patch 7]
> > 
> > Christian Schoenebeck (7):
> >   tests/9pfs: walk to non-existent dir
> >   tests/9pfs: Twalk with nwname=0
> >   tests/9pfs: compare QIDs in fs_walk_none() test
> >   9pfs: refactor 'name_idx' -> 'nwalked' in v9fs_walk()
> >   9pfs: fix 'Twalk' to only send error if no component walked
> >   tests/9pfs: guard recent 'Twalk' behaviour fix
> >   tests/9pfs: check fid being unaffected in fs_walk_2nd_nonexistent
> > 
> >  hw/9pfs/9p.c                 |  57 ++++++----
> >  tests/qtest/virtio-9p-test.c | 201 ++++++++++++++++++++++++++++++++++-
> >  2 files changed, 231 insertions(+), 27 deletions(-)
> 
> ping
> 
> No hurry, as this is something for the subsequent QEMU release cycle, but 
> would be good to know whether you will be able to look at this at all.
> 

Yes I will but probably not before next week.

Cheers,

--
Greg

> Best regards,
> Christian Schoenebeck
> 
> 



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v4 3/7] tests/9pfs: compare QIDs in fs_walk_none() test
  2022-03-15 10:08 ` [PATCH v4 3/7] tests/9pfs: compare QIDs in fs_walk_none() test Christian Schoenebeck
@ 2022-06-15 15:08   ` Greg Kurz
  0 siblings, 0 replies; 16+ messages in thread
From: Greg Kurz @ 2022-06-15 15:08 UTC (permalink / raw)
  To: Christian Schoenebeck; +Cc: qemu-devel

On Tue, 15 Mar 2022 11:08:35 +0100
Christian Schoenebeck <qemu_oss@crudebyte.com> wrote:

> Extend previously added fs_walk_none() test by comparing the QID
> of the root fid with the QID of the cloned fid. They should be
> equal.
> 
> Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
> ---

LGTM.

Reviewed-by: Greg Kurz <groug@kaod.org>

>  tests/qtest/virtio-9p-test.c | 87 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 87 insertions(+)
> 
> diff --git a/tests/qtest/virtio-9p-test.c b/tests/qtest/virtio-9p-test.c
> index 6c00da03f4..a1160f4659 100644
> --- a/tests/qtest/virtio-9p-test.c
> +++ b/tests/qtest/virtio-9p-test.c
> @@ -371,8 +371,15 @@ static P9Req *v9fs_tattach(QVirtio9P *v9p, uint32_t fid, uint32_t n_uname,
>      return req;
>  }
>  
> +/* type[1] version[4] path[8] */
>  typedef char v9fs_qid[13];
>  
> +static inline bool is_same_qid(v9fs_qid a, v9fs_qid b)
> +{
> +    /* don't compare QID version for checking for file ID equalness */
> +    return a[0] == b[0] && memcmp(&a[5], &b[5], 8) == 0;
> +}
> +
>  /* size[4] Rattach tag[2] qid[13] */
>  static void v9fs_rattach(P9Req *req, v9fs_qid *qid)
>  {
> @@ -425,6 +432,79 @@ static void v9fs_rwalk(P9Req *req, uint16_t *nwqid, v9fs_qid **wqid)
>      v9fs_req_free(req);
>  }
>  
> +/* size[4] Tgetattr tag[2] fid[4] request_mask[8] */
> +static P9Req *v9fs_tgetattr(QVirtio9P *v9p, uint32_t fid, uint64_t request_mask,
> +                            uint16_t tag)
> +{
> +    P9Req *req;
> +
> +    req = v9fs_req_init(v9p, 4 + 8, P9_TGETATTR, tag);
> +    v9fs_uint32_write(req, fid);
> +    v9fs_uint64_write(req, request_mask);
> +    v9fs_req_send(req);
> +    return req;
> +}
> +
> +typedef struct v9fs_attr {
> +    uint64_t valid;
> +    v9fs_qid qid;
> +    uint32_t mode;
> +    uint32_t uid;
> +    uint32_t gid;
> +    uint64_t nlink;
> +    uint64_t rdev;
> +    uint64_t size;
> +    uint64_t blksize;
> +    uint64_t blocks;
> +    uint64_t atime_sec;
> +    uint64_t atime_nsec;
> +    uint64_t mtime_sec;
> +    uint64_t mtime_nsec;
> +    uint64_t ctime_sec;
> +    uint64_t ctime_nsec;
> +    uint64_t btime_sec;
> +    uint64_t btime_nsec;
> +    uint64_t gen;
> +    uint64_t data_version;
> +} v9fs_attr;
> +
> +#define P9_GETATTR_BASIC    0x000007ffULL /* Mask for fields up to BLOCKS */
> +
> +/*
> + * size[4] Rgetattr tag[2] valid[8] qid[13] mode[4] uid[4] gid[4] nlink[8]
> + *                  rdev[8] size[8] blksize[8] blocks[8]
> + *                  atime_sec[8] atime_nsec[8] mtime_sec[8] mtime_nsec[8]
> + *                  ctime_sec[8] ctime_nsec[8] btime_sec[8] btime_nsec[8]
> + *                  gen[8] data_version[8]
> + */
> +static void v9fs_rgetattr(P9Req *req, v9fs_attr *attr)
> +{
> +    v9fs_req_recv(req, P9_RGETATTR);
> +
> +    v9fs_uint64_read(req, &attr->valid);
> +    v9fs_memread(req, &attr->qid, 13);
> +    v9fs_uint32_read(req, &attr->mode);
> +    v9fs_uint32_read(req, &attr->uid);
> +    v9fs_uint32_read(req, &attr->gid);
> +    v9fs_uint64_read(req, &attr->nlink);
> +    v9fs_uint64_read(req, &attr->rdev);
> +    v9fs_uint64_read(req, &attr->size);
> +    v9fs_uint64_read(req, &attr->blksize);
> +    v9fs_uint64_read(req, &attr->blocks);
> +    v9fs_uint64_read(req, &attr->atime_sec);
> +    v9fs_uint64_read(req, &attr->atime_nsec);
> +    v9fs_uint64_read(req, &attr->mtime_sec);
> +    v9fs_uint64_read(req, &attr->mtime_nsec);
> +    v9fs_uint64_read(req, &attr->ctime_sec);
> +    v9fs_uint64_read(req, &attr->ctime_nsec);
> +    v9fs_uint64_read(req, &attr->btime_sec);
> +    v9fs_uint64_read(req, &attr->btime_nsec);
> +    v9fs_uint64_read(req, &attr->gen);
> +    v9fs_uint64_read(req, &attr->data_version);
> +
> +    v9fs_req_free(req);
> +}
> +
>  /* size[4] Treaddir tag[2] fid[4] offset[8] count[4] */
>  static P9Req *v9fs_treaddir(QVirtio9P *v9p, uint32_t fid, uint64_t offset,
>                              uint32_t count, uint16_t tag)
> @@ -1009,6 +1089,7 @@ static void fs_walk_none(void *obj, void *data, QGuestAllocator *t_alloc)
>      v9fs_qid root_qid;
>      g_autofree v9fs_qid *wqid = NULL;
>      P9Req *req;
> +    struct v9fs_attr attr;
>  
>      do_version(v9p);
>      req = v9fs_tattach(v9p, 0, getuid(), 0);
> @@ -1021,6 +1102,12 @@ static void fs_walk_none(void *obj, void *data, QGuestAllocator *t_alloc)
>  
>      /* special case: no QID is returned if nwname=0 was sent */
>      g_assert(wqid == NULL);
> +
> +    req = v9fs_tgetattr(v9p, 1, P9_GETATTR_BASIC, 0);
> +    v9fs_req_wait_for_reply(req, NULL);
> +    v9fs_rgetattr(req, &attr);
> +
> +    g_assert(is_same_qid(root_qid, attr.qid));
>  }
>  
>  static void fs_walk_dotdot(void *obj, void *data, QGuestAllocator *t_alloc)



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v4 5/7] 9pfs: fix 'Twalk' to only send error if no component walked
  2022-03-15 10:08 ` [PATCH v4 5/7] 9pfs: fix 'Twalk' to only send error if no component walked Christian Schoenebeck
@ 2022-06-15 15:52   ` Greg Kurz
  2022-06-15 16:36     ` Christian Schoenebeck
  0 siblings, 1 reply; 16+ messages in thread
From: Greg Kurz @ 2022-06-15 15:52 UTC (permalink / raw)
  To: Christian Schoenebeck; +Cc: qemu-devel

On Tue, 15 Mar 2022 11:08:39 +0100
Christian Schoenebeck <qemu_oss@crudebyte.com> wrote:

> Current implementation of 'Twalk' request handling always sends an 'Rerror'
> response if any error occured. The 9p2000 protocol spec says though:
> 
>   "
>   If the first element cannot be walked for any reason, Rerror is returned.
>   Otherwise, the walk will return an Rwalk message containing nwqid qids
>   corresponding, in order, to the files that are visited by the nwqid
>   successful elementwise walks; nwqid is therefore either nwname or the index
>   of the first elementwise walk that failed.
>   "
> 
>   http://ericvh.github.io/9p-rfc/rfc9p2000.html#anchor33
> 
> For that reason we are no longer leaving from an error path in function
> v9fs_walk(), unless really no path component could be walked successfully or
> if the request has been interrupted.
> 
> Local variable 'nwalked' counts and reflects the number of path components
> successfully processed by background I/O thread, whereas local variable
> 'name_idx' subsequently counts and reflects the number of path components
> eventually accepted successfully by 9p server controller portion.
> 
> New local variable 'any_err' is an aggregate variable reflecting whether any
> error occurred at all, while already existing variable 'err' only reflects
> the last error.
> 
> Despite QIDs being delivered to client in a more relaxed way now, it is
> important to note though that fid still must remain unaffected if any error
> occurred.
> 
> Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
> ---
>  hw/9pfs/9p.c | 43 +++++++++++++++++++++++++++----------------
>  1 file changed, 27 insertions(+), 16 deletions(-)
> 
> diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
> index 298f4e6548..e770972a71 100644
> --- a/hw/9pfs/9p.c
> +++ b/hw/9pfs/9p.c
> @@ -1766,7 +1766,7 @@ static void coroutine_fn v9fs_walk(void *opaque)
>  {
>      int name_idx, nwalked;
>      g_autofree V9fsQID *qids = NULL;
> -    int i, err = 0;
> +    int i, err = 0, any_err = 0;
>      V9fsPath dpath, path;
>      P9ARRAY_REF(V9fsPath) pathes = NULL;
>      uint16_t nwnames;
> @@ -1832,19 +1832,20 @@ static void coroutine_fn v9fs_walk(void *opaque)
>       * driver code altogether inside the following block.
>       */
>      v9fs_co_run_in_worker({
> +        nwalked = 0;
>          if (v9fs_request_cancelled(pdu)) {
> -            err = -EINTR;
> +            any_err |= err = -EINTR;

Not super fan of such constructs but I cannot think of anything
better.. so be it ! :-)

>              break;
>          }
>          err = s->ops->lstat(&s->ctx, &dpath, &fidst);
>          if (err < 0) {
> -            err = -errno;
> +            any_err |= err = -errno;
>              break;
>          }
>          stbuf = fidst;
> -        for (nwalked = 0; nwalked < nwnames; nwalked++) {
> +        for (; nwalked < nwnames; nwalked++) {
>              if (v9fs_request_cancelled(pdu)) {
> -                err = -EINTR;
> +                any_err |= err = -EINTR;
>                  break;
>              }
>              if (!same_stat_id(&pdu->s->root_st, &stbuf) ||
> @@ -1854,16 +1855,16 @@ static void coroutine_fn v9fs_walk(void *opaque)
>                                             wnames[nwalked].data,
>                                             &pathes[nwalked]);
>                  if (err < 0) {
> -                    err = -errno;
> +                    any_err |= err = -errno;
>                      break;
>                  }
>                  if (v9fs_request_cancelled(pdu)) {
> -                    err = -EINTR;
> +                    any_err |= err = -EINTR;
>                      break;
>                  }
>                  err = s->ops->lstat(&s->ctx, &pathes[nwalked], &stbuf);
>                  if (err < 0) {
> -                    err = -errno;
> +                    any_err |= err = -errno;
>                      break;
>                  }
>                  stbufs[nwalked] = stbuf;
> @@ -1874,12 +1875,12 @@ static void coroutine_fn v9fs_walk(void *opaque)
>      /*
>       * Handle all the rest of this Twalk request on main thread ...
>       */
> -    if (err < 0) {
> +    if ((err < 0 && !nwalked) || err == -EINTR) {

So this is making an exception to the spec excerpt you're mentioning
in the changelog.

EINTR can only come from the v9fs_request_cancelled(pdu) == true case,
since QEMU doesn't have signal handlers AFAIK. This would be the result
of a TFLUSH , likely to handle ^C from the client side. I guess that in
that peculiar case, it quite makes sense to return RERROR/RLERROR instead
of the "degraded" RWALK that the end user isn't waiting for. To sum up,
TFLUSH behavior prevails on TWALK. Please add a comment though since
this isn't super obvious in the spec.

Apart from that, LGTM.

Reviewed-by: Greg Kurz <groug@kaod.org>

>          goto out;
>      }
>  
> -    err = stat_to_qid(pdu, &fidst, &qid);
> -    if (err < 0) {
> +    any_err |= err = stat_to_qid(pdu, &fidst, &qid);
> +    if (err < 0 && !nwalked) {
>          goto out;
>      }
>      stbuf = fidst;
> @@ -1888,20 +1889,29 @@ static void coroutine_fn v9fs_walk(void *opaque)
>      v9fs_path_copy(&dpath, &fidp->path);
>      v9fs_path_copy(&path, &fidp->path);
>  
> -    for (name_idx = 0; name_idx < nwnames; name_idx++) {
> +    for (name_idx = 0; name_idx < nwalked; name_idx++) {
>          if (!same_stat_id(&pdu->s->root_st, &stbuf) ||
>              strcmp("..", wnames[name_idx].data))
>          {
>              stbuf = stbufs[name_idx];
> -            err = stat_to_qid(pdu, &stbuf, &qid);
> +            any_err |= err = stat_to_qid(pdu, &stbuf, &qid);
>              if (err < 0) {
> -                goto out;
> +                break;
>              }
>              v9fs_path_copy(&path, &pathes[name_idx]);
>              v9fs_path_copy(&dpath, &path);
>          }
>          memcpy(&qids[name_idx], &qid, sizeof(qid));
>      }
> +    if (any_err < 0) {
> +        if (!name_idx) {
> +            /* don't send any QIDs, send Rlerror instead */
> +            goto out;
> +        } else {
> +            /* send QIDs (not Rlerror), but fid MUST remain unaffected */
> +            goto send_qids;
> +        }
> +    }
>      if (fid == newfid) {
>          if (fidp->fid_type != P9_FID_NONE) {
>              err = -EINVAL;
> @@ -1919,8 +1929,9 @@ static void coroutine_fn v9fs_walk(void *opaque)
>          newfidp->uid = fidp->uid;
>          v9fs_path_copy(&newfidp->path, &path);
>      }
> -    err = v9fs_walk_marshal(pdu, nwnames, qids);
> -    trace_v9fs_walk_return(pdu->tag, pdu->id, nwnames, qids);
> +send_qids:
> +    err = v9fs_walk_marshal(pdu, name_idx, qids);
> +    trace_v9fs_walk_return(pdu->tag, pdu->id, name_idx, qids);
>  out:
>      put_fid(pdu, fidp);
>      if (newfidp) {



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v4 7/7] tests/9pfs: check fid being unaffected in fs_walk_2nd_nonexistent
  2022-03-15 10:08 ` [PATCH v4 7/7] tests/9pfs: check fid being unaffected in fs_walk_2nd_nonexistent Christian Schoenebeck
@ 2022-06-15 15:57   ` Greg Kurz
  0 siblings, 0 replies; 16+ messages in thread
From: Greg Kurz @ 2022-06-15 15:57 UTC (permalink / raw)
  To: Christian Schoenebeck; +Cc: qemu-devel

On Tue, 15 Mar 2022 11:08:47 +0100
Christian Schoenebeck <qemu_oss@crudebyte.com> wrote:

> Extend previously added test case by checking that fid was unaffected
> by 'Twalk' request (i.e. when 2nd path component of request being
> invalid). Do that by subsequently sending a 'Tgetattr' request with
> the fid previously used for 'Twalk'; that 'Tgetattr' request should
> return an 'Rlerror' response by 9p server with error code ENOENT as
> that fid is basically invalid.
> 
> And as we are at it, also check that the QID returned by 'Twalk' is
> not identical to the root node's QID.
> 
> Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
> ---

Reviewed-by: Greg Kurz <groug@kaod.org>

>  tests/qtest/virtio-9p-test.c | 26 ++++++++++++++++++++++----
>  1 file changed, 22 insertions(+), 4 deletions(-)
> 
> diff --git a/tests/qtest/virtio-9p-test.c b/tests/qtest/virtio-9p-test.c
> index f6e78d388e..2784ee4b2d 100644
> --- a/tests/qtest/virtio-9p-test.c
> +++ b/tests/qtest/virtio-9p-test.c
> @@ -721,14 +721,19 @@ static void fs_version(void *obj, void *data, QGuestAllocator *t_alloc)
>      do_version(obj);
>  }
>  
> -static void do_attach(QVirtio9P *v9p)
> +static void do_attach_rqid(QVirtio9P *v9p, v9fs_qid *qid)
>  {
>      P9Req *req;
>  
>      do_version(v9p);
>      req = v9fs_tattach(v9p, 0, getuid(), 0);
>      v9fs_req_wait_for_reply(req, NULL);
> -    v9fs_rattach(req, NULL);
> +    v9fs_rattach(req, qid);
> +}
> +
> +static void do_attach(QVirtio9P *v9p)
> +{
> +    do_attach_rqid(v9p, NULL);
>  }
>  
>  static void fs_attach(void *obj, void *data, QGuestAllocator *t_alloc)
> @@ -1101,19 +1106,32 @@ static void fs_walk_2nd_nonexistent(void *obj, void *data,
>  {
>      QVirtio9P *v9p = obj;
>      alloc = t_alloc;
> +    v9fs_qid root_qid;
>      uint16_t nwqid;
> +    uint32_t fid, err;
> +    P9Req *req;
>      g_autofree v9fs_qid *wqid = NULL;
>      g_autofree char *path = g_strdup_printf(
>          QTEST_V9FS_SYNTH_WALK_FILE "/non-existent", 0
>      );
>  
> -    do_attach(v9p);
> -    do_walk_rqids(v9p, path, &nwqid, &wqid);
> +    do_attach_rqid(v9p, &root_qid);
> +    fid = do_walk_rqids(v9p, path, &nwqid, &wqid);
>      /*
>       * The 9p2000 protocol spec says: "nwqid is therefore either nwname or the
>       * index of the first elementwise walk that failed."
>       */
>      assert(nwqid == 1);
> +
> +    /* returned QID wqid[0] is file ID of 1st subdir */
> +    g_assert(wqid && wqid[0] && !is_same_qid(root_qid, wqid[0]));
> +
> +    /* expect fid being unaffected by walk above */
> +    req = v9fs_tgetattr(v9p, fid, P9_GETATTR_BASIC, 0);
> +    v9fs_req_wait_for_reply(req, NULL);
> +    v9fs_rlerror(req, &err);
> +
> +    g_assert_cmpint(err, ==, ENOENT);
>  }
>  
>  static void fs_walk_none(void *obj, void *data, QGuestAllocator *t_alloc)



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v4 5/7] 9pfs: fix 'Twalk' to only send error if no component walked
  2022-06-15 15:52   ` Greg Kurz
@ 2022-06-15 16:36     ` Christian Schoenebeck
  2022-06-16 10:17       ` Greg Kurz
  0 siblings, 1 reply; 16+ messages in thread
From: Christian Schoenebeck @ 2022-06-15 16:36 UTC (permalink / raw)
  To: Greg Kurz; +Cc: qemu-devel

On Mittwoch, 15. Juni 2022 17:52:49 CEST Greg Kurz wrote:
> On Tue, 15 Mar 2022 11:08:39 +0100
> 
> Christian Schoenebeck <qemu_oss@crudebyte.com> wrote:
> > Current implementation of 'Twalk' request handling always sends an
> > 'Rerror'
> > 
> > response if any error occured. The 9p2000 protocol spec says though:
> >   "
> >   If the first element cannot be walked for any reason, Rerror is
> >   returned.
> >   Otherwise, the walk will return an Rwalk message containing nwqid qids
> >   corresponding, in order, to the files that are visited by the nwqid
> >   successful elementwise walks; nwqid is therefore either nwname or the
> >   index
> >   of the first elementwise walk that failed.
> >   "
> >   
> >   http://ericvh.github.io/9p-rfc/rfc9p2000.html#anchor33
> > 
> > For that reason we are no longer leaving from an error path in function
> > v9fs_walk(), unless really no path component could be walked successfully
> > or if the request has been interrupted.
> > 
> > Local variable 'nwalked' counts and reflects the number of path components
> > successfully processed by background I/O thread, whereas local variable
> > 'name_idx' subsequently counts and reflects the number of path components
> > eventually accepted successfully by 9p server controller portion.
> > 
> > New local variable 'any_err' is an aggregate variable reflecting whether
> > any error occurred at all, while already existing variable 'err' only
> > reflects the last error.
> > 
> > Despite QIDs being delivered to client in a more relaxed way now, it is
> > important to note though that fid still must remain unaffected if any
> > error
> > occurred.
> > 
> > Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
> > ---
> > 
> >  hw/9pfs/9p.c | 43 +++++++++++++++++++++++++++----------------
> >  1 file changed, 27 insertions(+), 16 deletions(-)
> > 
> > diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
> > index 298f4e6548..e770972a71 100644
> > --- a/hw/9pfs/9p.c
> > +++ b/hw/9pfs/9p.c
> > @@ -1766,7 +1766,7 @@ static void coroutine_fn v9fs_walk(void *opaque)
> > 
> >  {
> >  
> >      int name_idx, nwalked;
> >      g_autofree V9fsQID *qids = NULL;
> > 
> > -    int i, err = 0;
> > +    int i, err = 0, any_err = 0;
> > 
> >      V9fsPath dpath, path;
> >      P9ARRAY_REF(V9fsPath) pathes = NULL;
> >      uint16_t nwnames;
> > 
> > @@ -1832,19 +1832,20 @@ static void coroutine_fn v9fs_walk(void *opaque)
> > 
> >       * driver code altogether inside the following block.
> >       */
> >      
> >      v9fs_co_run_in_worker({
> > 
> > +        nwalked = 0;
> > 
> >          if (v9fs_request_cancelled(pdu)) {
> > 
> > -            err = -EINTR;
> > +            any_err |= err = -EINTR;
> 
> Not super fan of such constructs but I cannot think of anything
> better.. so be it ! :-)

Mwa, :( and I thought this was a slick (though probably yet again unorthodox) 
way to handle aggregate errors.

[...]
> > @@ -1874,12 +1875,12 @@ static void coroutine_fn v9fs_walk(void *opaque)
> > 
> >      /*
> >      
> >       * Handle all the rest of this Twalk request on main thread ...
> >       */
> > 
> > -    if (err < 0) {
> > +    if ((err < 0 && !nwalked) || err == -EINTR) {
> 
> So this is making an exception to the spec excerpt you're mentioning
> in the changelog.
> 
> EINTR can only come from the v9fs_request_cancelled(pdu) == true case,
> since QEMU doesn't have signal handlers AFAIK. This would be the result
> of a TFLUSH , likely to handle ^C from the client side. I guess that in
> that peculiar case, it quite makes sense to return RERROR/RLERROR instead
> of the "degraded" RWALK that the end user isn't waiting for. To sum up,
> TFLUSH behavior prevails on TWALK. Please add a comment though since
> this isn't super obvious in the spec.

Yes, everything you said is depicting this exception here precisely, and I 
agree that it deserves a comment for further clarification, which I'll simply 
add on my end to avoid the noise.

Does the following sound good to you?

"NOTE: -EINTR is an exception where we deviate from the protocol spec and 
simply send an (R)Lerror response instead of bothering to assemble a 
(deducted) Rwalk response; because -EINTR is always the result of a Tflush 
request, so client would no longer wait for a response in this case anyway."

> Apart from that, LGTM.
> 
> Reviewed-by: Greg Kurz <groug@kaod.org>

Thanks for your reviews, much appreciated!

Best regards,
Christian Schoenebeck




^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v4 5/7] 9pfs: fix 'Twalk' to only send error if no component walked
  2022-06-15 16:36     ` Christian Schoenebeck
@ 2022-06-16 10:17       ` Greg Kurz
  0 siblings, 0 replies; 16+ messages in thread
From: Greg Kurz @ 2022-06-16 10:17 UTC (permalink / raw)
  To: Christian Schoenebeck; +Cc: qemu-devel

On Wed, 15 Jun 2022 18:36:46 +0200
Christian Schoenebeck <qemu_oss@crudebyte.com> wrote:

> On Mittwoch, 15. Juni 2022 17:52:49 CEST Greg Kurz wrote:
> > On Tue, 15 Mar 2022 11:08:39 +0100
> > 
> > Christian Schoenebeck <qemu_oss@crudebyte.com> wrote:
> > > Current implementation of 'Twalk' request handling always sends an
> > > 'Rerror'
> > > 
> > > response if any error occured. The 9p2000 protocol spec says though:
> > >   "
> > >   If the first element cannot be walked for any reason, Rerror is
> > >   returned.
> > >   Otherwise, the walk will return an Rwalk message containing nwqid qids
> > >   corresponding, in order, to the files that are visited by the nwqid
> > >   successful elementwise walks; nwqid is therefore either nwname or the
> > >   index
> > >   of the first elementwise walk that failed.
> > >   "
> > >   
> > >   http://ericvh.github.io/9p-rfc/rfc9p2000.html#anchor33
> > > 
> > > For that reason we are no longer leaving from an error path in function
> > > v9fs_walk(), unless really no path component could be walked successfully
> > > or if the request has been interrupted.
> > > 
> > > Local variable 'nwalked' counts and reflects the number of path components
> > > successfully processed by background I/O thread, whereas local variable
> > > 'name_idx' subsequently counts and reflects the number of path components
> > > eventually accepted successfully by 9p server controller portion.
> > > 
> > > New local variable 'any_err' is an aggregate variable reflecting whether
> > > any error occurred at all, while already existing variable 'err' only
> > > reflects the last error.
> > > 
> > > Despite QIDs being delivered to client in a more relaxed way now, it is
> > > important to note though that fid still must remain unaffected if any
> > > error
> > > occurred.
> > > 
> > > Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
> > > ---
> > > 
> > >  hw/9pfs/9p.c | 43 +++++++++++++++++++++++++++----------------
> > >  1 file changed, 27 insertions(+), 16 deletions(-)
> > > 
> > > diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
> > > index 298f4e6548..e770972a71 100644
> > > --- a/hw/9pfs/9p.c
> > > +++ b/hw/9pfs/9p.c
> > > @@ -1766,7 +1766,7 @@ static void coroutine_fn v9fs_walk(void *opaque)
> > > 
> > >  {
> > >  
> > >      int name_idx, nwalked;
> > >      g_autofree V9fsQID *qids = NULL;
> > > 
> > > -    int i, err = 0;
> > > +    int i, err = 0, any_err = 0;
> > > 
> > >      V9fsPath dpath, path;
> > >      P9ARRAY_REF(V9fsPath) pathes = NULL;
> > >      uint16_t nwnames;
> > > 
> > > @@ -1832,19 +1832,20 @@ static void coroutine_fn v9fs_walk(void *opaque)
> > > 
> > >       * driver code altogether inside the following block.
> > >       */
> > >      
> > >      v9fs_co_run_in_worker({
> > > 
> > > +        nwalked = 0;
> > > 
> > >          if (v9fs_request_cancelled(pdu)) {
> > > 
> > > -            err = -EINTR;
> > > +            any_err |= err = -EINTR;
> > 
> > Not super fan of such constructs but I cannot think of anything
> > better.. so be it ! :-)
> 
> Mwa, :( and I thought this was a slick (though probably yet again unorthodox) 
> way to handle aggregate errors.
> 
> [...]
> > > @@ -1874,12 +1875,12 @@ static void coroutine_fn v9fs_walk(void *opaque)
> > > 
> > >      /*
> > >      
> > >       * Handle all the rest of this Twalk request on main thread ...
> > >       */
> > > 
> > > -    if (err < 0) {
> > > +    if ((err < 0 && !nwalked) || err == -EINTR) {
> > 
> > So this is making an exception to the spec excerpt you're mentioning
> > in the changelog.
> > 
> > EINTR can only come from the v9fs_request_cancelled(pdu) == true case,
> > since QEMU doesn't have signal handlers AFAIK. This would be the result
> > of a TFLUSH , likely to handle ^C from the client side. I guess that in
> > that peculiar case, it quite makes sense to return RERROR/RLERROR instead
> > of the "degraded" RWALK that the end user isn't waiting for. To sum up,
> > TFLUSH behavior prevails on TWALK. Please add a comment though since
> > this isn't super obvious in the spec.
> 
> Yes, everything you said is depicting this exception here precisely, and I 
> agree that it deserves a comment for further clarification, which I'll simply 
> add on my end to avoid the noise.
> 
> Does the following sound good to you?
> 
> "NOTE: -EINTR is an exception where we deviate from the protocol spec and 
> simply send an (R)Lerror response instead of bothering to assemble a 
> (deducted) Rwalk response; because -EINTR is always the result of a Tflush 
> request, so client would no longer wait for a response in this case anyway."
> 

LGTM

> > Apart from that, LGTM.
> > 
> > Reviewed-by: Greg Kurz <groug@kaod.org>
> 
> Thanks for your reviews, much appreciated!
> 

Sorry for the 3-month delay...

Cheers,

--
Greg

> Best regards,
> Christian Schoenebeck
> 
> 



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v4 0/7] 9pfs: fix 'Twalk' protocol violation
  2022-03-15 10:10 [PATCH v4 0/7] 9pfs: fix 'Twalk' protocol violation Christian Schoenebeck
                   ` (7 preceding siblings ...)
  2022-03-29 10:21 ` [PATCH v4 0/7] 9pfs: fix 'Twalk' protocol violation Christian Schoenebeck
@ 2022-06-16 10:53 ` Christian Schoenebeck
  8 siblings, 0 replies; 16+ messages in thread
From: Christian Schoenebeck @ 2022-06-16 10:53 UTC (permalink / raw)
  To: qemu-devel; +Cc: Greg Kurz

On Dienstag, 15. März 2022 11:10:25 CEST Christian Schoenebeck wrote:
> Currently the implementation of 'Twalk' does not behave exactly as specified
> by the 9p2000 protocol specification. Actual fix is patch 5; see the
> description of that patch for details of what this overall fix and series
> is about.
> 
> PREREQUISITES
> =============
> 
> This series requires the following additional patch to work correctly:
> https://lore.kernel.org/qemu-devel/E1nTpyU-0000yR-9o@lizzy.crudebyte.com/
> 
> OVERVIEW OF PATCHES
> ===================
> 
> Patch 4 is a preparatory (pure) refactoring change to make actual 'Twalk'
> fix patch 5 better readable.
> 
> All the other patches are just additional test cases for guarding 'Twalk'
> behaviour.
> 
> v3 -> v4:
> 
>   * QID returned by Twalk request in fs_walk_2nd_nonexistent() test should
> NOT be identical to root node's QID. [patch 7]
> 
>   * Fix actual 'fid unaffected' check in fs_walk_2nd_nonexistent() test by
>     sending a subsequent 'Tgetattr' request. [patch 7]
> 
> Christian Schoenebeck (7):
>   tests/9pfs: walk to non-existent dir
>   tests/9pfs: Twalk with nwname=0
>   tests/9pfs: compare QIDs in fs_walk_none() test
>   9pfs: refactor 'name_idx' -> 'nwalked' in v9fs_walk()
>   9pfs: fix 'Twalk' to only send error if no component walked
>   tests/9pfs: guard recent 'Twalk' behaviour fix
>   tests/9pfs: check fid being unaffected in fs_walk_2nd_nonexistent
> 
>  hw/9pfs/9p.c                 |  57 ++++++----
>  tests/qtest/virtio-9p-test.c | 201 ++++++++++++++++++++++++++++++++++-
>  2 files changed, 231 insertions(+), 27 deletions(-)

Queued on 9p.next:
https://github.com/cschoenebeck/qemu/commits/9p.next

Good time to send a PR for this.

Thanks!

Best regards,
Christian Schoenebeck




^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2022-06-16 11:16 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-15 10:10 [PATCH v4 0/7] 9pfs: fix 'Twalk' protocol violation Christian Schoenebeck
2022-03-15 10:08 ` [PATCH v4 1/7] tests/9pfs: walk to non-existent dir Christian Schoenebeck
2022-03-15 10:08 ` [PATCH v4 2/7] tests/9pfs: Twalk with nwname=0 Christian Schoenebeck
2022-03-15 10:08 ` [PATCH v4 3/7] tests/9pfs: compare QIDs in fs_walk_none() test Christian Schoenebeck
2022-06-15 15:08   ` Greg Kurz
2022-03-15 10:08 ` [PATCH v4 4/7] 9pfs: refactor 'name_idx' -> 'nwalked' in v9fs_walk() Christian Schoenebeck
2022-03-15 10:08 ` [PATCH v4 5/7] 9pfs: fix 'Twalk' to only send error if no component walked Christian Schoenebeck
2022-06-15 15:52   ` Greg Kurz
2022-06-15 16:36     ` Christian Schoenebeck
2022-06-16 10:17       ` Greg Kurz
2022-03-15 10:08 ` [PATCH v4 6/7] tests/9pfs: guard recent 'Twalk' behaviour fix Christian Schoenebeck
2022-03-15 10:08 ` [PATCH v4 7/7] tests/9pfs: check fid being unaffected in fs_walk_2nd_nonexistent Christian Schoenebeck
2022-06-15 15:57   ` Greg Kurz
2022-03-29 10:21 ` [PATCH v4 0/7] 9pfs: fix 'Twalk' protocol violation Christian Schoenebeck
2022-03-29 10:59   ` Greg Kurz
2022-06-16 10:53 ` Christian Schoenebeck

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.