diff options
-rw-r--r-- | MAINTAINERS | 2 | ||||
-rw-r--r-- | fsdev/file-op-9p.h | 36 | ||||
-rw-r--r-- | fsdev/qemu-fsdev.c | 4 | ||||
-rw-r--r-- | hw/9pfs/9p-handle.c | 54 | ||||
-rw-r--r-- | hw/9pfs/9p-local.c | 36 | ||||
-rw-r--r-- | hw/9pfs/9p-proxy.c | 30 | ||||
-rw-r--r-- | hw/9pfs/9p-synth.c | 2 | ||||
-rw-r--r-- | hw/9pfs/9p-xattr.h | 5 | ||||
-rw-r--r-- | hw/9pfs/9p.c | 22 | ||||
-rw-r--r-- | hw/9pfs/9p.h | 14 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p-device.c | 62 | ||||
-rw-r--r-- | hw/9pfs/xen-9p-backend.c | 2 | ||||
-rw-r--r-- | qemu-doc.texi | 8 | ||||
-rw-r--r-- | tests/virtio-9p-test.c | 33 |
14 files changed, 161 insertions, 149 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 73a5555..bc2d3a4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1083,13 +1083,11 @@ F: include/hw/virtio/ F: tests/virtio-balloon-test.c virtio-9p -M: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> M: Greg Kurz <groug@kaod.org> S: Supported F: hw/9pfs/ F: fsdev/ F: tests/virtio-9p-test.c -T: git git://github.com/kvaneesh/QEMU.git T: git git://github.com/gkurz/qemu.git 9p-next virtio-blk diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h index 474c79d..3fa062b 100644 --- a/fsdev/file-op-9p.h +++ b/fsdev/file-op-9p.h @@ -22,22 +22,19 @@ #define SM_LOCAL_MODE_BITS 0600 #define SM_LOCAL_DIR_MODE_BITS 0700 -typedef struct FsCred -{ +typedef struct FsCred { uid_t fc_uid; gid_t fc_gid; mode_t fc_mode; dev_t fc_rdev; } FsCred; -struct xattr_operations; -struct FsContext; -struct V9fsPath; +typedef struct FsContext FsContext; +typedef struct V9fsPath V9fsPath; -typedef struct extended_ops { - int (*get_st_gen)(struct FsContext *, struct V9fsPath *, - mode_t, uint64_t *); -} extended_ops; +typedef struct ExtendedOps { + int (*get_st_gen)(FsContext *, V9fsPath *, mode_t, uint64_t *); +} ExtendedOps; /* export flags */ #define V9FS_IMMEDIATE_WRITEOUT 0x00000001 @@ -67,6 +64,8 @@ typedef struct extended_ops { typedef struct FileOperations FileOperations; +typedef struct XattrOperations XattrOperations; + /* * Structure to store the various fsdev's passed through command line. */ @@ -80,24 +79,23 @@ typedef struct FsDriverEntry { mode_t dmode; } FsDriverEntry; -typedef struct FsContext -{ +struct FsContext { uid_t uid; char *fs_root; int export_flags; - struct xattr_operations **xops; - struct extended_ops exops; + XattrOperations **xops; + ExtendedOps exops; FsThrottle *fst; /* fs driver specific data */ void *private; mode_t fmode; mode_t dmode; -} FsContext; +}; -typedef struct V9fsPath { +struct V9fsPath { uint16_t size; char *data; -} V9fsPath; +}; typedef union V9fsFidOpenState V9fsFidOpenState; @@ -105,9 +103,9 @@ void cred_init(FsCred *); struct FileOperations { - int (*parse_opts)(QemuOpts *, struct FsDriverEntry *); - int (*init)(struct FsContext *); - void (*cleanup)(struct FsContext *); + int (*parse_opts)(QemuOpts *, FsDriverEntry *, Error **errp); + int (*init)(FsContext *, Error **errp); + void (*cleanup)(FsContext *); int (*lstat)(FsContext *, V9fsPath *, struct stat *); ssize_t (*readlink)(FsContext *, V9fsPath *, char *, size_t); int (*chmod)(FsContext *, V9fsPath *, FsCred *); diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c index 266e442..941e309 100644 --- a/fsdev/qemu-fsdev.c +++ b/fsdev/qemu-fsdev.c @@ -37,6 +37,7 @@ int qemu_fsdev_add(QemuOpts *opts) const char *fsdriver = qemu_opt_get(opts, "fsdriver"); const char *writeout = qemu_opt_get(opts, "writeout"); bool ro = qemu_opt_get_bool(opts, "readonly", 0); + Error *local_err = NULL; if (!fsdev_id) { error_report("fsdev: No id specified"); @@ -74,7 +75,8 @@ int qemu_fsdev_add(QemuOpts *opts) } if (fsle->fse.ops->parse_opts) { - if (fsle->fse.ops->parse_opts(opts, &fsle->fse)) { + if (fsle->fse.ops->parse_opts(opts, &fsle->fse, &local_err)) { + error_report_err(local_err); g_free(fsle->fse.fsdev_id); g_free(fsle); return -1; diff --git a/hw/9pfs/9p-handle.c b/hw/9pfs/9p-handle.c index 9875f18..c1681d3 100644 --- a/hw/9pfs/9p-handle.c +++ b/hw/9pfs/9p-handle.c @@ -41,10 +41,10 @@ #define BTRFS_SUPER_MAGIC 0x9123683E #endif -struct handle_data { +typedef struct HandleData { int mountfd; int handle_bytes; -}; +} HandleData; static inline int name_to_handle(int dirfd, const char *name, struct file_handle *fh, int *mnt_id, int flags) @@ -79,7 +79,7 @@ static int handle_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf) { int fd, ret; - struct handle_data *data = (struct handle_data *)fs_ctx->private; + HandleData *data = (HandleData *) fs_ctx->private; fd = open_by_handle(data->mountfd, fs_path->data, O_PATH); if (fd < 0) { @@ -94,7 +94,7 @@ static ssize_t handle_readlink(FsContext *fs_ctx, V9fsPath *fs_path, char *buf, size_t bufsz) { int fd, ret; - struct handle_data *data = (struct handle_data *)fs_ctx->private; + HandleData *data = (HandleData *) fs_ctx->private; fd = open_by_handle(data->mountfd, fs_path->data, O_PATH); if (fd < 0) { @@ -118,7 +118,7 @@ static int handle_closedir(FsContext *ctx, V9fsFidOpenState *fs) static int handle_open(FsContext *ctx, V9fsPath *fs_path, int flags, V9fsFidOpenState *fs) { - struct handle_data *data = (struct handle_data *)ctx->private; + HandleData *data = (HandleData *) ctx->private; fs->fd = open_by_handle(data->mountfd, fs_path->data, flags); return fs->fd; @@ -207,7 +207,7 @@ static ssize_t handle_pwritev(FsContext *ctx, V9fsFidOpenState *fs, static int handle_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp) { int fd, ret; - struct handle_data *data = (struct handle_data *)fs_ctx->private; + HandleData *data = (HandleData *) fs_ctx->private; fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK); if (fd < 0) { @@ -222,7 +222,7 @@ static int handle_mknod(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, FsCred *credp) { int dirfd, ret; - struct handle_data *data = (struct handle_data *)fs_ctx->private; + HandleData *data = (HandleData *) fs_ctx->private; dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH); if (dirfd < 0) { @@ -240,7 +240,7 @@ static int handle_mkdir(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, FsCred *credp) { int dirfd, ret; - struct handle_data *data = (struct handle_data *)fs_ctx->private; + HandleData *data = (HandleData *) fs_ctx->private; dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH); if (dirfd < 0) { @@ -272,7 +272,7 @@ static int handle_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, { int ret; int dirfd, fd; - struct handle_data *data = (struct handle_data *)fs_ctx->private; + HandleData *data = (HandleData *) fs_ctx->private; dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH); if (dirfd < 0) { @@ -297,7 +297,7 @@ static int handle_symlink(FsContext *fs_ctx, const char *oldpath, V9fsPath *dir_path, const char *name, FsCred *credp) { int fd, dirfd, ret; - struct handle_data *data = (struct handle_data *)fs_ctx->private; + HandleData *data = (HandleData *) fs_ctx->private; dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH); if (dirfd < 0) { @@ -322,7 +322,7 @@ static int handle_link(FsContext *ctx, V9fsPath *oldpath, V9fsPath *dirpath, const char *name) { int oldfd, newdirfd, ret; - struct handle_data *data = (struct handle_data *)ctx->private; + HandleData *data = (HandleData *) ctx->private; oldfd = open_by_handle(data->mountfd, oldpath->data, O_PATH); if (oldfd < 0) { @@ -342,7 +342,7 @@ static int handle_link(FsContext *ctx, V9fsPath *oldpath, static int handle_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size) { int fd, ret; - struct handle_data *data = (struct handle_data *)ctx->private; + HandleData *data = (HandleData *) ctx->private; fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK | O_WRONLY); if (fd < 0) { @@ -363,7 +363,7 @@ static int handle_rename(FsContext *ctx, const char *oldpath, static int handle_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp) { int fd, ret; - struct handle_data *data = (struct handle_data *)fs_ctx->private; + HandleData *data = (HandleData *) fs_ctx->private; fd = open_by_handle(data->mountfd, fs_path->data, O_PATH); if (fd < 0) { @@ -379,7 +379,7 @@ static int handle_utimensat(FsContext *ctx, V9fsPath *fs_path, { int ret; int fd; - struct handle_data *data = (struct handle_data *)ctx->private; + HandleData *data = (HandleData *) ctx->private; fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK); if (fd < 0) { @@ -418,7 +418,7 @@ static int handle_statfs(FsContext *ctx, V9fsPath *fs_path, struct statfs *stbuf) { int fd, ret; - struct handle_data *data = (struct handle_data *)ctx->private; + HandleData *data = (HandleData *) ctx->private; fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK); if (fd < 0) { @@ -433,7 +433,7 @@ static ssize_t handle_lgetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name, void *value, size_t size) { int fd, ret; - struct handle_data *data = (struct handle_data *)ctx->private; + HandleData *data = (HandleData *) ctx->private; fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK); if (fd < 0) { @@ -448,7 +448,7 @@ static ssize_t handle_llistxattr(FsContext *ctx, V9fsPath *fs_path, void *value, size_t size) { int fd, ret; - struct handle_data *data = (struct handle_data *)ctx->private; + HandleData *data = (HandleData *) ctx->private; fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK); if (fd < 0) { @@ -463,7 +463,7 @@ static int handle_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name, void *value, size_t size, int flags) { int fd, ret; - struct handle_data *data = (struct handle_data *)ctx->private; + HandleData *data = (HandleData *) ctx->private; fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK); if (fd < 0) { @@ -478,7 +478,7 @@ static int handle_lremovexattr(FsContext *ctx, V9fsPath *fs_path, const char *name) { int fd, ret; - struct handle_data *data = (struct handle_data *)ctx->private; + HandleData *data = (HandleData *) ctx->private; fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK); if (fd < 0) { @@ -495,7 +495,7 @@ static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path, char *buffer; struct file_handle *fh; int dirfd, ret, mnt_id; - struct handle_data *data = (struct handle_data *)ctx->private; + HandleData *data = (HandleData *) ctx->private; /* "." and ".." are not allowed */ if (!strcmp(name, ".") || !strcmp(name, "..")) { @@ -536,7 +536,7 @@ static int handle_renameat(FsContext *ctx, V9fsPath *olddir, const char *new_name) { int olddirfd, newdirfd, ret; - struct handle_data *data = (struct handle_data *)ctx->private; + HandleData *data = (HandleData *) ctx->private; olddirfd = open_by_handle(data->mountfd, olddir->data, O_PATH); if (olddirfd < 0) { @@ -557,7 +557,7 @@ static int handle_unlinkat(FsContext *ctx, V9fsPath *dir, const char *name, int flags) { int dirfd, ret; - struct handle_data *data = (struct handle_data *)ctx->private; + HandleData *data = (HandleData *) ctx->private; int rflags; dirfd = open_by_handle(data->mountfd, dir->data, O_PATH); @@ -604,12 +604,12 @@ static int handle_ioc_getversion(FsContext *ctx, V9fsPath *path, #endif } -static int handle_init(FsContext *ctx) +static int handle_init(FsContext *ctx, Error **errp) { int ret, mnt_id; struct statfs stbuf; struct file_handle fh; - struct handle_data *data = g_malloc(sizeof(struct handle_data)); + HandleData *data = g_malloc(sizeof(HandleData)); data->mountfd = open(ctx->fs_root, O_DIRECTORY); if (data->mountfd < 0) { @@ -646,17 +646,19 @@ out: static void handle_cleanup(FsContext *ctx) { - struct handle_data *data = ctx->private; + HandleData *data = ctx->private; close(data->mountfd); g_free(data); } -static int handle_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse) +static int handle_parse_opts(QemuOpts *opts, FsDriverEntry *fse, Error **errp) { const char *sec_model = qemu_opt_get(opts, "security_model"); const char *path = qemu_opt_get(opts, "path"); + warn_report("handle backend is deprecated"); + if (sec_model) { error_report("Invalid argument security_model specified with handle fsdriver"); return -1; diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c index e51af87..b25c185 100644 --- a/hw/9pfs/9p-local.c +++ b/hw/9pfs/9p-local.c @@ -1400,13 +1400,14 @@ static int local_ioc_getversion(FsContext *ctx, V9fsPath *path, #endif } -static int local_init(FsContext *ctx) +static int local_init(FsContext *ctx, Error **errp) { struct statfs stbuf; LocalData *data = g_malloc(sizeof(*data)); data->mountfd = open(ctx->fs_root, O_DIRECTORY | O_RDONLY); if (data->mountfd == -1) { + error_setg_errno(errp, errno, "failed to open '%s'", ctx->fs_root); goto err; } @@ -1459,16 +1460,21 @@ static void local_cleanup(FsContext *ctx) g_free(data); } -static int local_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse) +static void error_append_security_model_hint(Error **errp) +{ + error_append_hint(errp, "Valid options are: security_model=" + "[passthrough|mapped-xattr|mapped-file|none]\n"); +} + +static int local_parse_opts(QemuOpts *opts, FsDriverEntry *fse, Error **errp) { const char *sec_model = qemu_opt_get(opts, "security_model"); const char *path = qemu_opt_get(opts, "path"); - Error *err = NULL; + Error *local_err = NULL; if (!sec_model) { - error_report("Security model not specified, local fs needs security model"); - error_printf("valid options are:" - "\tsecurity_model=[passthrough|mapped-xattr|mapped-file|none]\n"); + error_setg(errp, "security_model property not set"); + error_append_security_model_hint(errp); return -1; } @@ -1482,20 +1488,20 @@ static int local_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse) } else if (!strcmp(sec_model, "mapped-file")) { fse->export_flags |= V9FS_SM_MAPPED_FILE; } else { - error_report("Invalid security model %s specified", sec_model); - error_printf("valid options are:" - "\t[passthrough|mapped-xattr|mapped-file|none]\n"); + error_setg(errp, "invalid security_model property '%s'", sec_model); + error_append_security_model_hint(errp); return -1; } if (!path) { - error_report("fsdev: No path specified"); + error_setg(errp, "path property not set"); return -1; } - fsdev_throttle_parse_opts(opts, &fse->fst, &err); - if (err) { - error_reportf_err(err, "Throttle configuration is not valid: "); + fsdev_throttle_parse_opts(opts, &fse->fst, &local_err); + if (local_err) { + error_propagate(errp, local_err); + error_prepend(errp, "invalid throttle configuration: "); return -1; } @@ -1507,11 +1513,11 @@ static int local_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse) qemu_opt_get_number(opts, "dmode", SM_LOCAL_DIR_MODE_BITS) & 0777; } else { if (qemu_opt_find(opts, "fmode")) { - error_report("fmode is only valid for mapped 9p modes"); + error_setg(errp, "fmode is only valid for mapped security modes"); return -1; } if (qemu_opt_find(opts, "dmode")) { - error_report("dmode is only valid for mapped 9p modes"); + error_setg(errp, "dmode is only valid for mapped security modes"); return -1; } } diff --git a/hw/9pfs/9p-proxy.c b/hw/9pfs/9p-proxy.c index 28b20a7..f030c6a 100644 --- a/hw/9pfs/9p-proxy.c +++ b/hw/9pfs/9p-proxy.c @@ -1083,25 +1083,25 @@ static int proxy_ioc_getversion(FsContext *fs_ctx, V9fsPath *path, return err; } -static int connect_namedsocket(const char *path) +static int connect_namedsocket(const char *path, Error **errp) { int sockfd, size; struct sockaddr_un helper; if (strlen(path) >= sizeof(helper.sun_path)) { - error_report("Socket name too long"); + error_setg(errp, "socket name too long"); return -1; } sockfd = socket(AF_UNIX, SOCK_STREAM, 0); if (sockfd < 0) { - error_report("Failed to create socket: %s", strerror(errno)); + error_setg_errno(errp, errno, "failed to create client socket"); return -1; } strcpy(helper.sun_path, path); helper.sun_family = AF_UNIX; size = strlen(helper.sun_path) + sizeof(helper.sun_family); if (connect(sockfd, (struct sockaddr *)&helper, size) < 0) { - error_report("Failed to connect to %s: %s", path, strerror(errno)); + error_setg_errno(errp, errno, "failed to connect to '%s'", path); close(sockfd); return -1; } @@ -1111,17 +1111,27 @@ static int connect_namedsocket(const char *path) return sockfd; } -static int proxy_parse_opts(QemuOpts *opts, struct FsDriverEntry *fs) +static void error_append_socket_sockfd_hint(Error **errp) +{ + error_append_hint(errp, "Either specify socket=/some/path where /some/path" + " points to a listening AF_UNIX socket or sock_fd=fd" + " where fd is a file descriptor to a connected AF_UNIX" + " socket\n"); +} + +static int proxy_parse_opts(QemuOpts *opts, FsDriverEntry *fs, Error **errp) { const char *socket = qemu_opt_get(opts, "socket"); const char *sock_fd = qemu_opt_get(opts, "sock_fd"); if (!socket && !sock_fd) { - error_report("Must specify either socket or sock_fd"); + error_setg(errp, "both socket and sock_fd properties are missing"); + error_append_socket_sockfd_hint(errp); return -1; } if (socket && sock_fd) { - error_report("Both socket and sock_fd options specified"); + error_setg(errp, "both socket and sock_fd properties are set"); + error_append_socket_sockfd_hint(errp); return -1; } if (socket) { @@ -1134,17 +1144,17 @@ static int proxy_parse_opts(QemuOpts *opts, struct FsDriverEntry *fs) return 0; } -static int proxy_init(FsContext *ctx) +static int proxy_init(FsContext *ctx, Error **errp) { V9fsProxy *proxy = g_malloc(sizeof(V9fsProxy)); int sock_id; if (ctx->export_flags & V9FS_PROXY_SOCK_NAME) { - sock_id = connect_namedsocket(ctx->fs_root); + sock_id = connect_namedsocket(ctx->fs_root, errp); } else { sock_id = atoi(ctx->fs_root); if (sock_id < 0) { - error_report("Socket descriptor not initialized"); + error_setg(errp, "socket descriptor not initialized"); } } if (sock_id < 0) { diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c index df0a8de..8f255e9 100644 --- a/hw/9pfs/9p-synth.c +++ b/hw/9pfs/9p-synth.c @@ -514,7 +514,7 @@ static int synth_unlinkat(FsContext *ctx, V9fsPath *dir, return -1; } -static int synth_init(FsContext *ctx) +static int synth_init(FsContext *ctx, Error **errp) { QLIST_INIT(&synth_root.child); qemu_mutex_init(&synth_mutex); diff --git a/hw/9pfs/9p-xattr.h b/hw/9pfs/9p-xattr.h index 0d83996..35bcd24 100644 --- a/hw/9pfs/9p-xattr.h +++ b/hw/9pfs/9p-xattr.h @@ -16,8 +16,7 @@ #include "qemu/xattr.h" -typedef struct xattr_operations -{ +struct XattrOperations { const char *name; ssize_t (*getxattr)(FsContext *ctx, const char *path, const char *name, void *value, size_t size); @@ -27,7 +26,7 @@ typedef struct xattr_operations void *value, size_t size, int flags); int (*removexattr)(FsContext *ctx, const char *path, const char *name); -} XattrOperations; +}; ssize_t local_getxattr_nofollow(FsContext *ctx, const char *path, const char *name, void *value, size_t size); diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index 52d4663..909a611 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -41,7 +41,7 @@ enum { Oappend = 0x80, }; -ssize_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...) +static ssize_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...) { ssize_t ret; va_list ap; @@ -53,7 +53,7 @@ ssize_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...) return ret; } -ssize_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...) +static ssize_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...) { ssize_t ret; va_list ap; @@ -99,10 +99,10 @@ static int omode_to_uflags(int8_t mode) return ret; } -struct dotl_openflag_map { +typedef struct DotlOpenflagMap { int dotl_flag; int open_flag; -}; +} DotlOpenflagMap; static int dotl_to_open_flags(int flags) { @@ -113,7 +113,7 @@ static int dotl_to_open_flags(int flags) */ int oflags = flags & O_ACCMODE; - struct dotl_openflag_map dotl_oflag_map[] = { + DotlOpenflagMap dotl_oflag_map[] = { { P9_DOTL_CREATE, O_CREAT }, { P9_DOTL_EXCL, O_EXCL }, { P9_DOTL_NOCTTY , O_NOCTTY }, @@ -3473,14 +3473,12 @@ void pdu_submit(V9fsPDU *pdu, P9MsgHeader *hdr) if (pdu->id >= ARRAY_SIZE(pdu_co_handlers) || (pdu_co_handlers[pdu->id] == NULL)) { handler = v9fs_op_not_supp; + } else if (is_ro_export(&s->ctx) && !is_read_only_op(pdu)) { + handler = v9fs_fs_ro; } else { handler = pdu_co_handlers[pdu->id]; } - if (is_ro_export(&s->ctx) && !is_read_only_op(pdu)) { - handler = v9fs_fs_ro; - } - qemu_co_queue_init(&pdu->complete); co = qemu_coroutine_create(handler, pdu); qemu_coroutine_enter(co); @@ -3544,9 +3542,9 @@ int v9fs_device_realize_common(V9fsState *s, Error **errp) s->fid_list = NULL; qemu_co_rwlock_init(&s->rename_lock); - if (s->ops->init(&s->ctx) < 0) { - error_setg(errp, "9pfs Failed to initialize fs-driver with id:%s" - " and export path:%s", s->fsconf.fsdev_id, s->ctx.fs_root); + if (s->ops->init(&s->ctx, errp) < 0) { + error_prepend(errp, "cannot initialize fsdev '%s': ", + s->fsconf.fsdev_id); goto out; } diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h index cdfc4f4..ffe658a 100644 --- a/hw/9pfs/9p.h +++ b/hw/9pfs/9p.h @@ -94,10 +94,10 @@ enum { P9_QTFILE = 0x00, }; -enum p9_proto_version { +typedef enum P9ProtoVersion { V9FS_PROTO_2000U = 0x01, V9FS_PROTO_2000L = 0x02, -}; +} P9ProtoVersion; #define P9_NOTAG UINT16_MAX #define P9_NOFID UINT32_MAX @@ -118,6 +118,7 @@ static inline char *rpath(FsContext *ctx, const char *path) typedef struct V9fsPDU V9fsPDU; typedef struct V9fsState V9fsState; +typedef struct V9fsTransport V9fsTransport; typedef struct { uint32_t size_le; @@ -238,10 +239,10 @@ struct V9fsState FileOperations *ops; FsContext ctx; char *tag; - enum p9_proto_version proto_version; + P9ProtoVersion proto_version; int32_t msize; V9fsPDU pdus[MAX_REQ]; - const struct V9fsTransport *transport; + const V9fsTransport *transport; /* * lock ensuring atomic path update * on rename. @@ -348,8 +349,6 @@ int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath, int v9fs_device_realize_common(V9fsState *s, Error **errp); void v9fs_device_unrealize_common(V9fsState *s, Error **errp); -ssize_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...); -ssize_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...); V9fsPDU *pdu_alloc(V9fsState *s); void pdu_free(V9fsPDU *pdu); void pdu_submit(V9fsPDU *pdu, P9MsgHeader *hdr); @@ -367,8 +366,7 @@ struct V9fsTransport { void (*push_and_notify)(V9fsPDU *pdu); }; -static inline int v9fs_register_transport(V9fsState *s, - const struct V9fsTransport *t) +static inline int v9fs_register_transport(V9fsState *s, const V9fsTransport *t) { assert(!s->transport); s->transport = t; diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c index 62650b0..43f4e53 100644 --- a/hw/9pfs/virtio-9p-device.c +++ b/hw/9pfs/virtio-9p-device.c @@ -20,8 +20,6 @@ #include "hw/virtio/virtio-access.h" #include "qemu/iov.h" -static const struct V9fsTransport virtio_9p_transport; - static void virtio_9p_push_and_notify(V9fsPDU *pdu) { V9fsState *s = pdu->s; @@ -104,35 +102,6 @@ static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config) g_free(cfg); } -static void virtio_9p_device_realize(DeviceState *dev, Error **errp) -{ - VirtIODevice *vdev = VIRTIO_DEVICE(dev); - V9fsVirtioState *v = VIRTIO_9P(dev); - V9fsState *s = &v->state; - - if (v9fs_device_realize_common(s, errp)) { - goto out; - } - - v->config_size = sizeof(struct virtio_9p_config) + strlen(s->fsconf.tag); - virtio_init(vdev, "virtio-9p", VIRTIO_ID_9P, v->config_size); - v->vq = virtio_add_queue(vdev, MAX_REQ, handle_9p_output); - v9fs_register_transport(s, &virtio_9p_transport); - -out: - return; -} - -static void virtio_9p_device_unrealize(DeviceState *dev, Error **errp) -{ - VirtIODevice *vdev = VIRTIO_DEVICE(dev); - V9fsVirtioState *v = VIRTIO_9P(dev); - V9fsState *s = &v->state; - - virtio_cleanup(vdev); - v9fs_device_unrealize_common(s, errp); -} - static void virtio_9p_reset(VirtIODevice *vdev) { V9fsVirtioState *v = (V9fsVirtioState *)vdev; @@ -215,7 +184,7 @@ static void virtio_init_out_iov_from_pdu(V9fsPDU *pdu, struct iovec **piov, *pniov = elem->out_num; } -static const struct V9fsTransport virtio_9p_transport = { +static const V9fsTransport virtio_9p_transport = { .pdu_vmarshal = virtio_pdu_vmarshal, .pdu_vunmarshal = virtio_pdu_vunmarshal, .init_in_iov_from_pdu = virtio_init_in_iov_from_pdu, @@ -223,6 +192,35 @@ static const struct V9fsTransport virtio_9p_transport = { .push_and_notify = virtio_9p_push_and_notify, }; +static void virtio_9p_device_realize(DeviceState *dev, Error **errp) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + V9fsVirtioState *v = VIRTIO_9P(dev); + V9fsState *s = &v->state; + + if (v9fs_device_realize_common(s, errp)) { + goto out; + } + + v->config_size = sizeof(struct virtio_9p_config) + strlen(s->fsconf.tag); + virtio_init(vdev, "virtio-9p", VIRTIO_ID_9P, v->config_size); + v->vq = virtio_add_queue(vdev, MAX_REQ, handle_9p_output); + v9fs_register_transport(s, &virtio_9p_transport); + +out: + return; +} + +static void virtio_9p_device_unrealize(DeviceState *dev, Error **errp) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + V9fsVirtioState *v = VIRTIO_9P(dev); + V9fsState *s = &v->state; + + virtio_cleanup(vdev); + v9fs_device_unrealize_common(s, errp); +} + /* virtio-9p device */ static const VMStateDescription vmstate_virtio_9p = { diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c index ee87f08..df2a410 100644 --- a/hw/9pfs/xen-9p-backend.c +++ b/hw/9pfs/xen-9p-backend.c @@ -233,7 +233,7 @@ static void xen_9pfs_push_and_notify(V9fsPDU *pdu) qemu_bh_schedule(ring->bh); } -static const struct V9fsTransport xen_9p_transport = { +static const V9fsTransport xen_9p_transport = { .pdu_vmarshal = xen_9pfs_pdu_vmarshal, .pdu_vunmarshal = xen_9pfs_pdu_vunmarshal, .init_in_iov_from_pdu = xen_9pfs_init_in_iov_from_pdu, diff --git a/qemu-doc.texi b/qemu-doc.texi index 8d0c809..9d01598 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -2725,6 +2725,14 @@ default channel subsystem image for guests that do not support multiple channel subsystems, all devices can be put into the default channel subsystem image. +@subsection -fsdev handle (since 2.12.0) + +The ``handle'' fsdev backend does not support symlinks and causes the 9p +filesystem in the guest to fail a fair amount of tests from the PJD POSIX +filesystem test suite. Also it requires the CAP_DAC_READ_SEARCH capability, +which is not the recommended way to run QEMU. This backend should not be +used and it will be removed with no replacement. + @section qemu-img command line arguments @subsection convert -s (since 2.0.0) diff --git a/tests/virtio-9p-test.c b/tests/virtio-9p-test.c index ad33d96..00f00f7 100644 --- a/tests/virtio-9p-test.c +++ b/tests/virtio-9p-test.c @@ -18,6 +18,8 @@ #include "standard-headers/linux/virtio_pci.h" #include "hw/9pfs/9p.h" +#define QVIRTIO_9P_TIMEOUT_US (10 * 1000 * 1000) + static const char mount_tag[] = "qtest"; typedef struct { @@ -73,6 +75,9 @@ static QVirtIO9P *qvirtio_9p_pci_start(void) qvirtio_set_driver(v9p->dev); v9p->vq = qvirtqueue_setup(v9p->dev, v9p->qs->alloc, 0); + + qvirtio_set_driver_ok(v9p->dev); + return v9p; } @@ -111,6 +116,7 @@ typedef struct { /* No r_size, it is hardcoded to P9_MAX_SIZE */ size_t t_off; size_t r_off; + uint32_t free_head; } P9Req; static void v9fs_memwrite(P9Req *req, const void *addr, size_t len) @@ -124,11 +130,6 @@ static void v9fs_memskip(P9Req *req, size_t len) req->r_off += len; } -static void v9fs_memrewind(P9Req *req, size_t len) -{ - req->r_off -= len; -} - static void v9fs_memread(P9Req *req, void *addr, size_t len) { memread(req->r_msg + req->r_off, addr, len); @@ -227,12 +228,12 @@ static P9Req *v9fs_req_init(QVirtIO9P *v9p, uint32_t size, uint8_t id, static void v9fs_req_send(P9Req *req) { QVirtIO9P *v9p = req->v9p; - uint32_t free_head; req->r_msg = guest_alloc(v9p->qs->alloc, P9_MAX_SIZE); - free_head = qvirtqueue_add(v9p->vq, req->t_msg, req->t_size, false, true); + req->free_head = qvirtqueue_add(v9p->vq, req->t_msg, req->t_size, false, + true); qvirtqueue_add(v9p->vq, req->r_msg, P9_MAX_SIZE, true, false); - qvirtqueue_kick(v9p->dev, v9p->vq, free_head); + qvirtqueue_kick(v9p->dev, v9p->vq, req->free_head); req->t_off = 0; } @@ -250,19 +251,13 @@ static void v9fs_req_recv(P9Req *req, uint8_t id) { QVirtIO9P *v9p = req->v9p; P9Hdr hdr; - int i; - for (i = 0; i < 10; i++) { - qvirtio_wait_queue_isr(v9p->dev, v9p->vq, 1000 * 1000); + qvirtio_wait_used_elem(v9p->dev, v9p->vq, req->free_head, + QVIRTIO_9P_TIMEOUT_US); - v9fs_memread(req, &hdr, 7); - hdr.size = ldl_le_p(&hdr.size); - hdr.tag = lduw_le_p(&hdr.tag); - if (hdr.size >= 7) { - break; - } - v9fs_memrewind(req, 7); - } + v9fs_memread(req, &hdr, 7); + hdr.size = ldl_le_p(&hdr.size); + hdr.tag = lduw_le_p(&hdr.tag); g_assert_cmpint(hdr.size, >=, 7); g_assert_cmpint(hdr.size, <=, P9_MAX_SIZE); |