diff options
Diffstat (limited to 'hw/9pfs')
| -rw-r--r-- | hw/9pfs/codir.c | 6 | ||||
| -rw-r--r-- | hw/9pfs/cofile.c | 4 | ||||
| -rw-r--r-- | hw/9pfs/virtio-9p-coth.h | 2 | ||||
| -rw-r--r-- | hw/9pfs/virtio-9p-device.c | 25 | ||||
| -rw-r--r-- | hw/9pfs/virtio-9p-handle.c | 65 | ||||
| -rw-r--r-- | hw/9pfs/virtio-9p-local.c | 50 | ||||
| -rw-r--r-- | hw/9pfs/virtio-9p-synth.c | 5 | ||||
| -rw-r--r-- | hw/9pfs/virtio-9p.c | 49 | ||||
| -rw-r--r-- | hw/9pfs/virtio-9p.h | 5 |
9 files changed, 133 insertions, 78 deletions
diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c index 9b6d47d91d..3d188284ba 100644 --- a/hw/9pfs/codir.c +++ b/hw/9pfs/codir.c @@ -90,7 +90,7 @@ int v9fs_co_mkdir(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, V9fsState *s = pdu->s; if (v9fs_request_cancelled(pdu)) { - return -EINTR;; + return -EINTR; } cred_init(&cred); cred.fc_mode = mode; @@ -124,7 +124,7 @@ int v9fs_co_opendir(V9fsPDU *pdu, V9fsFidState *fidp) V9fsState *s = pdu->s; if (v9fs_request_cancelled(pdu)) { - return -EINTR;; + return -EINTR; } v9fs_path_read_lock(s); v9fs_co_run_in_worker( @@ -152,7 +152,7 @@ int v9fs_co_closedir(V9fsPDU *pdu, V9fsFidOpenState *fs) V9fsState *s = pdu->s; if (v9fs_request_cancelled(pdu)) { - return -EINTR;; + return -EINTR; } v9fs_co_run_in_worker( { 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-coth.h b/hw/9pfs/virtio-9p-coth.h index c4b74b0221..c31c96578b 100644 --- a/hw/9pfs/virtio-9p-coth.h +++ b/hw/9pfs/virtio-9p-coth.h @@ -44,7 +44,7 @@ typedef struct V9fsThPool { qemu_coroutine_self()); \ qemu_bh_schedule(co_bh); \ /* \ - * yeild in qemu thread and re-enter back \ + * yield in qemu thread and re-enter back \ * in glib worker thread \ */ \ qemu_coroutine_yield(); \ 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..b556e39702 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,43 +55,11 @@ 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) { int fd, ret; - fd = openat(dirfd, name, O_NONBLOCK | O_NOFOLLOW);; + fd = openat(dirfd, name, O_NONBLOCK | O_NOFOLLOW); if (fd < 0) { return fd; } @@ -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); } } @@ -537,7 +520,7 @@ static int handle_name_to_path(FsContext *ctx, V9fsPath *dir_path, } fh = g_malloc(sizeof(struct file_handle) + data->handle_bytes); fh->handle_bytes = data->handle_bytes; - /* add a "./" at the begining of the path */ + /* add a "./" at the beginning of the path */ snprintf(buffer, PATH_MAX, "./%s", name); /* flag = 0 imply don't follow symlink */ ret = name_to_handle(dirfd, buffer, fh, &mnt_id, 0); diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c index 7f1c0894de..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; } @@ -583,8 +590,7 @@ static int local_utimensat(FsContext *s, V9fsPath *fs_path, char buffer[PATH_MAX]; char *path = fs_path->data; - return qemu_utimensat(AT_FDCWD, rpath(s, path, buffer), buf, - AT_SYMLINK_NOFOLLOW); + return qemu_utimens(rpath(s, path, buffer), buf); } static int local_remove(FsContext *ctx, const char *path) @@ -593,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); } } @@ -694,6 +709,7 @@ static int local_ioc_getversion(FsContext *ctx, V9fsPath *path, mode_t st_mode, uint64_t *st_gen) { int err; +#ifdef FS_IOC_GETVERSION V9fsFidOpenState fid_open; /* @@ -709,15 +725,22 @@ static int local_ioc_getversion(FsContext *ctx, V9fsPath *path, } err = ioctl(fid_open.fd, FS_IOC_GETVERSION, st_gen); local_close(ctx, &fid_open); +#else + err = -ENOTTY; +#endif return err; } static int local_init(FsContext *ctx) { - int err; + int err = 0; struct statfs stbuf; ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT; +#ifdef FS_IOC_GETVERSION + /* + * use ioc_getversion only if the iocl is definied + */ err = statfs(ctx->fs_root, &stbuf); if (!err) { switch (stbuf.f_type) { @@ -729,6 +752,7 @@ static int local_init(FsContext *ctx) break; } } +#endif return err; } 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..36a862f1f1 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: @@ -1447,7 +1492,7 @@ static void v9fs_walk(void *opaque) int32_t fid, newfid; V9fsString *wnames = NULL; V9fsFidState *fidp; - V9fsFidState *newfidp = NULL;; + V9fsFidState *newfidp = NULL; V9fsPDU *pdu = opaque; V9fsState *s = pdu->s; @@ -2353,7 +2398,7 @@ static void v9fs_link(void *opaque) V9fsState *s = pdu->s; int32_t dfid, oldfid; V9fsFidState *dfidp, *oldfidp; - V9fsString name;; + V9fsString name; size_t offset = 7; int err = 0; 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 { |