diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/9pfs/cofile.c | 4 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p-device.c | 25 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p-handle.c | 61 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p-local.c | 36 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p-synth.c | 5 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p.c | 45 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p.h | 5 | ||||
-rw-r--r-- | hw/virtio-pci.c | 2 | ||||
-rw-r--r-- | hw/virtio-pci.h | 1 |
9 files changed, 116 insertions, 68 deletions
diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c index 586b0382f6..b15838c1e6 100644 --- a/hw/9pfs/cofile.c +++ b/hw/9pfs/cofile.c @@ -71,7 +71,7 @@ int v9fs_co_fstat(V9fsPDU *pdu, V9fsFidState *fidp, struct stat *stbuf) } v9fs_co_run_in_worker( { - err = s->ops->fstat(&s->ctx, &fidp->fs, stbuf); + err = s->ops->fstat(&s->ctx, fidp->fid_type, &fidp->fs, stbuf); if (err < 0) { err = -errno; } @@ -192,7 +192,7 @@ int v9fs_co_fsync(V9fsPDU *pdu, V9fsFidState *fidp, int datasync) } v9fs_co_run_in_worker( { - err = s->ops->fsync(&s->ctx, &fidp->fs, datasync); + err = s->ops->fsync(&s->ctx, fidp->fid_type, &fidp->fs, datasync); if (err < 0) { err = -errno; } diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c index bba4c54762..cd343e1d81 100644 --- a/hw/9pfs/virtio-9p-device.c +++ b/hw/9pfs/virtio-9p-device.c @@ -33,13 +33,15 @@ static V9fsState *to_virtio_9p(VirtIODevice *vdev) static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config) { + int len; struct virtio_9p_config *cfg; V9fsState *s = to_virtio_9p(vdev); - cfg = g_malloc0(sizeof(struct virtio_9p_config) + - s->tag_len); - stw_raw(&cfg->tag_len, s->tag_len); - memcpy(cfg->tag, s->tag, s->tag_len); + len = strlen(s->tag); + cfg = g_malloc0(sizeof(struct virtio_9p_config) + len); + stw_raw(&cfg->tag_len, len); + /* We don't copy the terminating null to config space */ + memcpy(cfg->tag, s->tag, len); memcpy(config, cfg, s->config_size); g_free(cfg); } @@ -96,20 +98,18 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf) } len = strlen(conf->tag); - if (len > MAX_TAG_LEN) { + if (len > MAX_TAG_LEN - 1) { fprintf(stderr, "mount tag '%s' (%d bytes) is longer than " - "maximum (%d bytes)", conf->tag, len, MAX_TAG_LEN); + "maximum (%d bytes)", conf->tag, len, MAX_TAG_LEN - 1); exit(1); } - /* s->tag is non-NULL terminated string */ - s->tag = g_malloc(len); - memcpy(s->tag, conf->tag, len); - s->tag_len = len; + + s->tag = strdup(conf->tag); s->ctx.uid = -1; s->ops = fse->ops; s->vdev.get_features = virtio_9p_get_features; - s->config_size = sizeof(struct virtio_9p_config) + s->tag_len; + s->config_size = sizeof(struct virtio_9p_config) + len; s->vdev.get_config = virtio_9p_get_config; s->fid_list = NULL; qemu_co_rwlock_init(&s->rename_lock); @@ -176,7 +176,8 @@ static PCIDeviceInfo virtio_9p_info = { DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag), DEFINE_PROP_STRING("fsdev", VirtIOPCIProxy, fsconf.fsdev_id), DEFINE_PROP_END_OF_LIST(), - } + }, + .qdev.reset = virtio_pci_reset, }; static void virtio_9p_register_devices(void) diff --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/virtio-9p-handle.c index 7644ae5ab9..f97d8984bd 100644 --- a/hw/9pfs/virtio-9p-handle.c +++ b/hw/9pfs/virtio-9p-handle.c @@ -45,7 +45,6 @@ struct handle_data { int handle_bytes; }; -#ifdef CONFIG_OPEN_BY_HANDLE static inline int name_to_handle(int dirfd, const char *name, struct file_handle *fh, int *mnt_id, int flags) { @@ -56,38 +55,6 @@ static inline int open_by_handle(int mountfd, const char *fh, int flags) { return open_by_handle_at(mountfd, (struct file_handle *)fh, flags); } -#else - -struct rpl_file_handle { - unsigned int handle_bytes; - int handle_type; - unsigned char handle[0]; -}; -#define file_handle rpl_file_handle - -#ifndef AT_REMOVEDIR -#define AT_REMOVEDIR 0x200 -#endif -#ifndef AT_EMPTY_PATH -#define AT_EMPTY_PATH 0x1000 /* Allow empty relative pathname */ -#endif -#ifndef O_PATH -#define O_PATH 010000000 -#endif - -static inline int name_to_handle(int dirfd, const char *name, - struct file_handle *fh, int *mnt_id, int flags) -{ - errno = ENOSYS; - return -1; -} - -static inline int open_by_handle(int mountfd, const char *fh, int flags) -{ - errno = ENOSYS; - return -1; -} -#endif static int handle_update_file_cred(int dirfd, const char *name, FsCred *credp) { @@ -288,10 +255,17 @@ static int handle_mkdir(FsContext *fs_ctx, V9fsPath *dir_path, return ret; } -static int handle_fstat(FsContext *fs_ctx, V9fsFidOpenState *fs, - struct stat *stbuf) +static int handle_fstat(FsContext *fs_ctx, int fid_type, + V9fsFidOpenState *fs, struct stat *stbuf) { - return fstat(fs->fd, stbuf); + int fd; + + if (fid_type == P9_FID_DIR) { + fd = dirfd(fs->dir); + } else { + fd = fs->fd; + } + return fstat(fd, stbuf); } static int handle_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name, @@ -428,12 +402,21 @@ static int handle_remove(FsContext *ctx, const char *path) return -1; } -static int handle_fsync(FsContext *ctx, V9fsFidOpenState *fs, int datasync) +static int handle_fsync(FsContext *ctx, int fid_type, + V9fsFidOpenState *fs, int datasync) { + int fd; + + if (fid_type == P9_FID_DIR) { + fd = dirfd(fs->dir); + } else { + fd = fs->fd; + } + if (datasync) { - return qemu_fdatasync(fs->fd); + return qemu_fdatasync(fd); } else { - return fsync(fs->fd); + return fsync(fd); } } diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c index 99ef0cd333..371a94dfff 100644 --- a/hw/9pfs/virtio-9p-local.c +++ b/hw/9pfs/virtio-9p-local.c @@ -366,11 +366,18 @@ out: return err; } -static int local_fstat(FsContext *fs_ctx, +static int local_fstat(FsContext *fs_ctx, int fid_type, V9fsFidOpenState *fs, struct stat *stbuf) { - int err; - err = fstat(fs->fd, stbuf); + int err, fd; + + if (fid_type == P9_FID_DIR) { + fd = dirfd(fs->dir); + } else { + fd = fs->fd; + } + + err = fstat(fd, stbuf); if (err) { return err; } @@ -381,19 +388,19 @@ static int local_fstat(FsContext *fs_ctx, mode_t tmp_mode; dev_t tmp_dev; - if (fgetxattr(fs->fd, "user.virtfs.uid", + if (fgetxattr(fd, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) { stbuf->st_uid = tmp_uid; } - if (fgetxattr(fs->fd, "user.virtfs.gid", + if (fgetxattr(fd, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) { stbuf->st_gid = tmp_gid; } - if (fgetxattr(fs->fd, "user.virtfs.mode", + if (fgetxattr(fd, "user.virtfs.mode", &tmp_mode, sizeof(mode_t)) > 0) { stbuf->st_mode = tmp_mode; } - if (fgetxattr(fs->fd, "user.virtfs.rdev", + if (fgetxattr(fd, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) { stbuf->st_rdev = tmp_dev; } @@ -592,12 +599,21 @@ static int local_remove(FsContext *ctx, const char *path) return remove(rpath(ctx, path, buffer)); } -static int local_fsync(FsContext *ctx, V9fsFidOpenState *fs, int datasync) +static int local_fsync(FsContext *ctx, int fid_type, + V9fsFidOpenState *fs, int datasync) { + int fd; + + if (fid_type == P9_FID_DIR) { + fd = dirfd(fs->dir); + } else { + fd = fs->fd; + } + if (datasync) { - return qemu_fdatasync(fs->fd); + return qemu_fdatasync(fd); } else { - return fsync(fs->fd); + return fsync(fd); } } diff --git a/hw/9pfs/virtio-9p-synth.c b/hw/9pfs/virtio-9p-synth.c index f573616363..92e0b09d38 100644 --- a/hw/9pfs/virtio-9p-synth.c +++ b/hw/9pfs/virtio-9p-synth.c @@ -166,7 +166,7 @@ static int v9fs_synth_lstat(FsContext *fs_ctx, return 0; } -static int v9fs_synth_fstat(FsContext *fs_ctx, +static int v9fs_synth_fstat(FsContext *fs_ctx, int fid_type, V9fsFidOpenState *fs, struct stat *stbuf) { V9fsSynthOpenState *synth_open = fs->private; @@ -414,7 +414,8 @@ static int v9fs_synth_remove(FsContext *ctx, const char *path) return -1; } -static int v9fs_synth_fsync(FsContext *ctx, V9fsFidOpenState *fs, int datasync) +static int v9fs_synth_fsync(FsContext *ctx, int fid_type, + V9fsFidOpenState *fs, int datasync) { errno = ENOSYS; return 0; diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index 1b2fc5dfb6..dd432091ff 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -23,6 +23,7 @@ #include "virtio-9p-xattr.h" #include "virtio-9p-coth.h" #include "trace.h" +#include "migration.h" int open_fd_hw; int total_open_fd; @@ -373,6 +374,19 @@ static void put_fid(V9fsPDU *pdu, V9fsFidState *fidp) * Don't free the fid if it is in reclaim list */ if (!fidp->ref && fidp->clunked) { + if (fidp->fid == pdu->s->root_fid) { + /* + * if the clunked fid is root fid then we + * have unmounted the fs on the client side. + * delete the migration blocker. Ideally, this + * should be hooked to transport close notification + */ + if (pdu->s->migration_blocker) { + migrate_del_blocker(pdu->s->migration_blocker); + error_free(pdu->s->migration_blocker); + pdu->s->migration_blocker = NULL; + } + } free_fid(pdu, fidp); } } @@ -509,6 +523,30 @@ static int v9fs_mark_fids_unreclaim(V9fsPDU *pdu, V9fsPath *path) return 0; } +static void virtfs_reset(V9fsPDU *pdu) +{ + V9fsState *s = pdu->s; + V9fsFidState *fidp = NULL; + + /* Free all fids */ + while (s->fid_list) { + fidp = s->fid_list; + s->fid_list = fidp->next; + + if (fidp->ref) { + fidp->clunked = 1; + } else { + free_fid(pdu, fidp); + } + } + if (fidp) { + /* One or more unclunked fids found... */ + error_report("9pfs:%s: One or more uncluncked fids " + "found during reset", __func__); + } + return; +} + #define P9_QID_TYPE_DIR 0x80 #define P9_QID_TYPE_SYMLINK 0x02 @@ -1182,6 +1220,8 @@ static void v9fs_version(void *opaque) pdu_unmarshal(pdu, offset, "ds", &s->msize, &version); trace_v9fs_version(pdu->tag, pdu->id, s->msize, version.data); + virtfs_reset(pdu); + if (!strcmp(version.data, "9P2000.u")) { s->proto_version = V9FS_PROTO_2000U; } else if (!strcmp(version.data, "9P2000.L")) { @@ -1235,6 +1275,11 @@ static void v9fs_attach(void *opaque) err = offset; trace_v9fs_attach_return(pdu->tag, pdu->id, qid.type, qid.version, qid.path); + s->root_fid = fid; + /* disable migration */ + error_set(&s->migration_blocker, QERR_VIRTFS_FEATURE_BLOCKS_MIGRATION, + s->ctx.fs_root, s->tag); + migrate_add_blocker(s->migration_blocker); out: put_fid(pdu, fidp); out_nofid: diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h index 7f883563d6..8b612da529 100644 --- a/hw/9pfs/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -246,8 +246,7 @@ typedef struct V9fsState V9fsFidState *fid_list; FileOperations *ops; FsContext ctx; - uint16_t tag_len; - uint8_t *tag; + char *tag; size_t config_size; enum p9_proto_version proto_version; int32_t msize; @@ -256,6 +255,8 @@ typedef struct V9fsState * on rename. */ CoRwlock rename_lock; + int32_t root_fid; + Error *migration_blocker; } V9fsState; typedef struct V9fsStatState { diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 64c6a9414f..c665f5c94b 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -266,7 +266,7 @@ static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy) proxy->ioeventfd_started = false; } -static void virtio_pci_reset(DeviceState *d) +void virtio_pci_reset(DeviceState *d) { VirtIOPCIProxy *proxy = container_of(d, VirtIOPCIProxy, pci_dev.qdev); virtio_pci_stop_ioeventfd(proxy); diff --git a/hw/virtio-pci.h b/hw/virtio-pci.h index f8404de92b..344c22b68f 100644 --- a/hw/virtio-pci.h +++ b/hw/virtio-pci.h @@ -45,6 +45,7 @@ typedef struct { } VirtIOPCIProxy; void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev); +void virtio_pci_reset(DeviceState *d); /* Virtio ABI version, if we increment this, we break the guest driver. */ #define VIRTIO_PCI_ABI_VERSION 0 |