diff options
author | Sooyoung Ha <yoosah.ha@samsung.com> | 2016-12-20 16:41:29 +0900 |
---|---|---|
committer | Sooyoung Ha <yoosah.ha@samsung.com> | 2016-12-26 18:44:34 +0900 |
commit | c9e4166a48698f3668fb868e6de6cf3502b1cdf6 (patch) | |
tree | 23a8cc75c2e0df1d529f4536c91030d51d29fbac | |
parent | 8935c7723c92aed73c2d7dfe2435829eade30246 (diff) | |
download | qemu-c9e4166a48698f3668fb868e6de6cf3502b1cdf6.tar.gz qemu-c9e4166a48698f3668fb868e6de6cf3502b1cdf6.tar.bz2 qemu-c9e4166a48698f3668fb868e6de6cf3502b1cdf6.zip |
9pfs: enable 9pfs on Windows and Macos for 2.8
I modify the maru defined codes of 9pfs for applying qemu 2.8 upgrade.
Change-Id: I6746a73de8f66b6ca1940c09a001d6ee6c21562a
Signed-off-by: Sooyoung Ha <yoosah.ha@samsung.com>
-rwxr-xr-x | configure | 2 | ||||
-rw-r--r-- | hw/9pfs/9p-local-maru.c | 11 | ||||
-rw-r--r-- | hw/9pfs/9p-maru.c | 308 |
3 files changed, 191 insertions, 130 deletions
@@ -1916,7 +1916,6 @@ fi # avx2 optimization requirement check cat > $TMPC << EOF -#ifndef __clang__ #pragma GCC push_options #pragma GCC target("avx2") #include <cpuid.h> @@ -1926,7 +1925,6 @@ static int bar(void *a) { return _mm256_testz_si256(x, x); } int main(int argc, char *argv[]) { return bar(argv[0]); } -#endif //__clang__ EOF if compile_object "" ; then avx2_opt="yes" diff --git a/hw/9pfs/9p-local-maru.c b/hw/9pfs/9p-local-maru.c index 7605f1dd13..cac8784dda 100644 --- a/hw/9pfs/9p-local-maru.c +++ b/hw/9pfs/9p-local-maru.c @@ -587,6 +587,7 @@ again: } entry->d_type = DT_UNKNOWN; } + #else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { if (!strcmp(entry->d_name, VIRTFS_META_DIR)) { @@ -1558,20 +1559,16 @@ static int local_name_to_path(FsContext *ctx, V9fsPath *dir_path, LOG_TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); if (dir_path) { #ifndef CONFIG_WIN32 - v9fs_string_sprintf((V9fsString *)target, "%s/%s", - dir_path->data, name); + v9fs_path_sprintf(target, "%s/%s", dir_path->data, name); #else - v9fs_string_sprintf((V9fsString *)target, "%s\\%s", - dir_path->data, name); + v9fs_path_sprintf(target, "%s\\%s", dir_path->data, name); while((target->data)[strlen(target->data)-1] == '\\'){ (target->data)[strlen(target->data)-1] = '\0'; } #endif } else { - v9fs_string_sprintf((V9fsString *)target, "%s", name); + v9fs_path_sprintf(target, "%s", name); } - /* Bump the size for including terminating NULL */ - target->size++; return 0; } diff --git a/hw/9pfs/9p-maru.c b/hw/9pfs/9p-maru.c index ebe4987d73..20d0d07a46 100644 --- a/hw/9pfs/9p-maru.c +++ b/hw/9pfs/9p-maru.c @@ -29,6 +29,7 @@ */ #include "qemu/osdep.h" +#include <glib/gprintf.h> #include "hw/virtio/virtio.h" #include "qapi/error.h" #include "qemu/error-report.h" @@ -58,6 +59,9 @@ extern uint64_t hostBytesPerSector; #ifdef CONFIG_DARWIN #define O_DIRECT 040000 /* Direct disk access */ #define O_NOATIME 01000000 /* Do not set atime */ +#ifndef XATTR_SIZE_MAX +#define XATTR_SIZE_MAX 65536 +#endif #endif #include "../../tizen/src/debug_ch.h" @@ -218,6 +222,20 @@ void v9fs_path_free(V9fsPath *path) path->size = 0; } + +void GCC_FMT_ATTR(2, 3) +v9fs_path_sprintf(V9fsPath *path, const char *fmt, ...) +{ + va_list ap; + + v9fs_path_free(path); + + va_start(ap, fmt); + /* Bump the size for including terminating NULL */ + path->size = g_vasprintf(&path->data, fmt, ap) + 1; + va_end(ap); +} + void v9fs_path_copy(V9fsPath *lhs, V9fsPath *rhs) { v9fs_path_free(lhs); @@ -265,7 +283,7 @@ static size_t v9fs_string_size(V9fsString *str) /* * returns 0 if fid got re-opened, 1 if not, < 0 on error */ -static int v9fs_reopen_fid(V9fsPDU *pdu, V9fsFidState *f) +static int coroutine_fn v9fs_reopen_fid(V9fsPDU *pdu, V9fsFidState *f) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); int err = 1; @@ -285,7 +303,7 @@ static int v9fs_reopen_fid(V9fsPDU *pdu, V9fsFidState *f) return err; } -static V9fsFidState *get_fid(V9fsPDU *pdu, int32_t fid) +static V9fsFidState *coroutine_fn get_fid(V9fsPDU *pdu, int32_t fid) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); int err; @@ -355,12 +373,12 @@ static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid) } #ifndef CONFIG_WIN32 -static int v9fs_xattr_fid_clunk(V9fsPDU *pdu, V9fsFidState *fidp) +static int coroutine_fn v9fs_xattr_fid_clunk(V9fsPDU *pdu, V9fsFidState *fidp) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); int retval = 0; - if (fidp->fs.xattr.copied_len == -1) { + if (fidp->fs.xattr.xattrwalk_fid) { /* getxattr/listxattr fid */ goto free_value; } @@ -389,7 +407,7 @@ free_value: } #endif -static int free_fid(V9fsPDU *pdu, V9fsFidState *fidp) +static int coroutine_fn free_fid(V9fsPDU *pdu, V9fsFidState *fidp) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); int retval = 0; @@ -415,7 +433,7 @@ static int free_fid(V9fsPDU *pdu, V9fsFidState *fidp) return retval; } -static int put_fid(V9fsPDU *pdu, V9fsFidState *fidp) +static int coroutine_fn put_fid(V9fsPDU *pdu, V9fsFidState *fidp) { BUG_ON(!fidp->ref); fidp->ref--; @@ -459,7 +477,7 @@ static V9fsFidState *clunk_fid(V9fsState *s, int32_t fid) return fidp; } -void v9fs_reclaim_fd(V9fsPDU *pdu) +void coroutine_fn v9fs_reclaim_fd(V9fsPDU *pdu) { int reclaim_count = 0; V9fsState *s = pdu->s; @@ -540,7 +558,7 @@ void v9fs_reclaim_fd(V9fsPDU *pdu) } } -static int v9fs_mark_fids_unreclaim(V9fsPDU *pdu, V9fsPath *path) +static int coroutine_fn v9fs_mark_fids_unreclaim(V9fsPDU *pdu, V9fsPath *path) { TRACE("[%d][ >> %s]\n", __LINE__, __func__); int err; @@ -574,11 +592,11 @@ static int v9fs_mark_fids_unreclaim(V9fsPDU *pdu, V9fsPath *path) return 0; } -static void virtfs_reset(V9fsPDU *pdu) +static void coroutine_fn virtfs_reset(V9fsPDU *pdu) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); V9fsState *s = pdu->s; - V9fsFidState *fidp = NULL; + V9fsFidState *fidp; /* Free all fids */ while (s->fid_list) { @@ -591,11 +609,6 @@ static void virtfs_reset(V9fsPDU *pdu) 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__); - } } #define P9_QID_TYPE_DIR 0x80 @@ -645,7 +658,8 @@ static void stat_to_qid(const struct stat *stbuf, V9fsQID *qidp) } } -static int fid_to_qid(V9fsPDU *pdu, V9fsFidState *fidp, V9fsQID *qidp) +static int coroutine_fn fid_to_qid(V9fsPDU *pdu, V9fsFidState *fidp, + V9fsQID *qidp) { TRACE("[%d][ >> %s]\n", __LINE__, __func__); struct stat stbuf; @@ -673,17 +687,11 @@ V9fsPDU *pdu_alloc(V9fsState *s) void pdu_free(V9fsPDU *pdu) { - if (pdu) { - V9fsState *s = pdu->s; - /* - * Cancelled pdu are added back to the freelist - * by flush request . - */ - if (!pdu->cancelled) { - QLIST_REMOVE(pdu, next); - QLIST_INSERT_HEAD(&s->free_list, pdu, next); - } - } + V9fsState *s = pdu->s; + + g_assert(!pdu->cancelled); + QLIST_REMOVE(pdu, next); + QLIST_INSERT_HEAD(&s->free_list, pdu, next); } /* @@ -691,7 +699,7 @@ void pdu_free(V9fsPDU *pdu) * because we always expect to have enough space to encode * error details */ -static void pdu_complete(V9fsPDU *pdu, ssize_t len) +static void coroutine_fn pdu_complete(V9fsPDU *pdu, ssize_t len) { int8_t id = pdu->id + 1; /* Response */ V9fsState *s = pdu->s; @@ -729,9 +737,9 @@ static void pdu_complete(V9fsPDU *pdu, ssize_t len) pdu_push_and_notify(pdu); /* Now wakeup anybody waiting in flush for this request */ - qemu_co_queue_next(&pdu->complete); - - pdu_free(pdu); + if (!qemu_co_queue_next(&pdu->complete)) { + pdu_free(pdu); + } } #ifndef CONFIG_WIN32 @@ -863,9 +871,9 @@ static uint32_t stat_to_v9mode(const struct stat *stbuf) return mode; } -static int stat_to_v9stat(V9fsPDU *pdu, V9fsPath *name, - const struct stat *stbuf, - V9fsStat *v9stat) +static int coroutine_fn stat_to_v9stat(V9fsPDU *pdu, V9fsPath *name, + const struct stat *stbuf, + V9fsStat *v9stat) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); int err; @@ -879,15 +887,15 @@ static int stat_to_v9stat(V9fsPDU *pdu, V9fsPath *name, v9stat->mtime = stbuf->st_mtime; v9stat->length = stbuf->st_size; - v9fs_string_null(&v9stat->uid); - v9fs_string_null(&v9stat->gid); - v9fs_string_null(&v9stat->muid); + v9fs_string_free(&v9stat->uid); + v9fs_string_free(&v9stat->gid); + v9fs_string_free(&v9stat->muid); v9stat->n_uid = stbuf->st_uid; v9stat->n_gid = stbuf->st_gid; v9stat->n_muid = 0; - v9fs_string_null(&v9stat->extension); + v9fs_string_free(&v9stat->extension); if (v9stat->mode & P9_STAT_MODE_SYMLINK) { err = v9fs_co_readlink(pdu, name, &v9stat->extension); @@ -1011,10 +1019,8 @@ static void v9fs_fix_path(V9fsPath *dst, V9fsPath *src, int len) V9fsPath str; v9fs_path_init(&str); v9fs_path_copy(&str, dst); - v9fs_string_sprintf((V9fsString *)dst, "%s%s", src->data, str.data+len); + v9fs_path_sprintf(dst, "%s%s", src->data, str.data + len); v9fs_path_free(&str); - /* +1 to include terminating NULL */ - dst->size++; } static inline bool is_ro_export(FsContext *ctx) @@ -1022,7 +1028,7 @@ static inline bool is_ro_export(FsContext *ctx) return ctx->export_flags & V9FS_RDONLY; } -static void v9fs_version(void *opaque) +static void coroutine_fn v9fs_version(void *opaque) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); ssize_t err; @@ -1061,7 +1067,7 @@ out: v9fs_string_free(&version); } -static void v9fs_attach(void *opaque) +static void coroutine_fn v9fs_attach(void *opaque) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); V9fsPDU *pdu = opaque; @@ -1132,7 +1138,7 @@ out_nofid: v9fs_string_free(&aname); } -static void v9fs_stat(void *opaque) +static void coroutine_fn v9fs_stat(void *opaque) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); int32_t fid; @@ -1177,7 +1183,7 @@ out_nofid: pdu_complete(pdu, err); } -static void v9fs_getattr(void *opaque) +static void coroutine_fn v9fs_getattr(void *opaque) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); int32_t fid; @@ -1254,7 +1260,7 @@ out_nofid: #define P9_ATTR_MASK 127 -static void v9fs_setattr(void *opaque) +static void coroutine_fn v9fs_setattr(void *opaque) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); int err = 0; @@ -1387,7 +1393,7 @@ static bool not_same_qid(const V9fsQID *qid1, const V9fsQID *qid2) qid1->path != qid2->path; } -static void v9fs_walk(void *opaque) +static void coroutine_fn v9fs_walk(void *opaque) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); int name_idx; @@ -1442,13 +1448,14 @@ static void v9fs_walk(void *opaque) goto out_nofid; } + v9fs_path_init(&dpath); + v9fs_path_init(&path); + err = fid_to_qid(pdu, fidp, &qid); if (err < 0) { goto out; } - v9fs_path_init(&dpath); - v9fs_path_init(&path); /* * Both dpath and path initially poin to fidp. * Needed to handle request with nwnames == 0 @@ -1475,7 +1482,10 @@ static void v9fs_walk(void *opaque) memcpy(&qids[name_idx], &qid, sizeof(qid)); } if (fid == newfid) { - BUG_ON(fidp->fid_type != P9_FID_NONE); + if (fidp->fid_type != P9_FID_NONE) { + err = -EINVAL; + goto out; + } WARN("[%d][ >> %s]\n", __LINE__, __func__); v9fs_path_copy(&fidp->path, &path); } else { @@ -1508,7 +1518,7 @@ out_nofid: } } -static int32_t get_iounit(V9fsPDU *pdu, V9fsPath *path) +static int32_t coroutine_fn get_iounit(V9fsPDU *pdu, V9fsPath *path) { struct statfs stbuf; int32_t iounit = 0; @@ -1528,7 +1538,7 @@ static int32_t get_iounit(V9fsPDU *pdu, V9fsPath *path) return iounit; } -static void v9fs_open(void *opaque) +static void coroutine_fn v9fs_open(void *opaque) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); int flags; @@ -1562,7 +1572,11 @@ static void v9fs_open(void *opaque) err = -ENOENT; goto out_nofid; } - BUG_ON(fidp->fid_type != P9_FID_NONE); + if (fidp->fid_type != P9_FID_NONE) { + ERR("[%d][ >> %s]\n", __LINE__, __func__); + err = -EINVAL; + goto out; + } err = v9fs_co_lstat(pdu, &fidp->path, &stbuf); if (err < 0) { @@ -1627,7 +1641,7 @@ out_nofid: pdu_complete(pdu, err); } -static void v9fs_lcreate(void *opaque) +static void coroutine_fn v9fs_lcreate(void *opaque) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); int32_t dfid, flags, mode; @@ -1732,7 +1746,7 @@ out_nofid: pdu_complete(pdu, err); } -static void v9fs_clunk(void *opaque) +static void coroutine_fn v9fs_clunk(void *opaque) { int err; int32_t fid; @@ -1771,20 +1785,17 @@ static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, { ssize_t err; size_t offset = 7; - int read_count; - int64_t xattr_len; + uint64_t read_count; V9fsVirtioState *v = container_of(s, V9fsVirtioState, state); VirtQueueElement *elem = v->elems[pdu->idx]; - xattr_len = fidp->fs.xattr.len; - read_count = xattr_len - off; + if (fidp->fs.xattr.len < off) { + read_count = 0; + } else { + read_count = fidp->fs.xattr.len - off; + } if (read_count > max_count) { read_count = max_count; - } else if (read_count < 0) { - /* - * read beyond XATTR value - */ - read_count = 0; } err = pdu_marshal(pdu, offset, "d", read_count); if (err < 0) { @@ -1803,8 +1814,9 @@ static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, } #endif -static int v9fs_do_readdir_with_stat(V9fsPDU *pdu, - V9fsFidState *fidp, uint32_t max_count) +static int coroutine_fn v9fs_do_readdir_with_stat(V9fsPDU *pdu, + V9fsFidState *fidp, + uint32_t max_count) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); V9fsPath path; @@ -1903,7 +1915,7 @@ static void v9fs_init_qiov_from_pdu(QEMUIOVector *qiov, V9fsPDU *pdu, qemu_iovec_concat(qiov, &elem, skip, size); } -static void v9fs_read(void *opaque) +static void coroutine_fn v9fs_read(void *opaque) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); int32_t fid; @@ -1973,15 +1985,16 @@ static void v9fs_read(void *opaque) /* IO error return the error */ ERR("[%d][ >> %s]\n", __LINE__, __func__); err = len; - goto out; + goto out_free_iovec; } } while (count < max_count && len > 0); err = pdu_marshal(pdu, offset, "d", count); if (err < 0) { ERR("[%d][ >> %s]\n", __LINE__, __func__); - goto out; + goto out_free_iovec; } err += offset + count; +out_free_iovec: qemu_iovec_destroy(&qiov); qemu_iovec_destroy(&qiov_full); #ifndef CONFIG_WIN32 @@ -2008,8 +2021,8 @@ static size_t v9fs_readdir_data_size(V9fsString *name) return 24 + v9fs_string_size(name); } -static int v9fs_do_readdir(V9fsPDU *pdu, - V9fsFidState *fidp, int32_t max_count) +static int coroutine_fn v9fs_do_readdir(V9fsPDU *pdu, V9fsFidState *fidp, + int32_t max_count) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); size_t size; @@ -2034,7 +2047,6 @@ static int v9fs_do_readdir(V9fsPDU *pdu, err = v9fs_co_readdir(pdu, fidp, &dent); if (err || !dent) { - ERR("[%d][ >> %s]\n", __LINE__, __func__); break; } v9fs_string_init(&name); @@ -2100,7 +2112,7 @@ static int v9fs_do_readdir(V9fsPDU *pdu, return count; } -static void v9fs_readdir(void *opaque) +static void coroutine_fn v9fs_readdir(void *opaque) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); int32_t fid; @@ -2162,23 +2174,18 @@ static int v9fs_xattr_write(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, { int i, to_copy; ssize_t err = 0; - int write_count; - int64_t xattr_len; + uint64_t write_count; size_t offset = 7; - xattr_len = fidp->fs.xattr.len; - write_count = xattr_len - off; - if (write_count > count) { - write_count = count; - } else if (write_count < 0) { - /* - * write beyond XATTR value len specified in - * xattrcreate - */ + if (fidp->fs.xattr.len < off) { err = -ENOSPC; goto out; } + write_count = fidp->fs.xattr.len - off; + if (write_count > count) { + write_count = count; + } err = pdu_marshal(pdu, offset, "d", write_count); if (err < 0) { return err; @@ -2204,7 +2211,7 @@ out: } #endif -static void v9fs_write(void *opaque) +static void coroutine_fn v9fs_write(void *opaque) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); ssize_t err; @@ -2285,7 +2292,7 @@ static void v9fs_write(void *opaque) err = pdu_marshal(pdu, offset, "d", total); if (err < 0) { ERR("[%d][ >> %s]\n", __LINE__, __func__); - goto out; + goto out_qiov; } err += offset; trace_v9fs_write_return(pdu->tag, pdu->id, total, err); @@ -2298,7 +2305,7 @@ out_nofid: pdu_complete(pdu, err); } -static void v9fs_create(void *opaque) +static void coroutine_fn v9fs_create(void *opaque) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); int32_t fid; @@ -2501,7 +2508,7 @@ out_nofid: v9fs_path_free(&path); } -static void v9fs_symlink(void *opaque) +static void coroutine_fn v9fs_symlink(void *opaque) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); V9fsPDU *pdu = opaque; @@ -2596,7 +2603,7 @@ static void v9fs_flush(void *opaque) pdu_complete(pdu, 7); } -static void v9fs_link(void *opaque) +static void coroutine_fn v9fs_link(void *opaque) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); V9fsPDU *pdu = opaque; @@ -2638,6 +2645,7 @@ static void v9fs_link(void *opaque) if (!err) { err = offset; } + put_fid(pdu, oldfidp); out: put_fid(pdu, dfidp); out_nofid: @@ -2646,7 +2654,7 @@ out_nofid: } /* Only works with path name based fid */ -static void v9fs_remove(void *opaque) +static void coroutine_fn v9fs_remove(void *opaque) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); int32_t fid; @@ -2691,7 +2699,7 @@ out_nofid: pdu_complete(pdu, err); } -static void v9fs_unlinkat(void *opaque) +static void coroutine_fn v9fs_unlinkat(void *opaque) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); int err = 0; @@ -2753,9 +2761,11 @@ out_nofid: v9fs_string_free(&name); } + /* Only works with path name based fid */ -static int v9fs_complete_rename(V9fsPDU *pdu, V9fsFidState *fidp, - int32_t newdirfid, V9fsString *name) +static int coroutine_fn v9fs_complete_rename(V9fsPDU *pdu, V9fsFidState *fidp, + int32_t newdirfid, + V9fsString *name) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); char *end; @@ -2773,7 +2783,10 @@ static int v9fs_complete_rename(V9fsPDU *pdu, V9fsFidState *fidp, err = -ENOENT; goto out_nofid; } - BUG_ON(dirfidp->fid_type != P9_FID_NONE); + if (fidp->fid_type != P9_FID_NONE) { + err = -EINVAL; + goto out; + } v9fs_co_name_to_path(pdu, &dirfidp->path, name->data, &new_path); } else { old_name = fidp->path.data; @@ -2813,7 +2826,7 @@ out_nofid: } /* Only works with path name based fid */ -static void v9fs_rename(void *opaque) +static void coroutine_fn v9fs_rename(void *opaque) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); int32_t fid; @@ -2846,7 +2859,10 @@ static void v9fs_rename(void *opaque) err = -ENOENT; goto out_nofid; } - BUG_ON(fidp->fid_type != P9_FID_NONE); + if (fidp->fid_type != P9_FID_NONE) { + err = -EINVAL; + goto out; + } /* if fs driver is not path based, return EOPNOTSUPP */ if (!(pdu->s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT)) { err = -EOPNOTSUPP; @@ -2865,9 +2881,10 @@ out_nofid: v9fs_string_free(&name); } -static void v9fs_fix_fid_paths(V9fsPDU *pdu, V9fsPath *olddir, - V9fsString *old_name, V9fsPath *newdir, - V9fsString *new_name) +static void coroutine_fn v9fs_fix_fid_paths(V9fsPDU *pdu, V9fsPath *olddir, + V9fsString *old_name, + V9fsPath *newdir, + V9fsString *new_name) { V9fsFidState *tfidp; V9fsPath oldpath, newpath; @@ -2893,9 +2910,10 @@ static void v9fs_fix_fid_paths(V9fsPDU *pdu, V9fsPath *olddir, v9fs_path_free(&newpath); } -static int v9fs_complete_renameat(V9fsPDU *pdu, int32_t olddirfid, - V9fsString *old_name, int32_t newdirfid, - V9fsString *new_name) +static int coroutine_fn v9fs_complete_renameat(V9fsPDU *pdu, int32_t olddirfid, + V9fsString *old_name, + int32_t newdirfid, + V9fsString *new_name) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); int err = 0; @@ -2937,7 +2955,7 @@ out: return err; } -static void v9fs_renameat(void *opaque) +static void coroutine_fn v9fs_renameat(void *opaque) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); ssize_t err = 0; @@ -2980,7 +2998,7 @@ out_err: v9fs_string_free(&new_name); } -static void v9fs_wstat(void *opaque) +static void coroutine_fn v9fs_wstat(void *opaque) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); int32_t fid; @@ -3134,7 +3152,7 @@ static int v9fs_fill_statfs(V9fsState *s, V9fsPDU *pdu, struct statfs *stbuf) fsid_val, f_namelen); } -static void v9fs_statfs(void *opaque) +static void coroutine_fn v9fs_statfs(void *opaque) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); int32_t fid; @@ -3169,7 +3187,7 @@ out_nofid: pdu_complete(pdu, retval); } -static void v9fs_mknod(void *opaque) +static void coroutine_fn v9fs_mknod(void *opaque) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); @@ -3240,7 +3258,7 @@ out_nofid: * do any thing in * qemu 9p server side lock code path. * So when a TLOCK request comes, always return success */ -static void v9fs_lock(void *opaque) +static void coroutine_fn v9fs_lock(void *opaque) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); int8_t status; @@ -3294,7 +3312,7 @@ out_nofid: * When a TGETLOCK request comes, always return success because all lock * handling is done by client's VFS layer. */ -static void v9fs_getlock(void *opaque) +static void coroutine_fn v9fs_getlock(void *opaque) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); size_t offset = 7; @@ -3340,7 +3358,7 @@ out_nofid: v9fs_string_free(&glock.client_id); } -static void v9fs_mkdir(void *opaque) +static void coroutine_fn v9fs_mkdir(void *opaque) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); V9fsPDU *pdu = opaque; @@ -3396,7 +3414,7 @@ out_nofid: } #ifndef CONFIG_WIN32 -static void v9fs_xattrwalk(void *opaque) +static void coroutine_fn v9fs_xattrwalk(void *opaque) { int64_t size; V9fsString name; @@ -3426,7 +3444,7 @@ static void v9fs_xattrwalk(void *opaque) goto out; } v9fs_path_copy(&xattr_fidp->path, &file_fidp->path); - if (name.data == NULL) { + if (!v9fs_string_size(&name)) { /* * listxattr request. Get the size first */ @@ -3441,7 +3459,7 @@ static void v9fs_xattrwalk(void *opaque) */ xattr_fidp->fs.xattr.len = size; xattr_fidp->fid_type = P9_FID_XATTR; - xattr_fidp->fs.xattr.copied_len = -1; + xattr_fidp->fs.xattr.xattrwalk_fid = true; if (size) { xattr_fidp->fs.xattr.value = g_malloc(size); err = v9fs_co_llistxattr(pdu, &xattr_fidp->path, @@ -3474,7 +3492,7 @@ static void v9fs_xattrwalk(void *opaque) */ xattr_fidp->fs.xattr.len = size; xattr_fidp->fid_type = P9_FID_XATTR; - xattr_fidp->fs.xattr.copied_len = -1; + xattr_fidp->fs.xattr.xattrwalk_fid = true; if (size) { xattr_fidp->fs.xattr.value = g_malloc(size); err = v9fs_co_lgetxattr(pdu, &xattr_fidp->path, @@ -3502,11 +3520,11 @@ out_nofid: v9fs_string_free(&name); } -static void v9fs_xattrcreate(void *opaque) +static void coroutine_fn v9fs_xattrcreate(void *opaque) { int flags; int32_t fid; - int64_t size; + uint64_t size; ssize_t err = 0; V9fsString name; size_t offset = 7; @@ -3521,21 +3539,33 @@ static void v9fs_xattrcreate(void *opaque) } trace_v9fs_xattrcreate(pdu->tag, pdu->id, fid, name.data, size, flags); + if (size > XATTR_SIZE_MAX) { + err = -E2BIG; + goto out_nofid; + } + file_fidp = get_fid(pdu, fid); if (file_fidp == NULL) { err = -EINVAL; goto out_nofid; } + if (file_fidp->fid_type != P9_FID_NONE) { + err = -EINVAL; + goto out_put_fid; + } + /* Make the file fid point to xattr */ xattr_fidp = file_fidp; xattr_fidp->fid_type = P9_FID_XATTR; xattr_fidp->fs.xattr.copied_len = 0; + xattr_fidp->fs.xattr.xattrwalk_fid = false; xattr_fidp->fs.xattr.len = size; xattr_fidp->fs.xattr.flags = flags; v9fs_string_init(&xattr_fidp->fs.xattr.name); v9fs_string_copy(&xattr_fidp->fs.xattr.name, &name); - xattr_fidp->fs.xattr.value = g_malloc(size); + xattr_fidp->fs.xattr.value = g_malloc0(size); err = offset; +out_put_fid: put_fid(pdu, file_fidp); out_nofid: pdu_complete(pdu, err); @@ -3543,7 +3573,7 @@ out_nofid: } #endif -static void v9fs_readlink(void *opaque) +static void coroutine_fn v9fs_readlink(void *opaque) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); V9fsPDU *pdu = opaque; @@ -3622,14 +3652,14 @@ static CoroutineEntry *pdu_co_handlers[] = { [P9_TREMOVE] = v9fs_remove, }; -static void v9fs_op_not_supp(void *opaque) +static void coroutine_fn v9fs_op_not_supp(void *opaque) { WARN("[%d][%s] >> This operation is not supported.\n", __LINE__, __func__); V9fsPDU *pdu = opaque; pdu_complete(pdu, -EOPNOTSUPP); } -static void v9fs_fs_ro(void *opaque) +static void coroutine_fn v9fs_fs_ro(void *opaque) { WARN("[%d][%s] >> This is the read-only operation.\n", __LINE__, __func__); V9fsPDU *pdu = opaque; @@ -3772,8 +3802,11 @@ int v9fs_device_realize_common(V9fsState *s, Error **errp) rc = 0; out: if (rc) { - g_free(s->ctx.fs_root); + if (s->ops->cleanup && s->ctx.private) { + s->ops->cleanup(&s->ctx); + } g_free(s->tag); + g_free(s->ctx.fs_root); v9fs_path_free(&path); } return rc; @@ -3782,8 +3815,41 @@ out: void v9fs_device_unrealize_common(V9fsState *s, Error **errp) { TRACE("[%d][ Enter >> %s]\n", __LINE__, __func__); - g_free(s->ctx.fs_root); + if (s->ops->cleanup) { + s->ops->cleanup(&s->ctx); + } g_free(s->tag); + g_free(s->ctx.fs_root); +} + +typedef struct VirtfsCoResetData { + V9fsPDU pdu; + bool done; +} VirtfsCoResetData; + +static void coroutine_fn virtfs_co_reset(void *opaque) +{ + VirtfsCoResetData *data = opaque; + + virtfs_reset(&data->pdu); + data->done = true; +} + +void v9fs_reset(V9fsState *s) +{ + VirtfsCoResetData data = { .pdu = { .s = s }, .done = false }; + Coroutine *co; + + while (!QLIST_EMPTY(&s->active_list)) { + aio_poll(qemu_get_aio_context(), true); + } + + co = qemu_coroutine_create(virtfs_co_reset, &data); + qemu_coroutine_enter(co); + + while (!data.done) { + aio_poll(qemu_get_aio_context(), true); + } } static void __attribute__((__constructor__)) v9fs_set_fd_limit(void) |