hw/9pfs: Read-only support for 9p export
authorM. Mohan Kumar <mohan@in.ibm.com>
Tue, 25 Oct 2011 06:40:39 +0000 (12:10 +0530)
committerAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Mon, 31 Oct 2011 07:04:17 +0000 (12:34 +0530)
A new fsdev parameter "readonly" is introduced to control accessing 9p export.
"readonly" can be used to specify the access type. By default "rw" access
is given to 9p export.

Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
fsdev/file-op-9p.h
fsdev/qemu-fsdev.c
hw/9pfs/virtio-9p.c
qemu-config.c
qemu-options.hx
vl.c

index 908e2a5edcc64472f0c7f306099cac2fe00e632a..5788ff911c9a072bc25b0d956e76cc3d2a9b6ca5 100644 (file)
@@ -56,10 +56,12 @@ typedef struct extended_ops {
  * On failure ignore the error.
  */
 #define V9FS_SM_NONE                0x00000010
-
+#define V9FS_RDONLY                 0x00000020
 
 #define V9FS_SEC_MASK               0x0000001C
 
+
+
 typedef struct FsContext
 {
     uid_t uid;
index 5977bcca4cf4e83a67ad90509d78824c1ac6d0fd..27d10cb3b36f9456d9ca848ff0cd1931e6c97459 100644 (file)
@@ -35,7 +35,7 @@ int qemu_fsdev_add(QemuOpts *opts)
     const char *path = qemu_opt_get(opts, "path");
     const char *sec_model = qemu_opt_get(opts, "security_model");
     const char *writeout = qemu_opt_get(opts, "writeout");
-
+    bool ro = qemu_opt_get_bool(opts, "readonly", 0);
 
     if (!fsdev_id) {
         fprintf(stderr, "fsdev: No id specified\n");
@@ -86,6 +86,11 @@ int qemu_fsdev_add(QemuOpts *opts)
             fsle->fse.export_flags |= V9FS_IMMEDIATE_WRITEOUT;
         }
     }
+    if (ro) {
+        fsle->fse.export_flags |= V9FS_RDONLY;
+    } else {
+        fsle->fse.export_flags &= ~V9FS_RDONLY;
+    }
 
     if (strcmp(fsdriver, "local")) {
         goto done;
index 8b6813f8de75f875cf58251b8dac28071131aa32..e7618d72baa5ed9168183476d8a7d06f6f201e38 100644 (file)
@@ -1271,6 +1271,11 @@ static void v9fs_fix_path(V9fsPath *dst, V9fsPath *src, int len)
     dst->size++;
 }
 
+static inline bool is_ro_export(FsContext *ctx)
+{
+    return ctx->export_flags & V9FS_RDONLY;
+}
+
 static void v9fs_version(void *opaque)
 {
     V9fsPDU *pdu = opaque;
@@ -1690,6 +1695,14 @@ static void v9fs_open(void *opaque)
         } else {
             flags = omode_to_uflags(mode);
         }
+        if (is_ro_export(&s->ctx)) {
+            if (mode & O_WRONLY || mode & O_RDWR ||
+                mode & O_APPEND || mode & O_TRUNC) {
+                err = -EROFS;
+                goto out;
+            }
+            flags |= O_NOATIME;
+        }
         err = v9fs_co_open(pdu, fidp, flags);
         if (err < 0) {
             goto out;
@@ -3309,6 +3322,39 @@ static void v9fs_op_not_supp(void *opaque)
     complete_pdu(pdu->s, pdu, -EOPNOTSUPP);
 }
 
+static void v9fs_fs_ro(void *opaque)
+{
+    V9fsPDU *pdu = opaque;
+    complete_pdu(pdu->s, pdu, -EROFS);
+}
+
+static inline bool is_read_only_op(V9fsPDU *pdu)
+{
+    switch (pdu->id) {
+    case P9_TREADDIR:
+    case P9_TSTATFS:
+    case P9_TGETATTR:
+    case P9_TXATTRWALK:
+    case P9_TLOCK:
+    case P9_TGETLOCK:
+    case P9_TREADLINK:
+    case P9_TVERSION:
+    case P9_TLOPEN:
+    case P9_TATTACH:
+    case P9_TSTAT:
+    case P9_TWALK:
+    case P9_TCLUNK:
+    case P9_TFSYNC:
+    case P9_TOPEN:
+    case P9_TREAD:
+    case P9_TAUTH:
+    case P9_TFLUSH:
+        return 1;
+    default:
+        return 0;
+    }
+}
+
 static void submit_pdu(V9fsState *s, V9fsPDU *pdu)
 {
     Coroutine *co;
@@ -3320,6 +3366,10 @@ static void submit_pdu(V9fsState *s, V9fsPDU *pdu)
     } else {
         handler = pdu_co_handlers[pdu->id];
     }
+
+    if (is_ro_export(&s->ctx) && !is_read_only_op(pdu)) {
+        handler = v9fs_fs_ro;
+    }
     co = qemu_coroutine_create(handler);
     qemu_coroutine_enter(co, pdu);
 }
