diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2016-01-12 17:37:22 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2016-01-12 17:37:22 +0000 |
commit | 649a1bbaf95adb228f1030ab0618a932bc26aa8b (patch) | |
tree | 80115f368366726a935705ca158881afbda3184b /hw | |
parent | 8acc216b956f30c140520c6c3aff5edcfde16ea6 (diff) | |
parent | 00588a0aa2ade2e32a552633bbbefdc6ae5e32a2 (diff) | |
download | qemu-649a1bbaf95adb228f1030ab0618a932bc26aa8b.zip qemu-649a1bbaf95adb228f1030ab0618a932bc26aa8b.tar.gz qemu-649a1bbaf95adb228f1030ab0618a932bc26aa8b.tar.bz2 |
Merge remote-tracking branch 'remotes/kvaneesh/tags/for-upstream-signed' into staging
VirtFS update:
Cleanups mostly isolating virtio related details into separate files. This
is done to enable easy addition of Xen transport for VirtFS.
The changes include:
1. Rename a bunch of files and functions to make clear they are generic.
2. disentangle virtio transport code and generic 9pfs code.
3. Some function name clean-up.
# gpg: Signature made Tue 12 Jan 2016 06:04:35 GMT using RSA key ID 04C4E23A
# gpg: Good signature from "Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>"
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg: There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 4846 9DE7 1860 360F A6E9 968C DE41 A4FE 04C4 E23A
* remotes/kvaneesh/tags/for-upstream-signed: (25 commits)
9pfs: introduce V9fsVirtioState
9pfs: factor out v9fs_device_{,un}realize_common
9pfs: rename virtio-9p.c to 9p.c
9pfs: rename virtio_9p_set_fd_limit to use v9fs_ prefix
9pfs: move handle_9p_output and make it static function
9pfs: export pdu_{submit,alloc,free}
9pfs: factor out virtio_9p_push_and_notify
9pfs: break out 9p.h from virtio-9p.h
9pfs: break out virtio_init_iov_from_pdu
9pfs: factor out pdu_push_and_notify
9pfs: factor out virtio_pdu_{,un}marshal
9pfs: make pdu_{,un}marshal proper functions
9pfs: PDU processing functions should start pdu_ prefix
9pfs: PDU processing functions don't need to take V9fsState as argument
fsdev: rename virtio-9p-marshal.{c,h} to 9p-iov-marshal.{c,h}
fsdev: break out 9p-marshal.{c,h} from virtio-9p-marshal.{c,h}
9pfs: remove dead code
9pfs: merge hw/virtio/virtio-9p.h into hw/9pfs/virtio-9p.h
9pfs: rename virtio-9p-xattr{,-user}.{c,h} to 9p-xattr{,-user}.{c,h}
9pfs: rename virtio-9p-synth.{c,h} to 9p-synth.{c,h}
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/9pfs/9p-handle.c (renamed from hw/9pfs/virtio-9p-handle.c) | 7 | ||||
-rw-r--r-- | hw/9pfs/9p-local.c (renamed from hw/9pfs/virtio-9p-local.c) | 7 | ||||
-rw-r--r-- | hw/9pfs/9p-posix-acl.c (renamed from hw/9pfs/virtio-9p-posix-acl.c) | 7 | ||||
-rw-r--r-- | hw/9pfs/9p-proxy.c (renamed from hw/9pfs/virtio-9p-proxy.c) | 7 | ||||
-rw-r--r-- | hw/9pfs/9p-proxy.h (renamed from hw/9pfs/virtio-9p-proxy.h) | 10 | ||||
-rw-r--r-- | hw/9pfs/9p-synth.c (renamed from hw/9pfs/virtio-9p-synth.c) | 6 | ||||
-rw-r--r-- | hw/9pfs/9p-synth.h (renamed from hw/9pfs/virtio-9p-synth.h) | 6 | ||||
-rw-r--r-- | hw/9pfs/9p-xattr-user.c (renamed from hw/9pfs/virtio-9p-xattr-user.c) | 7 | ||||
-rw-r--r-- | hw/9pfs/9p-xattr.c (renamed from hw/9pfs/virtio-9p-xattr.c) | 7 | ||||
-rw-r--r-- | hw/9pfs/9p-xattr.h (renamed from hw/9pfs/virtio-9p-xattr.h) | 6 | ||||
-rw-r--r-- | hw/9pfs/9p.c (renamed from hw/9pfs/virtio-9p.c) | 260 | ||||
-rw-r--r-- | hw/9pfs/9p.h | 326 | ||||
-rw-r--r-- | hw/9pfs/Makefile.objs | 14 | ||||
-rw-r--r-- | hw/9pfs/codir.c | 2 | ||||
-rw-r--r-- | hw/9pfs/cofile.c | 2 | ||||
-rw-r--r-- | hw/9pfs/cofs.c | 2 | ||||
-rw-r--r-- | hw/9pfs/coth.c (renamed from hw/9pfs/virtio-9p-coth.c) | 4 | ||||
-rw-r--r-- | hw/9pfs/coth.h (renamed from hw/9pfs/virtio-9p-coth.h) | 6 | ||||
-rw-r--r-- | hw/9pfs/coxattr.c | 2 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p-device.c | 201 | ||||
-rw-r--r-- | hw/9pfs/virtio-9p.h | 391 | ||||
-rw-r--r-- | hw/s390x/virtio-ccw.h | 2 | ||||
-rw-r--r-- | hw/virtio/virtio-pci.h | 3 |
23 files changed, 667 insertions, 618 deletions
diff --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/9p-handle.c index 13eabb9..58b77b4 100644 --- a/hw/9pfs/virtio-9p-handle.c +++ b/hw/9pfs/9p-handle.c @@ -1,5 +1,5 @@ /* - * Virtio 9p handle callback + * 9p handle callback * * Copyright IBM, Corp. 2011 * @@ -11,9 +11,8 @@ * */ -#include "hw/virtio/virtio.h" -#include "virtio-9p.h" -#include "virtio-9p-xattr.h" +#include "9p.h" +#include "9p-xattr.h" #include <arpa/inet.h> #include <pwd.h> #include <grp.h> diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/9p-local.c index f1f2e25..bf63eab 100644 --- a/hw/9pfs/virtio-9p-local.c +++ b/hw/9pfs/9p-local.c @@ -1,5 +1,5 @@ /* - * Virtio 9p Posix callback + * 9p Posix callback * * Copyright IBM, Corp. 2010 * @@ -11,9 +11,8 @@ * */ -#include "hw/virtio/virtio.h" -#include "virtio-9p.h" -#include "virtio-9p-xattr.h" +#include "9p.h" +#include "9p-xattr.h" #include "fsdev/qemu-fsdev.h" /* local_ops */ #include <arpa/inet.h> #include <pwd.h> diff --git a/hw/9pfs/virtio-9p-posix-acl.c b/hw/9pfs/9p-posix-acl.c index 09dad07..8df8228 100644 --- a/hw/9pfs/virtio-9p-posix-acl.c +++ b/hw/9pfs/9p-posix-acl.c @@ -1,5 +1,5 @@ /* - * Virtio 9p system.posix* xattr callback + * 9p system.posix* xattr callback * * Copyright IBM, Corp. 2010 * @@ -13,10 +13,9 @@ #include <sys/types.h> #include "qemu/xattr.h" -#include "hw/virtio/virtio.h" -#include "virtio-9p.h" +#include "9p.h" #include "fsdev/file-op-9p.h" -#include "virtio-9p-xattr.h" +#include "9p-xattr.h" #define MAP_ACL_ACCESS "user.virtfs.system.posix_acl_access" #define MAP_ACL_DEFAULT "user.virtfs.system.posix_acl_default" diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/9p-proxy.c index 1bc7881..73d00dd 100644 --- a/hw/9pfs/virtio-9p-proxy.c +++ b/hw/9pfs/9p-proxy.c @@ -1,5 +1,5 @@ /* - * Virtio 9p Proxy callback + * 9p Proxy callback * * Copyright IBM, Corp. 2011 * @@ -11,11 +11,10 @@ */ #include <sys/socket.h> #include <sys/un.h> -#include "hw/virtio/virtio.h" -#include "virtio-9p.h" +#include "9p.h" #include "qemu/error-report.h" #include "fsdev/qemu-fsdev.h" -#include "virtio-9p-proxy.h" +#include "9p-proxy.h" typedef struct V9fsProxy { int sockfd; diff --git a/hw/9pfs/virtio-9p-proxy.h b/hw/9pfs/9p-proxy.h index 005c1ad..ba9ca20 100644 --- a/hw/9pfs/virtio-9p-proxy.h +++ b/hw/9pfs/9p-proxy.h @@ -1,5 +1,5 @@ /* - * Virtio 9p Proxy callback + * 9p Proxy callback * * Copyright IBM, Corp. 2011 * @@ -9,8 +9,8 @@ * 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_PROXY_H -#define _QEMU_VIRTIO_9P_PROXY_H +#ifndef _QEMU_9P_PROXY_H +#define _QEMU_9P_PROXY_H #define PROXY_MAX_IO_SZ (64 * 1024) #define V9FS_FD_VALID INT_MAX @@ -20,9 +20,9 @@ * marsha/unmarshal doesn't do little endian conversion. */ #define proxy_unmarshal(in_sg, offset, fmt, args...) \ - v9fs_unmarshal(in_sg, 1, offset, 0, fmt, ##args) + v9fs_iov_unmarshal(in_sg, 1, offset, 0, fmt, ##args) #define proxy_marshal(out_sg, offset, fmt, args...) \ - v9fs_marshal(out_sg, 1, offset, 0, fmt, ##args) + v9fs_iov_marshal(out_sg, 1, offset, 0, fmt, ##args) union MsgControl { struct cmsghdr cmsg; diff --git a/hw/9pfs/virtio-9p-synth.c b/hw/9pfs/9p-synth.c index a0ab9a8..090ae0c 100644 --- a/hw/9pfs/virtio-9p-synth.c +++ b/hw/9pfs/9p-synth.c @@ -13,10 +13,10 @@ */ #include "hw/virtio/virtio.h" -#include "virtio-9p.h" -#include "virtio-9p-xattr.h" +#include "9p.h" +#include "9p-xattr.h" #include "fsdev/qemu-fsdev.h" -#include "virtio-9p-synth.h" +#include "9p-synth.h" #include "qemu/rcu.h" #include "qemu/rcu_queue.h" #include <sys/stat.h> diff --git a/hw/9pfs/virtio-9p-synth.h b/hw/9pfs/9p-synth.h index ab05a8e..eaf5a0c 100644 --- a/hw/9pfs/virtio-9p-synth.h +++ b/hw/9pfs/9p-synth.h @@ -1,5 +1,5 @@ /* - * Virtio 9p + * 9p * * Copyright IBM, Corp. 2011 * @@ -10,8 +10,8 @@ * the COPYING file in the top-level directory. * */ -#ifndef HW_9PFS_VIRTIO9P_SYNTH_H -#define HW_9PFS_VIRTIO9P_SYNTH_H 1 +#ifndef HW_9PFS_SYNTH_H +#define HW_9PFS_SYNTH_H 1 #include <unistd.h> #include <sys/types.h> diff --git a/hw/9pfs/virtio-9p-xattr-user.c b/hw/9pfs/9p-xattr-user.c index 46133e0..c490ec3 100644 --- a/hw/9pfs/virtio-9p-xattr-user.c +++ b/hw/9pfs/9p-xattr-user.c @@ -1,5 +1,5 @@ /* - * Virtio 9p user. xattr callback + * 9p user. xattr callback * * Copyright IBM, Corp. 2010 * @@ -12,10 +12,9 @@ */ #include <sys/types.h> -#include "hw/virtio/virtio.h" -#include "virtio-9p.h" +#include "9p.h" #include "fsdev/file-op-9p.h" -#include "virtio-9p-xattr.h" +#include "9p-xattr.h" static ssize_t mp_user_getxattr(FsContext *ctx, const char *path, diff --git a/hw/9pfs/virtio-9p-xattr.c b/hw/9pfs/9p-xattr.c index 0718388..741dd03 100644 --- a/hw/9pfs/virtio-9p-xattr.c +++ b/hw/9pfs/9p-xattr.c @@ -1,5 +1,5 @@ /* - * Virtio 9p xattr callback + * 9p xattr callback * * Copyright IBM, Corp. 2010 * @@ -11,10 +11,9 @@ * */ -#include "hw/virtio/virtio.h" -#include "virtio-9p.h" +#include "9p.h" #include "fsdev/file-op-9p.h" -#include "virtio-9p-xattr.h" +#include "9p-xattr.h" static XattrOperations *get_xattr_operations(XattrOperations **h, diff --git a/hw/9pfs/virtio-9p-xattr.h b/hw/9pfs/9p-xattr.h index 327b32b..4d39a20 100644 --- a/hw/9pfs/virtio-9p-xattr.h +++ b/hw/9pfs/9p-xattr.h @@ -1,5 +1,5 @@ /* - * Virtio 9p + * 9p * * Copyright IBM, Corp. 2010 * @@ -10,8 +10,8 @@ * the COPYING file in the top-level directory. * */ -#ifndef _QEMU_VIRTIO_9P_XATTR_H -#define _QEMU_VIRTIO_9P_XATTR_H +#ifndef _QEMU_9P_XATTR_H +#define _QEMU_9P_XATTR_H #include "qemu/xattr.h" diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/9p.c index f972731..3ff3106 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/9p.c @@ -18,8 +18,8 @@ #include "qemu/sockets.h" #include "virtio-9p.h" #include "fsdev/qemu-fsdev.h" -#include "virtio-9p-xattr.h" -#include "virtio-9p-coth.h" +#include "9p-xattr.h" +#include "coth.h" #include "trace.h" #include "migration/migration.h" @@ -39,6 +39,35 @@ enum { Oappend = 0x80, }; +ssize_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...) +{ + ssize_t ret; + va_list ap; + + va_start(ap, fmt); + ret = virtio_pdu_vmarshal(pdu, offset, fmt, ap); + va_end(ap); + + return ret; +} + +ssize_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...) +{ + ssize_t ret; + va_list ap; + + va_start(ap, fmt); + ret = virtio_pdu_vunmarshal(pdu, offset, fmt, ap); + va_end(ap); + + return ret; +} + +static void pdu_push_and_notify(V9fsPDU *pdu) +{ + virtio_9p_push_and_notify(pdu); +} + static int omode_to_uflags(int8_t mode) { int ret = 0; @@ -563,7 +592,7 @@ static int fid_to_qid(V9fsPDU *pdu, V9fsFidState *fidp, V9fsQID *qidp) return 0; } -static V9fsPDU *alloc_pdu(V9fsState *s) +V9fsPDU *pdu_alloc(V9fsState *s) { V9fsPDU *pdu = NULL; @@ -575,9 +604,10 @@ static V9fsPDU *alloc_pdu(V9fsState *s) return pdu; } -static void free_pdu(V9fsState *s, V9fsPDU *pdu) +void pdu_free(V9fsPDU *pdu) { if (pdu) { + V9fsState *s = pdu->s; /* * Cancelled pdu are added back to the freelist * by flush request . @@ -594,9 +624,10 @@ static void free_pdu(V9fsState *s, V9fsPDU *pdu) * because we always expect to have enough space to encode * error details */ -static void complete_pdu(V9fsState *s, V9fsPDU *pdu, ssize_t len) +static void pdu_complete(V9fsPDU *pdu, ssize_t len) { int8_t id = pdu->id + 1; /* Response */ + V9fsState *s = pdu->s; if (len < 0) { int err = -len; @@ -627,16 +658,12 @@ static void complete_pdu(V9fsState *s, V9fsPDU *pdu, ssize_t len) pdu->size = len; pdu->id = id; - /* push onto queue and notify */ - virtqueue_push(s->vq, &pdu->elem, len); - - /* FIXME: we should batch these completions */ - virtio_notify(VIRTIO_DEVICE(s), s->vq); + pdu_push_and_notify(pdu); /* Now wakeup anybody waiting in flush for this request */ qemu_co_queue_next(&pdu->complete); - free_pdu(s, pdu); + pdu_free(pdu); } static mode_t v9mode_to_mode(uint32_t mode, V9fsString *extension) @@ -931,7 +958,7 @@ static void v9fs_version(void *opaque) offset += err; trace_v9fs_version_return(pdu->tag, pdu->id, s->msize, version.data); out: - complete_pdu(s, pdu, offset); + pdu_complete(pdu, offset); v9fs_string_free(&version); } @@ -995,7 +1022,7 @@ static void v9fs_attach(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); v9fs_string_free(&uname); v9fs_string_free(&aname); } @@ -1009,7 +1036,6 @@ static void v9fs_stat(void *opaque) struct stat stbuf; V9fsFidState *fidp; V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; err = pdu_unmarshal(pdu, offset, "d", &fid); if (err < 0) { @@ -1042,7 +1068,7 @@ static void v9fs_stat(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); } static void v9fs_getattr(void *opaque) @@ -1105,7 +1131,7 @@ static void v9fs_getattr(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(s, pdu, retval); + pdu_complete(pdu, retval); } /* Attribute flags */ @@ -1129,7 +1155,6 @@ static void v9fs_setattr(void *opaque) size_t offset = 7; V9fsIattr v9iattr; V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; err = pdu_unmarshal(pdu, offset, "dI", &fid, &v9iattr); if (err < 0) { @@ -1203,7 +1228,7 @@ static void v9fs_setattr(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); } static int v9fs_walk_marshal(V9fsPDU *pdu, uint16_t nwnames, V9fsQID *qids) @@ -1245,7 +1270,7 @@ static void v9fs_walk(void *opaque) err = pdu_unmarshal(pdu, offset, "ddw", &fid, &newfid, &nwnames); if (err < 0) { - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); return ; } offset += err; @@ -1313,7 +1338,7 @@ out: v9fs_path_free(&dpath); v9fs_path_free(&path); out_nofid: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); if (nwnames && nwnames <= P9_MAXWELEM) { for (name_idx = 0; name_idx < nwnames; name_idx++) { v9fs_string_free(&wnames[name_idx]); @@ -1430,7 +1455,7 @@ static void v9fs_open(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); } static void v9fs_lcreate(void *opaque) @@ -1487,7 +1512,7 @@ static void v9fs_lcreate(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(pdu->s, pdu, err); + pdu_complete(pdu, err); v9fs_string_free(&name); } @@ -1499,7 +1524,6 @@ static void v9fs_fsync(void *opaque) size_t offset = 7; V9fsFidState *fidp; V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; err = pdu_unmarshal(pdu, offset, "dd", &fid, &datasync); if (err < 0) { @@ -1518,7 +1542,7 @@ static void v9fs_fsync(void *opaque) } put_fid(pdu, fidp); out_nofid: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); } static void v9fs_clunk(void *opaque) @@ -1551,7 +1575,7 @@ static void v9fs_clunk(void *opaque) err = offset; } out_nofid: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); } static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, @@ -1561,6 +1585,8 @@ static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, size_t offset = 7; int read_count; int64_t xattr_len; + V9fsVirtioState *v = container_of(s, V9fsVirtioState, state); + VirtQueueElement *elem = &v->elems[pdu->idx]; xattr_len = fidp->fs.xattr.len; read_count = xattr_len - off; @@ -1577,7 +1603,8 @@ static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, return err; } offset += err; - err = v9fs_pack(pdu->elem.in_sg, pdu->elem.in_num, offset, + + err = v9fs_pack(elem->in_sg, elem->in_num, offset, ((char *)fidp->fs.xattr.value) + off, read_count); if (err < 0) { @@ -1667,13 +1694,7 @@ static void v9fs_init_qiov_from_pdu(QEMUIOVector *qiov, V9fsPDU *pdu, struct iovec *iov; unsigned int niov; - if (is_write) { - iov = pdu->elem.out_sg; - niov = pdu->elem.out_num; - } else { - iov = pdu->elem.in_sg; - niov = pdu->elem.in_num; - } + virtio_init_iov_from_pdu(pdu, &iov, &niov, is_write); qemu_iovec_init_external(&elem, iov, niov); qemu_iovec_init(qiov, niov); @@ -1761,7 +1782,7 @@ static void v9fs_read(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); } static size_t v9fs_readdir_data_size(V9fsString *name) @@ -1848,7 +1869,6 @@ static void v9fs_readdir(void *opaque) int32_t count; uint32_t max_count; V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; retval = pdu_unmarshal(pdu, offset, "dqd", &fid, &initial_offset, &max_count); @@ -1885,7 +1905,7 @@ static void v9fs_readdir(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(s, pdu, retval); + pdu_complete(pdu, retval); } static int v9fs_xattr_write(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, @@ -1952,7 +1972,7 @@ static void v9fs_write(void *opaque) err = pdu_unmarshal(pdu, offset, "dqd", &fid, &off, &count); if (err < 0) { - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); return; } offset += err; @@ -2015,7 +2035,7 @@ out: put_fid(pdu, fidp); out_nofid: qemu_iovec_destroy(&qiov_full); - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); } static void v9fs_create(void *opaque) @@ -2182,7 +2202,7 @@ static void v9fs_create(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(pdu->s, pdu, err); + pdu_complete(pdu, err); v9fs_string_free(&name); v9fs_string_free(&extension); v9fs_path_free(&path); @@ -2229,7 +2249,7 @@ static void v9fs_symlink(void *opaque) out: put_fid(pdu, dfidp); out_nofid: - complete_pdu(pdu->s, pdu, err); + pdu_complete(pdu, err); v9fs_string_free(&name); v9fs_string_free(&symname); } @@ -2245,7 +2265,7 @@ static void v9fs_flush(void *opaque) err = pdu_unmarshal(pdu, offset, "w", &tag); if (err < 0) { - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); return; } trace_v9fs_flush(pdu->tag, pdu->id, tag); @@ -2262,15 +2282,14 @@ static void v9fs_flush(void *opaque) */ qemu_co_queue_wait(&cancel_pdu->complete); cancel_pdu->cancelled = 0; - free_pdu(pdu->s, cancel_pdu); + pdu_free(cancel_pdu); } - complete_pdu(s, pdu, 7); + pdu_complete(pdu, 7); } static void v9fs_link(void *opaque) { V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; int32_t dfid, oldfid; V9fsFidState *dfidp, *oldfidp; V9fsString name; @@ -2303,7 +2322,7 @@ out: put_fid(pdu, dfidp); out_nofid: v9fs_string_free(&name); - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); } /* Only works with path name based fid */ @@ -2348,7 +2367,7 @@ out_err: clunk_fid(pdu->s, fidp->fid); put_fid(pdu, fidp); out_nofid: - complete_pdu(pdu->s, pdu, err); + pdu_complete(pdu, err); } static void v9fs_unlinkat(void *opaque) @@ -2392,7 +2411,7 @@ out_err: put_fid(pdu, dfidp); v9fs_path_free(&path); out_nofid: - complete_pdu(pdu->s, pdu, err); + pdu_complete(pdu, err); v9fs_string_free(&name); } @@ -2492,7 +2511,7 @@ static void v9fs_rename(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); v9fs_string_free(&name); } @@ -2593,7 +2612,7 @@ static void v9fs_renameat(void *opaque) } out_err: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); v9fs_string_free(&old_name); v9fs_string_free(&new_name); } @@ -2608,7 +2627,6 @@ static void v9fs_wstat(void *opaque) struct stat stbuf; V9fsFidState *fidp; V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; v9fs_stat_init(&v9stat); err = pdu_unmarshal(pdu, offset, "dwS", &fid, &unused, &v9stat); @@ -2690,7 +2708,7 @@ out: put_fid(pdu, fidp); out_nofid: v9fs_stat_free(&v9stat); - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); } static int v9fs_fill_statfs(V9fsState *s, V9fsPDU *pdu, struct statfs *stbuf) @@ -2769,7 +2787,7 @@ static void v9fs_statfs(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(s, pdu, retval); + pdu_complete(pdu, retval); } static void v9fs_mknod(void *opaque) @@ -2786,7 +2804,6 @@ static void v9fs_mknod(void *opaque) struct stat stbuf; V9fsFidState *fidp; V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; v9fs_string_init(&name); err = pdu_unmarshal(pdu, offset, "dsdddd", &fid, &name, &mode, @@ -2817,7 +2834,7 @@ static void v9fs_mknod(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); v9fs_string_free(&name); } @@ -2838,7 +2855,6 @@ static void v9fs_lock(void *opaque) V9fsFidState *fidp; int32_t fid, err = 0; V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; status = P9_LOCK_ERROR; v9fs_string_init(&flock.client_id); @@ -2875,7 +2891,7 @@ out_nofid: err += offset; } trace_v9fs_lock_return(pdu->tag, pdu->id, status); - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); v9fs_string_free(&flock.client_id); } @@ -2891,7 +2907,6 @@ static void v9fs_getlock(void *opaque) V9fsGetlock glock; int32_t fid, err = 0; V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; v9fs_string_init(&glock.client_id); err = pdu_unmarshal(pdu, offset, "dbqqds", &fid, &glock.type, @@ -2925,7 +2940,7 @@ static void v9fs_getlock(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); v9fs_string_free(&glock.client_id); } @@ -2969,7 +2984,7 @@ static void v9fs_mkdir(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(pdu->s, pdu, err); + pdu_complete(pdu, err); v9fs_string_free(&name); } @@ -3075,7 +3090,7 @@ out: put_fid(pdu, xattr_fidp); } out_nofid: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); v9fs_string_free(&name); } @@ -3090,7 +3105,6 @@ static void v9fs_xattrcreate(void *opaque) V9fsFidState *file_fidp; V9fsFidState *xattr_fidp; V9fsPDU *pdu = opaque; - V9fsState *s = pdu->s; v9fs_string_init(&name); err = pdu_unmarshal(pdu, offset, "dsqd", &fid, &name, &size, &flags); @@ -3116,7 +3130,7 @@ static void v9fs_xattrcreate(void *opaque) err = offset; put_fid(pdu, file_fidp); out_nofid: - complete_pdu(s, pdu, err); + pdu_complete(pdu, err); v9fs_string_free(&name); } @@ -3156,7 +3170,7 @@ static void v9fs_readlink(void *opaque) out: put_fid(pdu, fidp); out_nofid: - complete_pdu(pdu->s, pdu, err); + pdu_complete(pdu, err); } static CoroutineEntry *pdu_co_handlers[] = { @@ -3199,13 +3213,13 @@ static CoroutineEntry *pdu_co_handlers[] = { static void v9fs_op_not_supp(void *opaque) { V9fsPDU *pdu = opaque; - complete_pdu(pdu->s, pdu, -EOPNOTSUPP); + pdu_complete(pdu, -EOPNOTSUPP); } static void v9fs_fs_ro(void *opaque) { V9fsPDU *pdu = opaque; - complete_pdu(pdu->s, pdu, -EROFS); + pdu_complete(pdu, -EROFS); } static inline bool is_read_only_op(V9fsPDU *pdu) @@ -3235,10 +3249,11 @@ static inline bool is_read_only_op(V9fsPDU *pdu) } } -static void submit_pdu(V9fsState *s, V9fsPDU *pdu) +void pdu_submit(V9fsPDU *pdu) { Coroutine *co; CoroutineEntry *handler; + V9fsState *s = pdu->s; if (pdu->id >= ARRAY_SIZE(pdu_co_handlers) || (pdu_co_handlers[pdu->id] == NULL)) { @@ -3254,41 +3269,104 @@ static void submit_pdu(V9fsState *s, V9fsPDU *pdu) qemu_coroutine_enter(co, pdu); } -void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq) +/* Returns 0 on success, 1 on failure. */ +int v9fs_device_realize_common(V9fsState *s, Error **errp) { - V9fsState *s = (V9fsState *)vdev; - V9fsPDU *pdu; - ssize_t len; + V9fsVirtioState *v = container_of(s, V9fsVirtioState, state); + int i, len; + struct stat stat; + FsDriverEntry *fse; + V9fsPath path; + int rc = 1; + + /* initialize pdu allocator */ + QLIST_INIT(&s->free_list); + QLIST_INIT(&s->active_list); + for (i = 0; i < (MAX_REQ - 1); i++) { + QLIST_INSERT_HEAD(&s->free_list, &v->pdus[i], next); + v->pdus[i].s = s; + v->pdus[i].idx = i; + } + + v9fs_path_init(&path); + + fse = get_fsdev_fsentry(s->fsconf.fsdev_id); + + if (!fse) { + /* We don't have a fsdev identified by fsdev_id */ + error_setg(errp, "9pfs device couldn't find fsdev with the " + "id = %s", + s->fsconf.fsdev_id ? s->fsconf.fsdev_id : "NULL"); + goto out; + } + + if (!s->fsconf.tag) { + /* we haven't specified a mount_tag */ + error_setg(errp, "fsdev with id %s needs mount_tag arguments", + s->fsconf.fsdev_id); + goto out; + } + + s->ctx.export_flags = fse->export_flags; + s->ctx.fs_root = g_strdup(fse->path); + s->ctx.exops.get_st_gen = NULL; + len = strlen(s->fsconf.tag); + if (len > MAX_TAG_LEN - 1) { + error_setg(errp, "mount tag '%s' (%d bytes) is longer than " + "maximum (%d bytes)", s->fsconf.tag, len, MAX_TAG_LEN - 1); + goto out; + } - while ((pdu = alloc_pdu(s)) && - (len = virtqueue_pop(vq, &pdu->elem)) != 0) { - struct { - uint32_t size_le; - uint8_t id; - uint16_t tag_le; - } QEMU_PACKED out; - int len; + s->tag = g_strdup(s->fsconf.tag); + s->ctx.uid = -1; - pdu->s = s; - BUG_ON(pdu->elem.out_num == 0 || pdu->elem.in_num == 0); - QEMU_BUILD_BUG_ON(sizeof out != 7); + s->ops = fse->ops; - len = iov_to_buf(pdu->elem.out_sg, pdu->elem.out_num, 0, - &out, sizeof out); - BUG_ON(len != sizeof out); + s->fid_list = NULL; + qemu_co_rwlock_init(&s->rename_lock); - pdu->size = le32_to_cpu(out.size_le); + if (s->ops->init(&s->ctx) < 0) { + error_setg(errp, "9pfs Failed to initialize fs-driver with id:%s" + " and export path:%s", s->fsconf.fsdev_id, s->ctx.fs_root); + goto out; + } - pdu->id = out.id; - pdu->tag = le16_to_cpu(out.tag_le); + /* + * Check details of export path, We need to use fs driver + * call back to do that. Since we are in the init path, we don't + * use co-routines here. + */ + if (s->ops->name_to_path(&s->ctx, NULL, "/", &path) < 0) { + error_setg(errp, + "error in converting name to path %s", strerror(errno)); + goto out; + } + if (s->ops->lstat(&s->ctx, &path, &stat)) { + error_setg(errp, "share path %s does not exist", fse->path); + goto out; + } else if (!S_ISDIR(stat.st_mode)) { + error_setg(errp, "share path %s is not a directory", fse->path); + goto out; + } + v9fs_path_free(&path); - qemu_co_queue_init(&pdu->complete); - submit_pdu(s, pdu); + rc = 0; +out: + if (rc) { + g_free(s->ctx.fs_root); + g_free(s->tag); + v9fs_path_free(&path); } - free_pdu(s, pdu); + return rc; +} + +void v9fs_device_unrealize_common(V9fsState *s, Error **errp) +{ + g_free(s->ctx.fs_root); + g_free(s->tag); } -static void __attribute__((__constructor__)) virtio_9p_set_fd_limit(void) +static void __attribute__((__constructor__)) v9fs_set_fd_limit(void) { struct rlimit rlim; if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h new file mode 100644 index 0000000..edcd51b --- /dev/null +++ b/hw/9pfs/9p.h @@ -0,0 +1,326 @@ +#ifndef _QEMU_9P_H +#define _QEMU_9P_H + +#include <sys/types.h> +#include <dirent.h> +#include <sys/time.h> +#include <utime.h> +#include <sys/resource.h> +#include <glib.h> +#include "standard-headers/linux/virtio_9p.h" +#include "hw/virtio/virtio.h" +#include "fsdev/file-op-9p.h" +#include "fsdev/9p-iov-marshal.h" +#include "qemu/thread.h" +#include "qemu/coroutine.h" + +enum { + P9_TLERROR = 6, + P9_RLERROR, + P9_TSTATFS = 8, + P9_RSTATFS, + P9_TLOPEN = 12, + P9_RLOPEN, + P9_TLCREATE = 14, + P9_RLCREATE, + P9_TSYMLINK = 16, + P9_RSYMLINK, + P9_TMKNOD = 18, + P9_RMKNOD, + P9_TRENAME = 20, + P9_RRENAME, + P9_TREADLINK = 22, + P9_RREADLINK, + P9_TGETATTR = 24, + P9_RGETATTR, + P9_TSETATTR = 26, + P9_RSETATTR, + P9_TXATTRWALK = 30, + P9_RXATTRWALK, + P9_TXATTRCREATE = 32, + P9_RXATTRCREATE, + P9_TREADDIR = 40, + P9_RREADDIR, + P9_TFSYNC = 50, + P9_RFSYNC, + P9_TLOCK = 52, + P9_RLOCK, + P9_TGETLOCK = 54, + P9_RGETLOCK, + P9_TLINK = 70, + P9_RLINK, + P9_TMKDIR = 72, + P9_RMKDIR, + P9_TRENAMEAT = 74, + P9_RRENAMEAT, + P9_TUNLINKAT = 76, + P9_RUNLINKAT, + P9_TVERSION = 100, + P9_RVERSION, + P9_TAUTH = 102, + P9_RAUTH, + P9_TATTACH = 104, + P9_RATTACH, + P9_TERROR = 106, + P9_RERROR, + P9_TFLUSH = 108, + P9_RFLUSH, + P9_TWALK = 110, + P9_RWALK, + P9_TOPEN = 112, + P9_ROPEN, + P9_TCREATE = 114, + P9_RCREATE, + P9_TREAD = 116, + P9_RREAD, + P9_TWRITE = 118, + P9_RWRITE, + P9_TCLUNK = 120, + P9_RCLUNK, + P9_TREMOVE = 122, + P9_RREMOVE, + P9_TSTAT = 124, + P9_RSTAT, + P9_TWSTAT = 126, + P9_RWSTAT, +}; + + +/* qid.types */ +enum { + P9_QTDIR = 0x80, + P9_QTAPPEND = 0x40, + P9_QTEXCL = 0x20, + P9_QTMOUNT = 0x10, + P9_QTAUTH = 0x08, + P9_QTTMP = 0x04, + P9_QTSYMLINK = 0x02, + P9_QTLINK = 0x01, + P9_QTFILE = 0x00, +}; + +enum p9_proto_version { + V9FS_PROTO_2000U = 0x01, + V9FS_PROTO_2000L = 0x02, +}; + +#define P9_NOTAG (u16)(~0) +#define P9_NOFID (u32)(~0) +#define P9_MAXWELEM 16 + +#define FID_REFERENCED 0x1 +#define FID_NON_RECLAIMABLE 0x2 +static inline char *rpath(FsContext *ctx, const char *path) +{ + return g_strdup_printf("%s/%s", ctx->fs_root, path); +} + +/* + * ample room for Twrite/Rread header + * size[4] Tread/Twrite tag[2] fid[4] offset[8] count[4] + */ +#define P9_IOHDRSZ 24 + +typedef struct V9fsPDU V9fsPDU; +struct V9fsState; + +struct V9fsPDU +{ + uint32_t size; + uint16_t tag; + uint8_t id; + uint8_t cancelled; + CoQueue complete; + struct V9fsState *s; + QLIST_ENTRY(V9fsPDU) next; + uint32_t idx; +}; + + +/* FIXME + * 1) change user needs to set groups and stuff + */ + +#define MAX_REQ 128 +#define MAX_TAG_LEN 32 + +#define BUG_ON(cond) assert(!(cond)) + +typedef struct V9fsFidState V9fsFidState; + +enum { + P9_FID_NONE = 0, + P9_FID_FILE, + P9_FID_DIR, + P9_FID_XATTR, +}; + +typedef struct V9fsConf +{ + /* tag name for the device */ + char *tag; + char *fsdev_id; +} V9fsConf; + +typedef struct V9fsXattr +{ + int64_t copied_len; + int64_t len; + void *value; + V9fsString name; + int flags; +} V9fsXattr; + +/* + * Filled by fs driver on open and other + * calls. + */ +union V9fsFidOpenState { + int fd; + DIR *dir; + V9fsXattr xattr; + /* + * private pointer for fs drivers, that + * have its own internal representation of + * open files. + */ + void *private; +}; + +struct V9fsFidState +{ + int fid_type; + int32_t fid; + V9fsPath path; + V9fsFidOpenState fs; + V9fsFidOpenState fs_reclaim; + int flags; + int open_flags; + uid_t uid; + int ref; + int clunked; + V9fsFidState *next; + V9fsFidState *rclm_lst; +}; + +typedef struct V9fsState +{ + QLIST_HEAD(, V9fsPDU) free_list; + QLIST_HEAD(, V9fsPDU) active_list; + V9fsFidState *fid_list; + FileOperations *ops; + FsContext ctx; + char *tag; + enum p9_proto_version proto_version; + int32_t msize; + /* + * lock ensuring atomic path update + * on rename. + */ + CoRwlock rename_lock; + int32_t root_fid; + Error *migration_blocker; + V9fsConf fsconf; +} V9fsState; + +/* 9p2000.L open flags */ +#define P9_DOTL_RDONLY 00000000 +#define P9_DOTL_WRONLY 00000001 +#define P9_DOTL_RDWR 00000002 +#define P9_DOTL_NOACCESS 00000003 +#define P9_DOTL_CREATE 00000100 +#define P9_DOTL_EXCL 00000200 +#define P9_DOTL_NOCTTY 00000400 +#define P9_DOTL_TRUNC 00001000 +#define P9_DOTL_APPEND 00002000 +#define P9_DOTL_NONBLOCK 00004000 +#define P9_DOTL_DSYNC 00010000 +#define P9_DOTL_FASYNC 00020000 +#define P9_DOTL_DIRECT 00040000 +#define P9_DOTL_LARGEFILE 00100000 +#define P9_DOTL_DIRECTORY 00200000 +#define P9_DOTL_NOFOLLOW 00400000 +#define P9_DOTL_NOATIME 01000000 +#define P9_DOTL_CLOEXEC 02000000 +#define P9_DOTL_SYNC 04000000 + +/* 9p2000.L at flags */ +#define P9_DOTL_AT_REMOVEDIR 0x200 + +/* 9P2000.L lock type */ +#define P9_LOCK_TYPE_RDLCK 0 +#define P9_LOCK_TYPE_WRLCK 1 +#define P9_LOCK_TYPE_UNLCK 2 + +#define P9_LOCK_SUCCESS 0 +#define P9_LOCK_BLOCKED 1 +#define P9_LOCK_ERROR 2 +#define P9_LOCK_GRACE 3 + +#define P9_LOCK_FLAGS_BLOCK 1 +#define P9_LOCK_FLAGS_RECLAIM 2 + +typedef struct V9fsFlock +{ + uint8_t type; + uint32_t flags; + uint64_t start; /* absolute offset */ + uint64_t length; + uint32_t proc_id; + V9fsString client_id; +} V9fsFlock; + +typedef struct V9fsGetlock +{ + uint8_t type; + uint64_t start; /* absolute offset */ + uint64_t length; + uint32_t proc_id; + V9fsString client_id; +} V9fsGetlock; + +extern int open_fd_hw; +extern int total_open_fd; + +static inline void v9fs_path_write_lock(V9fsState *s) +{ + if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { + qemu_co_rwlock_wrlock(&s->rename_lock); + } +} + +static inline void v9fs_path_read_lock(V9fsState *s) +{ + if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { + qemu_co_rwlock_rdlock(&s->rename_lock); + } +} + +static inline void v9fs_path_unlock(V9fsState *s) +{ + if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { + qemu_co_rwlock_unlock(&s->rename_lock); + } +} + +static inline uint8_t v9fs_request_cancelled(V9fsPDU *pdu) +{ + return pdu->cancelled; +} + +extern void v9fs_reclaim_fd(V9fsPDU *pdu); +extern void v9fs_path_init(V9fsPath *path); +extern void v9fs_path_free(V9fsPath *path); +extern void v9fs_path_copy(V9fsPath *lhs, V9fsPath *rhs); +extern int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath, + const char *name, V9fsPath *path); +extern int v9fs_device_realize_common(V9fsState *s, Error **errp); +extern void v9fs_device_unrealize_common(V9fsState *s, Error **errp); + +ssize_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...); +ssize_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...); +V9fsPDU *pdu_alloc(V9fsState *s); +void pdu_free(V9fsPDU *pdu); +void pdu_submit(V9fsPDU *pdu); + +#endif diff --git a/hw/9pfs/Makefile.objs b/hw/9pfs/Makefile.objs index 1e9b595..da0ae0c 100644 --- a/hw/9pfs/Makefile.objs +++ b/hw/9pfs/Makefile.objs @@ -1,9 +1,9 @@ -common-obj-y = virtio-9p.o -common-obj-y += virtio-9p-local.o virtio-9p-xattr.o -common-obj-y += virtio-9p-xattr-user.o virtio-9p-posix-acl.o -common-obj-y += virtio-9p-coth.o cofs.o codir.o cofile.o -common-obj-y += coxattr.o virtio-9p-synth.o -common-obj-$(CONFIG_OPEN_BY_HANDLE) += virtio-9p-handle.o -common-obj-y += virtio-9p-proxy.o +common-obj-y = 9p.o +common-obj-y += 9p-local.o 9p-xattr.o +common-obj-y += 9p-xattr-user.o 9p-posix-acl.o +common-obj-y += coth.o cofs.o codir.o cofile.o +common-obj-y += coxattr.o 9p-synth.o +common-obj-$(CONFIG_OPEN_BY_HANDLE) += 9p-handle.o +common-obj-y += 9p-proxy.o obj-y += virtio-9p-device.o diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c index ec9cc7f..5a4f74d 100644 --- a/hw/9pfs/codir.c +++ b/hw/9pfs/codir.c @@ -15,7 +15,7 @@ #include "fsdev/qemu-fsdev.h" #include "qemu/thread.h" #include "qemu/coroutine.h" -#include "virtio-9p-coth.h" +#include "coth.h" int v9fs_co_readdir_r(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent *dent, struct dirent **result) diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c index 7cb55ee..893df2c 100644 --- a/hw/9pfs/cofile.c +++ b/hw/9pfs/cofile.c @@ -15,7 +15,7 @@ #include "fsdev/qemu-fsdev.h" #include "qemu/thread.h" #include "qemu/coroutine.h" -#include "virtio-9p-coth.h" +#include "coth.h" int v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t st_mode, V9fsStatDotl *v9stat) diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c index e1953a9..7b4202b 100644 --- a/hw/9pfs/cofs.c +++ b/hw/9pfs/cofs.c @@ -15,7 +15,7 @@ #include "fsdev/qemu-fsdev.h" #include "qemu/thread.h" #include "qemu/coroutine.h" -#include "virtio-9p-coth.h" +#include "coth.h" static ssize_t __readlink(V9fsState *s, V9fsPath *path, V9fsString *buf) { diff --git a/hw/9pfs/virtio-9p-coth.c b/hw/9pfs/coth.c index ab9425c..56772d6 100644 --- a/hw/9pfs/virtio-9p-coth.c +++ b/hw/9pfs/coth.c @@ -1,5 +1,5 @@ /* - * Virtio 9p backend + * 9p backend * * Copyright IBM, Corp. 2010 * @@ -16,7 +16,7 @@ #include "block/thread-pool.h" #include "qemu/coroutine.h" #include "qemu/main-loop.h" -#include "virtio-9p-coth.h" +#include "coth.h" /* Called from QEMU I/O thread. */ static void coroutine_enter_cb(void *opaque, int ret) diff --git a/hw/9pfs/virtio-9p-coth.h b/hw/9pfs/coth.h index 4ac1aaf..209fc6a 100644 --- a/hw/9pfs/virtio-9p-coth.h +++ b/hw/9pfs/coth.h @@ -1,5 +1,5 @@ /* - * Virtio 9p backend + * 9p backend * * Copyright IBM, Corp. 2010 * @@ -12,8 +12,8 @@ * */ -#ifndef _QEMU_VIRTIO_9P_COTH_H -#define _QEMU_VIRTIO_9P_COTH_H +#ifndef _QEMU_9P_COTH_H +#define _QEMU_9P_COTH_H #include "qemu/thread.h" #include "qemu/coroutine.h" diff --git a/hw/9pfs/coxattr.c b/hw/9pfs/coxattr.c index 55c0d23..0590cbf 100644 --- a/hw/9pfs/coxattr.c +++ b/hw/9pfs/coxattr.c @@ -15,7 +15,7 @@ #include "fsdev/qemu-fsdev.h" #include "qemu/thread.h" #include "qemu/coroutine.h" -#include "virtio-9p-coth.h" +#include "coth.h" int v9fs_co_llistxattr(V9fsPDU *pdu, V9fsPath *path, void *value, size_t size) { diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c index b42d3b3..5643fd5 100644 --- a/hw/9pfs/virtio-9p-device.c +++ b/hw/9pfs/virtio-9p-device.c @@ -12,14 +12,65 @@ */ #include "hw/virtio/virtio.h" -#include "hw/virtio/virtio-9p.h" #include "hw/i386/pc.h" #include "qemu/sockets.h" #include "virtio-9p.h" #include "fsdev/qemu-fsdev.h" -#include "virtio-9p-xattr.h" -#include "virtio-9p-coth.h" +#include "9p-xattr.h" +#include "coth.h" #include "hw/virtio/virtio-access.h" +#include "qemu/iov.h" + +void virtio_9p_push_and_notify(V9fsPDU *pdu) +{ + V9fsState *s = pdu->s; + V9fsVirtioState *v = container_of(s, V9fsVirtioState, state); + VirtQueueElement *elem = &v->elems[pdu->idx]; + + /* push onto queue and notify */ + virtqueue_push(v->vq, elem, pdu->size); + + /* FIXME: we should batch these completions */ + virtio_notify(VIRTIO_DEVICE(v), v->vq); +} + +static void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq) +{ + V9fsVirtioState *v = (V9fsVirtioState *)vdev; + V9fsState *s = &v->state; + V9fsPDU *pdu; + ssize_t len; + + while ((pdu = pdu_alloc(s))) { + struct { + uint32_t size_le; + uint8_t id; + uint16_t tag_le; + } QEMU_PACKED out; + VirtQueueElement *elem = &v->elems[pdu->idx]; + + len = virtqueue_pop(vq, elem); + if (!len) { + pdu_free(pdu); + break; + } + + BUG_ON(elem->out_num == 0 || elem->in_num == 0); + QEMU_BUILD_BUG_ON(sizeof out != 7); + + len = iov_to_buf(elem->out_sg, elem->out_num, 0, + &out, sizeof out); + BUG_ON(len != sizeof out); + + pdu->size = le32_to_cpu(out.size_le); + + pdu->id = out.id; + pdu->tag = le16_to_cpu(out.tag_le); + + qemu_co_queue_init(&pdu->complete); + pdu_submit(pdu); + } +} static uint64_t virtio_9p_get_features(VirtIODevice *vdev, uint64_t features, Error **errp) @@ -32,14 +83,15 @@ static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config) { int len; struct virtio_9p_config *cfg; - V9fsState *s = VIRTIO_9P(vdev); + V9fsVirtioState *v = VIRTIO_9P(vdev); + V9fsState *s = &v->state; len = strlen(s->tag); cfg = g_malloc0(sizeof(struct virtio_9p_config) + len); virtio_stw_p(vdev, &cfg->tag_len, len); /* We don't copy the terminating null to config space */ memcpy(cfg->tag, s->tag, len); - memcpy(config, cfg, s->config_size); + memcpy(config, cfg, v->config_size); g_free(cfg); } @@ -56,111 +108,74 @@ static int virtio_9p_load(QEMUFile *f, void *opaque, int version_id) static void virtio_9p_device_realize(DeviceState *dev, Error **errp) { VirtIODevice *vdev = VIRTIO_DEVICE(dev); - V9fsState *s = VIRTIO_9P(dev); - int i, len; - struct stat stat; - FsDriverEntry *fse; - V9fsPath path; - - virtio_init(vdev, "virtio-9p", VIRTIO_ID_9P, - sizeof(struct virtio_9p_config) + MAX_TAG_LEN); - - /* initialize pdu allocator */ - QLIST_INIT(&s->free_list); - QLIST_INIT(&s->active_list); - for (i = 0; i < (MAX_REQ - 1); i++) { - QLIST_INSERT_HEAD(&s->free_list, &s->pdus[i], next); - } - - s->vq = virtio_add_queue(vdev, MAX_REQ, handle_9p_output); - - v9fs_path_init(&path); - - fse = get_fsdev_fsentry(s->fsconf.fsdev_id); - - if (!fse) { - /* We don't have a fsdev identified by fsdev_id */ - error_setg(errp, "Virtio-9p device couldn't find fsdev with the " - "id = %s", - s->fsconf.fsdev_id ? s->fsconf.fsdev_id : "NULL"); - goto out; - } - - if (!s->fsconf.tag) { - /* we haven't specified a mount_tag */ - error_setg(errp, "fsdev with id %s needs mount_tag arguments", - s->fsconf.fsdev_id); - goto out; - } - - s->ctx.export_flags = fse->export_flags; - s->ctx.fs_root = g_strdup(fse->path); - s->ctx.exops.get_st_gen = NULL; - len = strlen(s->fsconf.tag); - if (len > MAX_TAG_LEN - 1) { - error_setg(errp, "mount tag '%s' (%d bytes) is longer than " - "maximum (%d bytes)", s->fsconf.tag, len, MAX_TAG_LEN - 1); - goto out; - } + V9fsVirtioState *v = VIRTIO_9P(dev); + V9fsState *s = &v->state; - s->tag = g_strdup(s->fsconf.tag); - s->ctx.uid = -1; - - s->ops = fse->ops; - s->config_size = sizeof(struct virtio_9p_config) + len; - s->fid_list = NULL; - qemu_co_rwlock_init(&s->rename_lock); - - if (s->ops->init(&s->ctx) < 0) { - error_setg(errp, "Virtio-9p Failed to initialize fs-driver with id:%s" - " and export path:%s", s->fsconf.fsdev_id, s->ctx.fs_root); + if (v9fs_device_realize_common(s, errp)) { goto out; } - /* - * Check details of export path, We need to use fs driver - * call back to do that. Since we are in the init path, we don't - * use co-routines here. - */ - if (s->ops->name_to_path(&s->ctx, NULL, "/", &path) < 0) { - error_setg(errp, - "error in converting name to path %s", strerror(errno)); - goto out; - } - if (s->ops->lstat(&s->ctx, &path, &stat)) { - error_setg(errp, "share path %s does not exist", fse->path); - goto out; - } else if (!S_ISDIR(stat.st_mode)) { - error_setg(errp, "share path %s is not a directory", fse->path); - goto out; - } - v9fs_path_free(&path); + v->config_size = sizeof(struct virtio_9p_config) + strlen(s->fsconf.tag); + virtio_init(vdev, "virtio-9p", VIRTIO_ID_9P, v->config_size); + v->vq = virtio_add_queue(vdev, MAX_REQ, handle_9p_output); + register_savevm(dev, "virtio-9p", -1, 1, virtio_9p_save, virtio_9p_load, v); - register_savevm(dev, "virtio-9p", -1, 1, virtio_9p_save, virtio_9p_load, s); - return; out: - g_free(s->ctx.fs_root); - g_free(s->tag); - virtio_cleanup(vdev); - v9fs_path_free(&path); + return; } static void virtio_9p_device_unrealize(DeviceState *dev, Error **errp) { VirtIODevice *vdev = VIRTIO_DEVICE(dev); - V9fsState *s = VIRTIO_9P(dev); + V9fsVirtioState *v = VIRTIO_9P(dev); + V9fsState *s = &v->state; virtio_cleanup(vdev); - unregister_savevm(dev, "virtio-9p", s); - g_free(s->ctx.fs_root); - g_free(s->tag); + unregister_savevm(dev, "virtio-9p", v); + v9fs_device_unrealize_common(s, errp); +} + +ssize_t virtio_pdu_vmarshal(V9fsPDU *pdu, size_t offset, + const char *fmt, va_list ap) +{ + V9fsState *s = pdu->s; + V9fsVirtioState *v = container_of(s, V9fsVirtioState, state); + VirtQueueElement *elem = &v->elems[pdu->idx]; + + return v9fs_iov_vmarshal(elem->in_sg, elem->in_num, offset, 1, fmt, ap); +} + +ssize_t virtio_pdu_vunmarshal(V9fsPDU *pdu, size_t offset, + const char *fmt, va_list ap) +{ + V9fsState *s = pdu->s; + V9fsVirtioState *v = container_of(s, V9fsVirtioState, state); + VirtQueueElement *elem = &v->elems[pdu->idx]; + + return v9fs_iov_vunmarshal(elem->out_sg, elem->out_num, offset, 1, fmt, ap); +} + +void virtio_init_iov_from_pdu(V9fsPDU *pdu, struct iovec **piov, + unsigned int *pniov, bool is_write) +{ + V9fsState *s = pdu->s; + V9fsVirtioState *v = container_of(s, V9fsVirtioState, state); + VirtQueueElement *elem = &v->elems[pdu->idx]; + + if (is_write) { + *piov = elem->out_sg; + *pniov = elem->out_num; + } else { + *piov = elem->in_sg; + *pniov = elem->in_num; + } } /* virtio-9p device */ static Property virtio_9p_properties[] = { - DEFINE_PROP_STRING("mount_tag", V9fsState, fsconf.tag), - DEFINE_PROP_STRING("fsdev", V9fsState, fsconf.fsdev_id), + DEFINE_PROP_STRING("mount_tag", V9fsVirtioState, state.fsconf.tag), + DEFINE_PROP_STRING("fsdev", V9fsVirtioState, state.fsconf.fsdev_id), DEFINE_PROP_END_OF_LIST(), }; @@ -180,7 +195,7 @@ static void virtio_9p_class_init(ObjectClass *klass, void *data) static const TypeInfo virtio_device_info = { .name = TYPE_VIRTIO_9P, .parent = TYPE_VIRTIO_DEVICE, - .instance_size = sizeof(V9fsState), + .instance_size = sizeof(V9fsVirtioState), .class_init = virtio_9p_class_init, }; diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h index d7a4dc1..1cdf0a2 100644 --- a/hw/9pfs/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -1,394 +1,31 @@ #ifndef _QEMU_VIRTIO_9P_H #define _QEMU_VIRTIO_9P_H -#include <sys/types.h> -#include <dirent.h> -#include <sys/time.h> -#include <utime.h> -#include <sys/resource.h> -#include <glib.h> #include "standard-headers/linux/virtio_9p.h" #include "hw/virtio/virtio.h" -#include "hw/virtio/virtio-9p.h" -#include "fsdev/file-op-9p.h" -#include "fsdev/virtio-9p-marshal.h" -#include "qemu/thread.h" -#include "qemu/coroutine.h" +#include "9p.h" -enum { - P9_TLERROR = 6, - P9_RLERROR, - P9_TSTATFS = 8, - P9_RSTATFS, - P9_TLOPEN = 12, - P9_RLOPEN, - P9_TLCREATE = 14, - P9_RLCREATE, - P9_TSYMLINK = 16, - P9_RSYMLINK, - P9_TMKNOD = 18, - P9_RMKNOD, - P9_TRENAME = 20, - P9_RRENAME, - P9_TREADLINK = 22, - P9_RREADLINK, - P9_TGETATTR = 24, - P9_RGETATTR, - P9_TSETATTR = 26, - P9_RSETATTR, - P9_TXATTRWALK = 30, - P9_RXATTRWALK, - P9_TXATTRCREATE = 32, - P9_RXATTRCREATE, - P9_TREADDIR = 40, - P9_RREADDIR, - P9_TFSYNC = 50, - P9_RFSYNC, - P9_TLOCK = 52, - P9_RLOCK, - P9_TGETLOCK = 54, - P9_RGETLOCK, - P9_TLINK = 70, - P9_RLINK, - P9_TMKDIR = 72, - P9_RMKDIR, - P9_TRENAMEAT = 74, - P9_RRENAMEAT, - P9_TUNLINKAT = 76, - P9_RUNLINKAT, - P9_TVERSION = 100, - P9_RVERSION, - P9_TAUTH = 102, - P9_RAUTH, - P9_TATTACH = 104, - P9_RATTACH, - P9_TERROR = 106, - P9_RERROR, - P9_TFLUSH = 108, - P9_RFLUSH, - P9_TWALK = 110, - P9_RWALK, - P9_TOPEN = 112, - P9_ROPEN, - P9_TCREATE = 114, - P9_RCREATE, - P9_TREAD = 116, - P9_RREAD, - P9_TWRITE = 118, - P9_RWRITE, - P9_TCLUNK = 120, - P9_RCLUNK, - P9_TREMOVE = 122, - P9_RREMOVE, - P9_TSTAT = 124, - P9_RSTAT, - P9_TWSTAT = 126, - P9_RWSTAT, -}; - - -/* qid.types */ -enum { - P9_QTDIR = 0x80, - P9_QTAPPEND = 0x40, - P9_QTEXCL = 0x20, - P9_QTMOUNT = 0x10, - P9_QTAUTH = 0x08, - P9_QTTMP = 0x04, - P9_QTSYMLINK = 0x02, - P9_QTLINK = 0x01, - P9_QTFILE = 0x00, -}; - -enum p9_proto_version { - V9FS_PROTO_2000U = 0x01, - V9FS_PROTO_2000L = 0x02, -}; - -#define P9_NOTAG (u16)(~0) -#define P9_NOFID (u32)(~0) -#define P9_MAXWELEM 16 - -#define FID_REFERENCED 0x1 -#define FID_NON_RECLAIMABLE 0x2 -static inline char *rpath(FsContext *ctx, const char *path) -{ - return g_strdup_printf("%s/%s", ctx->fs_root, path); -} - -/* - * ample room for Twrite/Rread header - * size[4] Tread/Twrite tag[2] fid[4] offset[8] count[4] - */ -#define P9_IOHDRSZ 24 - -typedef struct V9fsPDU V9fsPDU; -struct V9fsState; - -struct V9fsPDU -{ - uint32_t size; - uint16_t tag; - uint8_t id; - uint8_t cancelled; - CoQueue complete; - VirtQueueElement elem; - struct V9fsState *s; - QLIST_ENTRY(V9fsPDU) next; -}; - - -/* FIXME - * 1) change user needs to set groups and stuff - */ - -#define MAX_REQ 128 -#define MAX_TAG_LEN 32 - -#define BUG_ON(cond) assert(!(cond)) - -typedef struct V9fsFidState V9fsFidState; - -enum { - P9_FID_NONE = 0, - P9_FID_FILE, - P9_FID_DIR, - P9_FID_XATTR, -}; - -typedef struct V9fsXattr -{ - int64_t copied_len; - int64_t len; - void *value; - V9fsString name; - int flags; -} V9fsXattr; - -/* - * Filled by fs driver on open and other - * calls. - */ -union V9fsFidOpenState { - int fd; - DIR *dir; - V9fsXattr xattr; - /* - * private pointer for fs drivers, that - * have its own internal representation of - * open files. - */ - void *private; -}; - -struct V9fsFidState -{ - int fid_type; - int32_t fid; - V9fsPath path; - V9fsFidOpenState fs; - V9fsFidOpenState fs_reclaim; - int flags; - int open_flags; - uid_t uid; - int ref; - int clunked; - V9fsFidState *next; - V9fsFidState *rclm_lst; -}; - -typedef struct V9fsState +typedef struct V9fsVirtioState { VirtIODevice parent_obj; VirtQueue *vq; - V9fsPDU pdus[MAX_REQ]; - QLIST_HEAD(, V9fsPDU) free_list; - QLIST_HEAD(, V9fsPDU) active_list; - V9fsFidState *fid_list; - FileOperations *ops; - FsContext ctx; - char *tag; size_t config_size; - enum p9_proto_version proto_version; - int32_t msize; - /* - * lock ensuring atomic path update - * on rename. - */ - CoRwlock rename_lock; - int32_t root_fid; - Error *migration_blocker; - V9fsConf fsconf; -} V9fsState; - -typedef struct V9fsStatState { - V9fsPDU *pdu; - size_t offset; - V9fsStat v9stat; - V9fsFidState *fidp; - struct stat stbuf; -} V9fsStatState; - -typedef struct V9fsOpenState { - V9fsPDU *pdu; - size_t offset; - int32_t mode; - V9fsFidState *fidp; - V9fsQID qid; - struct stat stbuf; - int iounit; -} V9fsOpenState; - -typedef struct V9fsReadState { - V9fsPDU *pdu; - size_t offset; - int32_t count; - int32_t total; - int64_t off; - V9fsFidState *fidp; - struct iovec iov[128]; /* FIXME: bad, bad, bad */ - struct iovec *sg; - off_t dir_pos; - struct dirent *dent; - struct stat stbuf; - V9fsString name; - V9fsStat v9stat; - int32_t len; - int32_t cnt; - int32_t max_count; -} V9fsReadState; - -typedef struct V9fsWriteState { - V9fsPDU *pdu; - size_t offset; - int32_t len; - int32_t count; - int32_t total; - int64_t off; - V9fsFidState *fidp; - struct iovec iov[128]; /* FIXME: bad, bad, bad */ - struct iovec *sg; - int cnt; -} V9fsWriteState; - -typedef struct V9fsMkState { - V9fsPDU *pdu; - size_t offset; - V9fsQID qid; - struct stat stbuf; - V9fsString name; - V9fsString fullname; -} V9fsMkState; - -/* 9p2000.L open flags */ -#define P9_DOTL_RDONLY 00000000 -#define P9_DOTL_WRONLY 00000001 -#define P9_DOTL_RDWR 00000002 -#define P9_DOTL_NOACCESS 00000003 -#define P9_DOTL_CREATE 00000100 -#define P9_DOTL_EXCL 00000200 -#define P9_DOTL_NOCTTY 00000400 -#define P9_DOTL_TRUNC 00001000 -#define P9_DOTL_APPEND 00002000 -#define P9_DOTL_NONBLOCK 00004000 -#define P9_DOTL_DSYNC 00010000 -#define P9_DOTL_FASYNC 00020000 -#define P9_DOTL_DIRECT 00040000 -#define P9_DOTL_LARGEFILE 00100000 -#define P9_DOTL_DIRECTORY 00200000 -#define P9_DOTL_NOFOLLOW 00400000 -#define P9_DOTL_NOATIME 01000000 -#define P9_DOTL_CLOEXEC 02000000 -#define P9_DOTL_SYNC 04000000 - -/* 9p2000.L at flags */ -#define P9_DOTL_AT_REMOVEDIR 0x200 - -/* 9P2000.L lock type */ -#define P9_LOCK_TYPE_RDLCK 0 -#define P9_LOCK_TYPE_WRLCK 1 -#define P9_LOCK_TYPE_UNLCK 2 - -#define P9_LOCK_SUCCESS 0 -#define P9_LOCK_BLOCKED 1 -#define P9_LOCK_ERROR 2 -#define P9_LOCK_GRACE 3 - -#define P9_LOCK_FLAGS_BLOCK 1 -#define P9_LOCK_FLAGS_RECLAIM 2 - -typedef struct V9fsFlock -{ - uint8_t type; - uint32_t flags; - uint64_t start; /* absolute offset */ - uint64_t length; - uint32_t proc_id; - V9fsString client_id; -} V9fsFlock; - -typedef struct V9fsGetlock -{ - uint8_t type; - uint64_t start; /* absolute offset */ - uint64_t length; - uint32_t proc_id; - V9fsString client_id; -} V9fsGetlock; - -extern int open_fd_hw; -extern int total_open_fd; - -size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count, - size_t offset, size_t size, int pack); - -static inline size_t do_pdu_unpack(void *dst, struct iovec *sg, int sg_count, - size_t offset, size_t size) -{ - return pdu_packunpack(dst, sg, sg_count, offset, size, 0); -} - -static inline void v9fs_path_write_lock(V9fsState *s) -{ - if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { - qemu_co_rwlock_wrlock(&s->rename_lock); - } -} - -static inline void v9fs_path_read_lock(V9fsState *s) -{ - if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { - qemu_co_rwlock_rdlock(&s->rename_lock); - } -} - -static inline void v9fs_path_unlock(V9fsState *s) -{ - if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { - qemu_co_rwlock_unlock(&s->rename_lock); - } -} - -static inline uint8_t v9fs_request_cancelled(V9fsPDU *pdu) -{ - return pdu->cancelled; -} + V9fsPDU pdus[MAX_REQ]; + VirtQueueElement elems[MAX_REQ]; + V9fsState state; +} V9fsVirtioState; -extern void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq); -extern void v9fs_reclaim_fd(V9fsPDU *pdu); -extern void v9fs_path_init(V9fsPath *path); -extern void v9fs_path_free(V9fsPath *path); -extern void v9fs_path_copy(V9fsPath *lhs, V9fsPath *rhs); -extern int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath, - const char *name, V9fsPath *path); +extern void virtio_9p_push_and_notify(V9fsPDU *pdu); -#define pdu_marshal(pdu, offset, fmt, args...) \ - v9fs_marshal(pdu->elem.in_sg, pdu->elem.in_num, offset, 1, fmt, ##args) -#define pdu_unmarshal(pdu, offset, fmt, args...) \ - v9fs_unmarshal(pdu->elem.out_sg, pdu->elem.out_num, offset, 1, fmt, ##args) +ssize_t virtio_pdu_vmarshal(V9fsPDU *pdu, size_t offset, + const char *fmt, va_list ap); +ssize_t virtio_pdu_vunmarshal(V9fsPDU *pdu, size_t offset, + const char *fmt, va_list ap); +void virtio_init_iov_from_pdu(V9fsPDU *pdu, struct iovec **piov, + unsigned int *pniov, bool is_write); #define TYPE_VIRTIO_9P "virtio-9p-device" #define VIRTIO_9P(obj) \ - OBJECT_CHECK(V9fsState, (obj), TYPE_VIRTIO_9P) + OBJECT_CHECK(V9fsVirtioState, (obj), TYPE_VIRTIO_9P) #endif diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h index 7ab8367..a526d2f 100644 --- a/hw/s390x/virtio-ccw.h +++ b/hw/s390x/virtio-ccw.h @@ -210,7 +210,7 @@ VirtIODevice *virtio_ccw_get_vdev(SubchDev *sch); typedef struct V9fsCCWState { VirtioCcwDevice parent_obj; - V9fsState vdev; + V9fsVirtioState vdev; } V9fsCCWState; #endif /* CONFIG_VIRTFS */ diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h index a104ff2..e096e98 100644 --- a/hw/virtio/virtio-pci.h +++ b/hw/virtio/virtio-pci.h @@ -23,7 +23,6 @@ #include "hw/virtio/virtio-scsi.h" #include "hw/virtio/virtio-balloon.h" #include "hw/virtio/virtio-bus.h" -#include "hw/virtio/virtio-9p.h" #include "hw/virtio/virtio-input.h" #include "hw/virtio/virtio-gpu.h" #ifdef CONFIG_VIRTFS @@ -243,7 +242,7 @@ struct VirtIONetPCI { typedef struct V9fsPCIState { VirtIOPCIProxy parent_obj; - V9fsState vdev; + V9fsVirtioState vdev; } V9fsPCIState; #endif |