diff mbox series

[1/6] tests/9p: add 'use-after-unlink' test

Message ID 3d6449d4df25bcdd3e807eff169f46f1385e5257.1732465720.git.qemu_oss@crudebyte.com (mailing list archive)
State New, archived
Headers show
Series 9pfs: fix fstat() after unlink() (with a Linux guest) | expand

Commit Message

Christian Schoenebeck Feb. 21, 2024, 2:13 p.m. UTC
After removing a file from the file system, we should still be able to
work with the file if we already had it open before removal.

As a first step we verify that it is possible to write to an unlinked
file, as this is what already works. This test is extended later on
after having fixed other use cases after unlink that are not working
yet.

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

Comments

Greg Kurz Nov. 25, 2024, 8:47 a.m. UTC | #1
Hi Christian,

On Wed, 21 Feb 2024 15:13:13 +0100
Christian Schoenebeck <qemu_oss@crudebyte.com> wrote:

> After removing a file from the file system, we should still be able to
> work with the file if we already had it open before removal.
> 
> As a first step we verify that it is possible to write to an unlinked
> file, as this is what already works. This test is extended later on
> after having fixed other use cases after unlink that are not working
> yet.
> 
> Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
> ---

Test looks good but make sure it is merged last to preserve bisect.

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

>  tests/qtest/virtio-9p-test.c | 41 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 41 insertions(+)
> 
> diff --git a/tests/qtest/virtio-9p-test.c b/tests/qtest/virtio-9p-test.c
> index 3c8cd235cf..f6d7400a87 100644
> --- a/tests/qtest/virtio-9p-test.c
> +++ b/tests/qtest/virtio-9p-test.c
> @@ -693,6 +693,45 @@ static void fs_unlinkat_hardlink(void *obj, void *data,
>      g_assert(stat(real_file, &st_real) == 0);
>  }
>  
> +static void fs_use_after_unlink(void *obj, void *data,
> +                                QGuestAllocator *t_alloc)
> +{
> +    QVirtio9P *v9p = obj;
> +    v9fs_set_allocator(t_alloc);
> +    static const uint32_t write_count = P9_MAX_SIZE / 2;
> +    g_autofree char *real_file = virtio_9p_test_path("09/doa_file");
> +    g_autofree char *buf = g_malloc0(write_count);
> +    struct stat st_file;
> +    uint32_t fid_file;
> +    uint32_t count;
> +
> +    tattach({ .client = v9p });
> +
> +    /* create a file "09/doa_file" and make sure it exists and is regular */
> +    tmkdir({ .client = v9p, .atPath = "/", .name = "09" });
> +    tlcreate({ .client = v9p, .atPath = "09", .name = "doa_file" });
> +    g_assert(stat(real_file, &st_file) == 0);
> +    g_assert((st_file.st_mode & S_IFMT) == S_IFREG);
> +
> +    /* request a FID for that regular file that we can work with next */
> +    fid_file = twalk({
> +        .client = v9p, .fid = 0, .path = "09/doa_file"
> +    }).newfid;
> +    g_assert(fid_file != 0);
> +
> +    /* now first open the file in write mode before ... */
> +    tlopen({ .client = v9p, .fid = fid_file, .flags = O_WRONLY });
> +    /* ... removing the file from file system */
> +    tunlinkat({ .client = v9p, .atPath = "09", .name = "doa_file" });
> +
> +    /* file is removed, but we still have it open, so this should succeed */
> +    count = twrite({
> +        .client = v9p, .fid = fid_file, .offset = 0, .count = write_count,
> +        .data = buf
> +    }).count;
> +    g_assert_cmpint(count, ==, write_count);
> +}
> +
>  static void cleanup_9p_local_driver(void *data)
>  {
>      /* remove previously created test dir when test is completed */
> @@ -758,6 +797,8 @@ static void register_virtio_9p_test(void)
>      qos_add_test("local/hardlink_file", "virtio-9p", fs_hardlink_file, &opts);
>      qos_add_test("local/unlinkat_hardlink", "virtio-9p", fs_unlinkat_hardlink,
>                   &opts);
> +    qos_add_test("local/use_after_unlink", "virtio-9p", fs_use_after_unlink,
> +                 &opts);
>  }
>  
>  libqos_init(register_virtio_9p_test);


