- Aneesh no longer listed in MAINTAINERS,

- deprecation of the handle backend,
 - improved error reporting, especially when the local backend fails to
   open the VirtFS root,
 - virtio-9p-test to behave more like a real virtio guest driver: set
   DRIVER_OK when ready to use the device and process the used ring
   for completed requests,
 - cosmetic fixes (mostly coding style related).
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEtIKLr5QxQM7yo0kQcdTV5YIvc9YFAlpTRaYACgkQcdTV5YIv
 c9a7whAAirmxuFubIELmGDZiihqlCddq8ez4YfEWg2QXJ4I4I2TVcMRqPvxOqDM1
 w3bFgBD1N6ukA16i9wn2vevzU7NTdr6CHJFReDALZteOxLD+36VeZf159kSISA7L
 bXENI893mUVxaLzx9ce/I7A06Hl4BlZtSs0mrpzLhaP+WE1t2Hth0Atw6sWSyCJP
 JanB+5mMsh4VFv/S7YiA21bPt8O5q5BWiyzQQ8kikPj+KBThLa5J711lAakEeQTZ
 gKqmOzeou/r2XfXi3ZkfMm4QmDdnA4gXIe8OXIaP/Rg88413DnGWUAFyaa06VYfc
 CsVX1t7EeqP6F+DR+G/6LhdhcSVrZ62//Ie3a9ZsWy0Ul8nTB08CLxIxhCKmV+gg
 bJyruhwH7s09NtsEmPg+HFQ7Hkq+qUdFiNBLtjFOvaLu3XTPKFopvDK/fohcS5Yc
 7vJLQ676rGcQIEb5/Ws3tlAzARSqELmUSp/X6RXj/4mVK/HE4l5z2OLlJPXVVWUS
 xE5wz/p/qNnTCJeBXHjVl2nhyW4clwunuc/RANm5FiQMqJmNel8rrpnszQgsX0g7
 eLCyXuWn4Poq3YSr69lK/KkqREqu5OhxesCw23TrPY1/vvtSbxywr1V9d4ITywQc
 v/I67ZSxF9zQOgKw/XvAyal7De+A8VJw7GhqHpYc1//jCzarLQ4=
 =aKjv
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/gkurz/tags/for-upstream' into staging

- Aneesh no longer listed in MAINTAINERS,
- deprecation of the handle backend,
- improved error reporting, especially when the local backend fails to
  open the VirtFS root,
- virtio-9p-test to behave more like a real virtio guest driver: set
  DRIVER_OK when ready to use the device and process the used ring
  for completed requests,
- cosmetic fixes (mostly coding style related).

# gpg: Signature made Mon 08 Jan 2018 10:19:18 GMT
# gpg:                using RSA key 0x71D4D5E5822F73D6
# gpg: Good signature from "Greg Kurz <groug@kaod.org>"
# gpg:                 aka "Gregory Kurz <gregory.kurz@free.fr>"
# gpg:                 aka "[jpeg image of size 3330]"
# Primary key fingerprint: B482 8BAF 9431 40CE F2A3  4910 71D4 D5E5 822F 73D6

* remotes/gkurz/tags/for-upstream:
  MAINTAINERS: Drop Aneesh as 9pfs maintainer
  9pfs: deprecate handle backend
  fsdev: improve error handling of backend init
  fsdev: improve error handling of backend opts parsing
  tests: virtio-9p: set DRIVER_OK before using the device
  tests: virtio-9p: fix ISR dependence
  9pfs: make pdu_marshal() and pdu_unmarshal() static functions
  9pfs: fix error path in pdu_submit()
  9pfs: fix type in *_parse_opts declarations
  9pfs: handle: fix type definition
  9pfs: fix some type definitions
  fsdev: fix some type definitions
  9pfs: fix XattrOperations typedef
  virtio-9p: move unrealize/realize after virtio_9p_transport definition

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2018-01-08 22:14:24 +00:00
commit ee98a6b089
14 changed files with 161 additions and 149 deletions

View File