index 90b6b3e85b4509375f8e3438130268a7a6f7fcd3..597d7e10b18d19572d9f3038144e0c9dc2d969e5 100644 (file)
@@ -180,7 +180,11 @@ QemuOptsList qemu_fsdev_opts = {
         }, {
             .name = "writeout",
             .type = QEMU_OPT_STRING,
+        }, {
+            .name = "readonly",
+            .type = QEMU_OPT_BOOL,
         },
+
         { /*End of list */ }
     },
 };
@@ -205,6 +209,9 @@ QemuOptsList qemu_virtfs_opts = {
         }, {
             .name = "writeout",
             .type = QEMU_OPT_STRING,
+        }, {
+            .name = "readonly",
+            .type = QEMU_OPT_BOOL,
         },
 
         { /*End of list */ }
index 5d2a7765e88310d802f8a8103060692f1ce3cbfc..1baa381ab95ab1e260e8e0b0453e5ae2bfc0e807 100644 (file)
@@ -528,12 +528,12 @@ DEFHEADING(File system options:)
 
 DEF("fsdev", HAS_ARG, QEMU_OPTION_fsdev,
     "-fsdev fsdriver,id=id,path=path,[security_model={mapped|passthrough|none}]\n"
-    "       [,writeout=immediate]\n",
+    "       [,writeout=immediate][,readonly]\n",
     QEMU_ARCH_ALL)
 
 STEXI
 
-@item -fsdev @var{fsdriver},id=@var{id},path=@var{path},[security_model=@var{security_model}][,writeout=@var{writeout}]
+@item -fsdev @var{fsdriver},id=@var{id},path=@var{path},[security_model=@var{security_model}][,writeout=@var{writeout}][,readonly]
 @findex -fsdev
 Define a new file system device. Valid options are:
 @table @option
@@ -563,6 +563,9 @@ This is an optional argument. The only supported value is "immediate".
 This means that host page cache will be used to read and write data but
 write notification will be sent to the guest only when the data has been
 reported as written by the storage subsystem.
+@item readonly
+Enables exporting 9p share as a readonly mount for guests. By default
+read-write access is given.
 @end table
 
 -fsdev option is used along with -device driver "virtio-9p-pci".
@@ -583,12 +586,12 @@ DEFHEADING(Virtual File system pass-through options:)
 
 DEF("virtfs", HAS_ARG, QEMU_OPTION_virtfs,
     "-virtfs local,path=path,mount_tag=tag,security_model=[mapped|passthrough|none]\n"
-    "        [,writeout=immediate]\n",
+    "        [,writeout=immediate][,readonly]\n",
     QEMU_ARCH_ALL)
 
 STEXI
 
-@item -virtfs @var{fsdriver},path=@var{path},mount_tag=@var{mount_tag},security_model=@var{security_model}[,writeout=@var{writeout}]
+@item -virtfs @var{fsdriver},path=@var{path},mount_tag=@var{mount_tag},security_model=@var{security_model}[,writeout=@var{writeout}][,readonly]
 @findex -virtfs
 
 The general form of a Virtual File system pass-through options are:
@@ -619,6 +622,9 @@ This is an optional argument. The only supported value is "immediate".
 This means that host page cache will be used to read and write data but
 write notification will be sent to the guest only when the data has been
 reported as written by the storage subsystem.
+@item readonly
+Enables exporting 9p share as a readonly mount for guests. By default
+read-write access is given.
 @end table
 ETEXI
 
diff --git a/vl.c b/vl.c
index 1ddb17bfd950f34164629437b5d7a94b0809a982..c51a7403cb8ff18ab7fad29eb77cc2e09f4609dd 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -2707,6 +2707,8 @@ int main(int argc, char **argv, char **envp)
                 qemu_opt_set(fsdev, "security_model",
                              qemu_opt_get(opts, "security_model"));
 
+                qemu_opt_set_bool(fsdev, "readonly",
+                                qemu_opt_get_bool(opts, "readonly", 0));
                 device = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
                 qemu_opt_set(device, "driver", "virtio-9p-pci");
                 qemu_opt_set(device, "fsdev",