Merge remote-tracking branch 'aneesh/for-upstream-1' into staging

This commit is contained in:
Anthony Liguori 2011-08-12 07:52:53 -05:00
commit eecaecedec
11 changed files with 1037 additions and 867 deletions

View file

@ -305,8 +305,11 @@ 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 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)
######################################################################

18
configure vendored
View file

@ -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
##########################################

85
hw/9pfs/codir.c Normal file
View file

@ -0,0 +1,85 @@
/*
* Virtio 9p backend
*
* Copyright IBM, Corp. 2011
*
* Authors:
* Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
*
* 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);
});
}
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;
}

32
hw/9pfs/cofile.c Normal file
View file

@ -0,0 +1,32 @@
/*
* Virtio 9p backend
*
* Copyright IBM, Corp. 2011
*
* Authors:
* Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
*
* 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;
}

171
hw/9pfs/cofs.c Normal file
View file

@ -0,0 +1,171 @@
/*
* Virtio 9p backend
*
* Copyright IBM, Corp. 2011
*
* Authors:
* Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
*
* 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;
}
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;
}
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;
}
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;
}
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;
}
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;
}

50
hw/9pfs/coxattr.c Normal file
View file

@ -0,0 +1,50 @@
/*
* Virtio 9p backend
*
* Copyright IBM, Corp. 2011
*
* Authors:
* Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
*
* 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;
}

102
hw/9pfs/virtio-9p-coth.c Normal file
View file

@ -0,0 +1,102 @@
/*
* Virtio 9p backend
*
* Copyright IBM, Corp. 2010
*
* Authors:
* Harsh Prateek Bora <harsh@linux.vnet.ibm.com>
* Venkateswararao Jujjuri(JV) <jvrao@linux.vnet.ibm.com>
*
* 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;
}

79
hw/9pfs/virtio-9p-coth.h Normal file
View file

@ -0,0 +1,79 @@
/*
* Virtio 9p backend
*
* Copyright IBM, Corp. 2010
*
* Authors:
* Harsh Prateek Bora <harsh@linux.vnet.ibm.com>
* Venkateswararao Jujjuri(JV) <jvrao@linux.vnet.ibm.com>
*
* 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 "virtio-9p.h"
#include <glib.h>
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);
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 *);
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);
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);
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

View file

@ -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;
}

File diff suppressed because it is too large Load diff

View file

@ -5,7 +5,7 @@
#include <dirent.h>
#include <sys/time.h>
#include <utime.h>
#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;
};
@ -276,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;
@ -339,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;
@ -380,14 +368,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 */
@ -396,28 +376,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;
@ -427,26 +385,6 @@ typedef struct V9fsMkState {
V9fsString fullname;
} V9fsMkState;
typedef struct V9fsRenameState {
V9fsPDU *pdu;
V9fsFidState *fidp;
size_t offset;
int32_t newdirfid;
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
#define P9_LOCK_ERROR 2
@ -493,13 +431,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);
@ -510,5 +441,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