@ -1083,13 +1083,11 @@ F: include/hw/virtio/
F: tests/virtio-balloon-test.c F: tests/virtio-balloon-test.c
virtio-9p virtio-9p
M: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
M: Greg Kurz <groug@kaod.org> M: Greg Kurz <groug@kaod.org>
S: Supported S: Supported
F: hw/9pfs/ F: hw/9pfs/
F: fsdev/ F: fsdev/
F: tests/virtio-9p-test.c F: tests/virtio-9p-test.c
T: git git://github.com/kvaneesh/QEMU.git
T: git git://github.com/gkurz/qemu.git 9p-next T: git git://github.com/gkurz/qemu.git 9p-next
virtio-blk virtio-blk

View File

@ -22,22 +22,19 @@
#define SM_LOCAL_MODE_BITS 0600 #define SM_LOCAL_MODE_BITS 0600
#define SM_LOCAL_DIR_MODE_BITS 0700 #define SM_LOCAL_DIR_MODE_BITS 0700
typedef struct FsCred typedef struct FsCred {
{
uid_t fc_uid; uid_t fc_uid;
gid_t fc_gid; gid_t fc_gid;
mode_t fc_mode; mode_t fc_mode;
dev_t fc_rdev; dev_t fc_rdev;
} FsCred; } FsCred;
struct xattr_operations; typedef struct FsContext FsContext;
struct FsContext; typedef struct V9fsPath V9fsPath;
struct V9fsPath;
typedef struct extended_ops { typedef struct ExtendedOps {
int (*get_st_gen)(struct FsContext *, struct V9fsPath *, int (*get_st_gen)(FsContext *, V9fsPath *, mode_t, uint64_t *);
mode_t, uint64_t *); } ExtendedOps;
} extended_ops;
/* export flags */ /* export flags */
#define V9FS_IMMEDIATE_WRITEOUT 0x00000001 #define V9FS_IMMEDIATE_WRITEOUT 0x00000001
@ -67,6 +64,8 @@ typedef struct extended_ops {
typedef struct FileOperations FileOperations; typedef struct FileOperations FileOperations;
typedef struct XattrOperations XattrOperations;
/* /*
* Structure to store the various fsdev's passed through command line. * Structure to store the various fsdev's passed through command line.
*/ */
@ -80,24 +79,23 @@ typedef struct FsDriverEntry {
mode_t dmode; mode_t dmode;
} FsDriverEntry; } FsDriverEntry;
typedef struct FsContext struct FsContext {
{
uid_t uid; uid_t uid;
char *fs_root; char *fs_root;
int export_flags; int export_flags;
struct xattr_operations **xops; XattrOperations **xops;
struct extended_ops exops; ExtendedOps exops;
FsThrottle *fst; FsThrottle *fst;
/* fs driver specific data */ /* fs driver specific data */
void *private; void *private;
mode_t fmode; mode_t fmode;
mode_t dmode; mode_t dmode;
} FsContext; };
typedef struct V9fsPath { struct V9fsPath {
uint16_t size; uint16_t size;
char *data; char *data;
} V9fsPath; };
typedef union V9fsFidOpenState V9fsFidOpenState; typedef union V9fsFidOpenState V9fsFidOpenState;
@ -105,9 +103,9 @@ void cred_init(FsCred *);
struct FileOperations struct FileOperations
{ {
int (*parse_opts)(QemuOpts *, struct FsDriverEntry *); int (*parse_opts)(QemuOpts *, FsDriverEntry *, Error **errp);
int (*init)(struct FsContext *); int (*init)(FsContext *, Error **errp);
void (*cleanup)(struct FsContext *); void (*cleanup)(FsContext *);
int (*lstat)(FsContext *, V9fsPath *, struct stat *); int (*lstat)(FsContext *, V9fsPath *, struct stat *);
ssize_t (*readlink)(FsContext *, V9fsPath *, char *, size_t); ssize_t (*readlink)(FsContext *, V9fsPath *, char *, size_t);
int (*chmod)(FsContext *, V9fsPath *, FsCred *); int (*chmod)(FsContext *, V9fsPath *, FsCred *);

View File

@ -37,6 +37,7 @@ int qemu_fsdev_add(QemuOpts *opts)
const char *fsdriver = qemu_opt_get(opts, "fsdriver"); const char *fsdriver = qemu_opt_get(opts, "fsdriver");
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); bool ro = qemu_opt_get_bool(opts, "readonly", 0);
Error *local_err = NULL;
if (!fsdev_id) { if (!fsdev_id) {
error_report("fsdev: No id specified"); 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) {
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->fse.fsdev_id);
g_free(fsle); g_free(fsle);
return -1; return -1;

View File

@ -41,10 +41,10 @@
#define BTRFS_SUPER_MAGIC 0x9123683E #define BTRFS_SUPER_MAGIC 0x9123683E
#endif #endif
struct handle_data { typedef struct HandleData {
int mountfd; int mountfd;
int handle_bytes; int handle_bytes;
}; } HandleData;
static inline int name_to_handle(int dirfd, const char *name, static inline int name_to_handle(int dirfd, const char *name,
struct file_handle *fh, int *mnt_id, int flags) 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) struct stat *stbuf)
{ {
int fd, ret; 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); fd = open_by_handle(data->mountfd, fs_path->data, O_PATH);
if (fd < 0) { if (fd < 0) {
@ -94,7 +94,7 @@ static ssize_t handle_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
char *buf, size_t bufsz) char *buf, size_t bufsz)
{ {
int fd, ret; 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); fd = open_by_handle(data->mountfd, fs_path->data, O_PATH);
if (fd < 0) { if (fd < 0) {
@ -118,7 +118,7 @@ static int handle_closedir(FsContext *ctx, V9fsFidOpenState *fs)
static int handle_open(FsContext *ctx, V9fsPath *fs_path, static int handle_open(FsContext *ctx, V9fsPath *fs_path,
int flags, V9fsFidOpenState *fs) 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); fs->fd = open_by_handle(data->mountfd, fs_path->data, flags);
return fs->fd; 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) static int handle_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
{ {
int fd, ret; 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); fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
if (fd < 0) { if (fd < 0) {
@ -222,7 +222,7 @@ static int handle_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
const char *name, FsCred *credp) const char *name, FsCred *credp)
{ {
int dirfd, ret; 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); dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
if (dirfd < 0) { if (dirfd < 0) {
@ -240,7 +240,7 @@ static int handle_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
const char *name, FsCred *credp) const char *name, FsCred *credp)
{ {
int dirfd, ret; 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); dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
if (dirfd < 0) { if (dirfd < 0) {
@ -272,7 +272,7 @@ static int handle_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
{ {
int ret; int ret;
int dirfd, fd; 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); dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
if (dirfd < 0) { 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) V9fsPath *dir_path, const char *name, FsCred *credp)
{ {
int fd, dirfd, ret; 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); dirfd = open_by_handle(data->mountfd, dir_path->data, O_PATH);
if (dirfd < 0) { if (dirfd < 0) {
@ -322,7 +322,7 @@ static int handle_link(FsContext *ctx, V9fsPath *oldpath,
V9fsPath *dirpath, const char *name) V9fsPath *dirpath, const char *name)
{ {
int oldfd, newdirfd, ret; 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); oldfd = open_by_handle(data->mountfd, oldpath->data, O_PATH);
if (oldfd < 0) { 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) static int handle_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
{ {
int fd, ret; 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); fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK | O_WRONLY);
if (fd < 0) { 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) static int handle_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
{ {
int fd, ret; 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); fd = open_by_handle(data->mountfd, fs_path->data, O_PATH);
if (fd < 0) { if (fd < 0) {
@ -379,7 +379,7 @@ static int handle_utimensat(FsContext *ctx, V9fsPath *fs_path,
{ {
int ret; int ret;
int fd; 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); fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
if (fd < 0) { if (fd < 0) {
@ -418,7 +418,7 @@ static int handle_statfs(FsContext *ctx, V9fsPath *fs_path,
struct statfs *stbuf) struct statfs *stbuf)
{ {
int fd, ret; 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); fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
if (fd < 0) { 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) const char *name, void *value, size_t size)
{ {
int fd, ret; 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); fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
if (fd < 0) { if (fd < 0) {
@ -448,7 +448,7 @@ static ssize_t handle_llistxattr(FsContext *ctx, V9fsPath *fs_path,
void *value, size_t size) void *value, size_t size)
{ {
int fd, ret; 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); fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
if (fd < 0) { 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) void *value, size_t size, int flags)
{ {
int fd, ret; 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); fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
if (fd < 0) { if (fd < 0) {
@ -478,7 +478,7 @@ static int handle_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
const char *name) const char *name)
{ {
int fd, ret; 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); fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
if (fd < 0) { if (fd < 0) {
@ -495,7 +495,7 @@ static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path,
char *buffer; char *buffer;
struct file_handle *fh; struct file_handle *fh;
int dirfd, ret, mnt_id; int dirfd, ret, mnt_id;
struct handle_data *data = (struct handle_data *)ctx->private; HandleData *data = (HandleData *) ctx->private;
/* "." and ".." are not allowed */ /* "." and ".." are not allowed */
if (!strcmp(name, ".") || !strcmp(name, "..")) { if (!strcmp(name, ".") || !strcmp(name, "..")) {
@ -536,7 +536,7 @@ static int handle_renameat(FsContext *ctx, V9fsPath *olddir,
const char *new_name) const char *new_name)
{ {
int olddirfd, newdirfd, ret; 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); olddirfd = open_by_handle(data->mountfd, olddir->data, O_PATH);
if (olddirfd < 0) { if (olddirfd < 0) {
@ -557,7 +557,7 @@ static int handle_unlinkat(FsContext *ctx, V9fsPath *dir,
const char *name, int flags) const char *name, int flags)
{ {
int dirfd, ret; int dirfd, ret;
struct handle_data *data = (struct handle_data *)ctx->private; HandleData *data = (HandleData *) ctx->private;
int rflags; int rflags;
dirfd = open_by_handle(data->mountfd, dir->data, O_PATH); dirfd = open_by_handle(data->mountfd, dir->data, O_PATH);
@ -604,12 +604,12 @@ static int handle_ioc_getversion(FsContext *ctx, V9fsPath *path,
#endif #endif
} }
static int handle_init(FsContext *ctx) static int handle_init(FsContext *ctx, Error **errp)
{ {
int ret, mnt_id; int ret, mnt_id;
struct statfs stbuf; struct statfs stbuf;
struct file_handle fh; 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); data->mountfd = open(ctx->fs_root, O_DIRECTORY);
if (data->mountfd < 0) { if (data->mountfd < 0) {
@ -646,17 +646,19 @@ out:
static void handle_cleanup(FsContext *ctx) static void handle_cleanup(FsContext *ctx)
{ {
struct handle_data *data = ctx->private; HandleData *data = ctx->private;
close(data->mountfd); close(data->mountfd);
g_free(data); 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 *sec_model = qemu_opt_get(opts, "security_model");
const char *path = qemu_opt_get(opts, "path"); const char *path = qemu_opt_get(opts, "path");
warn_report("handle backend is deprecated");
if (sec_model) { if (sec_model) {
error_report("Invalid argument security_model specified with handle fsdriver"); error_report("Invalid argument security_model specified with handle fsdriver");
return -1; return -1;

View File

@ -1400,13 +1400,14 @@ static int local_ioc_getversion(FsContext *ctx, V9fsPath *path,
#endif #endif
} }
static int local_init(FsContext *ctx) static int local_init(FsContext *ctx, Error **errp)
{ {
struct statfs stbuf; struct statfs stbuf;
LocalData *data = g_malloc(sizeof(*data)); LocalData *data = g_malloc(sizeof(*data));
data->mountfd = open(ctx->fs_root, O_DIRECTORY | O_RDONLY); data->mountfd = open(ctx->fs_root, O_DIRECTORY | O_RDONLY);
if (data->mountfd == -1) { if (data->mountfd == -1) {
error_setg_errno(errp, errno, "failed to open '%s'", ctx->fs_root);
goto err; goto err;
} }
@ -1459,16 +1460,21 @@ static void local_cleanup(FsContext *ctx)
g_free(data); 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 *sec_model = qemu_opt_get(opts, "security_model");
const char *path = qemu_opt_get(opts, "path"); const char *path = qemu_opt_get(opts, "path");
Error *err = NULL; Error *local_err = NULL;
if (!sec_model) { if (!sec_model) {
error_report("Security model not specified, local fs needs security model"); error_setg(errp, "security_model property not set");
error_printf("valid options are:" error_append_security_model_hint(errp);
"\tsecurity_model=[passthrough|mapped-xattr|mapped-file|none]\n");
return -1; return -1;
} }
@ -1482,20 +1488,20 @@ static int local_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse)
} else if (!strcmp(sec_model, "mapped-file")) { } else if (!strcmp(sec_model, "mapped-file")) {
fse->export_flags |= V9FS_SM_MAPPED_FILE; fse->export_flags |= V9FS_SM_MAPPED_FILE;
} else { } else {
error_report("Invalid security model %s specified", sec_model); error_setg(errp, "invalid security_model property '%s'", sec_model);
error_printf("valid options are:" error_append_security_model_hint(errp);
"\t[passthrough|mapped-xattr|mapped-file|none]\n");
return -1; return -1;
} }
if (!path) { if (!path) {
error_report("fsdev: No path specified"); error_setg(errp, "path property not set");
return -1; return -1;
} }
fsdev_throttle_parse_opts(opts, &fse->fst, &err); fsdev_throttle_parse_opts(opts, &fse->fst, &local_err);
if (err) { if (local_err) {
error_reportf_err(err, "Throttle configuration is not valid: "); error_propagate(errp, local_err);
error_prepend(errp, "invalid throttle configuration: ");
return -1; 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; qemu_opt_get_number(opts, "dmode", SM_LOCAL_DIR_MODE_BITS) & 0777;
} else { } else {
if (qemu_opt_find(opts, "fmode")) { 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; return -1;
} }
if (qemu_opt_find(opts, "dmode")) { 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; return -1;
} }
} }

View File

@ -1083,25 +1083,25 @@ static int proxy_ioc_getversion(FsContext *fs_ctx, V9fsPath *path,
return err; return err;
} }
static int connect_namedsocket(const char *path) static int connect_namedsocket(const char *path, Error **errp)
{ {
int sockfd, size; int sockfd, size;
struct sockaddr_un helper; struct sockaddr_un helper;
if (strlen(path) >= sizeof(helper.sun_path)) { if (strlen(path) >= sizeof(helper.sun_path)) {
error_report("Socket name too long"); error_setg(errp, "socket name too long");
return -1; return -1;
} }
sockfd = socket(AF_UNIX, SOCK_STREAM, 0); sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sockfd < 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; return -1;
} }
strcpy(helper.sun_path, path); strcpy(helper.sun_path, path);
helper.sun_family = AF_UNIX; helper.sun_family = AF_UNIX;
size = strlen(helper.sun_path) + sizeof(helper.sun_family); size = strlen(helper.sun_path) + sizeof(helper.sun_family);
if (connect(sockfd, (struct sockaddr *)&helper, size) < 0) { 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); close(sockfd);
return -1; return -1;
} }
@ -1111,17 +1111,27 @@ static int connect_namedsocket(const char *path)
return sockfd; 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 *socket = qemu_opt_get(opts, "socket");
const char *sock_fd = qemu_opt_get(opts, "sock_fd"); const char *sock_fd = qemu_opt_get(opts, "sock_fd");
if (!socket && !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; return -1;
} }
if (socket && sock_fd) { 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; return -1;
} }
if (socket) { if (socket) {
@ -1134,17 +1144,17 @@ static int proxy_parse_opts(QemuOpts *opts, struct FsDriverEntry *fs)
return 0; return 0;
} }
static int proxy_init(FsContext *ctx) static int proxy_init(FsContext *ctx, Error **errp)
{ {
V9fsProxy *proxy = g_malloc(sizeof(V9fsProxy)); V9fsProxy *proxy = g_malloc(sizeof(V9fsProxy));
int sock_id; int sock_id;
if (ctx->export_flags & V9FS_PROXY_SOCK_NAME) { if (ctx->export_flags & V9FS_PROXY_SOCK_NAME) {
sock_id = connect_namedsocket(ctx->fs_root); sock_id = connect_namedsocket(ctx->fs_root, errp);
} else { } else {
sock_id = atoi(ctx->fs_root); sock_id = atoi(ctx->fs_root);
if (sock_id < 0) { if (sock_id < 0) {
error_report("Socket descriptor not initialized"); error_setg(errp, "socket descriptor not initialized");
} }
} }
if (sock_id < 0) { if (sock_id < 0) {

View File

@ -514,7 +514,7 @@ static int synth_unlinkat(FsContext *ctx, V9fsPath *dir,
return -1; return -1;
} }
static int synth_init(FsContext *ctx) static int synth_init(FsContext *ctx, Error **errp)
{ {
QLIST_INIT(&synth_root.child); QLIST_INIT(&synth_root.child);
qemu_mutex_init(&synth_mutex); qemu_mutex_init(&synth_mutex);

View File

@ -16,8 +16,7 @@
#include "qemu/xattr.h" #include "qemu/xattr.h"
typedef struct xattr_operations struct XattrOperations {
{
const char *name; const char *name;
ssize_t (*getxattr)(FsContext *ctx, const char *path, ssize_t (*getxattr)(FsContext *ctx, const char *path,
const char *name, void *value, size_t size); const char *name, void *value, size_t size);
@ -27,7 +26,7 @@ typedef struct xattr_operations
void *value, size_t size, int flags); void *value, size_t size, int flags);
int (*removexattr)(FsContext *ctx, int (*removexattr)(FsContext *ctx,
const char *path, const char *name); const char *path, const char *name);
} XattrOperations; };
ssize_t local_getxattr_nofollow(FsContext *ctx, const char *path, ssize_t local_getxattr_nofollow(FsContext *ctx, const char *path,
const char *name, void *value, size_t size); const char *name, void *value, size_t size);

View File

@ -41,7 +41,7 @@ enum {
Oappend = 0x80, 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; ssize_t ret;
va_list ap; va_list ap;
@ -53,7 +53,7 @@ ssize_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
return ret; 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; ssize_t ret;
va_list ap; va_list ap;
@ -99,10 +99,10 @@ static int omode_to_uflags(int8_t mode)
return ret; return ret;
} }
struct dotl_openflag_map { typedef struct DotlOpenflagMap {
int dotl_flag; int dotl_flag;
int open_flag; int open_flag;
}; } DotlOpenflagMap;
static int dotl_to_open_flags(int flags) 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; int oflags = flags & O_ACCMODE;
struct dotl_openflag_map dotl_oflag_map[] = { DotlOpenflagMap dotl_oflag_map[] = {
{ P9_DOTL_CREATE, O_CREAT }, { P9_DOTL_CREATE, O_CREAT },
{ P9_DOTL_EXCL, O_EXCL }, { P9_DOTL_EXCL, O_EXCL },
{ P9_DOTL_NOCTTY , O_NOCTTY }, { P9_DOTL_NOCTTY , O_NOCTTY },
@ -3473,14 +3473,12 @@ void pdu_submit(V9fsPDU *pdu, P9MsgHeader *hdr)
if (pdu->id >= ARRAY_SIZE(pdu_co_handlers) || if (pdu->id >= ARRAY_SIZE(pdu_co_handlers) ||
(pdu_co_handlers[pdu->id] == NULL)) { (pdu_co_handlers[pdu->id] == NULL)) {
handler = v9fs_op_not_supp; handler = v9fs_op_not_supp;
} else if (is_ro_export(&s->ctx) && !is_read_only_op(pdu)) {
handler = v9fs_fs_ro;
} 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;
}
qemu_co_queue_init(&pdu->complete); qemu_co_queue_init(&pdu->complete);
co = qemu_coroutine_create(handler, pdu); co = qemu_coroutine_create(handler, pdu);
qemu_coroutine_enter(co); qemu_coroutine_enter(co);
@ -3544,9 +3542,9 @@ int v9fs_device_realize_common(V9fsState *s, Error **errp)
s->fid_list = NULL; s->fid_list = NULL;
qemu_co_rwlock_init(&s->rename_lock); qemu_co_rwlock_init(&s->rename_lock);
if (s->ops->init(&s->ctx) < 0) { if (s->ops->init(&s->ctx, errp) < 0) {
error_setg(errp, "9pfs Failed to initialize fs-driver with id:%s" error_prepend(errp, "cannot initialize fsdev '%s': ",
" and export path:%s", s->fsconf.fsdev_id, s->ctx.fs_root); s->fsconf.fsdev_id);
goto out; goto out;
} }

View File

@ -94,10 +94,10 @@ enum {
P9_QTFILE = 0x00, P9_QTFILE = 0x00,
}; };
enum p9_proto_version { typedef enum P9ProtoVersion {
V9FS_PROTO_2000U = 0x01, V9FS_PROTO_2000U = 0x01,
V9FS_PROTO_2000L = 0x02, V9FS_PROTO_2000L = 0x02,
}; } P9ProtoVersion;
#define P9_NOTAG UINT16_MAX #define P9_NOTAG UINT16_MAX
#define P9_NOFID UINT32_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 V9fsPDU V9fsPDU;
typedef struct V9fsState V9fsState; typedef struct V9fsState V9fsState;
typedef struct V9fsTransport V9fsTransport;
typedef struct { typedef struct {
uint32_t size_le; uint32_t size_le;
@ -238,10 +239,10 @@ struct V9fsState
FileOperations *ops; FileOperations *ops;
FsContext ctx; FsContext ctx;
char *tag; char *tag;
enum p9_proto_version proto_version; P9ProtoVersion proto_version;
int32_t msize; int32_t msize;
V9fsPDU pdus[MAX_REQ]; V9fsPDU pdus[MAX_REQ];
const struct V9fsTransport *transport; const V9fsTransport *transport;
/* /*
* lock ensuring atomic path update * lock ensuring atomic path update
* on rename. * on rename.
@ -348,8 +349,6 @@ int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath,
int v9fs_device_realize_common(V9fsState *s, Error **errp); int v9fs_device_realize_common(V9fsState *s, Error **errp);
void v9fs_device_unrealize_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); V9fsPDU *pdu_alloc(V9fsState *s);
void pdu_free(V9fsPDU *pdu); void pdu_free(V9fsPDU *pdu);
void pdu_submit(V9fsPDU *pdu, P9MsgHeader *hdr); void pdu_submit(V9fsPDU *pdu, P9MsgHeader *hdr);
@ -367,8 +366,7 @@ struct V9fsTransport {
void (*push_and_notify)(V9fsPDU *pdu); void (*push_and_notify)(V9fsPDU *pdu);
}; };
static inline int v9fs_register_transport(V9fsState *s, static inline int v9fs_register_transport(V9fsState *s, const V9fsTransport *t)
const struct V9fsTransport *t)
{ {
assert(!s->transport); assert(!s->transport);
s->transport = t; s->transport = t;

View File

@ -20,8 +20,6 @@
#include "hw/virtio/virtio-access.h" #include "hw/virtio/virtio-access.h"
#include "qemu/iov.h" #include "qemu/iov.h"
static const struct V9fsTransport virtio_9p_transport;
static void virtio_9p_push_and_notify(V9fsPDU *pdu) static void virtio_9p_push_and_notify(V9fsPDU *pdu)
{ {
V9fsState *s = pdu->s; V9fsState *s = pdu->s;
@ -104,35 +102,6 @@ static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config)
g_free(cfg); 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) static void virtio_9p_reset(VirtIODevice *vdev)
{ {
V9fsVirtioState *v = (V9fsVirtioState *)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; *pniov = elem->out_num;
} }
static const struct V9fsTransport virtio_9p_transport = { static const V9fsTransport virtio_9p_transport = {
.pdu_vmarshal = virtio_pdu_vmarshal, .pdu_vmarshal = virtio_pdu_vmarshal,
.pdu_vunmarshal = virtio_pdu_vunmarshal, .pdu_vunmarshal = virtio_pdu_vunmarshal,
.init_in_iov_from_pdu = virtio_init_in_iov_from_pdu, .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, .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 */ /* virtio-9p device */
static const VMStateDescription vmstate_virtio_9p = { static const VMStateDescription vmstate_virtio_9p = {

View File

@ -233,7 +233,7 @@ static void xen_9pfs_push_and_notify(V9fsPDU *pdu)
qemu_bh_schedule(ring->bh); 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_vmarshal = xen_9pfs_pdu_vmarshal,
.pdu_vunmarshal = xen_9pfs_pdu_vunmarshal, .pdu_vunmarshal = xen_9pfs_pdu_vunmarshal,
.init_in_iov_from_pdu = xen_9pfs_init_in_iov_from_pdu, .init_in_iov_from_pdu = xen_9pfs_init_in_iov_from_pdu,

View File

@ -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 channel subsystems, all devices can be put into the default channel
subsystem image. 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 @section qemu-img command line arguments
@subsection convert -s (since 2.0.0) @subsection convert -s (since 2.0.0)

View File

@ -18,6 +18,8 @@
#include "standard-headers/linux/virtio_pci.h" #include "standard-headers/linux/virtio_pci.h"
#include "hw/9pfs/9p.h" #include "hw/9pfs/9p.h"
#define QVIRTIO_9P_TIMEOUT_US (10 * 1000 * 1000)
static const char mount_tag[] = "qtest"; static const char mount_tag[] = "qtest";
typedef struct { typedef struct {
@ -73,6 +75,9 @@ static QVirtIO9P *qvirtio_9p_pci_start(void)
qvirtio_set_driver(v9p->dev); qvirtio_set_driver(v9p->dev);
v9p->vq = qvirtqueue_setup(v9p->dev, v9p->qs->alloc, 0); v9p->vq = qvirtqueue_setup(v9p->dev, v9p->qs->alloc, 0);
qvirtio_set_driver_ok(v9p->dev);
return v9p; return v9p;
} }
@ -111,6 +116,7 @@ typedef struct {
/* No r_size, it is hardcoded to P9_MAX_SIZE */ /* No r_size, it is hardcoded to P9_MAX_SIZE */
size_t t_off; size_t t_off;
size_t r_off; size_t r_off;
uint32_t free_head;
} P9Req; } P9Req;
static void v9fs_memwrite(P9Req *req, const void *addr, size_t len) 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; 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) static void v9fs_memread(P9Req *req, void *addr, size_t len)
{ {
memread(req->r_msg + req->r_off, addr, 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) static void v9fs_req_send(P9Req *req)
{ {
QVirtIO9P *v9p = req->v9p; QVirtIO9P *v9p = req->v9p;
uint32_t free_head;
req->r_msg = guest_alloc(v9p->qs->alloc, P9_MAX_SIZE); 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_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; req->t_off = 0;
} }
@ -250,19 +251,13 @@ static void v9fs_req_recv(P9Req *req, uint8_t id)
{ {
QVirtIO9P *v9p = req->v9p; QVirtIO9P *v9p = req->v9p;
P9Hdr hdr; P9Hdr hdr;
int i;
for (i = 0; i < 10; i++) { qvirtio_wait_used_elem(v9p->dev, v9p->vq, req->free_head,
qvirtio_wait_queue_isr(v9p->dev, v9p->vq, 1000 * 1000); QVIRTIO_9P_TIMEOUT_US);
v9fs_memread(req, &hdr, 7); v9fs_memread(req, &hdr, 7);
hdr.size = ldl_le_p(&hdr.size); hdr.size = ldl_le_p(&hdr.size);
hdr.tag = lduw_le_p(&hdr.tag); hdr.tag = lduw_le_p(&hdr.tag);
if (hdr.size >= 7) {
break;
}
v9fs_memrewind(req, 7);
}
g_assert_cmpint(hdr.size, >=, 7); g_assert_cmpint(hdr.size, >=, 7);
g_assert_cmpint(hdr.size, <=, P9_MAX_SIZE); g_assert_cmpint(hdr.size, <=, P9_MAX_SIZE);