Cheers,
Christian Schoenebeck Nov. 25, 2024, 9:34 a.m. UTC | #2
On Monday, November 25, 2024 9:47:17 AM CET Greg Kurz wrote:
> Hi Christian,
> 
> On Wed, 21 Feb 2024 15:13:13 +0100
> Christian Schoenebeck <qemu_oss@crudebyte.com> wrote:
> 
> > After removing a file from the file system, we should still be able to
> > work with the file if we already had it open before removal.
> > 
> > As a first step we verify that it is possible to write to an unlinked
> > file, as this is what already works. This test is extended later on
> > after having fixed other use cases after unlink that are not working
> > yet.
> > 
> > Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
> > ---
> 
> Test looks good but make sure it is merged last to preserve bisect.

I think there is a misapprehension: this test already passed! So no need to
move this patch.

What this test does is verifying the scenario open-unlink-write. I already
sent this patch in February and was surprised by myself that this idiom
already works:

https://lore.kernel.org/all/E1rcnYJ-0004KK-LV@lizzy.crudebyte.com/

What this entire series (i.e. patch 5) rather fixes is the idiom
open-unlink-fstat, and the test for this idiom is the last patch, not this
first one here.

So bisect is already fine.

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

Thanks!

/Christian
diff mbox series

Patch

diff --git a/tests/qtest/virtio-9p-test.c b/tests/qtest/virtio-9p-test.c
index 3c8cd235cf..f6d7400a87 100644
--- a/tests/qtest/virtio-9p-test.c
+++ b/tests/qtest/virtio-9p-test.c
@@ -693,6 +693,45 @@  static void fs_unlinkat_hardlink(void *obj, void *data,
     g_assert(stat(real_file, &st_real) == 0);
 }
 
+static void fs_use_after_unlink(void *obj, void *data,
+                                QGuestAllocator *t_alloc)
+{
+    QVirtio9P *v9p = obj;
+    v9fs_set_allocator(t_alloc);
+    static const uint32_t write_count = P9_MAX_SIZE / 2;
+    g_autofree char *real_file = virtio_9p_test_path("09/doa_file");
+    g_autofree char *buf = g_malloc0(write_count);
+    struct stat st_file;
+    uint32_t fid_file;
+    uint32_t count;
+
+    tattach({ .client = v9p });
+
+    /* create a file "09/doa_file" and make sure it exists and is regular */
+    tmkdir({ .client = v9p, .atPath = "/", .name = "09" });
+    tlcreate({ .client = v9p, .atPath = "09", .name = "doa_file" });
+    g_assert(stat(real_file, &st_file) == 0);
+    g_assert((st_file.st_mode & S_IFMT) == S_IFREG);
+
+    /* request a FID for that regular file that we can work with next */
+    fid_file = twalk({
+        .client = v9p, .fid = 0, .path = "09/doa_file"
+    }).newfid;
+    g_assert(fid_file != 0);
+
+    /* now first open the file in write mode before ... */
+    tlopen({ .client = v9p, .fid = fid_file, .flags = O_WRONLY });
+    /* ... removing the file from file system */
+    tunlinkat({ .client = v9p, .atPath = "09", .name = "doa_file" });
+
+    /* file is removed, but we still have it open, so this should succeed */
+    count = twrite({
+        .client = v9p, .fid = fid_file, .offset = 0, .count = write_count,
+        .data = buf
+    }).count;
+    g_assert_cmpint(count, ==, write_count);
+}
+
 static void cleanup_9p_local_driver(void *data)
 {
     /* remove previously created test dir when test is completed */
@@ -758,6 +797,8 @@  static void register_virtio_9p_test(void)
     qos_add_test("local/hardlink_file", "virtio-9p", fs_hardlink_file, &opts);
     qos_add_test("local/unlinkat_hardlink", "virtio-9p", fs_unlinkat_hardlink,
                  &opts);
+    qos_add_test("local/use_after_unlink", "virtio-9p", fs_use_after_unlink,
+                 &opts);
 }
 
 libqos_init(register_virtio_9p_test);