mirror of https://github.com/proxmox/mirror_qemu
hw/9pfs: Read-only support for 9p export
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>master
parent
f02b77c9bf
commit
2c74c2cb4b
|
@ -56,10 +56,12 @@ typedef struct extended_ops {
|
||||||
* On failure ignore the error.
|
* On failure ignore the error.
|
||||||
*/
|
*/
|
||||||
#define V9FS_SM_NONE 0x00000010
|
#define V9FS_SM_NONE 0x00000010
|
||||||
|
#define V9FS_RDONLY 0x00000020
|
||||||
|
|
||||||
#define V9FS_SEC_MASK 0x0000001C
|
#define V9FS_SEC_MASK 0x0000001C
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct FsContext
|
typedef struct FsContext
|
||||||
{
|
{
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
|
|
|
@ -35,7 +35,7 @@ int qemu_fsdev_add(QemuOpts *opts)
|
||||||
const char *path = qemu_opt_get(opts, "path");
|
const char *path = qemu_opt_get(opts, "path");
|
||||||
const char *sec_model = qemu_opt_get(opts, "security_model");
|
const char *sec_model = qemu_opt_get(opts, "security_model");
|
||||||
const char *writeout = qemu_opt_get(opts, "writeout");
|
const char *writeout = qemu_opt_get(opts, "writeout");
|
||||||
|
bool ro = qemu_opt_get_bool(opts, "readonly", 0);
|
||||||
|
|
||||||
if (!fsdev_id) {
|
if (!fsdev_id) {
|
||||||
fprintf(stderr, "fsdev: No id specified\n");
|
fprintf(stderr, "fsdev: No id specified\n");
|
||||||
|
@ -86,6 +86,11 @@ int qemu_fsdev_add(QemuOpts *opts)
|
||||||
fsle->fse.export_flags |= V9FS_IMMEDIATE_WRITEOUT;
|
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")) {
|
if (strcmp(fsdriver, "local")) {
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
@ -1271,6 +1271,11 @@ static void v9fs_fix_path(V9fsPath *dst, V9fsPath *src, int len)
|
||||||
dst->size++;
|
dst->size++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool is_ro_export(FsContext *ctx)
|
||||||
|
{
|
||||||
|
return ctx->export_flags & V9FS_RDONLY;
|
||||||
|
}
|
||||||
|
|
||||||
static void v9fs_version(void *opaque)
|
static void v9fs_version(void *opaque)
|
||||||
{
|
{
|
||||||
V9fsPDU *pdu = opaque;
|
V9fsPDU *pdu = opaque;
|
||||||
|
@ -1690,6 +1695,14 @@ static void v9fs_open(void *opaque)
|
||||||
} else {
|
} else {
|
||||||
flags = omode_to_uflags(mode);
|
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);
|
err = v9fs_co_open(pdu, fidp, flags);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -3309,6 +3322,39 @@ static void v9fs_op_not_supp(void *opaque)
|
||||||
complete_pdu(pdu->s, pdu, -EOPNOTSUPP);
|
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)
|
static void submit_pdu(V9fsState *s, V9fsPDU *pdu)
|
||||||
{
|
{
|
||||||
Coroutine *co;
|
Coroutine *co;
|
||||||
|
@ -3320,6 +3366,10 @@ static void submit_pdu(V9fsState *s, V9fsPDU *pdu)
|
||||||
} else {
|
} else {
|
||||||
handler = pdu_co_handlers[pdu->id];
|
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);
|
co = qemu_coroutine_create(handler);
|
||||||
qemu_coroutine_enter(co, pdu);
|
qemu_coroutine_enter(co, pdu);
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,7 +180,11 @@ QemuOptsList qemu_fsdev_opts = {
|
||||||
}, {
|
}, {
|
||||||
.name = "writeout",
|
.name = "writeout",
|
||||||
.type = QEMU_OPT_STRING,
|
.type = QEMU_OPT_STRING,
|
||||||
|
}, {
|
||||||
|
.name = "readonly",
|
||||||
|
.type = QEMU_OPT_BOOL,
|
||||||
},
|
},
|
||||||
|
|
||||||
{ /*End of list */ }
|
{ /*End of list */ }
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -205,6 +209,9 @@ QemuOptsList qemu_virtfs_opts = {
|
||||||
}, {
|
}, {
|
||||||
.name = "writeout",
|
.name = "writeout",
|
||||||
.type = QEMU_OPT_STRING,
|
.type = QEMU_OPT_STRING,
|
||||||
|
}, {
|
||||||
|
.name = "readonly",
|
||||||
|
.type = QEMU_OPT_BOOL,
|
||||||
},
|
},
|
||||||
|
|
||||||
{ /*End of list */ }
|
{ /*End of list */ }
|
||||||
|
|
|
@ -528,12 +528,12 @@ DEFHEADING(File system options:)
|
||||||
|
|
||||||
DEF("fsdev", HAS_ARG, QEMU_OPTION_fsdev,
|
DEF("fsdev", HAS_ARG, QEMU_OPTION_fsdev,
|
||||||
"-fsdev fsdriver,id=id,path=path,[security_model={mapped|passthrough|none}]\n"
|
"-fsdev fsdriver,id=id,path=path,[security_model={mapped|passthrough|none}]\n"
|
||||||
" [,writeout=immediate]\n",
|
" [,writeout=immediate][,readonly]\n",
|
||||||
QEMU_ARCH_ALL)
|
QEMU_ARCH_ALL)
|
||||||
|
|
||||||
STEXI
|
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
|
@findex -fsdev
|
||||||
Define a new file system device. Valid options are:
|
Define a new file system device. Valid options are:
|
||||||
@table @option
|
@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
|
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
|
write notification will be sent to the guest only when the data has been
|
||||||
reported as written by the storage subsystem.
|
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
|
@end table
|
||||||
|
|
||||||
-fsdev option is used along with -device driver "virtio-9p-pci".
|
-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,
|
DEF("virtfs", HAS_ARG, QEMU_OPTION_virtfs,
|
||||||
"-virtfs local,path=path,mount_tag=tag,security_model=[mapped|passthrough|none]\n"
|
"-virtfs local,path=path,mount_tag=tag,security_model=[mapped|passthrough|none]\n"
|
||||||
" [,writeout=immediate]\n",
|
" [,writeout=immediate][,readonly]\n",
|
||||||
QEMU_ARCH_ALL)
|
QEMU_ARCH_ALL)
|
||||||
|
|
||||||
STEXI
|
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
|
@findex -virtfs
|
||||||
|
|
||||||
The general form of a Virtual File system pass-through options are:
|
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
|
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
|
write notification will be sent to the guest only when the data has been
|
||||||
reported as written by the storage subsystem.
|
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
|
@end table
|
||||||
ETEXI
|
ETEXI
|
||||||
|
|
||||||
|
|
2
vl.c
2
vl.c
|
@ -2707,6 +2707,8 @@ int main(int argc, char **argv, char **envp)
|
||||||
qemu_opt_set(fsdev, "security_model",
|
qemu_opt_set(fsdev, "security_model",
|
||||||
qemu_opt_get(opts, "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);
|
device = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
|
||||||
qemu_opt_set(device, "driver", "virtio-9p-pci");
|
qemu_opt_set(device, "driver", "virtio-9p-pci");
|
||||||
qemu_opt_set(device, "fsdev",
|
qemu_opt_set(device, "fsdev",
|
||||||
|
|
Loading…
Reference in New Issue