From 4b76a481ee28166d5f415ef97833c624f4fc0792 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Mon, 8 Aug 2011 13:04:05 +0530 Subject: [PATCH 01/24] coroutine: add gthread dependency Commit 1fc7bd4a86a2bfeafcec29445871eb97469a2699 removed the gthread and gio dependency since qemu-ga did not require it. Coroutines require gthread, so add it back in. Signed-off-by: Stefan Hajnoczi --- configure | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/configure b/configure index 0c67a4abd9..a6687f7ad3 100755 --- a/configure +++ b/configure @@ -1844,16 +1844,14 @@ fi ########################################## # glib support probe -if test "$guest_agent" != "no" ; then - if $pkg_config --modversion glib-2.0 > /dev/null 2>&1 ; then - glib_cflags=`$pkg_config --cflags glib-2.0 2>/dev/null` - glib_libs=`$pkg_config --libs glib-2.0 2>/dev/null` - libs_softmmu="$glib_libs $libs_softmmu" - libs_tools="$glib_libs $libs_tools" - else - echo "glib-2.0 required to compile QEMU" - exit 1 - fi +if $pkg_config --modversion gthread-2.0 > /dev/null 2>&1 ; then + glib_cflags=`$pkg_config --cflags gthread-2.0 2>/dev/null` + glib_libs=`$pkg_config --libs gthread-2.0 2>/dev/null` + libs_softmmu="$glib_libs $libs_softmmu" + libs_tools="$glib_libs $libs_tools" +else + echo "glib-2.0 required to compile QEMU" + exit 1 fi ########################################## From 39c0564e00f85e70cc94de22035517b2f921d0a0 Mon Sep 17 00:00:00 2001 From: "Venkateswararao Jujjuri (JV)" Date: Sat, 23 Apr 2011 18:40:22 -0700 Subject: [PATCH 02/24] [virtio-9p] Add infrastructure to support glib threads and coroutines. This patch is originally made by Arun Bharadwaj for glib support. Later Harsh Prateek Bora added coroutines support. This version implemented with suggestions from Stefan Hajnoczi . Signed-off-by: Arun R Bharadwaj Signed-off-by: Harsh Prateek Bora Signed-off-by: Venkateswararao Jujjuri " Signed-off-by: Aneesh Kumar K.V --- Makefile.objs | 2 + hw/9pfs/virtio-9p-coth.c | 102 +++++++++++++++++++++++++++++++++++++ hw/9pfs/virtio-9p-coth.h | 58 +++++++++++++++++++++ hw/9pfs/virtio-9p-device.c | 7 ++- 4 files changed, 167 insertions(+), 2 deletions(-) create mode 100644 hw/9pfs/virtio-9p-coth.c create mode 100644 hw/9pfs/virtio-9p-coth.h diff --git a/Makefile.objs b/Makefile.objs index 432b6198e9..9bede6808b 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -305,8 +305,10 @@ hw-obj-$(CONFIG_SOUND) += $(sound-obj-y) 9pfs-nested-$(CONFIG_VIRTFS) = virtio-9p.o virtio-9p-debug.o 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-local.o virtio-9p-xattr.o 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o virtio-9p-posix-acl.o +9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-coth.o hw-obj-$(CONFIG_REALLY_VIRTFS) += $(addprefix 9pfs/, $(9pfs-nested-y)) +$(addprefix 9pfs/, $(9pfs-nested-y)): QEMU_CFLAGS+=$(GLIB_CFLAGS) ###################################################################### diff --git a/hw/9pfs/virtio-9p-coth.c b/hw/9pfs/virtio-9p-coth.c new file mode 100644 index 0000000000..ae05658632 --- /dev/null +++ b/hw/9pfs/virtio-9p-coth.c @@ -0,0 +1,102 @@ +/* + * Virtio 9p backend + * + * Copyright IBM, Corp. 2010 + * + * Authors: + * Harsh Prateek Bora + * Venkateswararao Jujjuri(JV) + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#include "qemu-char.h" +#include "fsdev/qemu-fsdev.h" +#include "qemu-thread.h" +#include "qemu-coroutine.h" +#include "virtio-9p-coth.h" + +/* v9fs glib thread pool */ +static V9fsThPool v9fs_pool; + +void co_run_in_worker_bh(void *opaque) +{ + Coroutine *co = opaque; + g_thread_pool_push(v9fs_pool.pool, co, NULL); +} + +static void v9fs_qemu_process_req_done(void *arg) +{ + char byte; + ssize_t len; + Coroutine *co; + + do { + len = read(v9fs_pool.rfd, &byte, sizeof(byte)); + } while (len == -1 && errno == EINTR); + + while ((co = g_async_queue_try_pop(v9fs_pool.completed)) != NULL) { + qemu_coroutine_enter(co, NULL); + } +} + +static void v9fs_thread_routine(gpointer data, gpointer user_data) +{ + ssize_t len; + char byte = 0; + Coroutine *co = data; + + qemu_coroutine_enter(co, NULL); + + g_async_queue_push(v9fs_pool.completed, co); + do { + len = write(v9fs_pool.wfd, &byte, sizeof(byte)); + } while (len == -1 && errno == EINTR); +} + +int v9fs_init_worker_threads(void) +{ + int ret = 0; + int notifier_fds[2]; + V9fsThPool *p = &v9fs_pool; + sigset_t set, oldset; + + sigfillset(&set); + /* Leave signal handling to the iothread. */ + pthread_sigmask(SIG_SETMASK, &set, &oldset); + + /* init thread system if not already initialized */ + if (!g_thread_get_initialized()) { + g_thread_init(NULL); + } + if (qemu_pipe(notifier_fds) == -1) { + ret = -1; + goto err_out; + } + p->pool = g_thread_pool_new(v9fs_thread_routine, p, -1, FALSE, NULL); + if (!p->pool) { + ret = -1; + goto err_out; + } + p->completed = g_async_queue_new(); + if (!p->completed) { + /* + * We are going to terminate. + * So don't worry about cleanup + */ + ret = -1; + goto err_out; + } + p->rfd = notifier_fds[0]; + p->wfd = notifier_fds[1]; + + fcntl(p->rfd, F_SETFL, O_NONBLOCK); + fcntl(p->wfd, F_SETFL, O_NONBLOCK); + + qemu_set_fd_handler(p->rfd, v9fs_qemu_process_req_done, NULL, NULL); +err_out: + pthread_sigmask(SIG_SETMASK, &oldset, NULL); + return ret; +} diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/virtio-9p-coth.h new file mode 100644 index 0000000000..8445d29bc4 --- /dev/null +++ b/hw/9pfs/virtio-9p-coth.h @@ -0,0 +1,58 @@ +/* + * Virtio 9p backend + * + * Copyright IBM, Corp. 2010 + * + * Authors: + * Harsh Prateek Bora + * Venkateswararao Jujjuri(JV) + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#ifndef _QEMU_VIRTIO_9P_COTH_H +#define _QEMU_VIRTIO_9P_COTH_H + +#include "qemu-thread.h" +#include "qemu-coroutine.h" +#include + +typedef struct V9fsThPool { + int rfd; + int wfd; + GThreadPool *pool; + GAsyncQueue *completed; +} V9fsThPool; + +/* + * we want to use bottom half because we want to make sure the below + * sequence of events. + * + * 1. Yield the coroutine in the QEMU thread. + * 2. Submit the coroutine to a worker thread. + * 3. Enter the coroutine in the worker thread. + * we cannot swap step 1 and 2, because that would imply worker thread + * can enter coroutine while step1 is still running + */ +#define v9fs_co_run_in_worker(code_block) \ + do { \ + QEMUBH *co_bh; \ + co_bh = qemu_bh_new(co_run_in_worker_bh, \ + qemu_coroutine_self()); \ + qemu_bh_schedule(co_bh); \ + /* \ + * yeild in qemu thread and re-enter back \ + * in glib worker thread \ + */ \ + qemu_coroutine_yield(); \ + qemu_bh_delete(co_bh); \ + code_block; \ + /* re-enter back to qemu thread */ \ + qemu_coroutine_yield(); \ + } while (0) + +extern void co_run_in_worker_bh(void *); +extern int v9fs_init_worker_threads(void); +#endif diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c index f235236ea0..f4bf471871 100644 --- a/hw/9pfs/virtio-9p-device.c +++ b/hw/9pfs/virtio-9p-device.c @@ -18,6 +18,7 @@ #include "virtio-9p.h" #include "fsdev/qemu-fsdev.h" #include "virtio-9p-xattr.h" +#include "virtio-9p-coth.h" static uint32_t virtio_9p_get_features(VirtIODevice *vdev, uint32_t features) { @@ -50,13 +51,11 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf) struct stat stat; FsTypeEntry *fse; - s = (V9fsState *)virtio_common_init("virtio-9p", VIRTIO_ID_9P, sizeof(struct virtio_9p_config)+ MAX_TAG_LEN, sizeof(V9fsState)); - /* initialize pdu allocator */ QLIST_INIT(&s->free_list); for (i = 0; i < (MAX_REQ - 1); i++) { @@ -132,6 +131,10 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf) s->tag_len; s->vdev.get_config = virtio_9p_get_config; + if (v9fs_init_worker_threads() < 0) { + fprintf(stderr, "worker thread initialization failed\n"); + exit(1); + } return &s->vdev; } From ff06030f660647bba1c60184dc32730fa06f38fe Mon Sep 17 00:00:00 2001 From: "Venkateswararao Jujjuri (JV)" Date: Wed, 18 May 2011 14:18:05 -0700 Subject: [PATCH 03/24] [virtio-9p] Change all pdu handlers to coroutines. This patch changes the top level handlers to coroutines and sets the base. It will be followed up with series of patches to convert all filesystem calls to threaded coroutines pushing all blocking clals in VirtFS out of vcpu threads. Signed-off-by: Venkateswararao Jujjuri " Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/virtio-9p-coth.h | 1 + hw/9pfs/virtio-9p.c | 142 +++++++++++++++++++++++++++------------ hw/9pfs/virtio-9p.h | 4 +- 3 files changed, 104 insertions(+), 43 deletions(-) diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/virtio-9p-coth.h index 8445d29bc4..9388f9b8b0 100644 --- a/hw/9pfs/virtio-9p-coth.h +++ b/hw/9pfs/virtio-9p-coth.h @@ -17,6 +17,7 @@ #include "qemu-thread.h" #include "qemu-coroutine.h" +#include "virtio-9p.h" #include typedef struct V9fsThPool { diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index 4890df6f75..113ce1e1f3 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -19,6 +19,7 @@ #include "fsdev/qemu-fsdev.h" #include "virtio-9p-debug.h" #include "virtio-9p-xattr.h" +#include "virtio-9p-coth.h" int debug_9p_pdu; @@ -1191,8 +1192,10 @@ static void v9fs_fix_path(V9fsString *dst, V9fsString *src, int len) v9fs_string_free(&str); } -static void v9fs_version(V9fsState *s, V9fsPDU *pdu) +static void v9fs_version(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; V9fsString version; size_t offset = 7; @@ -1210,10 +1213,13 @@ static void v9fs_version(V9fsState *s, V9fsPDU *pdu) complete_pdu(s, pdu, offset); v9fs_string_free(&version); + return; } -static void v9fs_attach(V9fsState *s, V9fsPDU *pdu) +static void v9fs_attach(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; int32_t fid, afid, n_uname; V9fsString uname, aname; V9fsFidState *fidp; @@ -1268,8 +1274,10 @@ out: qemu_free(vs); } -static void v9fs_stat(V9fsState *s, V9fsPDU *pdu) +static void v9fs_stat(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; int32_t fid; V9fsStatState *vs; ssize_t err = 0; @@ -1315,8 +1323,10 @@ out: qemu_free(vs); } -static void v9fs_getattr(V9fsState *s, V9fsPDU *pdu) +static void v9fs_getattr(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; int32_t fid; V9fsStatStateDotl *vs; ssize_t err = 0; @@ -1464,8 +1474,10 @@ out: qemu_free(vs); } -static void v9fs_setattr(V9fsState *s, V9fsPDU *pdu) +static void v9fs_setattr(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; int32_t fid; V9fsSetattrState *vs; int err = 0; @@ -1578,8 +1590,10 @@ out: v9fs_walk_complete(s, vs, err); } -static void v9fs_walk(V9fsState *s, V9fsPDU *pdu) +static void v9fs_walk(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; int32_t fid, newfid; V9fsWalkState *vs; int err = 0; @@ -1750,8 +1764,10 @@ out: qemu_free(vs); } -static void v9fs_open(V9fsState *s, V9fsPDU *pdu) +static void v9fs_open(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; int32_t fid; V9fsOpenState *vs; ssize_t err = 0; @@ -1835,8 +1851,10 @@ out: v9fs_post_lcreate(s, vs, err); } -static void v9fs_lcreate(V9fsState *s, V9fsPDU *pdu) +static void v9fs_lcreate(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; int32_t dfid, flags, mode; gid_t gid; V9fsLcreateState *vs; @@ -1882,8 +1900,10 @@ static void v9fs_post_do_fsync(V9fsState *s, V9fsPDU *pdu, int err) complete_pdu(s, pdu, err); } -static void v9fs_fsync(V9fsState *s, V9fsPDU *pdu) +static void v9fs_fsync(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; int32_t fid; size_t offset = 7; V9fsFidState *fidp; @@ -1901,8 +1921,10 @@ static void v9fs_fsync(V9fsState *s, V9fsPDU *pdu) v9fs_post_do_fsync(s, pdu, err); } -static void v9fs_clunk(V9fsState *s, V9fsPDU *pdu) +static void v9fs_clunk(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; int32_t fid; size_t offset = 7; int err; @@ -2067,8 +2089,10 @@ static void v9fs_xattr_read(V9fsState *s, V9fsReadState *vs) qemu_free(vs); } -static void v9fs_read(V9fsState *s, V9fsPDU *pdu) +static void v9fs_read(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; int32_t fid; V9fsReadState *vs; ssize_t err = 0; @@ -2206,8 +2230,10 @@ static void v9fs_readdir_post_setdir(V9fsState *s, V9fsReadDirState *vs) return; } -static void v9fs_readdir(V9fsState *s, V9fsPDU *pdu) +static void v9fs_readdir(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; int32_t fid; V9fsReadDirState *vs; ssize_t err = 0; @@ -2239,7 +2265,6 @@ static void v9fs_readdir(V9fsState *s, V9fsPDU *pdu) out: complete_pdu(s, pdu, err); qemu_free(vs); - return; } static void v9fs_write_post_pwritev(V9fsState *s, V9fsWriteState *vs, @@ -2318,8 +2343,10 @@ out: qemu_free(vs); } -static void v9fs_write(V9fsState *s, V9fsPDU *pdu) +static void v9fs_write(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; int32_t fid; V9fsWriteState *vs; ssize_t err; @@ -2552,8 +2579,10 @@ out: v9fs_post_create(s, vs, err); } -static void v9fs_create(V9fsState *s, V9fsPDU *pdu) +static void v9fs_create(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; int32_t fid; V9fsCreateState *vs; int err = 0; @@ -2614,8 +2643,10 @@ out: v9fs_post_symlink(s, vs, err); } -static void v9fs_symlink(V9fsState *s, V9fsPDU *pdu) +static void v9fs_symlink(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; int32_t dfid; V9fsSymlinkState *vs; int err = 0; @@ -2650,14 +2681,19 @@ out: qemu_free(vs); } -static void v9fs_flush(V9fsState *s, V9fsPDU *pdu) +static void v9fs_flush(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; /* A nop call with no return */ complete_pdu(s, pdu, 7); + return; } -static void v9fs_link(V9fsState *s, V9fsPDU *pdu) +static void v9fs_link(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; int32_t dfid, oldfid; V9fsFidState *dfidp, *oldfidp; V9fsString name, fullname; @@ -2709,8 +2745,10 @@ static void v9fs_remove_post_remove(V9fsState *s, V9fsRemoveState *vs, qemu_free(vs); } -static void v9fs_remove(V9fsState *s, V9fsPDU *pdu) +static void v9fs_remove(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; int32_t fid; V9fsRemoveState *vs; int err = 0; @@ -2876,8 +2914,10 @@ out: qemu_free(vs); } -static void v9fs_rename(V9fsState *s, V9fsPDU *pdu) +static void v9fs_rename(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; int32_t fid; V9fsRenameState *vs; ssize_t err = 0; @@ -3001,8 +3041,10 @@ out: qemu_free(vs); } -static void v9fs_wstat(V9fsState *s, V9fsPDU *pdu) +static void v9fs_wstat(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; int32_t fid; V9fsWstatState *vs; int err = 0; @@ -3086,8 +3128,10 @@ out: qemu_free(vs); } -static void v9fs_statfs(V9fsState *s, V9fsPDU *pdu) +static void v9fs_statfs(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; V9fsStatfsState *vs; ssize_t err = 0; @@ -3112,6 +3156,7 @@ static void v9fs_statfs(V9fsState *s, V9fsPDU *pdu) out: complete_pdu(s, vs->pdu, err); qemu_free(vs); + return; } static void v9fs_mknod_post_lstat(V9fsState *s, V9fsMkState *vs, int err) @@ -3148,8 +3193,10 @@ out: qemu_free(vs); } -static void v9fs_mknod(V9fsState *s, V9fsPDU *pdu) +static void v9fs_mknod(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; int32_t fid; V9fsMkState *vs; int err = 0; @@ -3194,8 +3241,10 @@ out: * So when a TLOCK request comes, always return success */ -static void v9fs_lock(V9fsState *s, V9fsPDU *pdu) +static void v9fs_lock(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; int32_t fid, err = 0; V9fsLockState *vs; @@ -3239,8 +3288,10 @@ out: * handling is done by client's VFS layer. */ -static void v9fs_getlock(V9fsState *s, V9fsPDU *pdu) +static void v9fs_getlock(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; int32_t fid, err = 0; V9fsGetlockState *vs; @@ -3308,8 +3359,10 @@ out: qemu_free(vs); } -static void v9fs_mkdir(V9fsState *s, V9fsPDU *pdu) +static void v9fs_mkdir(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; int32_t fid; V9fsMkState *vs; int err = 0; @@ -3432,8 +3485,10 @@ out: qemu_free(vs); } -static void v9fs_xattrwalk(V9fsState *s, V9fsPDU *pdu) +static void v9fs_xattrwalk(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; ssize_t err = 0; V9fsXattrState *vs; int32_t fid, newfid; @@ -3486,8 +3541,10 @@ out: qemu_free(vs); } -static void v9fs_xattrcreate(V9fsState *s, V9fsPDU *pdu) +static void v9fs_xattrcreate(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; int flags; int32_t fid; ssize_t err = 0; @@ -3540,8 +3597,10 @@ out: qemu_free(vs); } -static void v9fs_readlink(V9fsState *s, V9fsPDU *pdu) +static void v9fs_readlink(void *opaque) { + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; int32_t fid; V9fsReadLinkState *vs; int err = 0; @@ -3568,9 +3627,7 @@ out: qemu_free(vs); } -typedef void (pdu_handler_t)(V9fsState *s, V9fsPDU *pdu); - -static pdu_handler_t *pdu_handlers[] = { +static CoroutineEntry *pdu_co_handlers[] = { [P9_TREADDIR] = v9fs_readdir, [P9_TSTATFS] = v9fs_statfs, [P9_TGETATTR] = v9fs_getattr, @@ -3605,25 +3662,28 @@ static pdu_handler_t *pdu_handlers[] = { [P9_TREMOVE] = v9fs_remove, }; -static void v9fs_op_not_supp(V9fsState *s, V9fsPDU *pdu) +static void v9fs_op_not_supp(void *opaque) { - complete_pdu(s, pdu, -EOPNOTSUPP); + V9fsPDU *pdu = opaque; + complete_pdu(pdu->s, pdu, -EOPNOTSUPP); } static void submit_pdu(V9fsState *s, V9fsPDU *pdu) { - pdu_handler_t *handler; + Coroutine *co; + CoroutineEntry *handler; if (debug_9p_pdu) { pprint_pdu(pdu); } - if (pdu->id >= ARRAY_SIZE(pdu_handlers) || - (pdu_handlers[pdu->id] == NULL)) { + if (pdu->id >= ARRAY_SIZE(pdu_co_handlers) || + (pdu_co_handlers[pdu->id] == NULL)) { handler = v9fs_op_not_supp; } else { - handler = pdu_handlers[pdu->id]; + handler = pdu_co_handlers[pdu->id]; } - handler(s, pdu); + co = qemu_coroutine_create(handler); + qemu_coroutine_enter(co, pdu); } void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq) @@ -3635,7 +3695,7 @@ void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq) while ((pdu = alloc_pdu(s)) && (len = virtqueue_pop(vq, &pdu->elem)) != 0) { uint8_t *ptr; - + pdu->s = s; BUG_ON(pdu->elem.out_num == 0 || pdu->elem.in_num == 0); BUG_ON(pdu->elem.out_sg[0].iov_len < 7); @@ -3644,9 +3704,7 @@ void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq) memcpy(&pdu->size, ptr, 4); pdu->id = ptr[4]; memcpy(&pdu->tag, ptr + 5, 2); - submit_pdu(s, pdu); } - free_pdu(s, pdu); } diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h index 2bfbe622af..fb1e46581f 100644 --- a/hw/9pfs/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -5,7 +5,7 @@ #include #include #include - +#include "hw/virtio.h" #include "fsdev/file-op-9p.h" /* The feature bitmap for virtio 9P */ @@ -114,6 +114,7 @@ static inline const char *rpath(FsContext *ctx, const char *path, char *buffer) #define P9_IOHDRSZ 24 typedef struct V9fsPDU V9fsPDU; +struct V9fsState; struct V9fsPDU { @@ -121,6 +122,7 @@ struct V9fsPDU uint16_t tag; uint8_t id; VirtQueueElement elem; + struct V9fsState *s; QLIST_ENTRY(V9fsPDU) next; }; From 86e42d748211e58beee431b2639e57ac01ffe3be Mon Sep 17 00:00:00 2001 From: "Venkateswararao Jujjuri (JV)" Date: Mon, 8 Aug 2011 23:33:48 +0530 Subject: [PATCH 04/24] hw/9pfs: Add yeild support for readlink Signed-off-by: Venkateswararao Jujjuri (JV) Signed-off-by: Aneesh Kumar K.V --- Makefile.objs | 2 +- hw/9pfs/cofs.c | 44 ++++++++++++++++++++++++++++++++++++++++ hw/9pfs/virtio-9p-coth.h | 1 + 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 hw/9pfs/cofs.c diff --git a/Makefile.objs b/Makefile.objs index 9bede6808b..a534c1cff8 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -305,7 +305,7 @@ hw-obj-$(CONFIG_SOUND) += $(sound-obj-y) 9pfs-nested-$(CONFIG_VIRTFS) = virtio-9p.o virtio-9p-debug.o 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-local.o virtio-9p-xattr.o 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o virtio-9p-posix-acl.o -9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-coth.o +9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-coth.o cofs.o hw-obj-$(CONFIG_REALLY_VIRTFS) += $(addprefix 9pfs/, $(9pfs-nested-y)) $(addprefix 9pfs/, $(9pfs-nested-y)): QEMU_CFLAGS+=$(GLIB_CFLAGS) diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c new file mode 100644 index 0000000000..6bb8b47da3 --- /dev/null +++ b/hw/9pfs/cofs.c @@ -0,0 +1,44 @@ + +/* + * Virtio 9p backend + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Aneesh Kumar K.V + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#include "fsdev/qemu-fsdev.h" +#include "qemu-thread.h" +#include "qemu-coroutine.h" +#include "virtio-9p-coth.h" + +int v9fs_co_readlink(V9fsState *s, V9fsString *path, V9fsString *buf) +{ + int err; + ssize_t len; + + buf->data = qemu_malloc(PATH_MAX); + v9fs_co_run_in_worker( + { + len = s->ops->readlink(&s->ctx, path->data, + buf->data, PATH_MAX - 1); + if (len > -1) { + buf->size = len; + buf->data[len] = 0; + err = 0; + } else { + err = -errno; + } + }); + if (err) { + qemu_free(buf->data); + buf->data = NULL; + buf->size = 0; + } + return err; +} diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/virtio-9p-coth.h index 9388f9b8b0..94c5147683 100644 --- a/hw/9pfs/virtio-9p-coth.h +++ b/hw/9pfs/virtio-9p-coth.h @@ -56,4 +56,5 @@ typedef struct V9fsThPool { extern void co_run_in_worker_bh(void *); extern int v9fs_init_worker_threads(void); +extern int v9fs_co_readlink(V9fsState *, V9fsString *, V9fsString *); #endif From 7a5ca31eb4cceff0191a45963c3d25260be73347 Mon Sep 17 00:00:00 2001 From: Venkateswararao Jujjuri Date: Mon, 8 Aug 2011 23:36:41 +0530 Subject: [PATCH 05/24] hw/9pfs: Update v9fs_readlink to use coroutine Signed-off-by: Venkateswararao Jujjuri Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/virtio-9p.c | 69 +++++++++++---------------------------------- hw/9pfs/virtio-9p.h | 8 ------ 2 files changed, 17 insertions(+), 60 deletions(-) diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index 113ce1e1f3..a68ac3fe6e 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -82,21 +82,6 @@ static int v9fs_do_lstat(V9fsState *s, V9fsString *path, struct stat *stbuf) return s->ops->lstat(&s->ctx, path->data, stbuf); } -static ssize_t v9fs_do_readlink(V9fsState *s, V9fsString *path, V9fsString *buf) -{ - ssize_t len; - - buf->data = qemu_malloc(1024); - - len = s->ops->readlink(&s->ctx, path->data, buf->data, 1024 - 1); - if (len > -1) { - buf->size = len; - buf->data[len] = 0; - } - - return len; -} - static int v9fs_do_close(V9fsState *s, int fd) { return s->ops->close(&s->ctx, fd); @@ -1054,13 +1039,10 @@ static int stat_to_v9stat(V9fsState *s, V9fsString *name, v9fs_string_null(&v9stat->extension); if (v9stat->mode & P9_STAT_MODE_SYMLINK) { - err = v9fs_do_readlink(s, name, &v9stat->extension); - if (err == -1) { - err = -errno; + err = v9fs_co_readlink(s, name, &v9stat->extension); + if (err < 0) { return err; } - v9stat->extension.data[err] = 0; - v9stat->extension.size = err; } else if (v9stat->mode & P9_STAT_MODE_DEVICE) { v9fs_string_sprintf(&v9stat->extension, "%c %u %u", S_ISCHR(stbuf->st_mode) ? 'c' : 'b', @@ -1949,13 +1931,13 @@ static void v9fs_read_post_seekdir(V9fsState *s, V9fsReadState *vs, ssize_t err) if (err) { goto out; } - v9fs_stat_free(&vs->v9stat); - v9fs_string_free(&vs->name); vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->count); vs->offset += vs->count; err = vs->offset; out: complete_pdu(s, vs->pdu, err); + v9fs_stat_free(&vs->v9stat); + v9fs_string_free(&vs->name); qemu_free(vs); return; } @@ -3582,49 +3564,32 @@ out: qemu_free(vs); } -static void v9fs_readlink_post_readlink(V9fsState *s, V9fsReadLinkState *vs, - int err) -{ - if (err < 0) { - err = -errno; - goto out; - } - vs->offset += pdu_marshal(vs->pdu, vs->offset, "s", &vs->target); - err = vs->offset; -out: - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->target); - qemu_free(vs); -} - static void v9fs_readlink(void *opaque) { V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; + size_t offset = 7; + V9fsString target; int32_t fid; - V9fsReadLinkState *vs; int err = 0; V9fsFidState *fidp; - vs = qemu_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; - - pdu_unmarshal(vs->pdu, vs->offset, "d", &fid); - - fidp = lookup_fid(s, fid); + pdu_unmarshal(pdu, offset, "d", &fid); + fidp = lookup_fid(pdu->s, fid); if (fidp == NULL) { err = -ENOENT; goto out; } - v9fs_string_init(&vs->target); - err = v9fs_do_readlink(s, &fidp->path, &vs->target); - v9fs_readlink_post_readlink(s, vs, err); - return; + v9fs_string_init(&target); + err = v9fs_co_readlink(pdu->s, &fidp->path, &target); + if (err < 0) { + goto out; + } + offset += pdu_marshal(pdu, offset, "s", &target); + err = offset; + v9fs_string_free(&target); out: - complete_pdu(s, vs->pdu, err); - qemu_free(vs); + complete_pdu(pdu->s, pdu, err); } static CoroutineEntry *pdu_co_handlers[] = { diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h index fb1e46581f..8196da07ae 100644 --- a/hw/9pfs/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -495,13 +495,6 @@ typedef struct V9fsGetlockState V9fsGetlock *glock; } V9fsGetlockState; -typedef struct V9fsReadLinkState -{ - V9fsPDU *pdu; - size_t offset; - V9fsString target; -} V9fsReadLinkState; - size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count, size_t offset, size_t size, int pack); @@ -512,5 +505,4 @@ static inline size_t do_pdu_unpack(void *dst, struct iovec *sg, int sg_count, } extern void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq); - #endif From dcb9dbe3c701068aacadebcb4068b23b3d495f3a Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Wed, 18 May 2011 15:42:42 -0700 Subject: [PATCH 06/24] hw/9pfs: Add yield support for readdir related coroutines This include readdir, telldir, seekdir, rewinddir. Signed-off-by: Aneesh Kumar K.V --- Makefile.objs | 2 +- hw/9pfs/codir.c | 66 ++++++++++++++++++++++++++++++++++++++++ hw/9pfs/virtio-9p-coth.h | 5 +++ 3 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 hw/9pfs/codir.c diff --git a/Makefile.objs b/Makefile.objs index a534c1cff8..faa2a12528 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -305,7 +305,7 @@ hw-obj-$(CONFIG_SOUND) += $(sound-obj-y) 9pfs-nested-$(CONFIG_VIRTFS) = virtio-9p.o virtio-9p-debug.o 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-local.o virtio-9p-xattr.o 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o virtio-9p-posix-acl.o -9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-coth.o cofs.o +9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-coth.o cofs.o codir.o hw-obj-$(CONFIG_REALLY_VIRTFS) += $(addprefix 9pfs/, $(9pfs-nested-y)) $(addprefix 9pfs/, $(9pfs-nested-y)): QEMU_CFLAGS+=$(GLIB_CFLAGS) diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c new file mode 100644 index 0000000000..47b10df57d --- /dev/null +++ b/hw/9pfs/codir.c @@ -0,0 +1,66 @@ + +/* + * Virtio 9p backend + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Aneesh Kumar K.V + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#include "fsdev/qemu-fsdev.h" +#include "qemu-thread.h" +#include "qemu-coroutine.h" +#include "virtio-9p-coth.h" + +int v9fs_co_readdir(V9fsState *s, V9fsFidState *fidp, struct dirent **dent) +{ + int err; + + v9fs_co_run_in_worker( + { + errno = 0; + /*FIXME!! need to switch to readdir_r */ + *dent = s->ops->readdir(&s->ctx, fidp->fs.dir); + if (!*dent && errno) { + err = -errno; + } else { + err = 0; + } + }); + return err; +} + +off_t v9fs_co_telldir(V9fsState *s, V9fsFidState *fidp) +{ + off_t err; + + v9fs_co_run_in_worker( + { + err = s->ops->telldir(&s->ctx, fidp->fs.dir); + if (err < 0) { + err = -errno; + } + }); + return err; +} + +void v9fs_co_seekdir(V9fsState *s, V9fsFidState *fidp, off_t offset) +{ + v9fs_co_run_in_worker( + { + s->ops->seekdir(&s->ctx, fidp->fs.dir, offset); + }); +} + +void v9fs_co_rewinddir(V9fsState *s, V9fsFidState *fidp) +{ + v9fs_co_run_in_worker( + { + s->ops->rewinddir(&s->ctx, fidp->fs.dir); + }); +} diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/virtio-9p-coth.h index 94c5147683..9aa5953a0e 100644 --- a/hw/9pfs/virtio-9p-coth.h +++ b/hw/9pfs/virtio-9p-coth.h @@ -57,4 +57,9 @@ typedef struct V9fsThPool { extern void co_run_in_worker_bh(void *); extern int v9fs_init_worker_threads(void); extern int v9fs_co_readlink(V9fsState *, V9fsString *, V9fsString *); +extern int v9fs_co_readdir(V9fsState *, V9fsFidState *, + struct dirent **); +extern off_t v9fs_co_telldir(V9fsState *, V9fsFidState *); +extern void v9fs_co_seekdir(V9fsState *, V9fsFidState *, off_t); +extern void v9fs_co_rewinddir(V9fsState *, V9fsFidState *); #endif From 5e4eaa79cf4645d200742901d449789dfa607230 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Wed, 18 May 2011 15:57:17 -0700 Subject: [PATCH 07/24] hw/9pfs: Update v9fs_readdir to use coroutines Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/virtio-9p.c | 173 ++++++++++++++++++-------------------------- 1 file changed, 72 insertions(+), 101 deletions(-) diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index a68ac3fe6e..3f5e459b7c 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -112,11 +112,6 @@ static off_t v9fs_do_telldir(V9fsState *s, DIR *dir) return s->ops->telldir(&s->ctx, dir); } -static struct dirent *v9fs_do_readdir(V9fsState *s, DIR *dir) -{ - return s->ops->readdir(&s->ctx, dir); -} - static void v9fs_do_seekdir(V9fsState *s, DIR *dir, off_t off) { return s->ops->seekdir(&s->ctx, dir, off); @@ -1966,7 +1961,7 @@ static void v9fs_read_post_dir_lstat(V9fsState *s, V9fsReadState *vs, v9fs_stat_free(&vs->v9stat); v9fs_string_free(&vs->name); vs->dir_pos = vs->dent->d_off; - vs->dent = v9fs_do_readdir(s, vs->fidp->fs.dir); + v9fs_co_readdir(s, vs->fidp, &vs->dent); v9fs_read_post_readdir(s, vs, err); return; out: @@ -1998,7 +1993,7 @@ static void v9fs_read_post_readdir(V9fsState *s, V9fsReadState *vs, ssize_t err) static void v9fs_read_post_telldir(V9fsState *s, V9fsReadState *vs, ssize_t err) { - vs->dent = v9fs_do_readdir(s, vs->fidp->fs.dir); + v9fs_co_readdir(s, vs->fidp, &vs->dent); v9fs_read_post_readdir(s, vs, err); return; } @@ -2127,126 +2122,102 @@ out: qemu_free(vs); } -typedef struct V9fsReadDirState { - V9fsPDU *pdu; - V9fsFidState *fidp; - V9fsQID qid; - off_t saved_dir_pos; - struct dirent *dent; - int32_t count; - int32_t max_count; - size_t offset; - int64_t initial_offset; - V9fsString name; -} V9fsReadDirState; - -static void v9fs_readdir_post_seekdir(V9fsState *s, V9fsReadDirState *vs) +static size_t v9fs_readdir_data_size(V9fsString *name) { - vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->count); - vs->offset += vs->count; - complete_pdu(s, vs->pdu, vs->offset); - qemu_free(vs); - return; + /* + * Size of each dirent on the wire: size of qid (13) + size of offset (8) + * size of type (1) + size of name.size (2) + strlen(name.data) + */ + return 24 + v9fs_string_size(name); } -/* Size of each dirent on the wire: size of qid (13) + size of offset (8) - * size of type (1) + size of name.size (2) + strlen(name.data) - */ -#define V9_READDIR_DATA_SZ (24 + strlen(vs->name.data)) - -static void v9fs_readdir_post_readdir(V9fsState *s, V9fsReadDirState *vs) +static int v9fs_do_readdir(V9fsState *s, V9fsPDU *pdu, + V9fsFidState *fidp, int32_t max_count) { - int len; size_t size; + V9fsQID qid; + V9fsString name; + int len, err = 0; + int32_t count = 0; + off_t saved_dir_pos; + struct dirent *dent; - if (vs->dent) { - v9fs_string_init(&vs->name); - v9fs_string_sprintf(&vs->name, "%s", vs->dent->d_name); - - if ((vs->count + V9_READDIR_DATA_SZ) > vs->max_count) { - /* Ran out of buffer. Set dir back to old position and return */ - v9fs_do_seekdir(s, vs->fidp->fs.dir, vs->saved_dir_pos); - v9fs_readdir_post_seekdir(s, vs); - return; + /* save the directory position */ + saved_dir_pos = v9fs_co_telldir(s, fidp); + if (saved_dir_pos < 0) { + return saved_dir_pos; + } + while (1) { + err = v9fs_co_readdir(s, fidp, &dent); + if (err || !dent) { + break; } - - /* Fill up just the path field of qid because the client uses + v9fs_string_init(&name); + v9fs_string_sprintf(&name, "%s", dent->d_name); + if ((count + v9fs_readdir_data_size(&name)) > max_count) { + /* Ran out of buffer. Set dir back to old position and return */ + v9fs_co_seekdir(s, fidp, saved_dir_pos); + v9fs_string_free(&name); + return count; + } + /* + * Fill up just the path field of qid because the client uses * only that. To fill the entire qid structure we will have * to stat each dirent found, which is expensive */ - size = MIN(sizeof(vs->dent->d_ino), sizeof(vs->qid.path)); - memcpy(&vs->qid.path, &vs->dent->d_ino, size); + size = MIN(sizeof(dent->d_ino), sizeof(qid.path)); + memcpy(&qid.path, &dent->d_ino, size); /* Fill the other fields with dummy values */ - vs->qid.type = 0; - vs->qid.version = 0; + qid.type = 0; + qid.version = 0; - len = pdu_marshal(vs->pdu, vs->offset+4+vs->count, "Qqbs", - &vs->qid, vs->dent->d_off, - vs->dent->d_type, &vs->name); - vs->count += len; - v9fs_string_free(&vs->name); - vs->saved_dir_pos = vs->dent->d_off; - vs->dent = v9fs_do_readdir(s, vs->fidp->fs.dir); - v9fs_readdir_post_readdir(s, vs); - return; + /* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) */ + len = pdu_marshal(pdu, 11 + count, "Qqbs", + &qid, dent->d_off, + dent->d_type, &name); + count += len; + v9fs_string_free(&name); + saved_dir_pos = dent->d_off; } - - vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->count); - vs->offset += vs->count; - complete_pdu(s, vs->pdu, vs->offset); - qemu_free(vs); - return; -} - -static void v9fs_readdir_post_telldir(V9fsState *s, V9fsReadDirState *vs) -{ - vs->dent = v9fs_do_readdir(s, vs->fidp->fs.dir); - v9fs_readdir_post_readdir(s, vs); - return; -} - -static void v9fs_readdir_post_setdir(V9fsState *s, V9fsReadDirState *vs) -{ - vs->saved_dir_pos = v9fs_do_telldir(s, vs->fidp->fs.dir); - v9fs_readdir_post_telldir(s, vs); - return; + if (err < 0) { + return err; + } + return count; } static void v9fs_readdir(void *opaque) { + int32_t fid; + V9fsFidState *fidp; + ssize_t retval = 0; + size_t offset = 7; + int64_t initial_offset; + int32_t count, max_count; V9fsPDU *pdu = opaque; V9fsState *s = pdu->s; - int32_t fid; - V9fsReadDirState *vs; - ssize_t err = 0; - size_t offset = 7; - vs = qemu_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; - vs->count = 0; + pdu_unmarshal(pdu, offset, "dqd", &fid, &initial_offset, &max_count); - pdu_unmarshal(vs->pdu, offset, "dqd", &fid, &vs->initial_offset, - &vs->max_count); - - vs->fidp = lookup_fid(s, fid); - if (vs->fidp == NULL || !(vs->fidp->fs.dir)) { - err = -EINVAL; + fidp = lookup_fid(s, fid); + if (fidp == NULL || !fidp->fs.dir) { + retval = -EINVAL; goto out; } - - if (vs->initial_offset == 0) { - v9fs_do_rewinddir(s, vs->fidp->fs.dir); + if (initial_offset == 0) { + v9fs_co_rewinddir(s, fidp); } else { - v9fs_do_seekdir(s, vs->fidp->fs.dir, vs->initial_offset); + v9fs_co_seekdir(s, fidp, initial_offset); } - - v9fs_readdir_post_setdir(s, vs); - return; - + count = v9fs_do_readdir(s, pdu, fidp, max_count); + if (count < 0) { + retval = count; + goto out; + } + retval = offset; + retval += pdu_marshal(pdu, offset, "d", count); + retval += count; out: - complete_pdu(s, pdu, err); - qemu_free(vs); + complete_pdu(s, pdu, retval); } static void v9fs_write_post_pwritev(V9fsState *s, V9fsWriteState *vs, From 94840ff9f383d4f7099394cc53af48f0a7065132 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Wed, 18 May 2011 16:03:49 -0700 Subject: [PATCH 08/24] hw/9pfs: Add yield support to statfs coroutine Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/cofs.c | 14 ++++++++++++++ hw/9pfs/virtio-9p-coth.h | 1 + 2 files changed, 15 insertions(+) diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c index 6bb8b47da3..4138e4d02a 100644 --- a/hw/9pfs/cofs.c +++ b/hw/9pfs/cofs.c @@ -42,3 +42,17 @@ int v9fs_co_readlink(V9fsState *s, V9fsString *path, V9fsString *buf) } return err; } + +int v9fs_co_statfs(V9fsState *s, V9fsString *path, struct statfs *stbuf) +{ + int err; + + v9fs_co_run_in_worker( + { + err = s->ops->statfs(&s->ctx, path->data, stbuf); + if (err < 0) { + err = -errno; + } + }); + return err; +} diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/virtio-9p-coth.h index 9aa5953a0e..5d9dc0f6cc 100644 --- a/hw/9pfs/virtio-9p-coth.h +++ b/hw/9pfs/virtio-9p-coth.h @@ -62,4 +62,5 @@ extern int v9fs_co_readdir(V9fsState *, V9fsFidState *, extern off_t v9fs_co_telldir(V9fsState *, V9fsFidState *); extern void v9fs_co_seekdir(V9fsState *, V9fsFidState *, off_t); extern void v9fs_co_rewinddir(V9fsState *, V9fsFidState *); +extern int v9fs_co_statfs(V9fsState *, V9fsString *, struct statfs *); #endif From 88a4763e88e7724e739515d3e2c734f7ec0ea9cf Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Wed, 18 May 2011 16:04:01 -0700 Subject: [PATCH 09/24] hw/9pfs: Update v9fs_statfs to use coroutines Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/virtio-9p.c | 90 ++++++++++++++++++++++----------------------- hw/9pfs/virtio-9p.h | 22 ----------- 2 files changed, 43 insertions(+), 69 deletions(-) diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index 3f5e459b7c..69ef717fa3 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -3036,79 +3036,75 @@ out: qemu_free(vs); } -static void v9fs_statfs_post_statfs(V9fsState *s, V9fsStatfsState *vs, int err) +static int v9fs_fill_statfs(V9fsState *s, V9fsPDU *pdu, struct statfs *stbuf) { + uint32_t f_type; + uint32_t f_bsize; + uint64_t f_blocks; + uint64_t f_bfree; + uint64_t f_bavail; + uint64_t f_files; + uint64_t f_ffree; + uint64_t fsid_val; + uint32_t f_namelen; + size_t offset = 7; int32_t bsize_factor; - if (err) { - err = -errno; - goto out; - } - /* * compute bsize factor based on host file system block size * and client msize */ - bsize_factor = (s->msize - P9_IOHDRSZ)/vs->stbuf.f_bsize; + bsize_factor = (s->msize - P9_IOHDRSZ)/stbuf->f_bsize; if (!bsize_factor) { bsize_factor = 1; } - vs->v9statfs.f_type = vs->stbuf.f_type; - vs->v9statfs.f_bsize = vs->stbuf.f_bsize; - vs->v9statfs.f_bsize *= bsize_factor; + f_type = stbuf->f_type; + f_bsize = stbuf->f_bsize; + f_bsize *= bsize_factor; /* * f_bsize is adjusted(multiplied) by bsize factor, so we need to * adjust(divide) the number of blocks, free blocks and available * blocks by bsize factor */ - vs->v9statfs.f_blocks = vs->stbuf.f_blocks/bsize_factor; - vs->v9statfs.f_bfree = vs->stbuf.f_bfree/bsize_factor; - vs->v9statfs.f_bavail = vs->stbuf.f_bavail/bsize_factor; - vs->v9statfs.f_files = vs->stbuf.f_files; - vs->v9statfs.f_ffree = vs->stbuf.f_ffree; - vs->v9statfs.fsid_val = (unsigned int) vs->stbuf.f_fsid.__val[0] | - (unsigned long long)vs->stbuf.f_fsid.__val[1] << 32; - vs->v9statfs.f_namelen = vs->stbuf.f_namelen; + f_blocks = stbuf->f_blocks/bsize_factor; + f_bfree = stbuf->f_bfree/bsize_factor; + f_bavail = stbuf->f_bavail/bsize_factor; + f_files = stbuf->f_files; + f_ffree = stbuf->f_ffree; + fsid_val = (unsigned int) stbuf->f_fsid.__val[0] | + (unsigned long long)stbuf->f_fsid.__val[1] << 32; + f_namelen = stbuf->f_namelen; - vs->offset += pdu_marshal(vs->pdu, vs->offset, "ddqqqqqqd", - vs->v9statfs.f_type, vs->v9statfs.f_bsize, vs->v9statfs.f_blocks, - vs->v9statfs.f_bfree, vs->v9statfs.f_bavail, vs->v9statfs.f_files, - vs->v9statfs.f_ffree, vs->v9statfs.fsid_val, - vs->v9statfs.f_namelen); - -out: - complete_pdu(s, vs->pdu, vs->offset); - qemu_free(vs); + return pdu_marshal(pdu, offset, "ddqqqqqqd", + f_type, f_bsize, f_blocks, f_bfree, + f_bavail, f_files, f_ffree, + fsid_val, f_namelen); } static void v9fs_statfs(void *opaque) { + int32_t fid; + ssize_t retval = 0; + size_t offset = 7; + V9fsFidState *fidp; + struct statfs stbuf; V9fsPDU *pdu = opaque; V9fsState *s = pdu->s; - V9fsStatfsState *vs; - ssize_t err = 0; - vs = qemu_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; - - memset(&vs->v9statfs, 0, sizeof(vs->v9statfs)); - - pdu_unmarshal(vs->pdu, vs->offset, "d", &vs->fid); - - vs->fidp = lookup_fid(s, vs->fid); - if (vs->fidp == NULL) { - err = -ENOENT; + pdu_unmarshal(pdu, offset, "d", &fid); + fidp = lookup_fid(s, fid); + if (fidp == NULL) { + retval = -ENOENT; goto out; } - - err = v9fs_do_statfs(s, &vs->fidp->path, &vs->stbuf); - v9fs_statfs_post_statfs(s, vs, err); - return; - + retval = v9fs_co_statfs(s, &fidp->path, &stbuf); + if (retval < 0) { + goto out; + } + retval = offset; + retval += v9fs_fill_statfs(s, pdu, &stbuf); out: - complete_pdu(s, vs->pdu, err); - qemu_free(vs); + complete_pdu(s, pdu, retval); return; } diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h index 8196da07ae..eb6cd23540 100644 --- a/hw/9pfs/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -398,28 +398,6 @@ struct virtio_9p_config uint8_t tag[0]; } __attribute__((packed)); -typedef struct V9fsStatfs -{ - uint32_t f_type; - uint32_t f_bsize; - uint64_t f_blocks; - uint64_t f_bfree; - uint64_t f_bavail; - uint64_t f_files; - uint64_t f_ffree; - uint64_t fsid_val; - uint32_t f_namelen; -} V9fsStatfs; - -typedef struct V9fsStatfsState { - V9fsPDU *pdu; - size_t offset; - int32_t fid; - V9fsStatfs v9statfs; - V9fsFidState *fidp; - struct statfs stbuf; -} V9fsStatfsState; - typedef struct V9fsMkState { V9fsPDU *pdu; size_t offset; From 172198d4db28d537f9e2cfb8af3fef9cd4d2b543 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Wed, 18 May 2011 16:04:13 -0700 Subject: [PATCH 10/24] hw/9pfs: Add yield support to lstat coroutine Signed-off-by: Aneesh Kumar K.V --- Makefile.objs | 2 +- hw/9pfs/cofile.c | 32 ++++++++++++++++++++++++++++++++ hw/9pfs/virtio-9p-coth.h | 1 + 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 hw/9pfs/cofile.c diff --git a/Makefile.objs b/Makefile.objs index faa2a12528..efacf0fb22 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -305,7 +305,7 @@ hw-obj-$(CONFIG_SOUND) += $(sound-obj-y) 9pfs-nested-$(CONFIG_VIRTFS) = virtio-9p.o virtio-9p-debug.o 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-local.o virtio-9p-xattr.o 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o virtio-9p-posix-acl.o -9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-coth.o cofs.o codir.o +9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-coth.o cofs.o codir.o cofile.o hw-obj-$(CONFIG_REALLY_VIRTFS) += $(addprefix 9pfs/, $(9pfs-nested-y)) $(addprefix 9pfs/, $(9pfs-nested-y)): QEMU_CFLAGS+=$(GLIB_CFLAGS) diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c new file mode 100644 index 0000000000..a4c0ae75cc --- /dev/null +++ b/hw/9pfs/cofile.c @@ -0,0 +1,32 @@ + +/* + * Virtio 9p backend + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Aneesh Kumar K.V + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#include "fsdev/qemu-fsdev.h" +#include "qemu-thread.h" +#include "qemu-coroutine.h" +#include "virtio-9p-coth.h" + +int v9fs_co_lstat(V9fsState *s, V9fsString *path, struct stat *stbuf) +{ + int err; + + v9fs_co_run_in_worker( + { + err = s->ops->lstat(&s->ctx, path->data, stbuf); + if (err < 0) { + err = -errno; + } + }); + return err; +} diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/virtio-9p-coth.h index 5d9dc0f6cc..3538d91344 100644 --- a/hw/9pfs/virtio-9p-coth.h +++ b/hw/9pfs/virtio-9p-coth.h @@ -63,4 +63,5 @@ extern off_t v9fs_co_telldir(V9fsState *, V9fsFidState *); extern void v9fs_co_seekdir(V9fsState *, V9fsFidState *, off_t); extern void v9fs_co_rewinddir(V9fsState *, V9fsFidState *); extern int v9fs_co_statfs(V9fsState *, V9fsString *, struct statfs *); +extern int v9fs_co_lstat(V9fsState *, V9fsString *, struct stat *); #endif From 8db21ce73aab5e8c47053c9a7d3a833ee62de2d4 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Wed, 18 May 2011 16:04:33 -0700 Subject: [PATCH 11/24] hw/9pfs: Update v9fs_getattr to use coroutines Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/virtio-9p.c | 57 +++++++++++++++------------------------------ hw/9pfs/virtio-9p.h | 8 ------- 2 files changed, 19 insertions(+), 46 deletions(-) diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index 69ef717fa3..9fb1b3fe4b 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -1086,7 +1086,7 @@ static int stat_to_v9stat(V9fsState *s, V9fsString *name, static void stat_to_v9stat_dotl(V9fsState *s, const struct stat *stbuf, - V9fsStatDotl *v9lstat) + V9fsStatDotl *v9lstat) { memset(v9lstat, 0, sizeof(*v9lstat)); @@ -1283,57 +1283,38 @@ out: qemu_free(vs); } -static void v9fs_getattr_post_lstat(V9fsState *s, V9fsStatStateDotl *vs, - int err) -{ - if (err == -1) { - err = -errno; - goto out; - } - - stat_to_v9stat_dotl(s, &vs->stbuf, &vs->v9stat_dotl); - vs->offset += pdu_marshal(vs->pdu, vs->offset, "A", &vs->v9stat_dotl); - err = vs->offset; - -out: - complete_pdu(s, vs->pdu, err); - qemu_free(vs); -} - static void v9fs_getattr(void *opaque) { - V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; int32_t fid; - V9fsStatStateDotl *vs; - ssize_t err = 0; + size_t offset = 7; + ssize_t retval = 0; + struct stat stbuf; V9fsFidState *fidp; uint64_t request_mask; + V9fsStatDotl v9stat_dotl; + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; - vs = qemu_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; - - memset(&vs->v9stat_dotl, 0, sizeof(vs->v9stat_dotl)); - - pdu_unmarshal(vs->pdu, vs->offset, "dq", &fid, &request_mask); + pdu_unmarshal(pdu, offset, "dq", &fid, &request_mask); fidp = lookup_fid(s, fid); if (fidp == NULL) { - err = -ENOENT; + retval = -ENOENT; goto out; } - - /* Currently we only support BASIC fields in stat, so there is no + /* + * Currently we only support BASIC fields in stat, so there is no * need to look at request_mask. */ - err = v9fs_do_lstat(s, &fidp->path, &vs->stbuf); - v9fs_getattr_post_lstat(s, vs, err); - return; - + retval = v9fs_co_lstat(s, &fidp->path, &stbuf); + if (retval < 0) { + goto out; + } + stat_to_v9stat_dotl(s, &stbuf, &v9stat_dotl); + retval = offset; + retval += pdu_marshal(pdu, offset, "A", &v9stat_dotl); out: - complete_pdu(s, vs->pdu, err); - qemu_free(vs); + complete_pdu(s, pdu, retval); } /* From Linux kernel code */ diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h index eb6cd23540..a62eda078a 100644 --- a/hw/9pfs/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -278,14 +278,6 @@ typedef struct V9fsStatDotl { uint64_t st_data_version; } V9fsStatDotl; -typedef struct V9fsStatStateDotl { - V9fsPDU *pdu; - size_t offset; - V9fsStatDotl v9stat_dotl; - struct stat stbuf; -} V9fsStatStateDotl; - - typedef struct V9fsWalkState { V9fsPDU *pdu; size_t offset; From 4011ead2fdba4da764ffef3dbcf00d2f7772cdb9 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Wed, 18 May 2011 16:04:58 -0700 Subject: [PATCH 12/24] hw/9pfs: Add yield support to setattr related coroutines This include chmod, utimensat, chown and truncate. Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/cofs.c | 64 ++++++++++++++++++++++++++++++++++++++++ hw/9pfs/virtio-9p-coth.h | 4 +++ 2 files changed, 68 insertions(+) diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c index 4138e4d02a..7e9df852c5 100644 --- a/hw/9pfs/cofs.c +++ b/hw/9pfs/cofs.c @@ -56,3 +56,67 @@ int v9fs_co_statfs(V9fsState *s, V9fsString *path, struct statfs *stbuf) }); return err; } + +int v9fs_co_chmod(V9fsState *s, V9fsString *path, mode_t mode) +{ + int err; + FsCred cred; + + cred_init(&cred); + cred.fc_mode = mode; + v9fs_co_run_in_worker( + { + err = s->ops->chmod(&s->ctx, path->data, &cred); + if (err < 0) { + err = -errno; + } + }); + return err; +} + +int v9fs_co_utimensat(V9fsState *s, V9fsString *path, + struct timespec times[2]) +{ + int err; + + v9fs_co_run_in_worker( + { + err = s->ops->utimensat(&s->ctx, path->data, times); + if (err < 0) { + err = -errno; + } + }); + return err; +} + +int v9fs_co_chown(V9fsState *s, V9fsString *path, uid_t uid, gid_t gid) +{ + int err; + FsCred cred; + + cred_init(&cred); + cred.fc_uid = uid; + cred.fc_gid = gid; + v9fs_co_run_in_worker( + { + err = s->ops->chown(&s->ctx, path->data, &cred); + if (err < 0) { + err = -errno; + } + }); + return err; +} + +int v9fs_co_truncate(V9fsState *s, V9fsString *path, off_t size) +{ + int err; + + v9fs_co_run_in_worker( + { + err = s->ops->truncate(&s->ctx, path->data, size); + if (err < 0) { + err = -errno; + } + }); + return err; +} diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/virtio-9p-coth.h index 3538d91344..09f232adbe 100644 --- a/hw/9pfs/virtio-9p-coth.h +++ b/hw/9pfs/virtio-9p-coth.h @@ -64,4 +64,8 @@ extern void v9fs_co_seekdir(V9fsState *, V9fsFidState *, off_t); extern void v9fs_co_rewinddir(V9fsState *, V9fsFidState *); extern int v9fs_co_statfs(V9fsState *, V9fsString *, struct statfs *); extern int v9fs_co_lstat(V9fsState *, V9fsString *, struct stat *); +extern int v9fs_co_chmod(V9fsState *, V9fsString *, mode_t); +extern int v9fs_co_utimensat(V9fsState *, V9fsString *, struct timespec [2]); +extern int v9fs_co_chown(V9fsState *, V9fsString *, uid_t, gid_t); +extern int v9fs_co_truncate(V9fsState *, V9fsString *, off_t); #endif From 65c05f9a540faa9237301d8504a70ee7854eb910 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Wed, 18 May 2011 16:05:10 -0700 Subject: [PATCH 13/24] hw/9pfs: Update v9fs_setattr to use coroutines Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/virtio-9p.c | 171 +++++++++++++++----------------------------- hw/9pfs/virtio-9p.h | 8 --- 2 files changed, 58 insertions(+), 121 deletions(-) diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index 9fb1b3fe4b..fae09009a5 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -1329,139 +1329,84 @@ out: #define ATTR_ATIME_SET (1 << 7) #define ATTR_MTIME_SET (1 << 8) -static void v9fs_setattr_post_truncate(V9fsState *s, V9fsSetattrState *vs, - int err) +static void v9fs_setattr(void *opaque) { - if (err == -1) { - err = -errno; + int err = 0; + int32_t fid; + V9fsFidState *fidp; + size_t offset = 7; + V9fsIattr v9iattr; + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; + + pdu_unmarshal(pdu, offset, "dI", &fid, &v9iattr); + + fidp = lookup_fid(s, fid); + if (fidp == NULL) { + err = -EINVAL; goto out; } - err = vs->offset; - -out: - complete_pdu(s, vs->pdu, err); - qemu_free(vs); -} - -static void v9fs_setattr_post_chown(V9fsState *s, V9fsSetattrState *vs, int err) -{ - if (err == -1) { - err = -errno; - goto out; - } - - if (vs->v9iattr.valid & (ATTR_SIZE)) { - err = v9fs_do_truncate(s, &vs->fidp->path, vs->v9iattr.size); - } - v9fs_setattr_post_truncate(s, vs, err); - return; - -out: - complete_pdu(s, vs->pdu, err); - qemu_free(vs); -} - -static void v9fs_setattr_post_utimensat(V9fsState *s, V9fsSetattrState *vs, - int err) -{ - if (err == -1) { - err = -errno; - goto out; - } - - /* If the only valid entry in iattr is ctime we can call - * chown(-1,-1) to update the ctime of the file - */ - if ((vs->v9iattr.valid & (ATTR_UID | ATTR_GID)) || - ((vs->v9iattr.valid & ATTR_CTIME) - && !((vs->v9iattr.valid & ATTR_MASK) & ~ATTR_CTIME))) { - if (!(vs->v9iattr.valid & ATTR_UID)) { - vs->v9iattr.uid = -1; + if (v9iattr.valid & ATTR_MODE) { + err = v9fs_co_chmod(s, &fidp->path, v9iattr.mode); + if (err < 0) { + goto out; } - if (!(vs->v9iattr.valid & ATTR_GID)) { - vs->v9iattr.gid = -1; - } - err = v9fs_do_chown(s, &vs->fidp->path, vs->v9iattr.uid, - vs->v9iattr.gid); } - v9fs_setattr_post_chown(s, vs, err); - return; - -out: - complete_pdu(s, vs->pdu, err); - qemu_free(vs); -} - -static void v9fs_setattr_post_chmod(V9fsState *s, V9fsSetattrState *vs, int err) -{ - if (err == -1) { - err = -errno; - goto out; - } - - if (vs->v9iattr.valid & (ATTR_ATIME | ATTR_MTIME)) { + if (v9iattr.valid & (ATTR_ATIME | ATTR_MTIME)) { struct timespec times[2]; - if (vs->v9iattr.valid & ATTR_ATIME) { - if (vs->v9iattr.valid & ATTR_ATIME_SET) { - times[0].tv_sec = vs->v9iattr.atime_sec; - times[0].tv_nsec = vs->v9iattr.atime_nsec; + if (v9iattr.valid & ATTR_ATIME) { + if (v9iattr.valid & ATTR_ATIME_SET) { + times[0].tv_sec = v9iattr.atime_sec; + times[0].tv_nsec = v9iattr.atime_nsec; } else { times[0].tv_nsec = UTIME_NOW; } } else { times[0].tv_nsec = UTIME_OMIT; } - - if (vs->v9iattr.valid & ATTR_MTIME) { - if (vs->v9iattr.valid & ATTR_MTIME_SET) { - times[1].tv_sec = vs->v9iattr.mtime_sec; - times[1].tv_nsec = vs->v9iattr.mtime_nsec; + if (v9iattr.valid & ATTR_MTIME) { + if (v9iattr.valid & ATTR_MTIME_SET) { + times[1].tv_sec = v9iattr.mtime_sec; + times[1].tv_nsec = v9iattr.mtime_nsec; } else { times[1].tv_nsec = UTIME_NOW; } } else { times[1].tv_nsec = UTIME_OMIT; } - err = v9fs_do_utimensat(s, &vs->fidp->path, times); + err = v9fs_co_utimensat(s, &fidp->path, times); + if (err < 0) { + goto out; + } } - v9fs_setattr_post_utimensat(s, vs, err); - return; - + /* + * If the only valid entry in iattr is ctime we can call + * chown(-1,-1) to update the ctime of the file + */ + if ((v9iattr.valid & (ATTR_UID | ATTR_GID)) || + ((v9iattr.valid & ATTR_CTIME) + && !((v9iattr.valid & ATTR_MASK) & ~ATTR_CTIME))) { + if (!(v9iattr.valid & ATTR_UID)) { + v9iattr.uid = -1; + } + if (!(v9iattr.valid & ATTR_GID)) { + v9iattr.gid = -1; + } + err = v9fs_co_chown(s, &fidp->path, v9iattr.uid, + v9iattr.gid); + if (err < 0) { + goto out; + } + } + if (v9iattr.valid & (ATTR_SIZE)) { + err = v9fs_co_truncate(s, &fidp->path, v9iattr.size); + if (err < 0) { + goto out; + } + } + err = offset; out: - complete_pdu(s, vs->pdu, err); - qemu_free(vs); -} - -static void v9fs_setattr(void *opaque) -{ - V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; - int32_t fid; - V9fsSetattrState *vs; - int err = 0; - - vs = qemu_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; - - pdu_unmarshal(pdu, vs->offset, "dI", &fid, &vs->v9iattr); - - vs->fidp = lookup_fid(s, fid); - if (vs->fidp == NULL) { - err = -EINVAL; - goto out; - } - - if (vs->v9iattr.valid & ATTR_MODE) { - err = v9fs_do_chmod(s, &vs->fidp->path, vs->v9iattr.mode); - } - - v9fs_setattr_post_chmod(s, vs, err); - return; - -out: - complete_pdu(s, vs->pdu, err); - qemu_free(vs); + complete_pdu(s, pdu, err); } static void v9fs_walk_complete(V9fsState *s, V9fsWalkState *vs, int err) diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h index a62eda078a..6a82649205 100644 --- a/hw/9pfs/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -374,14 +374,6 @@ typedef struct V9fsIattr int64_t mtime_nsec; } V9fsIattr; -typedef struct V9fsSetattrState -{ - V9fsPDU *pdu; - size_t offset; - V9fsIattr v9iattr; - V9fsFidState *fidp; -} V9fsSetattrState; - struct virtio_9p_config { /* number of characters in tag */ From 1ceffa546aa756e8085828df2e33c7e6463a307c Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Wed, 18 May 2011 16:05:34 -0700 Subject: [PATCH 14/24] hw/9pfs: Add yield support to xattr related coroutine This include llistxattr and lgetxattr. Signed-off-by: Aneesh Kumar K.V --- Makefile.objs | 1 + hw/9pfs/coxattr.c | 50 ++++++++++++++++++++++++++++++++++++++++ hw/9pfs/virtio-9p-coth.h | 3 +++ 3 files changed, 54 insertions(+) create mode 100644 hw/9pfs/coxattr.c diff --git a/Makefile.objs b/Makefile.objs index efacf0fb22..16eef384f6 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -306,6 +306,7 @@ hw-obj-$(CONFIG_SOUND) += $(sound-obj-y) 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-local.o virtio-9p-xattr.o 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o virtio-9p-posix-acl.o 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-coth.o cofs.o codir.o cofile.o +9pfs-nested-$(CONFIG_VIRTFS) += coxattr.o hw-obj-$(CONFIG_REALLY_VIRTFS) += $(addprefix 9pfs/, $(9pfs-nested-y)) $(addprefix 9pfs/, $(9pfs-nested-y)): QEMU_CFLAGS+=$(GLIB_CFLAGS) diff --git a/hw/9pfs/coxattr.c b/hw/9pfs/coxattr.c new file mode 100644 index 0000000000..2fba2c98c2 --- /dev/null +++ b/hw/9pfs/coxattr.c @@ -0,0 +1,50 @@ + +/* + * Virtio 9p backend + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Aneesh Kumar K.V + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#include "fsdev/qemu-fsdev.h" +#include "qemu-thread.h" +#include "qemu-coroutine.h" +#include "virtio-9p-coth.h" + +int v9fs_co_llistxattr(V9fsState *s, V9fsString *path, void *value, size_t size) +{ + int err; + + v9fs_co_run_in_worker( + { + err = s->ops->llistxattr(&s->ctx, path->data, value, size); + if (err < 0) { + err = -errno; + } + }); + return err; +} + +int v9fs_co_lgetxattr(V9fsState *s, V9fsString *path, + V9fsString *xattr_name, + void *value, size_t size) +{ + int err; + + v9fs_co_run_in_worker( + { + err = s->ops->lgetxattr(&s->ctx, path->data, + xattr_name->data, + value, size); + if (err < 0) { + err = -errno; + } + }); + return err; +} diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/virtio-9p-coth.h index 09f232adbe..eb0c99a648 100644 --- a/hw/9pfs/virtio-9p-coth.h +++ b/hw/9pfs/virtio-9p-coth.h @@ -68,4 +68,7 @@ extern int v9fs_co_chmod(V9fsState *, V9fsString *, mode_t); extern int v9fs_co_utimensat(V9fsState *, V9fsString *, struct timespec [2]); extern int v9fs_co_chown(V9fsState *, V9fsString *, uid_t, gid_t); extern int v9fs_co_truncate(V9fsState *, V9fsString *, off_t); +extern int v9fs_co_llistxattr(V9fsState *, V9fsString *, void *, size_t); +extern int v9fs_co_lgetxattr(V9fsState *, V9fsString *, + V9fsString *, void *, size_t); #endif From 670185a64166c93d58df256c5f8ebd7596341f43 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Wed, 18 May 2011 16:05:48 -0700 Subject: [PATCH 15/24] hw/9pfs: Update v9fs_xattrwalk to coroutines Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/virtio-9p.c | 198 ++++++++++++++------------------------------ 1 file changed, 63 insertions(+), 135 deletions(-) diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index fae09009a5..124ca553e9 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -239,21 +239,6 @@ static int v9fs_do_statfs(V9fsState *s, V9fsString *path, struct statfs *stbuf) return s->ops->statfs(&s->ctx, path->data, stbuf); } -static ssize_t v9fs_do_lgetxattr(V9fsState *s, V9fsString *path, - V9fsString *xattr_name, - void *value, size_t size) -{ - return s->ops->lgetxattr(&s->ctx, path->data, - xattr_name->data, value, size); -} - -static ssize_t v9fs_do_llistxattr(V9fsState *s, V9fsString *path, - void *value, size_t size) -{ - return s->ops->llistxattr(&s->ctx, path->data, - value, size); -} - static int v9fs_do_lsetxattr(V9fsState *s, V9fsString *path, V9fsString *xattr_name, void *value, size_t size, int flags) @@ -3271,149 +3256,92 @@ out: qemu_free(vs); } -static void v9fs_post_xattr_getvalue(V9fsState *s, V9fsXattrState *vs, int err) -{ - - if (err < 0) { - err = -errno; - free_fid(s, vs->xattr_fidp->fid); - goto out; - } - vs->offset += pdu_marshal(vs->pdu, vs->offset, "q", vs->size); - err = vs->offset; -out: - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->name); - qemu_free(vs); - return; -} - -static void v9fs_post_xattr_check(V9fsState *s, V9fsXattrState *vs, ssize_t err) -{ - if (err < 0) { - err = -errno; - free_fid(s, vs->xattr_fidp->fid); - goto out; - } - /* - * Read the xattr value - */ - vs->xattr_fidp->fs.xattr.len = vs->size; - vs->xattr_fidp->fid_type = P9_FID_XATTR; - vs->xattr_fidp->fs.xattr.copied_len = -1; - if (vs->size) { - vs->xattr_fidp->fs.xattr.value = qemu_malloc(vs->size); - err = v9fs_do_lgetxattr(s, &vs->xattr_fidp->path, - &vs->name, vs->xattr_fidp->fs.xattr.value, - vs->xattr_fidp->fs.xattr.len); - } - v9fs_post_xattr_getvalue(s, vs, err); - return; -out: - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->name); - qemu_free(vs); -} - -static void v9fs_post_lxattr_getvalue(V9fsState *s, - V9fsXattrState *vs, int err) -{ - if (err < 0) { - err = -errno; - free_fid(s, vs->xattr_fidp->fid); - goto out; - } - vs->offset += pdu_marshal(vs->pdu, vs->offset, "q", vs->size); - err = vs->offset; -out: - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->name); - qemu_free(vs); - return; -} - -static void v9fs_post_lxattr_check(V9fsState *s, - V9fsXattrState *vs, ssize_t err) -{ - if (err < 0) { - err = -errno; - free_fid(s, vs->xattr_fidp->fid); - goto out; - } - /* - * Read the xattr value - */ - vs->xattr_fidp->fs.xattr.len = vs->size; - vs->xattr_fidp->fid_type = P9_FID_XATTR; - vs->xattr_fidp->fs.xattr.copied_len = -1; - if (vs->size) { - vs->xattr_fidp->fs.xattr.value = qemu_malloc(vs->size); - err = v9fs_do_llistxattr(s, &vs->xattr_fidp->path, - vs->xattr_fidp->fs.xattr.value, - vs->xattr_fidp->fs.xattr.len); - } - v9fs_post_lxattr_getvalue(s, vs, err); - return; -out: - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->name); - qemu_free(vs); -} - static void v9fs_xattrwalk(void *opaque) { + int64_t size; + V9fsString name; + ssize_t err = 0; + size_t offset = 7; + int32_t fid, newfid; + V9fsFidState *file_fidp; + V9fsFidState *xattr_fidp; V9fsPDU *pdu = opaque; V9fsState *s = pdu->s; - ssize_t err = 0; - V9fsXattrState *vs; - int32_t fid, newfid; - vs = qemu_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; - - pdu_unmarshal(vs->pdu, vs->offset, "dds", &fid, &newfid, &vs->name); - vs->file_fidp = lookup_fid(s, fid); - if (vs->file_fidp == NULL) { + pdu_unmarshal(pdu, offset, "dds", &fid, &newfid, &name); + file_fidp = lookup_fid(s, fid); + if (file_fidp == NULL) { err = -ENOENT; goto out; } - - vs->xattr_fidp = alloc_fid(s, newfid); - if (vs->xattr_fidp == NULL) { + xattr_fidp = alloc_fid(s, newfid); + if (xattr_fidp == NULL) { err = -EINVAL; goto out; } - - v9fs_string_copy(&vs->xattr_fidp->path, &vs->file_fidp->path); - if (vs->name.data[0] == 0) { + v9fs_string_copy(&xattr_fidp->path, &file_fidp->path); + if (name.data[0] == 0) { /* * listxattr request. Get the size first */ - vs->size = v9fs_do_llistxattr(s, &vs->xattr_fidp->path, - NULL, 0); - if (vs->size < 0) { - err = vs->size; + size = v9fs_co_llistxattr(s, &xattr_fidp->path, NULL, 0); + if (size < 0) { + err = size; + free_fid(s, xattr_fidp->fid); + goto out; } - v9fs_post_lxattr_check(s, vs, err); - return; + /* + * Read the xattr value + */ + xattr_fidp->fs.xattr.len = size; + xattr_fidp->fid_type = P9_FID_XATTR; + xattr_fidp->fs.xattr.copied_len = -1; + if (size) { + xattr_fidp->fs.xattr.value = qemu_malloc(size); + err = v9fs_co_llistxattr(s, &xattr_fidp->path, + xattr_fidp->fs.xattr.value, + xattr_fidp->fs.xattr.len); + if (err < 0) { + free_fid(s, xattr_fidp->fid); + goto out; + } + } + offset += pdu_marshal(pdu, offset, "q", size); + err = offset; } else { /* * specific xattr fid. We check for xattr * presence also collect the xattr size */ - vs->size = v9fs_do_lgetxattr(s, &vs->xattr_fidp->path, - &vs->name, NULL, 0); - if (vs->size < 0) { - err = vs->size; + size = v9fs_co_lgetxattr(s, &xattr_fidp->path, + &name, NULL, 0); + if (size < 0) { + err = size; + free_fid(s, xattr_fidp->fid); + goto out; } - v9fs_post_xattr_check(s, vs, err); - return; + /* + * Read the xattr value + */ + xattr_fidp->fs.xattr.len = size; + xattr_fidp->fid_type = P9_FID_XATTR; + xattr_fidp->fs.xattr.copied_len = -1; + if (size) { + xattr_fidp->fs.xattr.value = qemu_malloc(size); + err = v9fs_co_lgetxattr(s, &xattr_fidp->path, + &name, xattr_fidp->fs.xattr.value, + xattr_fidp->fs.xattr.len); + if (err < 0) { + free_fid(s, xattr_fidp->fid); + goto out; + } + } + offset += pdu_marshal(pdu, offset, "q", size); + err = offset; } out: - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->name); - qemu_free(vs); + complete_pdu(s, pdu, err); + v9fs_string_free(&name); } static void v9fs_xattrcreate(void *opaque) From f10ff58d019b5abf90d5533074e45f86253e5bc0 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Wed, 18 May 2011 16:06:26 -0700 Subject: [PATCH 16/24] hw/9pfs: Update v9fs_xattrcreate to use coroutines Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/virtio-9p.c | 53 ++++++++++++++++++++++----------------------- hw/9pfs/virtio-9p.h | 11 ---------- 2 files changed, 26 insertions(+), 38 deletions(-) diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index 124ca553e9..757316b769 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -3346,43 +3346,42 @@ out: static void v9fs_xattrcreate(void *opaque) { - V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; int flags; int32_t fid; + int64_t size; ssize_t err = 0; - V9fsXattrState *vs; + V9fsString name; + size_t offset = 7; + V9fsFidState *file_fidp; + V9fsFidState *xattr_fidp; + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; - vs = qemu_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; + pdu_unmarshal(pdu, offset, "dsqd", + &fid, &name, &size, &flags); - pdu_unmarshal(vs->pdu, vs->offset, "dsqd", - &fid, &vs->name, &vs->size, &flags); - - vs->file_fidp = lookup_fid(s, fid); - if (vs->file_fidp == NULL) { + file_fidp = lookup_fid(s, fid); + if (file_fidp == NULL) { err = -EINVAL; goto out; } - /* Make the file fid point to xattr */ - vs->xattr_fidp = vs->file_fidp; - vs->xattr_fidp->fid_type = P9_FID_XATTR; - vs->xattr_fidp->fs.xattr.copied_len = 0; - vs->xattr_fidp->fs.xattr.len = vs->size; - vs->xattr_fidp->fs.xattr.flags = flags; - v9fs_string_init(&vs->xattr_fidp->fs.xattr.name); - v9fs_string_copy(&vs->xattr_fidp->fs.xattr.name, &vs->name); - if (vs->size) - vs->xattr_fidp->fs.xattr.value = qemu_malloc(vs->size); - else - vs->xattr_fidp->fs.xattr.value = NULL; - + xattr_fidp = file_fidp; + xattr_fidp->fid_type = P9_FID_XATTR; + xattr_fidp->fs.xattr.copied_len = 0; + 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); + if (size) { + xattr_fidp->fs.xattr.value = qemu_malloc(size); + } else { + xattr_fidp->fs.xattr.value = NULL; + } + err = offset; out: - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->name); - qemu_free(vs); + complete_pdu(s, pdu, err); + v9fs_string_free(&name); } static void v9fs_readlink(void *opaque) diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h index 6a82649205..3ed46ab3d8 100644 --- a/hw/9pfs/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -399,17 +399,6 @@ typedef struct V9fsRenameState { V9fsString name; } V9fsRenameState; -typedef struct V9fsXattrState -{ - V9fsPDU *pdu; - size_t offset; - V9fsFidState *file_fidp; - V9fsFidState *xattr_fidp; - V9fsString name; - int64_t size; - int flags; - void *value; -} V9fsXattrState; #define P9_LOCK_SUCCESS 0 #define P9_LOCK_BLOCKED 1 From 00ace8c5c534d5b7d42099e7c2e82a79f8591cb7 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Wed, 18 May 2011 16:06:38 -0700 Subject: [PATCH 17/24] hw/9pfs: Add yield support to mknod coroutine Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/cofs.c | 21 +++++++++++++++++++++ hw/9pfs/virtio-9p-coth.h | 2 ++ 2 files changed, 23 insertions(+) diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c index 7e9df852c5..6fcedd8400 100644 --- a/hw/9pfs/cofs.c +++ b/hw/9pfs/cofs.c @@ -120,3 +120,24 @@ int v9fs_co_truncate(V9fsState *s, V9fsString *path, off_t size) }); return err; } + +int v9fs_co_mknod(V9fsState *s, V9fsString *path, uid_t uid, + gid_t gid, dev_t dev, mode_t mode) +{ + int err; + FsCred cred; + + cred_init(&cred); + cred.fc_uid = uid; + cred.fc_gid = gid; + cred.fc_mode = mode; + cred.fc_rdev = dev; + v9fs_co_run_in_worker( + { + err = s->ops->mknod(&s->ctx, path->data, &cred); + if (err < 0) { + err = -errno; + } + }); + return err; +} diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/virtio-9p-coth.h index eb0c99a648..d02368306e 100644 --- a/hw/9pfs/virtio-9p-coth.h +++ b/hw/9pfs/virtio-9p-coth.h @@ -71,4 +71,6 @@ extern int v9fs_co_truncate(V9fsState *, V9fsString *, off_t); extern int v9fs_co_llistxattr(V9fsState *, V9fsString *, void *, size_t); extern int v9fs_co_lgetxattr(V9fsState *, V9fsString *, V9fsString *, void *, size_t); +extern int v9fs_co_mknod(V9fsState *, V9fsString *, uid_t, + gid_t, dev_t, mode_t); #endif From 1b733fed7fe407169523cbdb73d97bb335a7f02c Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Wed, 18 May 2011 16:06:51 -0700 Subject: [PATCH 18/24] hw/9pfs: Update v9fs_mknod to use coroutines Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/virtio-9p.c | 90 ++++++++++++++++----------------------------- 1 file changed, 31 insertions(+), 59 deletions(-) diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index 757316b769..edbcd79776 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -3019,77 +3019,49 @@ out: return; } -static void v9fs_mknod_post_lstat(V9fsState *s, V9fsMkState *vs, int err) -{ - if (err == -1) { - err = -errno; - goto out; - } - - stat_to_qid(&vs->stbuf, &vs->qid); - vs->offset += pdu_marshal(vs->pdu, vs->offset, "Q", &vs->qid); - err = vs->offset; -out: - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->fullname); - v9fs_string_free(&vs->name); - qemu_free(vs); -} - -static void v9fs_mknod_post_mknod(V9fsState *s, V9fsMkState *vs, int err) -{ - if (err == -1) { - err = -errno; - goto out; - } - - err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf); - v9fs_mknod_post_lstat(s, vs, err); - return; -out: - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->fullname); - v9fs_string_free(&vs->name); - qemu_free(vs); -} - static void v9fs_mknod(void *opaque) { + + int mode; + gid_t gid; + int32_t fid; + V9fsQID qid; + int err = 0; + int major, minor; + size_t offset = 7; + V9fsString name; + struct stat stbuf; + V9fsString fullname; + V9fsFidState *fidp; V9fsPDU *pdu = opaque; V9fsState *s = pdu->s; - int32_t fid; - V9fsMkState *vs; - int err = 0; - V9fsFidState *fidp; - gid_t gid; - int mode; - int major, minor; - vs = qemu_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; - - v9fs_string_init(&vs->fullname); - pdu_unmarshal(vs->pdu, vs->offset, "dsdddd", &fid, &vs->name, &mode, - &major, &minor, &gid); + v9fs_string_init(&fullname); + pdu_unmarshal(pdu, offset, "dsdddd", &fid, &name, &mode, + &major, &minor, &gid); fidp = lookup_fid(s, fid); if (fidp == NULL) { err = -ENOENT; goto out; } - - v9fs_string_sprintf(&vs->fullname, "%s/%s", fidp->path.data, vs->name.data); - err = v9fs_do_mknod(s, vs->fullname.data, mode, makedev(major, minor), - fidp->uid, gid); - v9fs_mknod_post_mknod(s, vs, err); - return; - + v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data); + err = v9fs_co_mknod(s, &fullname, fidp->uid, gid, + makedev(major, minor), mode); + if (err < 0) { + goto out; + } + err = v9fs_co_lstat(s, &fullname, &stbuf); + if (err < 0) { + goto out; + } + stat_to_qid(&stbuf, &qid); + err = offset; + err += pdu_marshal(pdu, offset, "Q", &qid); out: - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->fullname); - v9fs_string_free(&vs->name); - qemu_free(vs); + complete_pdu(s, pdu, err); + v9fs_string_free(&fullname); + v9fs_string_free(&name); } /* From d0884642b827ec90a7e66d34f5cf1caa1a031990 Mon Sep 17 00:00:00 2001 From: Venkateswararao Jujjuri Date: Mon, 8 Aug 2011 23:44:24 +0530 Subject: [PATCH 19/24] hw/9pfs: Add yield support for mkdir coroutine Signed-off-by: Venkateswararao Jujjuri Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/codir.c | 19 +++++++++++++++++++ hw/9pfs/virtio-9p-coth.h | 1 + 2 files changed, 20 insertions(+) diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c index 47b10df57d..28f2ad7320 100644 --- a/hw/9pfs/codir.c +++ b/hw/9pfs/codir.c @@ -64,3 +64,22 @@ void v9fs_co_rewinddir(V9fsState *s, V9fsFidState *fidp) s->ops->rewinddir(&s->ctx, fidp->fs.dir); }); } + +int v9fs_co_mkdir(V9fsState *s, char *name, mode_t mode, uid_t uid, gid_t gid) +{ + int err; + FsCred cred; + + cred_init(&cred); + cred.fc_mode = mode; + cred.fc_uid = uid; + cred.fc_gid = gid; + v9fs_co_run_in_worker( + { + err = s->ops->mkdir(&s->ctx, name, &cred); + if (err < 0) { + err = -errno; + } + }); + return err; +} diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/virtio-9p-coth.h index d02368306e..96e88d8656 100644 --- a/hw/9pfs/virtio-9p-coth.h +++ b/hw/9pfs/virtio-9p-coth.h @@ -73,4 +73,5 @@ extern int v9fs_co_lgetxattr(V9fsState *, V9fsString *, V9fsString *, void *, size_t); extern int v9fs_co_mknod(V9fsState *, V9fsString *, uid_t, gid_t, dev_t, mode_t); +extern int v9fs_co_mkdir(V9fsState *, char *, mode_t, uid_t, gid_t); #endif From e84861f75e3bb6473cd8576870f3f4cac334d423 Mon Sep 17 00:00:00 2001 From: Venkateswararao Jujjuri Date: Mon, 8 Aug 2011 23:46:14 +0530 Subject: [PATCH 20/24] hw/9pfs: Update mkdir to use coroutines Signed-off-by: Venkateswararao Jujjuri " Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/virtio-9p.c | 96 ++++++++++++--------------------------------- 1 file changed, 25 insertions(+), 71 deletions(-) diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index edbcd79776..37ba72cc8f 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -149,19 +149,6 @@ static int v9fs_do_mknod(V9fsState *s, char *name, return s->ops->mknod(&s->ctx, name, &cred); } -static int v9fs_do_mkdir(V9fsState *s, char *name, mode_t mode, - uid_t uid, gid_t gid) -{ - FsCred cred; - - cred_init(&cred); - cred.fc_uid = uid; - cred.fc_gid = gid; - cred.fc_mode = mode; - - return s->ops->mkdir(&s->ctx, name, &cred); -} - static int v9fs_do_fstat(V9fsState *s, int fd, struct stat *stbuf) { return s->ops->fstat(&s->ctx, fd, stbuf); @@ -2329,8 +2316,7 @@ out: static void v9fs_create_post_mkdir(V9fsState *s, V9fsCreateState *vs, int err) { - if (err) { - err = -errno; + if (err < 0) { goto out; } @@ -2379,7 +2365,7 @@ static void v9fs_create_post_lstat(V9fsState *s, V9fsCreateState *vs, int err) } if (vs->perm & P9_STAT_MODE_DIR) { - err = v9fs_do_mkdir(s, vs->fullname.data, vs->perm & 0777, + err = v9fs_co_mkdir(s, vs->fullname.data, vs->perm & 0777, vs->fidp->uid, -1); v9fs_create_post_mkdir(s, vs, err); } else if (vs->perm & P9_STAT_MODE_SYMLINK) { @@ -3157,75 +3143,43 @@ out: qemu_free(vs); } -static void v9fs_mkdir_post_lstat(V9fsState *s, V9fsMkState *vs, int err) -{ - if (err == -1) { - err = -errno; - goto out; - } - - stat_to_qid(&vs->stbuf, &vs->qid); - vs->offset += pdu_marshal(vs->pdu, vs->offset, "Q", &vs->qid); - err = vs->offset; -out: - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->fullname); - v9fs_string_free(&vs->name); - qemu_free(vs); -} - -static void v9fs_mkdir_post_mkdir(V9fsState *s, V9fsMkState *vs, int err) -{ - if (err == -1) { - err = -errno; - goto out; - } - - err = v9fs_do_lstat(s, &vs->fullname, &vs->stbuf); - v9fs_mkdir_post_lstat(s, vs, err); - return; -out: - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->fullname); - v9fs_string_free(&vs->name); - qemu_free(vs); -} - static void v9fs_mkdir(void *opaque) { V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; + size_t offset = 7; int32_t fid; - V9fsMkState *vs; - int err = 0; + struct stat stbuf; + V9fsString name, fullname; + V9fsQID qid; V9fsFidState *fidp; gid_t gid; int mode; + int err = 0; - vs = qemu_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; + v9fs_string_init(&fullname); + pdu_unmarshal(pdu, offset, "dsdd", &fid, &name, &mode, &gid); - v9fs_string_init(&vs->fullname); - pdu_unmarshal(vs->pdu, vs->offset, "dsdd", &fid, &vs->name, &mode, - &gid); - - fidp = lookup_fid(s, fid); + fidp = lookup_fid(pdu->s, fid); if (fidp == NULL) { err = -ENOENT; goto out; } - - v9fs_string_sprintf(&vs->fullname, "%s/%s", fidp->path.data, vs->name.data); - err = v9fs_do_mkdir(s, vs->fullname.data, mode, fidp->uid, gid); - v9fs_mkdir_post_mkdir(s, vs, err); - return; - + v9fs_string_sprintf(&fullname, "%s/%s", fidp->path.data, name.data); + err = v9fs_co_mkdir(pdu->s, fullname.data, mode, fidp->uid, gid); + if (err < 0) { + goto out; + } + err = v9fs_co_lstat(pdu->s, &fullname, &stbuf); + if (err < 0) { + goto out; + } + stat_to_qid(&stbuf, &qid); + offset += pdu_marshal(pdu, offset, "Q", &qid); + err = offset; out: - complete_pdu(s, vs->pdu, err); - v9fs_string_free(&vs->fullname); - v9fs_string_free(&vs->name); - qemu_free(vs); + complete_pdu(pdu->s, pdu, err); + v9fs_string_free(&fullname); + v9fs_string_free(&name); } static void v9fs_xattrwalk(void *opaque) From b4b1537b96fc57b50a676006868ab97093d040c8 Mon Sep 17 00:00:00 2001 From: Venkateswararao Jujjuri Date: Mon, 8 Aug 2011 23:48:29 +0530 Subject: [PATCH 21/24] hw/9pfs: Add yield support for remove Signed-off-by: Venkateswararao Jujjuri Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/cofs.c | 14 ++++++++++++++ hw/9pfs/virtio-9p-coth.h | 1 + 2 files changed, 15 insertions(+) diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c index 6fcedd8400..8fbfe7359f 100644 --- a/hw/9pfs/cofs.c +++ b/hw/9pfs/cofs.c @@ -141,3 +141,17 @@ int v9fs_co_mknod(V9fsState *s, V9fsString *path, uid_t uid, }); return err; } + +int v9fs_co_remove(V9fsState *s, V9fsString *path) +{ + int err; + + v9fs_co_run_in_worker( + { + err = s->ops->remove(&s->ctx, path->data); + if (err < 0) { + err = -errno; + } + }); + return err; +} diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/virtio-9p-coth.h index 96e88d8656..60795c48fa 100644 --- a/hw/9pfs/virtio-9p-coth.h +++ b/hw/9pfs/virtio-9p-coth.h @@ -74,4 +74,5 @@ extern int v9fs_co_lgetxattr(V9fsState *, V9fsString *, extern int v9fs_co_mknod(V9fsState *, V9fsString *, uid_t, gid_t, dev_t, mode_t); extern int v9fs_co_mkdir(V9fsState *, char *, mode_t, uid_t, gid_t); +extern int v9fs_co_remove(V9fsState *, V9fsString *); #endif From ae1ef571fc4ce5cc016311a030357c6a8d851dfe Mon Sep 17 00:00:00 2001 From: Venkateswararao Jujjuri Date: Mon, 8 Aug 2011 23:50:20 +0530 Subject: [PATCH 22/24] hw/9pfs: Update v9fs_remove to use coroutines Signed-off-by: Venkateswararao Jujjuri Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/virtio-9p.c | 50 ++++++++++++--------------------------------- hw/9pfs/virtio-9p.h | 6 ------ 2 files changed, 13 insertions(+), 43 deletions(-) diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index 37ba72cc8f..86d4dec157 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -211,11 +211,6 @@ static int v9fs_do_utimensat(V9fsState *s, V9fsString *path, return s->ops->utimensat(&s->ctx, path->data, times); } -static int v9fs_do_remove(V9fsState *s, V9fsString *path) -{ - return s->ops->remove(&s->ctx, path->data); -} - static int v9fs_do_fsync(V9fsState *s, int fd, int datasync) { return s->ops->fsync(&s->ctx, fd, datasync); @@ -2579,49 +2574,30 @@ out: complete_pdu(s, pdu, err); } -static void v9fs_remove_post_remove(V9fsState *s, V9fsRemoveState *vs, - int err) -{ - if (err < 0) { - err = -errno; - } else { - err = vs->offset; - } - - /* For TREMOVE we need to clunk the fid even on failed remove */ - free_fid(s, vs->fidp->fid); - - complete_pdu(s, vs->pdu, err); - qemu_free(vs); -} - static void v9fs_remove(void *opaque) { - V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; int32_t fid; - V9fsRemoveState *vs; int err = 0; + size_t offset = 7; + V9fsFidState *fidp; + V9fsPDU *pdu = opaque; - vs = qemu_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; + pdu_unmarshal(pdu, offset, "d", &fid); - pdu_unmarshal(vs->pdu, vs->offset, "d", &fid); - - vs->fidp = lookup_fid(s, fid); - if (vs->fidp == NULL) { + fidp = lookup_fid(pdu->s, fid); + if (fidp == NULL) { err = -EINVAL; goto out; } + err = v9fs_co_remove(pdu->s, &fidp->path); + if (!err) { + err = offset; + } - err = v9fs_do_remove(s, &vs->fidp->path); - v9fs_remove_post_remove(s, vs, err); - return; - + /* For TREMOVE we need to clunk the fid even on failed remove */ + free_fid(pdu->s, fidp->fid); out: - complete_pdu(s, pdu, err); - qemu_free(vs); + complete_pdu(pdu->s, pdu, err); } static void v9fs_wstat_post_truncate(V9fsState *s, V9fsWstatState *vs, int err) diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h index 3ed46ab3d8..194f0ea6d3 100644 --- a/hw/9pfs/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -333,12 +333,6 @@ typedef struct V9fsWriteState { int cnt; } V9fsWriteState; -typedef struct V9fsRemoveState { - V9fsPDU *pdu; - size_t offset; - V9fsFidState *fidp; -} V9fsRemoveState; - typedef struct V9fsWstatState { V9fsPDU *pdu; From 2a487e05def38b73ae25db61f62fdc00b9e5e732 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Sat, 7 May 2011 16:09:10 +0530 Subject: [PATCH 23/24] hw/9pfs: Add yeild support to rename coroutine Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/cofs.c | 14 ++++++++++++++ hw/9pfs/virtio-9p-coth.h | 1 + 2 files changed, 15 insertions(+) diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c index 8fbfe7359f..473ce53568 100644 --- a/hw/9pfs/cofs.c +++ b/hw/9pfs/cofs.c @@ -155,3 +155,17 @@ int v9fs_co_remove(V9fsState *s, V9fsString *path) }); return err; } + +int v9fs_co_rename(V9fsState *s, V9fsString *oldpath, V9fsString *newpath) +{ + int err; + + v9fs_co_run_in_worker( + { + err = s->ops->rename(&s->ctx, oldpath->data, newpath->data); + if (err < 0) { + err = -errno; + } + }); + return err; +} diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/virtio-9p-coth.h index 60795c48fa..11272d3357 100644 --- a/hw/9pfs/virtio-9p-coth.h +++ b/hw/9pfs/virtio-9p-coth.h @@ -75,4 +75,5 @@ extern int v9fs_co_mknod(V9fsState *, V9fsString *, uid_t, gid_t, dev_t, mode_t); extern int v9fs_co_mkdir(V9fsState *, char *, mode_t, uid_t, gid_t); extern int v9fs_co_remove(V9fsState *, V9fsString *); +extern int v9fs_co_rename(V9fsState *, V9fsString *, V9fsString *); #endif From 930b1e173b31e1a0e77535a9868dc3ec1f426a43 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Sat, 7 May 2011 16:01:33 +0530 Subject: [PATCH 24/24] hw/9pfs: Update vfs_rename to use coroutines I guess TRENAME 9p operation needs an update. The 9p op should more similar renameat. Otherwise anything other than path cannot track the fid. Signed-off-by: Aneesh Kumar K.V --- hw/9pfs/virtio-9p.c | 134 ++++++++++++++++++-------------------------- hw/9pfs/virtio-9p.h | 9 --- 2 files changed, 53 insertions(+), 90 deletions(-) diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index 86d4dec157..f2193d6961 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -189,12 +189,6 @@ static int v9fs_do_truncate(V9fsState *s, V9fsString *path, off_t size) return s->ops->truncate(&s->ctx, path->data, size); } -static int v9fs_do_rename(V9fsState *s, V9fsString *oldpath, - V9fsString *newpath) -{ - return s->ops->rename(&s->ctx, oldpath->data, newpath->data); -} - static int v9fs_do_chown(V9fsState *s, V9fsString *path, uid_t uid, gid_t gid) { FsCred cred; @@ -2633,84 +2627,74 @@ out: qemu_free(vs); } -static int v9fs_complete_rename(V9fsState *s, V9fsRenameState *vs) +static int v9fs_complete_rename(V9fsState *s, V9fsFidState *fidp, + int32_t newdirfid, V9fsString *name) { + char *end; int err = 0; char *old_name, *new_name; - char *end; - if (vs->newdirfid != -1) { + if (newdirfid != -1) { V9fsFidState *dirfidp; - dirfidp = lookup_fid(s, vs->newdirfid); - + dirfidp = lookup_fid(s, newdirfid); if (dirfidp == NULL) { err = -ENOENT; goto out; } - BUG_ON(dirfidp->fid_type != P9_FID_NONE); - new_name = qemu_mallocz(dirfidp->path.size + vs->name.size + 2); + new_name = qemu_mallocz(dirfidp->path.size + name->size + 2); strcpy(new_name, dirfidp->path.data); strcat(new_name, "/"); - strcat(new_name + dirfidp->path.size, vs->name.data); + strcat(new_name + dirfidp->path.size, name->data); } else { - old_name = vs->fidp->path.data; + old_name = fidp->path.data; end = strrchr(old_name, '/'); if (end) { end++; } else { end = old_name; } - new_name = qemu_mallocz(end - old_name + vs->name.size + 1); + new_name = qemu_mallocz(end - old_name + name->size + 1); strncat(new_name, old_name, end - old_name); - strncat(new_name + (end - old_name), vs->name.data, vs->name.size); + strncat(new_name + (end - old_name), name->data, name->size); } - v9fs_string_free(&vs->name); - vs->name.data = qemu_strdup(new_name); - vs->name.size = strlen(new_name); + v9fs_string_free(name); + name->data = new_name; + name->size = strlen(new_name); - if (strcmp(new_name, vs->fidp->path.data) != 0) { - if (v9fs_do_rename(s, &vs->fidp->path, &vs->name)) { - err = -errno; - } else { - V9fsFidState *fidp; - /* - * Fixup fid's pointing to the old name to - * start pointing to the new name - */ - for (fidp = s->fid_list; fidp; fidp = fidp->next) { - if (vs->fidp == fidp) { - /* - * we replace name of this fid towards the end so - * that our below v9fs_path_is_ancestor check will - * work - */ - continue; - } - if (v9fs_path_is_ancestor(&vs->fidp->path, &fidp->path)) { - /* replace the name */ - v9fs_fix_path(&fidp->path, &vs->name, - strlen(vs->fidp->path.data)); - } - } - v9fs_string_copy(&vs->fidp->path, &vs->name); + if (strcmp(new_name, fidp->path.data) != 0) { + err = v9fs_co_rename(s, &fidp->path, name); + if (err < 0) { + goto out; } + V9fsFidState *tfidp; + /* + * Fixup fid's pointing to the old name to + * start pointing to the new name + */ + for (tfidp = s->fid_list; tfidp; tfidp = tfidp->next) { + if (fidp == tfidp) { + /* + * we replace name of this fid towards the end + * so that our below strcmp will work + */ + continue; + } + if (v9fs_path_is_ancestor(&fidp->path, &tfidp->path)) { + /* replace the name */ + v9fs_fix_path(&tfidp->path, name, strlen(fidp->path.data)); + } + } + v9fs_string_copy(&fidp->path, name); } out: - v9fs_string_free(&vs->name); return err; } -static void v9fs_rename_post_rename(V9fsState *s, V9fsRenameState *vs, int err) -{ - complete_pdu(s, vs->pdu, err); - qemu_free(vs); -} - static void v9fs_wstat_post_chown(V9fsState *s, V9fsWstatState *vs, int err) { if (err < 0) { @@ -2718,18 +2702,7 @@ static void v9fs_wstat_post_chown(V9fsState *s, V9fsWstatState *vs, int err) } if (vs->v9stat.name.size != 0) { - V9fsRenameState *vr; - - vr = qemu_mallocz(sizeof(V9fsRenameState)); - vr->newdirfid = -1; - vr->pdu = vs->pdu; - vr->fidp = vs->fidp; - vr->offset = vs->offset; - vr->name.size = vs->v9stat.name.size; - vr->name.data = qemu_strdup(vs->v9stat.name.data); - - err = v9fs_complete_rename(s, vr); - qemu_free(vr); + err = v9fs_complete_rename(s, vs->fidp, -1, &vs->v9stat.name); } v9fs_wstat_post_rename(s, vs, err); return; @@ -2742,32 +2715,31 @@ out: static void v9fs_rename(void *opaque) { + int32_t fid; + ssize_t err = 0; + size_t offset = 7; + V9fsString name; + int32_t newdirfid; + V9fsFidState *fidp; V9fsPDU *pdu = opaque; V9fsState *s = pdu->s; - int32_t fid; - V9fsRenameState *vs; - ssize_t err = 0; - vs = qemu_malloc(sizeof(*vs)); - vs->pdu = pdu; - vs->offset = 7; + pdu_unmarshal(pdu, offset, "dds", &fid, &newdirfid, &name); - pdu_unmarshal(vs->pdu, vs->offset, "dds", &fid, &vs->newdirfid, &vs->name); - - vs->fidp = lookup_fid(s, fid); - if (vs->fidp == NULL) { + fidp = lookup_fid(s, fid); + if (fidp == NULL) { err = -ENOENT; goto out; } + BUG_ON(fidp->fid_type != P9_FID_NONE); - BUG_ON(vs->fidp->fid_type != P9_FID_NONE); - - err = v9fs_complete_rename(s, vs); - v9fs_rename_post_rename(s, vs, err); - return; + err = v9fs_complete_rename(s, fidp, newdirfid, &name); + if (!err) { + err = offset; + } out: - complete_pdu(s, vs->pdu, err); - qemu_free(vs); + complete_pdu(s, pdu, err); + v9fs_string_free(&name); } static void v9fs_wstat_post_utime(V9fsState *s, V9fsWstatState *vs, int err) diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h index 194f0ea6d3..46d79da920 100644 --- a/hw/9pfs/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -385,15 +385,6 @@ typedef struct V9fsMkState { V9fsString fullname; } V9fsMkState; -typedef struct V9fsRenameState { - V9fsPDU *pdu; - V9fsFidState *fidp; - size_t offset; - int32_t newdirfid; - V9fsString name; -} V9fsRenameState; - - #define P9_LOCK_SUCCESS 0 #define P9_LOCK_BLOCKED 1 #define P9_LOCK_ERROR 2