mirror of https://github.com/xqemu/xqemu.git
Merge remote-tracking branch 'aneesh/for-upstream-6' into staging
Conflicts: trace-events
This commit is contained in:
commit
1f99b94932
|
@ -305,7 +305,7 @@ sound-obj-$(CONFIG_HDA) += intel-hda.o hda-audio.o
|
|||
adlib.o fmopl.o: QEMU_CFLAGS += -DBUILD_Y8950=0
|
||||
hw-obj-$(CONFIG_SOUND) += $(sound-obj-y)
|
||||
|
||||
9pfs-nested-$(CONFIG_VIRTFS) = virtio-9p.o virtio-9p-debug.o
|
||||
9pfs-nested-$(CONFIG_VIRTFS) = virtio-9p.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
|
||||
|
|
|
@ -2556,6 +2556,31 @@ EOF
|
|||
fi
|
||||
fi
|
||||
|
||||
##########################################
|
||||
# check if we have open_by_handle_at
|
||||
|
||||
open_by_hande_at=no
|
||||
cat > $TMPC << EOF
|
||||
#include <fcntl.h>
|
||||
int main(void) { struct file_handle *fh; open_by_handle_at(0, fh, 0); }
|
||||
EOF
|
||||
if compile_prog "" "" ; then
|
||||
open_by_handle_at=yes
|
||||
fi
|
||||
|
||||
########################################
|
||||
# check if we have linux/magic.h
|
||||
|
||||
linux_magic_h=no
|
||||
cat > $TMPC << EOF
|
||||
#include <linux/magic.h>
|
||||
int main(void) {
|
||||
}
|
||||
EOF
|
||||
if compile_prog "" "" ; then
|
||||
linux_magic_h=yes
|
||||
fi
|
||||
|
||||
##########################################
|
||||
# End of CC checks
|
||||
# After here, no more $cc or $ld runs
|
||||
|
@ -3035,6 +3060,14 @@ if test "$ucontext_coroutine" = "yes" ; then
|
|||
echo "CONFIG_UCONTEXT_COROUTINE=y" >> $config_host_mak
|
||||
fi
|
||||
|
||||
if test "$open_by_handle_at" = "yes" ; then
|
||||
echo "CONFIG_OPEN_BY_HANDLE=y" >> $config_host_mak
|
||||
fi
|
||||
|
||||
if test "$linux_magic_h" = "yes" ; then
|
||||
echo "CONFIG_LINUX_MAGIC_H=y" >> $config_host_mak
|
||||
fi
|
||||
|
||||
# USB host support
|
||||
case "$usb" in
|
||||
linux)
|
||||
|
|
|
@ -23,23 +23,6 @@
|
|||
#define SM_LOCAL_MODE_BITS 0600
|
||||
#define SM_LOCAL_DIR_MODE_BITS 0700
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/*
|
||||
* Server will try to set uid/gid.
|
||||
* On failure ignore the error.
|
||||
*/
|
||||
SM_NONE = 0,
|
||||
/*
|
||||
* uid/gid set on fileserver files
|
||||
*/
|
||||
SM_PASSTHROUGH = 1,
|
||||
/*
|
||||
* uid/gid part of xattr
|
||||
*/
|
||||
SM_MAPPED,
|
||||
} SecModel;
|
||||
|
||||
typedef struct FsCred
|
||||
{
|
||||
uid_t fc_uid;
|
||||
|
@ -49,17 +32,41 @@ typedef struct FsCred
|
|||
} FsCred;
|
||||
|
||||
struct xattr_operations;
|
||||
struct FsContext;
|
||||
struct V9fsPath;
|
||||
|
||||
/* FsContext flag values */
|
||||
#define PATHNAME_FSCONTEXT 0x1
|
||||
typedef struct extended_ops {
|
||||
int (*get_st_gen)(struct FsContext *, struct V9fsPath *,
|
||||
mode_t, uint64_t *);
|
||||
} extended_ops;
|
||||
|
||||
/* export flags */
|
||||
#define V9FS_IMMEDIATE_WRITEOUT 0x00000001
|
||||
#define V9FS_PATHNAME_FSCONTEXT 0x00000002
|
||||
/*
|
||||
* uid/gid set on fileserver files
|
||||
*/
|
||||
#define V9FS_SM_PASSTHROUGH 0x00000004
|
||||
/*
|
||||
* uid/gid part of xattr
|
||||
*/
|
||||
#define V9FS_SM_MAPPED 0x00000008
|
||||
/*
|
||||
* Server will try to set uid/gid.
|
||||
* On failure ignore the error.
|
||||
*/
|
||||
#define V9FS_SM_NONE 0x00000010
|
||||
|
||||
|
||||
#define V9FS_SEC_MASK 0x0000001C
|
||||
|
||||
typedef struct FsContext
|
||||
{
|
||||
int flags;
|
||||
char *fs_root;
|
||||
SecModel fs_sm;
|
||||
uid_t uid;
|
||||
char *fs_root;
|
||||
int export_flags;
|
||||
struct xattr_operations **xops;
|
||||
struct extended_ops exops;
|
||||
/* fs driver specific data */
|
||||
void *private;
|
||||
} FsContext;
|
||||
|
|
|
@ -18,46 +18,55 @@
|
|||
#include "qemu-common.h"
|
||||
#include "qemu-config.h"
|
||||
|
||||
static QTAILQ_HEAD(FsTypeEntry_head, FsTypeListEntry) fstype_entries =
|
||||
QTAILQ_HEAD_INITIALIZER(fstype_entries);
|
||||
static QTAILQ_HEAD(FsDriverEntry_head, FsDriverListEntry) fsdriver_entries =
|
||||
QTAILQ_HEAD_INITIALIZER(fsdriver_entries);
|
||||
|
||||
static FsTypeTable FsTypes[] = {
|
||||
static FsDriverTable FsDrivers[] = {
|
||||
{ .name = "local", .ops = &local_ops},
|
||||
{ .name = "handle", .ops = &handle_ops},
|
||||
};
|
||||
|
||||
int qemu_fsdev_add(QemuOpts *opts)
|
||||
{
|
||||
struct FsTypeListEntry *fsle;
|
||||
struct FsDriverListEntry *fsle;
|
||||
int i;
|
||||
const char *fsdev_id = qemu_opts_id(opts);
|
||||
const char *fstype = qemu_opt_get(opts, "fstype");
|
||||
const char *fsdriver = qemu_opt_get(opts, "fsdriver");
|
||||
const char *path = qemu_opt_get(opts, "path");
|
||||
const char *sec_model = qemu_opt_get(opts, "security_model");
|
||||
const char *writeout = qemu_opt_get(opts, "writeout");
|
||||
|
||||
|
||||
if (!fsdev_id) {
|
||||
fprintf(stderr, "fsdev: No id specified\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fstype) {
|
||||
for (i = 0; i < ARRAY_SIZE(FsTypes); i++) {
|
||||
if (strcmp(FsTypes[i].name, fstype) == 0) {
|
||||
if (fsdriver) {
|
||||
for (i = 0; i < ARRAY_SIZE(FsDrivers); i++) {
|
||||
if (strcmp(FsDrivers[i].name, fsdriver) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(FsTypes)) {
|
||||
fprintf(stderr, "fsdev: fstype %s not found\n", fstype);
|
||||
if (i == ARRAY_SIZE(FsDrivers)) {
|
||||
fprintf(stderr, "fsdev: fsdriver %s not found\n", fsdriver);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "fsdev: No fstype specified\n");
|
||||
fprintf(stderr, "fsdev: No fsdriver specified\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!sec_model) {
|
||||
fprintf(stderr, "fsdev: No security_model specified.\n");
|
||||
if (!strcmp(fsdriver, "local") && !sec_model) {
|
||||
fprintf(stderr, "security model not specified, "
|
||||
"local fs needs security model\nvalid options are:"
|
||||
"\tsecurity_model=[passthrough|mapped|none]\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(fsdriver, "local") && sec_model) {
|
||||
fprintf(stderr, "only local fs driver needs security model\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -70,20 +79,40 @@ int qemu_fsdev_add(QemuOpts *opts)
|
|||
|
||||
fsle->fse.fsdev_id = g_strdup(fsdev_id);
|
||||
fsle->fse.path = g_strdup(path);
|
||||
fsle->fse.security_model = g_strdup(sec_model);
|
||||
fsle->fse.ops = FsTypes[i].ops;
|
||||
fsle->fse.ops = FsDrivers[i].ops;
|
||||
fsle->fse.export_flags = 0;
|
||||
if (writeout) {
|
||||
if (!strcmp(writeout, "immediate")) {
|
||||
fsle->fse.export_flags |= V9FS_IMMEDIATE_WRITEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
QTAILQ_INSERT_TAIL(&fstype_entries, fsle, next);
|
||||
if (strcmp(fsdriver, "local")) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!strcmp(sec_model, "passthrough")) {
|
||||
fsle->fse.export_flags |= V9FS_SM_PASSTHROUGH;
|
||||
} else if (!strcmp(sec_model, "mapped")) {
|
||||
fsle->fse.export_flags |= V9FS_SM_MAPPED;
|
||||
} else if (!strcmp(sec_model, "none")) {
|
||||
fsle->fse.export_flags |= V9FS_SM_NONE;
|
||||
} else {
|
||||
fprintf(stderr, "Invalid security model %s specified, valid options are"
|
||||
"\n\t [passthrough|mapped|none]\n", sec_model);
|
||||
return -1;
|
||||
}
|
||||
done:
|
||||
QTAILQ_INSERT_TAIL(&fsdriver_entries, fsle, next);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
FsTypeEntry *get_fsdev_fsentry(char *id)
|
||||
FsDriverEntry *get_fsdev_fsentry(char *id)
|
||||
{
|
||||
if (id) {
|
||||
struct FsTypeListEntry *fsle;
|
||||
struct FsDriverListEntry *fsle;
|
||||
|
||||
QTAILQ_FOREACH(fsle, &fstype_entries, next) {
|
||||
QTAILQ_FOREACH(fsle, &fsdriver_entries, next) {
|
||||
if (strcmp(fsle->fse.fsdev_id, id) == 0) {
|
||||
return &fsle->fse;
|
||||
}
|
||||
|
|
|
@ -29,28 +29,28 @@
|
|||
* -----------------
|
||||
* etc
|
||||
*/
|
||||
typedef struct FsTypeTable {
|
||||
typedef struct FsDriverTable {
|
||||
const char *name;
|
||||
FileOperations *ops;
|
||||
} FsTypeTable;
|
||||
} FsDriverTable;
|
||||
|
||||
/*
|
||||
* Structure to store the various fsdev's passed through command line.
|
||||
*/
|
||||
typedef struct FsTypeEntry {
|
||||
typedef struct FsDriverEntry {
|
||||
char *fsdev_id;
|
||||
char *path;
|
||||
char *security_model;
|
||||
int export_flags;
|
||||
FileOperations *ops;
|
||||
} FsTypeEntry;
|
||||
} FsDriverEntry;
|
||||
|
||||
typedef struct FsTypeListEntry {
|
||||
FsTypeEntry fse;
|
||||
QTAILQ_ENTRY(FsTypeListEntry) next;
|
||||
} FsTypeListEntry;
|
||||
typedef struct FsDriverListEntry {
|
||||
FsDriverEntry fse;
|
||||
QTAILQ_ENTRY(FsDriverListEntry) next;
|
||||
} FsDriverListEntry;
|
||||
|
||||
int qemu_fsdev_add(QemuOpts *opts);
|
||||
FsTypeEntry *get_fsdev_fsentry(char *id);
|
||||
FsDriverEntry *get_fsdev_fsentry(char *id);
|
||||
extern FileOperations local_ops;
|
||||
extern FileOperations handle_ops;
|
||||
#endif
|
||||
|
|
|
@ -17,6 +17,30 @@
|
|||
#include "qemu-coroutine.h"
|
||||
#include "virtio-9p-coth.h"
|
||||
|
||||
int v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t st_mode,
|
||||
V9fsStatDotl *v9stat)
|
||||
{
|
||||
int err = 0;
|
||||
V9fsState *s = pdu->s;
|
||||
|
||||
if (v9fs_request_cancelled(pdu)) {
|
||||
return -EINTR;
|
||||
}
|
||||
if (s->ctx.exops.get_st_gen) {
|
||||
v9fs_path_read_lock(s);
|
||||
v9fs_co_run_in_worker(
|
||||
{
|
||||
err = s->ctx.exops.get_st_gen(&s->ctx, path, st_mode,
|
||||
&v9stat->st_gen);
|
||||
if (err < 0) {
|
||||
err = -errno;
|
||||
}
|
||||
});
|
||||
v9fs_path_unlock(s);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int v9fs_co_lstat(V9fsPDU *pdu, V9fsPath *path, struct stat *stbuf)
|
||||
{
|
||||
int err;
|
||||
|
|
|
@ -323,7 +323,7 @@ int v9fs_co_name_to_path(V9fsPDU *pdu, V9fsPath *dirpath,
|
|||
int err;
|
||||
V9fsState *s = pdu->s;
|
||||
|
||||
if (s->ctx.flags & PATHNAME_FSCONTEXT) {
|
||||
if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) {
|
||||
err = s->ops->name_to_path(&s->ctx, dirpath, name, path);
|
||||
if (err < 0) {
|
||||
err = -errno;
|
||||
|
|
|
@ -101,4 +101,7 @@ extern int v9fs_co_preadv(V9fsPDU *, V9fsFidState *,
|
|||
struct iovec *, int, int64_t);
|
||||
extern int v9fs_co_name_to_path(V9fsPDU *, V9fsPath *,
|
||||
const char *, V9fsPath *);
|
||||
extern int v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t,
|
||||
V9fsStatDotl *v9stat);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,646 +0,0 @@
|
|||
/*
|
||||
* Virtio 9p PDU debug
|
||||
*
|
||||
* Copyright IBM, Corp. 2010
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.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 "hw/virtio.h"
|
||||
#include "hw/pc.h"
|
||||
#include "virtio-9p.h"
|
||||
#include "virtio-9p-debug.h"
|
||||
|
||||
#define BUG_ON(cond) assert(!(cond))
|
||||
|
||||
static FILE *llogfile;
|
||||
|
||||
static struct iovec *get_sg(V9fsPDU *pdu, int rx)
|
||||
{
|
||||
if (rx) {
|
||||
return pdu->elem.in_sg;
|
||||
}
|
||||
return pdu->elem.out_sg;
|
||||
}
|
||||
|
||||
static int get_sg_count(V9fsPDU *pdu, int rx)
|
||||
{
|
||||
if (rx) {
|
||||
return pdu->elem.in_num;
|
||||
}
|
||||
return pdu->elem.out_num;
|
||||
|
||||
}
|
||||
|
||||
static void pprint_int8(V9fsPDU *pdu, int rx, size_t *offsetp,
|
||||
const char *name)
|
||||
{
|
||||
size_t copied;
|
||||
int count = get_sg_count(pdu, rx);
|
||||
size_t offset = *offsetp;
|
||||
struct iovec *sg = get_sg(pdu, rx);
|
||||
int8_t value;
|
||||
|
||||
copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
|
||||
|
||||
BUG_ON(copied != sizeof(value));
|
||||
offset += sizeof(value);
|
||||
fprintf(llogfile, "%s=0x%x", name, value);
|
||||
*offsetp = offset;
|
||||
}
|
||||
|
||||
static void pprint_int16(V9fsPDU *pdu, int rx, size_t *offsetp,
|
||||
const char *name)
|
||||
{
|
||||
size_t copied;
|
||||
int count = get_sg_count(pdu, rx);
|
||||
struct iovec *sg = get_sg(pdu, rx);
|
||||
size_t offset = *offsetp;
|
||||
int16_t value;
|
||||
|
||||
|
||||
copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
|
||||
|
||||
BUG_ON(copied != sizeof(value));
|
||||
offset += sizeof(value);
|
||||
fprintf(llogfile, "%s=0x%x", name, value);
|
||||
*offsetp = offset;
|
||||
}
|
||||
|
||||
static void pprint_int32(V9fsPDU *pdu, int rx, size_t *offsetp,
|
||||
const char *name)
|
||||
{
|
||||
size_t copied;
|
||||
int count = get_sg_count(pdu, rx);
|
||||
struct iovec *sg = get_sg(pdu, rx);
|
||||
size_t offset = *offsetp;
|
||||
int32_t value;
|
||||
|
||||
|
||||
copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
|
||||
|
||||
BUG_ON(copied != sizeof(value));
|
||||
offset += sizeof(value);
|
||||
fprintf(llogfile, "%s=0x%x", name, value);
|
||||
*offsetp = offset;
|
||||
}
|
||||
|
||||
static void pprint_int64(V9fsPDU *pdu, int rx, size_t *offsetp,
|
||||
const char *name)
|
||||
{
|
||||
size_t copied;
|
||||
int count = get_sg_count(pdu, rx);
|
||||
struct iovec *sg = get_sg(pdu, rx);
|
||||
size_t offset = *offsetp;
|
||||
int64_t value;
|
||||
|
||||
|
||||
copied = do_pdu_unpack(&value, sg, count, offset, sizeof(value));
|
||||
|
||||
BUG_ON(copied != sizeof(value));
|
||||
offset += sizeof(value);
|
||||
fprintf(llogfile, "%s=0x%" PRIx64, name, value);
|
||||
*offsetp = offset;
|
||||
}
|
||||
|
||||
static void pprint_str(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
|
||||
{
|
||||
int sg_count = get_sg_count(pdu, rx);
|
||||
struct iovec *sg = get_sg(pdu, rx);
|
||||
size_t offset = *offsetp;
|
||||
uint16_t tmp_size, size;
|
||||
size_t result;
|
||||
size_t copied = 0;
|
||||
int i = 0;
|
||||
|
||||
/* get the size */
|
||||
copied = do_pdu_unpack(&tmp_size, sg, sg_count, offset, sizeof(tmp_size));
|
||||
BUG_ON(copied != sizeof(tmp_size));
|
||||
size = le16_to_cpupu(&tmp_size);
|
||||
offset += copied;
|
||||
|
||||
fprintf(llogfile, "%s=", name);
|
||||
for (i = 0; size && i < sg_count; i++) {
|
||||
size_t len;
|
||||
if (offset >= sg[i].iov_len) {
|
||||
/* skip this sg */
|
||||
offset -= sg[i].iov_len;
|
||||
continue;
|
||||
} else {
|
||||
len = MIN(sg[i].iov_len - offset, size);
|
||||
result = fwrite(sg[i].iov_base + offset, 1, len, llogfile);
|
||||
BUG_ON(result != len);
|
||||
size -= len;
|
||||
copied += len;
|
||||
if (size) {
|
||||
offset = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
*offsetp += copied;
|
||||
}
|
||||
|
||||
static void pprint_qid(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
|
||||
{
|
||||
fprintf(llogfile, "%s={", name);
|
||||
pprint_int8(pdu, rx, offsetp, "type");
|
||||
pprint_int32(pdu, rx, offsetp, ", version");
|
||||
pprint_int64(pdu, rx, offsetp, ", path");
|
||||
fprintf(llogfile, "}");
|
||||
}
|
||||
|
||||
static void pprint_stat(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
|
||||
{
|
||||
fprintf(llogfile, "%s={", name);
|
||||
pprint_int16(pdu, rx, offsetp, "size");
|
||||
pprint_int16(pdu, rx, offsetp, ", type");
|
||||
pprint_int32(pdu, rx, offsetp, ", dev");
|
||||
pprint_qid(pdu, rx, offsetp, ", qid");
|
||||
pprint_int32(pdu, rx, offsetp, ", mode");
|
||||
pprint_int32(pdu, rx, offsetp, ", atime");
|
||||
pprint_int32(pdu, rx, offsetp, ", mtime");
|
||||
pprint_int64(pdu, rx, offsetp, ", length");
|
||||
pprint_str(pdu, rx, offsetp, ", name");
|
||||
pprint_str(pdu, rx, offsetp, ", uid");
|
||||
pprint_str(pdu, rx, offsetp, ", gid");
|
||||
pprint_str(pdu, rx, offsetp, ", muid");
|
||||
pprint_str(pdu, rx, offsetp, ", extension");
|
||||
pprint_int32(pdu, rx, offsetp, ", uid");
|
||||
pprint_int32(pdu, rx, offsetp, ", gid");
|
||||
pprint_int32(pdu, rx, offsetp, ", muid");
|
||||
fprintf(llogfile, "}");
|
||||
}
|
||||
|
||||
static void pprint_stat_dotl(V9fsPDU *pdu, int rx, size_t *offsetp,
|
||||
const char *name)
|
||||
{
|
||||
fprintf(llogfile, "%s={", name);
|
||||
pprint_qid(pdu, rx, offsetp, "qid");
|
||||
pprint_int32(pdu, rx, offsetp, ", st_mode");
|
||||
pprint_int64(pdu, rx, offsetp, ", st_nlink");
|
||||
pprint_int32(pdu, rx, offsetp, ", st_uid");
|
||||
pprint_int32(pdu, rx, offsetp, ", st_gid");
|
||||
pprint_int64(pdu, rx, offsetp, ", st_rdev");
|
||||
pprint_int64(pdu, rx, offsetp, ", st_size");
|
||||
pprint_int64(pdu, rx, offsetp, ", st_blksize");
|
||||
pprint_int64(pdu, rx, offsetp, ", st_blocks");
|
||||
pprint_int64(pdu, rx, offsetp, ", atime");
|
||||
pprint_int64(pdu, rx, offsetp, ", atime_nsec");
|
||||
pprint_int64(pdu, rx, offsetp, ", mtime");
|
||||
pprint_int64(pdu, rx, offsetp, ", mtime_nsec");
|
||||
pprint_int64(pdu, rx, offsetp, ", ctime");
|
||||
pprint_int64(pdu, rx, offsetp, ", ctime_nsec");
|
||||
fprintf(llogfile, "}");
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void pprint_strs(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
|
||||
{
|
||||
int sg_count = get_sg_count(pdu, rx);
|
||||
struct iovec *sg = get_sg(pdu, rx);
|
||||
size_t offset = *offsetp;
|
||||
uint16_t tmp_count, count, i;
|
||||
size_t copied = 0;
|
||||
|
||||
fprintf(llogfile, "%s={", name);
|
||||
|
||||
/* Get the count */
|
||||
copied = do_pdu_unpack(&tmp_count, sg, sg_count, offset, sizeof(tmp_count));
|
||||
BUG_ON(copied != sizeof(tmp_count));
|
||||
count = le16_to_cpupu(&tmp_count);
|
||||
offset += copied;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
char str[512];
|
||||
if (i) {
|
||||
fprintf(llogfile, ", ");
|
||||
}
|
||||
snprintf(str, sizeof(str), "[%d]", i);
|
||||
pprint_str(pdu, rx, &offset, str);
|
||||
}
|
||||
|
||||
fprintf(llogfile, "}");
|
||||
|
||||
*offsetp = offset;
|
||||
}
|
||||
|
||||
static void pprint_qids(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
|
||||
{
|
||||
int sg_count = get_sg_count(pdu, rx);
|
||||
struct iovec *sg = get_sg(pdu, rx);
|
||||
size_t offset = *offsetp;
|
||||
uint16_t tmp_count, count, i;
|
||||
size_t copied = 0;
|
||||
|
||||
fprintf(llogfile, "%s={", name);
|
||||
|
||||
copied = do_pdu_unpack(&tmp_count, sg, sg_count, offset, sizeof(tmp_count));
|
||||
BUG_ON(copied != sizeof(tmp_count));
|
||||
count = le16_to_cpupu(&tmp_count);
|
||||
offset += copied;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
char str[512];
|
||||
if (i) {
|
||||
fprintf(llogfile, ", ");
|
||||
}
|
||||
snprintf(str, sizeof(str), "[%d]", i);
|
||||
pprint_qid(pdu, rx, &offset, str);
|
||||
}
|
||||
|
||||
fprintf(llogfile, "}");
|
||||
|
||||
*offsetp = offset;
|
||||
}
|
||||
|
||||
static void pprint_sg(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
|
||||
{
|
||||
struct iovec *sg = get_sg(pdu, rx);
|
||||
unsigned int count;
|
||||
int i;
|
||||
|
||||
if (rx) {
|
||||
count = pdu->elem.in_num;
|
||||
} else {
|
||||
count = pdu->elem.out_num;
|
||||
}
|
||||
|
||||
fprintf(llogfile, "%s={", name);
|
||||
for (i = 0; i < count; i++) {
|
||||
if (i) {
|
||||
fprintf(llogfile, ", ");
|
||||
}
|
||||
fprintf(llogfile, "(%p, 0x%zx)", sg[i].iov_base, sg[i].iov_len);
|
||||
}
|
||||
fprintf(llogfile, "}");
|
||||
}
|
||||
|
||||
/* FIXME: read from a directory fid returns serialized stat_t's */
|
||||
#ifdef DEBUG_DATA
|
||||
static void pprint_data(V9fsPDU *pdu, int rx, size_t *offsetp, const char *name)
|
||||
{
|
||||
struct iovec *sg = get_sg(pdu, rx);
|
||||
size_t offset = *offsetp;
|
||||
unsigned int count;
|
||||
int32_t size;
|
||||
int total, i, j;
|
||||
ssize_t len;
|
||||
|
||||
if (rx) {
|
||||
count = pdu->elem.in_num;
|
||||
} else {
|
||||
count = pdu->elem.out_num;
|
||||
}
|
||||
|
||||
BUG_ON((offset + sizeof(size)) > sg[0].iov_len);
|
||||
|
||||
memcpy(&size, sg[0].iov_base + offset, sizeof(size));
|
||||
offset += sizeof(size);
|
||||
|
||||
fprintf(llogfile, "size: %x\n", size);
|
||||
|
||||
sg[0].iov_base += 11; /* skip header */
|
||||
sg[0].iov_len -= 11;
|
||||
|
||||
total = 0;
|
||||
for (i = 0; i < count; i++) {
|
||||
total += sg[i].iov_len;
|
||||
if (total >= size) {
|
||||
/* trim sg list so writev does the right thing */
|
||||
sg[i].iov_len -= (total - size);
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(llogfile, "%s={\"", name);
|
||||
fflush(llogfile);
|
||||
for (j = 0; j < i; j++) {
|
||||
if (j) {
|
||||
fprintf(llogfile, "\", \"");
|
||||
fflush(llogfile);
|
||||
}
|
||||
|
||||
do {
|
||||
len = writev(fileno(llogfile), &sg[j], 1);
|
||||
} while (len == -1 && errno == EINTR);
|
||||
fprintf(llogfile, "len == %ld: %m\n", len);
|
||||
BUG_ON(len != sg[j].iov_len);
|
||||
}
|
||||
fprintf(llogfile, "\"}");
|
||||
|
||||
sg[0].iov_base -= 11;
|
||||
sg[0].iov_len += 11;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
void pprint_pdu(V9fsPDU *pdu)
|
||||
{
|
||||
size_t offset = 7;
|
||||
|
||||
if (llogfile == NULL) {
|
||||
llogfile = fopen("/tmp/pdu.log", "w");
|
||||
}
|
||||
|
||||
BUG_ON(!llogfile);
|
||||
|
||||
switch (pdu->id) {
|
||||
case P9_TREADDIR:
|
||||
fprintf(llogfile, "TREADDIR: (");
|
||||
pprint_int32(pdu, 0, &offset, "fid");
|
||||
pprint_int64(pdu, 0, &offset, ", initial offset");
|
||||
pprint_int32(pdu, 0, &offset, ", max count");
|
||||
break;
|
||||
case P9_RREADDIR:
|
||||
fprintf(llogfile, "RREADDIR: (");
|
||||
pprint_int32(pdu, 1, &offset, "count");
|
||||
#ifdef DEBUG_DATA
|
||||
pprint_data(pdu, 1, &offset, ", data");
|
||||
#endif
|
||||
break;
|
||||
case P9_TMKDIR:
|
||||
fprintf(llogfile, "TMKDIR: (");
|
||||
pprint_int32(pdu, 0, &offset, "fid");
|
||||
pprint_str(pdu, 0, &offset, "name");
|
||||
pprint_int32(pdu, 0, &offset, "mode");
|
||||
pprint_int32(pdu, 0, &offset, "gid");
|
||||
break;
|
||||
case P9_RMKDIR:
|
||||
fprintf(llogfile, "RMKDIR: (");
|
||||
pprint_qid(pdu, 0, &offset, "qid");
|
||||
break;
|
||||
case P9_TVERSION:
|
||||
fprintf(llogfile, "TVERSION: (");
|
||||
pprint_int32(pdu, 0, &offset, "msize");
|
||||
pprint_str(pdu, 0, &offset, ", version");
|
||||
break;
|
||||
case P9_RVERSION:
|
||||
fprintf(llogfile, "RVERSION: (");
|
||||
pprint_int32(pdu, 1, &offset, "msize");
|
||||
pprint_str(pdu, 1, &offset, ", version");
|
||||
break;
|
||||
case P9_TGETATTR:
|
||||
fprintf(llogfile, "TGETATTR: (");
|
||||
pprint_int32(pdu, 0, &offset, "fid");
|
||||
break;
|
||||
case P9_RGETATTR:
|
||||
fprintf(llogfile, "RGETATTR: (");
|
||||
pprint_stat_dotl(pdu, 1, &offset, "getattr");
|
||||
break;
|
||||
case P9_TAUTH:
|
||||
fprintf(llogfile, "TAUTH: (");
|
||||
pprint_int32(pdu, 0, &offset, "afid");
|
||||
pprint_str(pdu, 0, &offset, ", uname");
|
||||
pprint_str(pdu, 0, &offset, ", aname");
|
||||
pprint_int32(pdu, 0, &offset, ", n_uname");
|
||||
break;
|
||||
case P9_RAUTH:
|
||||
fprintf(llogfile, "RAUTH: (");
|
||||
pprint_qid(pdu, 1, &offset, "qid");
|
||||
break;
|
||||
case P9_TATTACH:
|
||||
fprintf(llogfile, "TATTACH: (");
|
||||
pprint_int32(pdu, 0, &offset, "fid");
|
||||
pprint_int32(pdu, 0, &offset, ", afid");
|
||||
pprint_str(pdu, 0, &offset, ", uname");
|
||||
pprint_str(pdu, 0, &offset, ", aname");
|
||||
pprint_int32(pdu, 0, &offset, ", n_uname");
|
||||
break;
|
||||
case P9_RATTACH:
|
||||
fprintf(llogfile, "RATTACH: (");
|
||||
pprint_qid(pdu, 1, &offset, "qid");
|
||||
break;
|
||||
case P9_TERROR:
|
||||
fprintf(llogfile, "TERROR: (");
|
||||
break;
|
||||
case P9_RERROR:
|
||||
fprintf(llogfile, "RERROR: (");
|
||||
pprint_str(pdu, 1, &offset, "ename");
|
||||
pprint_int32(pdu, 1, &offset, ", ecode");
|
||||
break;
|
||||
case P9_TFLUSH:
|
||||
fprintf(llogfile, "TFLUSH: (");
|
||||
pprint_int16(pdu, 0, &offset, "oldtag");
|
||||
break;
|
||||
case P9_RFLUSH:
|
||||
fprintf(llogfile, "RFLUSH: (");
|
||||
break;
|
||||
case P9_TWALK:
|
||||
fprintf(llogfile, "TWALK: (");
|
||||
pprint_int32(pdu, 0, &offset, "fid");
|
||||
pprint_int32(pdu, 0, &offset, ", newfid");
|
||||
pprint_strs(pdu, 0, &offset, ", wnames");
|
||||
break;
|
||||
case P9_RWALK:
|
||||
fprintf(llogfile, "RWALK: (");
|
||||
pprint_qids(pdu, 1, &offset, "wqids");
|
||||
break;
|
||||
case P9_TOPEN:
|
||||
fprintf(llogfile, "TOPEN: (");
|
||||
pprint_int32(pdu, 0, &offset, "fid");
|
||||
pprint_int8(pdu, 0, &offset, ", mode");
|
||||
break;
|
||||
case P9_ROPEN:
|
||||
fprintf(llogfile, "ROPEN: (");
|
||||
pprint_qid(pdu, 1, &offset, "qid");
|
||||
pprint_int32(pdu, 1, &offset, ", iounit");
|
||||
break;
|
||||
case P9_TCREATE:
|
||||
fprintf(llogfile, "TCREATE: (");
|
||||
pprint_int32(pdu, 0, &offset, "fid");
|
||||
pprint_str(pdu, 0, &offset, ", name");
|
||||
pprint_int32(pdu, 0, &offset, ", perm");
|
||||
pprint_int8(pdu, 0, &offset, ", mode");
|
||||
pprint_str(pdu, 0, &offset, ", extension");
|
||||
break;
|
||||
case P9_RCREATE:
|
||||
fprintf(llogfile, "RCREATE: (");
|
||||
pprint_qid(pdu, 1, &offset, "qid");
|
||||
pprint_int32(pdu, 1, &offset, ", iounit");
|
||||
break;
|
||||
case P9_TSYMLINK:
|
||||
fprintf(llogfile, "TSYMLINK: (");
|
||||
pprint_int32(pdu, 0, &offset, "fid");
|
||||
pprint_str(pdu, 0, &offset, ", name");
|
||||
pprint_str(pdu, 0, &offset, ", symname");
|
||||
pprint_int32(pdu, 0, &offset, ", gid");
|
||||
break;
|
||||
case P9_RSYMLINK:
|
||||
fprintf(llogfile, "RSYMLINK: (");
|
||||
pprint_qid(pdu, 1, &offset, "qid");
|
||||
break;
|
||||
case P9_TLCREATE:
|
||||
fprintf(llogfile, "TLCREATE: (");
|
||||
pprint_int32(pdu, 0, &offset, "dfid");
|
||||
pprint_str(pdu, 0, &offset, ", name");
|
||||
pprint_int32(pdu, 0, &offset, ", flags");
|
||||
pprint_int32(pdu, 0, &offset, ", mode");
|
||||
pprint_int32(pdu, 0, &offset, ", gid");
|
||||
break;
|
||||
case P9_RLCREATE:
|
||||
fprintf(llogfile, "RLCREATE: (");
|
||||
pprint_qid(pdu, 1, &offset, "qid");
|
||||
pprint_int32(pdu, 1, &offset, ", iounit");
|
||||
break;
|
||||
case P9_TMKNOD:
|
||||
fprintf(llogfile, "TMKNOD: (");
|
||||
pprint_int32(pdu, 0, &offset, "fid");
|
||||
pprint_str(pdu, 0, &offset, "name");
|
||||
pprint_int32(pdu, 0, &offset, "mode");
|
||||
pprint_int32(pdu, 0, &offset, "major");
|
||||
pprint_int32(pdu, 0, &offset, "minor");
|
||||
pprint_int32(pdu, 0, &offset, "gid");
|
||||
break;
|
||||
case P9_RMKNOD:
|
||||
fprintf(llogfile, "RMKNOD: )");
|
||||
pprint_qid(pdu, 0, &offset, "qid");
|
||||
break;
|
||||
case P9_TREADLINK:
|
||||
fprintf(llogfile, "TREADLINK: (");
|
||||
pprint_int32(pdu, 0, &offset, "fid");
|
||||
break;
|
||||
case P9_RREADLINK:
|
||||
fprintf(llogfile, "RREADLINK: (");
|
||||
pprint_str(pdu, 0, &offset, "target");
|
||||
break;
|
||||
case P9_TREAD:
|
||||
fprintf(llogfile, "TREAD: (");
|
||||
pprint_int32(pdu, 0, &offset, "fid");
|
||||
pprint_int64(pdu, 0, &offset, ", offset");
|
||||
pprint_int32(pdu, 0, &offset, ", count");
|
||||
pprint_sg(pdu, 0, &offset, ", sg");
|
||||
break;
|
||||
case P9_RREAD:
|
||||
fprintf(llogfile, "RREAD: (");
|
||||
pprint_int32(pdu, 1, &offset, "count");
|
||||
pprint_sg(pdu, 1, &offset, ", sg");
|
||||
offset = 7;
|
||||
#ifdef DEBUG_DATA
|
||||
pprint_data(pdu, 1, &offset, ", data");
|
||||
#endif
|
||||
break;
|
||||
case P9_TWRITE:
|
||||
fprintf(llogfile, "TWRITE: (");
|
||||
pprint_int32(pdu, 0, &offset, "fid");
|
||||
pprint_int64(pdu, 0, &offset, ", offset");
|
||||
pprint_int32(pdu, 0, &offset, ", count");
|
||||
break;
|
||||
case P9_RWRITE:
|
||||
fprintf(llogfile, "RWRITE: (");
|
||||
pprint_int32(pdu, 1, &offset, "count");
|
||||
break;
|
||||
case P9_TCLUNK:
|
||||
fprintf(llogfile, "TCLUNK: (");
|
||||
pprint_int32(pdu, 0, &offset, "fid");
|
||||
break;
|
||||
case P9_RCLUNK:
|
||||
fprintf(llogfile, "RCLUNK: (");
|
||||
break;
|
||||
case P9_TFSYNC:
|
||||
fprintf(llogfile, "TFSYNC: (");
|
||||
pprint_int32(pdu, 0, &offset, "fid");
|
||||
break;
|
||||
case P9_RFSYNC:
|
||||
fprintf(llogfile, "RFSYNC: (");
|
||||
break;
|
||||
case P9_TLINK:
|
||||
fprintf(llogfile, "TLINK: (");
|
||||
pprint_int32(pdu, 0, &offset, "dfid");
|
||||
pprint_int32(pdu, 0, &offset, ", fid");
|
||||
pprint_str(pdu, 0, &offset, ", newpath");
|
||||
break;
|
||||
case P9_RLINK:
|
||||
fprintf(llogfile, "RLINK: (");
|
||||
break;
|
||||
case P9_TREMOVE:
|
||||
fprintf(llogfile, "TREMOVE: (");
|
||||
pprint_int32(pdu, 0, &offset, "fid");
|
||||
break;
|
||||
case P9_RREMOVE:
|
||||
fprintf(llogfile, "RREMOVE: (");
|
||||
break;
|
||||
case P9_TSTAT:
|
||||
fprintf(llogfile, "TSTAT: (");
|
||||
pprint_int32(pdu, 0, &offset, "fid");
|
||||
break;
|
||||
case P9_RSTAT:
|
||||
fprintf(llogfile, "RSTAT: (");
|
||||
offset += 2; /* ignored */
|
||||
pprint_stat(pdu, 1, &offset, "stat");
|
||||
break;
|
||||
case P9_TWSTAT:
|
||||
fprintf(llogfile, "TWSTAT: (");
|
||||
pprint_int32(pdu, 0, &offset, "fid");
|
||||
offset += 2; /* ignored */
|
||||
pprint_stat(pdu, 0, &offset, ", stat");
|
||||
break;
|
||||
case P9_RWSTAT:
|
||||
fprintf(llogfile, "RWSTAT: (");
|
||||
break;
|
||||
case P9_TXATTRWALK:
|
||||
fprintf(llogfile, "TXATTRWALK: (");
|
||||
pprint_int32(pdu, 0, &offset, "fid");
|
||||
pprint_int32(pdu, 0, &offset, ", newfid");
|
||||
pprint_str(pdu, 0, &offset, ", xattr name");
|
||||
break;
|
||||
case P9_RXATTRWALK:
|
||||
fprintf(llogfile, "RXATTRWALK: (");
|
||||
pprint_int64(pdu, 1, &offset, "xattrsize");
|
||||
case P9_TXATTRCREATE:
|
||||
fprintf(llogfile, "TXATTRCREATE: (");
|
||||
pprint_int32(pdu, 0, &offset, "fid");
|
||||
pprint_str(pdu, 0, &offset, ", name");
|
||||
pprint_int64(pdu, 0, &offset, ", xattrsize");
|
||||
pprint_int32(pdu, 0, &offset, ", flags");
|
||||
break;
|
||||
case P9_RXATTRCREATE:
|
||||
fprintf(llogfile, "RXATTRCREATE: (");
|
||||
break;
|
||||
case P9_TLOCK:
|
||||
fprintf(llogfile, "TLOCK: (");
|
||||
pprint_int32(pdu, 0, &offset, "fid");
|
||||
pprint_int8(pdu, 0, &offset, ", type");
|
||||
pprint_int32(pdu, 0, &offset, ", flags");
|
||||
pprint_int64(pdu, 0, &offset, ", start");
|
||||
pprint_int64(pdu, 0, &offset, ", length");
|
||||
pprint_int32(pdu, 0, &offset, ", proc_id");
|
||||
pprint_str(pdu, 0, &offset, ", client_id");
|
||||
break;
|
||||
case P9_RLOCK:
|
||||
fprintf(llogfile, "RLOCK: (");
|
||||
pprint_int8(pdu, 0, &offset, "status");
|
||||
break;
|
||||
case P9_TGETLOCK:
|
||||
fprintf(llogfile, "TGETLOCK: (");
|
||||
pprint_int32(pdu, 0, &offset, "fid");
|
||||
pprint_int8(pdu, 0, &offset, ", type");
|
||||
pprint_int64(pdu, 0, &offset, ", start");
|
||||
pprint_int64(pdu, 0, &offset, ", length");
|
||||
pprint_int32(pdu, 0, &offset, ", proc_id");
|
||||
pprint_str(pdu, 0, &offset, ", client_id");
|
||||
break;
|
||||
case P9_RGETLOCK:
|
||||
fprintf(llogfile, "RGETLOCK: (");
|
||||
pprint_int8(pdu, 0, &offset, "type");
|
||||
pprint_int64(pdu, 0, &offset, ", start");
|
||||
pprint_int64(pdu, 0, &offset, ", length");
|
||||
pprint_int32(pdu, 0, &offset, ", proc_id");
|
||||
pprint_str(pdu, 0, &offset, ", client_id");
|
||||
break;
|
||||
default:
|
||||
fprintf(llogfile, "unknown(%d): (", pdu->id);
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(llogfile, ")\n");
|
||||
/* Flush the log message out */
|
||||
fflush(llogfile);
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
#ifndef _QEMU_VIRTIO_9P_DEBUG_H
|
||||
#define _QEMU_VIRTIO_9P_DEBUG_H
|
||||
|
||||
void pprint_pdu(V9fsPDU *pdu);
|
||||
|
||||
#endif
|
|
@ -49,7 +49,8 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
|
|||
V9fsState *s;
|
||||
int i, len;
|
||||
struct stat stat;
|
||||
FsTypeEntry *fse;
|
||||
FsDriverEntry *fse;
|
||||
V9fsPath path;
|
||||
|
||||
s = (V9fsState *)virtio_common_init("virtio-9p",
|
||||
VIRTIO_ID_9P,
|
||||
|
@ -82,55 +83,33 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
if (!strcmp(fse->security_model, "passthrough")) {
|
||||
/* Files on the Fileserver set to client user credentials */
|
||||
s->ctx.fs_sm = SM_PASSTHROUGH;
|
||||
s->ctx.xops = passthrough_xattr_ops;
|
||||
} else if (!strcmp(fse->security_model, "mapped")) {
|
||||
/* Files on the fileserver are set to QEMU credentials.
|
||||
* Client user credentials are saved in extended attributes.
|
||||
*/
|
||||
s->ctx.fs_sm = SM_MAPPED;
|
||||
s->ctx.xops = mapped_xattr_ops;
|
||||
} else if (!strcmp(fse->security_model, "none")) {
|
||||
/*
|
||||
* Files on the fileserver are set to QEMU credentials.
|
||||
*/
|
||||
s->ctx.fs_sm = SM_NONE;
|
||||
s->ctx.xops = none_xattr_ops;
|
||||
} else {
|
||||
fprintf(stderr, "Default to security_model=none. You may want"
|
||||
" enable advanced security model using "
|
||||
"security option:\n\t security_model=passthrough\n\t "
|
||||
"security_model=mapped\n");
|
||||
s->ctx.fs_sm = SM_NONE;
|
||||
s->ctx.xops = none_xattr_ops;
|
||||
}
|
||||
|
||||
if (lstat(fse->path, &stat)) {
|
||||
fprintf(stderr, "share path %s does not exist\n", fse->path);
|
||||
exit(1);
|
||||
} else if (!S_ISDIR(stat.st_mode)) {
|
||||
fprintf(stderr, "share path %s is not a directory\n", fse->path);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
s->ctx.export_flags = fse->export_flags;
|
||||
s->ctx.fs_root = g_strdup(fse->path);
|
||||
s->ctx.exops.get_st_gen = NULL;
|
||||
|
||||
if (fse->export_flags & V9FS_SM_PASSTHROUGH) {
|
||||
s->ctx.xops = passthrough_xattr_ops;
|
||||
} else if (fse->export_flags & V9FS_SM_MAPPED) {
|
||||
s->ctx.xops = mapped_xattr_ops;
|
||||
} else if (fse->export_flags & V9FS_SM_NONE) {
|
||||
s->ctx.xops = none_xattr_ops;
|
||||
}
|
||||
|
||||
len = strlen(conf->tag);
|
||||
if (len > MAX_TAG_LEN) {
|
||||
len = MAX_TAG_LEN;
|
||||
fprintf(stderr, "mount tag '%s' (%d bytes) is longer than "
|
||||
"maximum (%d bytes)", conf->tag, len, MAX_TAG_LEN);
|
||||
exit(1);
|
||||
}
|
||||
/* s->tag is non-NULL terminated string */
|
||||
s->tag = g_malloc(len);
|
||||
memcpy(s->tag, conf->tag, len);
|
||||
s->tag_len = len;
|
||||
s->ctx.uid = -1;
|
||||
s->ctx.flags = 0;
|
||||
|
||||
s->ops = fse->ops;
|
||||
s->vdev.get_features = virtio_9p_get_features;
|
||||
s->config_size = sizeof(struct virtio_9p_config) +
|
||||
s->tag_len;
|
||||
s->config_size = sizeof(struct virtio_9p_config) + s->tag_len;
|
||||
s->vdev.get_config = virtio_9p_get_config;
|
||||
s->fid_list = NULL;
|
||||
qemu_co_rwlock_init(&s->rename_lock);
|
||||
|
@ -144,6 +123,27 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
|
|||
fprintf(stderr, "worker thread initialization failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
v9fs_path_init(&path);
|
||||
if (s->ops->name_to_path(&s->ctx, NULL, "/", &path) < 0) {
|
||||
fprintf(stderr,
|
||||
"error in converting name to path %s", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
if (s->ops->lstat(&s->ctx, &path, &stat)) {
|
||||
fprintf(stderr, "share path %s does not exist\n", fse->path);
|
||||
exit(1);
|
||||
} else if (!S_ISDIR(stat.st_mode)) {
|
||||
fprintf(stderr, "share path %s is not a directory\n", fse->path);
|
||||
exit(1);
|
||||
}
|
||||
v9fs_path_free(&path);
|
||||
|
||||
return &s->vdev;
|
||||
}
|
||||
|
||||
|
@ -169,6 +169,8 @@ static PCIDeviceInfo virtio_9p_info = {
|
|||
.revision = VIRTIO_PCI_ABI_VERSION,
|
||||
.class_id = 0x2,
|
||||
.qdev.props = (Property[]) {
|
||||
DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
|
||||
VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
|
||||
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
|
||||
DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
|
||||
DEFINE_PROP_STRING("mount_tag", VirtIOPCIProxy, fsconf.tag),
|
||||
|
|
|
@ -21,19 +21,48 @@
|
|||
#include <sys/un.h>
|
||||
#include <attr/xattr.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/fs.h>
|
||||
#ifdef CONFIG_LINUX_MAGIC_H
|
||||
#include <linux/magic.h>
|
||||
#endif
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#ifndef XFS_SUPER_MAGIC
|
||||
#define XFS_SUPER_MAGIC 0x58465342
|
||||
#endif
|
||||
#ifndef EXT2_SUPER_MAGIC
|
||||
#define EXT2_SUPER_MAGIC 0xEF53
|
||||
#endif
|
||||
#ifndef REISERFS_SUPER_MAGIC
|
||||
#define REISERFS_SUPER_MAGIC 0x52654973
|
||||
#endif
|
||||
#ifndef BTRFS_SUPER_MAGIC
|
||||
#define BTRFS_SUPER_MAGIC 0x9123683E
|
||||
#endif
|
||||
|
||||
struct handle_data {
|
||||
int mountfd;
|
||||
int handle_bytes;
|
||||
};
|
||||
|
||||
#if __GLIBC__ <= 2 && __GLIBC_MINOR__ < 14
|
||||
#ifdef CONFIG_OPEN_BY_HANDLE
|
||||
static inline int name_to_handle(int dirfd, const char *name,
|
||||
struct file_handle *fh, int *mnt_id, int flags)
|
||||
{
|
||||
return name_to_handle_at(dirfd, name, fh, mnt_id, flags);
|
||||
}
|
||||
|
||||
static inline int open_by_handle(int mountfd, const char *fh, int flags)
|
||||
{
|
||||
return open_by_handle_at(mountfd, (struct file_handle *)fh, flags);
|
||||
}
|
||||
#else
|
||||
|
||||
struct file_handle {
|
||||
unsigned int handle_bytes;
|
||||
int handle_type;
|
||||
unsigned char handle[0];
|
||||
unsigned int handle_bytes;
|
||||
int handle_type;
|
||||
unsigned char handle[0];
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef AT_EMPTY_PATH
|
||||
#define AT_EMPTY_PATH 0x1000 /* Allow empty relative pathname */
|
||||
|
@ -42,28 +71,6 @@ struct file_handle {
|
|||
#define O_PATH 010000000
|
||||
#endif
|
||||
|
||||
#ifndef __NR_name_to_handle_at
|
||||
#if defined(__i386__)
|
||||
#define __NR_name_to_handle_at 341
|
||||
#define __NR_open_by_handle_at 342
|
||||
#elif defined(__x86_64__)
|
||||
#define __NR_name_to_handle_at 303
|
||||
#define __NR_open_by_handle_at 304
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __NR_name_to_handle_at
|
||||
static inline int name_to_handle(int dirfd, const char *name,
|
||||
struct file_handle *fh, int *mnt_id, int flags)
|
||||
{
|
||||
return syscall(__NR_name_to_handle_at, dirfd, name, fh, mnt_id, flags);
|
||||
}
|
||||
|
||||
static inline int open_by_handle(int mountfd, const char *fh, int flags)
|
||||
{
|
||||
return syscall(__NR_open_by_handle_at, mountfd, fh, flags);
|
||||
}
|
||||
#else
|
||||
static inline int name_to_handle(int dirfd, const char *name,
|
||||
struct file_handle *fh, int *mnt_id, int flags)
|
||||
{
|
||||
|
@ -192,16 +199,29 @@ static ssize_t handle_preadv(FsContext *ctx, int fd, const struct iovec *iov,
|
|||
static ssize_t handle_pwritev(FsContext *ctx, int fd, const struct iovec *iov,
|
||||
int iovcnt, off_t offset)
|
||||
{
|
||||
ssize_t ret;
|
||||
#ifdef CONFIG_PREADV
|
||||
return pwritev(fd, iov, iovcnt, offset);
|
||||
ret = pwritev(fd, iov, iovcnt, offset);
|
||||
#else
|
||||
int err = lseek(fd, offset, SEEK_SET);
|
||||
if (err == -1) {
|
||||
return err;
|
||||
} else {
|
||||
return writev(fd, iov, iovcnt);
|
||||
ret = writev(fd, iov, iovcnt);
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_SYNC_FILE_RANGE
|
||||
if (ret > 0 && ctx->export_flags & V9FS_IMMEDIATE_WRITEOUT) {
|
||||
/*
|
||||
* Initiate a writeback. This is not a data integrity sync.
|
||||
* We want to ensure that we don't leave dirty pages in the cache
|
||||
* after write when writeout=immediate is sepcified.
|
||||
*/
|
||||
sync_file_range(fd, offset, ret,
|
||||
SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE);
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int handle_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
|
||||
|
@ -367,7 +387,9 @@ static int handle_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
|
|||
static int handle_utimensat(FsContext *ctx, V9fsPath *fs_path,
|
||||
const struct timespec *buf)
|
||||
{
|
||||
int fd, ret;
|
||||
int ret;
|
||||
#ifdef CONFIG_UTIMENSAT
|
||||
int fd;
|
||||
struct handle_data *data = (struct handle_data *)ctx->private;
|
||||
|
||||
fd = open_by_handle(data->mountfd, fs_path->data, O_NONBLOCK);
|
||||
|
@ -376,6 +398,10 @@ static int handle_utimensat(FsContext *ctx, V9fsPath *fs_path,
|
|||
}
|
||||
ret = futimens(fd, buf);
|
||||
close(fd);
|
||||
#else
|
||||
ret = -1;
|
||||
errno = ENOSYS;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -546,16 +572,50 @@ static int handle_unlinkat(FsContext *ctx, V9fsPath *dir,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int handle_ioc_getversion(FsContext *ctx, V9fsPath *path,
|
||||
mode_t st_mode, uint64_t *st_gen)
|
||||
{
|
||||
int err, fd;
|
||||
|
||||
/*
|
||||
* Do not try to open special files like device nodes, fifos etc
|
||||
* We can get fd for regular files and directories only
|
||||
*/
|
||||
if (!S_ISREG(st_mode) && !S_ISDIR(st_mode)) {
|
||||
return 0;
|
||||
}
|
||||
fd = handle_open(ctx, path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
return fd;
|
||||
}
|
||||
err = ioctl(fd, FS_IOC_GETVERSION, st_gen);
|
||||
handle_close(ctx, fd);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int handle_init(FsContext *ctx)
|
||||
{
|
||||
int ret, mnt_id;
|
||||
struct statfs stbuf;
|
||||
struct file_handle fh;
|
||||
struct handle_data *data = g_malloc(sizeof(struct handle_data));
|
||||
|
||||
data->mountfd = open(ctx->fs_root, O_DIRECTORY);
|
||||
if (data->mountfd < 0) {
|
||||
ret = data->mountfd;
|
||||
goto err_out;
|
||||
}
|
||||
ret = statfs(ctx->fs_root, &stbuf);
|
||||
if (!ret) {
|
||||
switch (stbuf.f_type) {
|
||||
case EXT2_SUPER_MAGIC:
|
||||
case BTRFS_SUPER_MAGIC:
|
||||
case REISERFS_SUPER_MAGIC:
|
||||
case XFS_SUPER_MAGIC:
|
||||
ctx->exops.get_st_gen = handle_ioc_getversion;
|
||||
break;
|
||||
}
|
||||
}
|
||||
memset(&fh, 0, sizeof(struct file_handle));
|
||||
ret = name_to_handle(data->mountfd, ".", &fh, &mnt_id, 0);
|
||||
if (ret && errno == EOVERFLOW) {
|
||||
|
|
|
@ -20,6 +20,24 @@
|
|||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <attr/xattr.h>
|
||||
#include <linux/fs.h>
|
||||
#ifdef CONFIG_LINUX_MAGIC_H
|
||||
#include <linux/magic.h>
|
||||
#endif
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#ifndef XFS_SUPER_MAGIC
|
||||
#define XFS_SUPER_MAGIC 0x58465342
|
||||
#endif
|
||||
#ifndef EXT2_SUPER_MAGIC
|
||||
#define EXT2_SUPER_MAGIC 0xEF53
|
||||
#endif
|
||||
#ifndef REISERFS_SUPER_MAGIC
|
||||
#define REISERFS_SUPER_MAGIC 0x52654973
|
||||
#endif
|
||||
#ifndef BTRFS_SUPER_MAGIC
|
||||
#define BTRFS_SUPER_MAGIC 0x9123683E
|
||||
#endif
|
||||
|
||||
static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
|
||||
{
|
||||
|
@ -31,7 +49,7 @@ static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
|
|||
if (err) {
|
||||
return err;
|
||||
}
|
||||
if (fs_ctx->fs_sm == SM_MAPPED) {
|
||||
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
|
||||
/* Actual credentials are part of extended attrs */
|
||||
uid_t tmp_uid;
|
||||
gid_t tmp_gid;
|
||||
|
@ -106,7 +124,7 @@ static int local_post_create_passthrough(FsContext *fs_ctx, const char *path,
|
|||
* If we fail to change ownership and if we are
|
||||
* using security model none. Ignore the error
|
||||
*/
|
||||
if (fs_ctx->fs_sm != SM_NONE) {
|
||||
if ((fs_ctx->export_flags & V9FS_SEC_MASK) != V9FS_SM_NONE) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -120,7 +138,7 @@ static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
|
|||
char buffer[PATH_MAX];
|
||||
char *path = fs_path->data;
|
||||
|
||||
if (fs_ctx->fs_sm == SM_MAPPED) {
|
||||
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
|
||||
int fd;
|
||||
fd = open(rpath(fs_ctx, path, buffer), O_RDONLY);
|
||||
if (fd == -1) {
|
||||
|
@ -131,8 +149,8 @@ static ssize_t local_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
|
|||
} while (tsize == -1 && errno == EINTR);
|
||||
close(fd);
|
||||
return tsize;
|
||||
} else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
|
||||
(fs_ctx->fs_sm == SM_NONE)) {
|
||||
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
|
||||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
|
||||
tsize = readlink(rpath(fs_ctx, path, buffer), buf, bufsz);
|
||||
}
|
||||
return tsize;
|
||||
|
@ -203,16 +221,30 @@ static ssize_t local_preadv(FsContext *ctx, int fd, const struct iovec *iov,
|
|||
static ssize_t local_pwritev(FsContext *ctx, int fd, const struct iovec *iov,
|
||||
int iovcnt, off_t offset)
|
||||
{
|
||||
ssize_t ret
|
||||
;
|
||||
#ifdef CONFIG_PREADV
|
||||
return pwritev(fd, iov, iovcnt, offset);
|
||||
ret = pwritev(fd, iov, iovcnt, offset);
|
||||
#else
|
||||
int err = lseek(fd, offset, SEEK_SET);
|
||||
if (err == -1) {
|
||||
return err;
|
||||
} else {
|
||||
return writev(fd, iov, iovcnt);
|
||||
ret = writev(fd, iov, iovcnt);
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_SYNC_FILE_RANGE
|
||||
if (ret > 0 && ctx->export_flags & V9FS_IMMEDIATE_WRITEOUT) {
|
||||
/*
|
||||
* Initiate a writeback. This is not a data integrity sync.
|
||||
* We want to ensure that we don't leave dirty pages in the cache
|
||||
* after write when writeout=immediate is sepcified.
|
||||
*/
|
||||
sync_file_range(fd, offset, ret,
|
||||
SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE);
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int local_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
|
||||
|
@ -220,10 +252,10 @@ static int local_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
|
|||
char buffer[PATH_MAX];
|
||||
char *path = fs_path->data;
|
||||
|
||||
if (fs_ctx->fs_sm == SM_MAPPED) {
|
||||
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
|
||||
return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
|
||||
} else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
|
||||
(fs_ctx->fs_sm == SM_NONE)) {
|
||||
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
|
||||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
|
||||
return chmod(rpath(fs_ctx, path, buffer), credp->fc_mode);
|
||||
}
|
||||
return -1;
|
||||
|
@ -243,7 +275,7 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
|
|||
path = fullname.data;
|
||||
|
||||
/* Determine the security model */
|
||||
if (fs_ctx->fs_sm == SM_MAPPED) {
|
||||
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
|
||||
err = mknod(rpath(fs_ctx, path, buffer),
|
||||
SM_LOCAL_MODE_BITS|S_IFREG, 0);
|
||||
if (err == -1) {
|
||||
|
@ -254,8 +286,8 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
|
|||
serrno = errno;
|
||||
goto err_end;
|
||||
}
|
||||
} else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
|
||||
(fs_ctx->fs_sm == SM_NONE)) {
|
||||
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
|
||||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
|
||||
err = mknod(rpath(fs_ctx, path, buffer), credp->fc_mode,
|
||||
credp->fc_rdev);
|
||||
if (err == -1) {
|
||||
|
@ -291,7 +323,7 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
|
|||
path = fullname.data;
|
||||
|
||||
/* Determine the security model */
|
||||
if (fs_ctx->fs_sm == SM_MAPPED) {
|
||||
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
|
||||
err = mkdir(rpath(fs_ctx, path, buffer), SM_LOCAL_DIR_MODE_BITS);
|
||||
if (err == -1) {
|
||||
goto out;
|
||||
|
@ -302,8 +334,8 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
|
|||
serrno = errno;
|
||||
goto err_end;
|
||||
}
|
||||
} else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
|
||||
(fs_ctx->fs_sm == SM_NONE)) {
|
||||
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
|
||||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
|
||||
err = mkdir(rpath(fs_ctx, path, buffer), credp->fc_mode);
|
||||
if (err == -1) {
|
||||
goto out;
|
||||
|
@ -331,7 +363,7 @@ static int local_fstat(FsContext *fs_ctx, int fd, struct stat *stbuf)
|
|||
if (err) {
|
||||
return err;
|
||||
}
|
||||
if (fs_ctx->fs_sm == SM_MAPPED) {
|
||||
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
|
||||
/* Actual credentials are part of extended attrs */
|
||||
uid_t tmp_uid;
|
||||
gid_t tmp_gid;
|
||||
|
@ -369,7 +401,7 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
|
|||
path = fullname.data;
|
||||
|
||||
/* Determine the security model */
|
||||
if (fs_ctx->fs_sm == SM_MAPPED) {
|
||||
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
|
||||
fd = open(rpath(fs_ctx, path, buffer), flags, SM_LOCAL_MODE_BITS);
|
||||
if (fd == -1) {
|
||||
err = fd;
|
||||
|
@ -382,8 +414,8 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
|
|||
serrno = errno;
|
||||
goto err_end;
|
||||
}
|
||||
} else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
|
||||
(fs_ctx->fs_sm == SM_NONE)) {
|
||||
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
|
||||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
|
||||
fd = open(rpath(fs_ctx, path, buffer), flags, credp->fc_mode);
|
||||
if (fd == -1) {
|
||||
err = fd;
|
||||
|
@ -422,7 +454,7 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
|
|||
newpath = fullname.data;
|
||||
|
||||
/* Determine the security model */
|
||||
if (fs_ctx->fs_sm == SM_MAPPED) {
|
||||
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
|
||||
int fd;
|
||||
ssize_t oldpath_size, write_size;
|
||||
fd = open(rpath(fs_ctx, newpath, buffer), O_CREAT|O_EXCL|O_RDWR,
|
||||
|
@ -451,8 +483,8 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
|
|||
serrno = errno;
|
||||
goto err_end;
|
||||
}
|
||||
} else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
|
||||
(fs_ctx->fs_sm == SM_NONE)) {
|
||||
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
|
||||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
|
||||
err = symlink(oldpath, rpath(fs_ctx, newpath, buffer));
|
||||
if (err) {
|
||||
goto out;
|
||||
|
@ -464,7 +496,7 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
|
|||
* If we fail to change ownership and if we are
|
||||
* using security model none. Ignore the error
|
||||
*/
|
||||
if (fs_ctx->fs_sm != SM_NONE) {
|
||||
if ((fs_ctx->export_flags & V9FS_SEC_MASK) != V9FS_SM_NONE) {
|
||||
serrno = errno;
|
||||
goto err_end;
|
||||
} else
|
||||
|
@ -519,13 +551,13 @@ static int local_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
|
|||
char *path = fs_path->data;
|
||||
|
||||
if ((credp->fc_uid == -1 && credp->fc_gid == -1) ||
|
||||
(fs_ctx->fs_sm == SM_PASSTHROUGH)) {
|
||||
(fs_ctx->export_flags & V9FS_SM_PASSTHROUGH)) {
|
||||
return lchown(rpath(fs_ctx, path, buffer), credp->fc_uid,
|
||||
credp->fc_gid);
|
||||
} else if (fs_ctx->fs_sm == SM_MAPPED) {
|
||||
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
|
||||
return local_set_xattr(rpath(fs_ctx, path, buffer), credp);
|
||||
} else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
|
||||
(fs_ctx->fs_sm == SM_NONE)) {
|
||||
} else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
|
||||
(fs_ctx->export_flags & V9FS_SM_NONE)) {
|
||||
return lchown(rpath(fs_ctx, path, buffer), credp->fc_uid,
|
||||
credp->fc_gid);
|
||||
}
|
||||
|
@ -645,10 +677,44 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int local_ioc_getversion(FsContext *ctx, V9fsPath *path,
|
||||
mode_t st_mode, uint64_t *st_gen)
|
||||
{
|
||||
int err, fd;
|
||||
/*
|
||||
* Do not try to open special files like device nodes, fifos etc
|
||||
* We can get fd for regular files and directories only
|
||||
*/
|
||||
if (!S_ISREG(st_mode) && !S_ISDIR(st_mode)) {
|
||||
return 0;
|
||||
}
|
||||
fd = local_open(ctx, path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
return fd;
|
||||
}
|
||||
err = ioctl(fd, FS_IOC_GETVERSION, st_gen);
|
||||
local_close(ctx, fd);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int local_init(FsContext *ctx)
|
||||
{
|
||||
ctx->flags |= PATHNAME_FSCONTEXT;
|
||||
return 0;
|
||||
int err;
|
||||
struct statfs stbuf;
|
||||
|
||||
ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT;
|
||||
err = statfs(ctx->fs_root, &stbuf);
|
||||
if (!err) {
|
||||
switch (stbuf.f_type) {
|
||||
case EXT2_SUPER_MAGIC:
|
||||
case BTRFS_SUPER_MAGIC:
|
||||
case REISERFS_SUPER_MAGIC:
|
||||
case XFS_SUPER_MAGIC:
|
||||
ctx->exops.get_st_gen = local_ioc_getversion;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
FileOperations local_ops = {
|
||||
|
|
|
@ -17,11 +17,10 @@
|
|||
#include "hw/virtio-pci.h"
|
||||
#include "virtio-9p.h"
|
||||
#include "fsdev/qemu-fsdev.h"
|
||||
#include "virtio-9p-debug.h"
|
||||
#include "virtio-9p-xattr.h"
|
||||
#include "virtio-9p-coth.h"
|
||||
#include "trace.h"
|
||||
|
||||
int debug_9p_pdu;
|
||||
int open_fd_hw;
|
||||
int total_open_fd;
|
||||
static int open_fd_rc;
|
||||
|
@ -72,6 +71,55 @@ static int omode_to_uflags(int8_t mode)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int dotl_to_at_flags(int flags)
|
||||
{
|
||||
int rflags = 0;
|
||||
if (flags & P9_DOTL_AT_REMOVEDIR) {
|
||||
rflags |= AT_REMOVEDIR;
|
||||
}
|
||||
return rflags;
|
||||
}
|
||||
|
||||
struct dotl_openflag_map {
|
||||
int dotl_flag;
|
||||
int open_flag;
|
||||
};
|
||||
|
||||
static int dotl_to_open_flags(int flags)
|
||||
{
|
||||
int i;
|
||||
/*
|
||||
* We have same bits for P9_DOTL_READONLY, P9_DOTL_WRONLY
|
||||
* and P9_DOTL_NOACCESS
|
||||
*/
|
||||
int oflags = flags & O_ACCMODE;
|
||||
|
||||
struct dotl_openflag_map dotl_oflag_map[] = {
|
||||
{ P9_DOTL_CREATE, O_CREAT },
|
||||
{ P9_DOTL_EXCL, O_EXCL },
|
||||
{ P9_DOTL_NOCTTY , O_NOCTTY },
|
||||
{ P9_DOTL_TRUNC, O_TRUNC },
|
||||
{ P9_DOTL_APPEND, O_APPEND },
|
||||
{ P9_DOTL_NONBLOCK, O_NONBLOCK } ,
|
||||
{ P9_DOTL_DSYNC, O_DSYNC },
|
||||
{ P9_DOTL_FASYNC, FASYNC },
|
||||
{ P9_DOTL_DIRECT, O_DIRECT },
|
||||
{ P9_DOTL_LARGEFILE, O_LARGEFILE },
|
||||
{ P9_DOTL_DIRECTORY, O_DIRECTORY },
|
||||
{ P9_DOTL_NOFOLLOW, O_NOFOLLOW },
|
||||
{ P9_DOTL_NOATIME, O_NOATIME },
|
||||
{ P9_DOTL_SYNC, O_SYNC },
|
||||
};
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dotl_oflag_map); i++) {
|
||||
if (flags & dotl_oflag_map[i].dotl_flag) {
|
||||
oflags |= dotl_oflag_map[i].open_flag;
|
||||
}
|
||||
}
|
||||
|
||||
return oflags;
|
||||
}
|
||||
|
||||
void cred_init(FsCred *credp)
|
||||
{
|
||||
credp->fc_uid = -1;
|
||||
|
@ -80,6 +128,21 @@ void cred_init(FsCred *credp)
|
|||
credp->fc_rdev = -1;
|
||||
}
|
||||
|
||||
static int get_dotl_openflags(V9fsState *s, int oflags)
|
||||
{
|
||||
int flags;
|
||||
/*
|
||||
* Filter the client open flags
|
||||
*/
|
||||
flags = dotl_to_open_flags(oflags);
|
||||
flags &= ~(O_NOCTTY | O_ASYNC | O_CREAT);
|
||||
/*
|
||||
* Ignore direct disk access hint until the server supports it.
|
||||
*/
|
||||
flags &= ~O_DIRECT;
|
||||
return flags;
|
||||
}
|
||||
|
||||
void v9fs_string_init(V9fsString *str)
|
||||
{
|
||||
str->data = NULL;
|
||||
|
@ -621,9 +684,6 @@ static V9fsPDU *alloc_pdu(V9fsState *s)
|
|||
static void free_pdu(V9fsState *s, V9fsPDU *pdu)
|
||||
{
|
||||
if (pdu) {
|
||||
if (debug_9p_pdu) {
|
||||
pprint_pdu(pdu);
|
||||
}
|
||||
/*
|
||||
* Cancelled pdu are added back to the freelist
|
||||
* by flush request .
|
||||
|
@ -909,6 +969,7 @@ static void complete_pdu(V9fsState *s, V9fsPDU *pdu, ssize_t len)
|
|||
if (s->proto_version == V9FS_PROTO_2000L) {
|
||||
id = P9_RLERROR;
|
||||
}
|
||||
trace_complete_pdu(pdu->tag, pdu->id, err); /* Trace ERROR */
|
||||
}
|
||||
|
||||
/* fill out the header */
|
||||
|
@ -1218,6 +1279,7 @@ static void v9fs_version(void *opaque)
|
|||
size_t offset = 7;
|
||||
|
||||
pdu_unmarshal(pdu, offset, "ds", &s->msize, &version);
|
||||
trace_v9fs_version(pdu->tag, pdu->id, s->msize, version.data);
|
||||
|
||||
if (!strcmp(version.data, "9P2000.u")) {
|
||||
s->proto_version = V9FS_PROTO_2000U;
|
||||
|
@ -1228,6 +1290,8 @@ static void v9fs_version(void *opaque)
|
|||
}
|
||||
|
||||
offset += pdu_marshal(pdu, offset, "ds", s->msize, &version);
|
||||
trace_v9fs_version_return(pdu->tag, pdu->id, s->msize, version.data);
|
||||
|
||||
complete_pdu(s, pdu, offset);
|
||||
|
||||
v9fs_string_free(&version);
|
||||
|
@ -1246,6 +1310,7 @@ static void v9fs_attach(void *opaque)
|
|||
ssize_t err;
|
||||
|
||||
pdu_unmarshal(pdu, offset, "ddssd", &fid, &afid, &uname, &aname, &n_uname);
|
||||
trace_v9fs_attach(pdu->tag, pdu->id, fid, afid, uname.data, aname.data);
|
||||
|
||||
fidp = alloc_fid(s, fid);
|
||||
if (fidp == NULL) {
|
||||
|
@ -1270,6 +1335,8 @@ static void v9fs_attach(void *opaque)
|
|||
out:
|
||||
put_fid(pdu, fidp);
|
||||
out_nofid:
|
||||
trace_v9fs_attach_return(pdu->tag, pdu->id,
|
||||
qid.type, qid.version, qid.path);
|
||||
complete_pdu(s, pdu, err);
|
||||
v9fs_string_free(&uname);
|
||||
v9fs_string_free(&aname);
|
||||
|
@ -1287,6 +1354,7 @@ static void v9fs_stat(void *opaque)
|
|||
V9fsState *s = pdu->s;
|
||||
|
||||
pdu_unmarshal(pdu, offset, "d", &fid);
|
||||
trace_v9fs_stat(pdu->tag, pdu->id, fid);
|
||||
|
||||
fidp = get_fid(pdu, fid);
|
||||
if (fidp == NULL) {
|
||||
|
@ -1307,6 +1375,9 @@ static void v9fs_stat(void *opaque)
|
|||
out:
|
||||
put_fid(pdu, fidp);
|
||||
out_nofid:
|
||||
trace_v9fs_stat_return(pdu->tag, pdu->id, v9stat.mode,
|
||||
v9stat.atime, v9stat.mtime, v9stat.length);
|
||||
|
||||
complete_pdu(s, pdu, err);
|
||||
}
|
||||
|
||||
|
@ -1323,6 +1394,7 @@ static void v9fs_getattr(void *opaque)
|
|||
V9fsState *s = pdu->s;
|
||||
|
||||
pdu_unmarshal(pdu, offset, "dq", &fid, &request_mask);
|
||||
trace_v9fs_getattr(pdu->tag, pdu->id, fid, request_mask);
|
||||
|
||||
fidp = get_fid(pdu, fid);
|
||||
if (fidp == NULL) {
|
||||
|
@ -1338,11 +1410,24 @@ static void v9fs_getattr(void *opaque)
|
|||
goto out;
|
||||
}
|
||||
stat_to_v9stat_dotl(s, &stbuf, &v9stat_dotl);
|
||||
|
||||
/* fill st_gen if requested and supported by underlying fs */
|
||||
if (request_mask & P9_STATS_GEN) {
|
||||
retval = v9fs_co_st_gen(pdu, &fidp->path, stbuf.st_mode, &v9stat_dotl);
|
||||
if (retval < 0) {
|
||||
goto out;
|
||||
}
|
||||
v9stat_dotl.st_result_mask |= P9_STATS_GEN;
|
||||
}
|
||||
retval = offset;
|
||||
retval += pdu_marshal(pdu, offset, "A", &v9stat_dotl);
|
||||
out:
|
||||
put_fid(pdu, fidp);
|
||||
out_nofid:
|
||||
trace_v9fs_getattr_return(pdu->tag, pdu->id, v9stat_dotl.st_result_mask,
|
||||
v9stat_dotl.st_mode, v9stat_dotl.st_uid,
|
||||
v9stat_dotl.st_gid);
|
||||
|
||||
complete_pdu(s, pdu, retval);
|
||||
}
|
||||
|
||||
|
@ -1470,6 +1555,8 @@ static void v9fs_walk(void *opaque)
|
|||
offset += pdu_unmarshal(pdu, offset, "ddw", &fid,
|
||||
&newfid, &nwnames);
|
||||
|
||||
trace_v9fs_walk(pdu->tag, pdu->id, fid, newfid, nwnames);
|
||||
|
||||
if (nwnames && nwnames <= P9_MAXWELEM) {
|
||||
wnames = g_malloc0(sizeof(wnames[0]) * nwnames);
|
||||
qids = g_malloc0(sizeof(qids[0]) * nwnames);
|
||||
|
@ -1526,6 +1613,7 @@ out:
|
|||
v9fs_path_free(&dpath);
|
||||
v9fs_path_free(&path);
|
||||
out_nofid:
|
||||
trace_v9fs_walk_return(pdu->tag, pdu->id, nwnames, qids);
|
||||
complete_pdu(s, pdu, err);
|
||||
if (nwnames && nwnames <= P9_MAXWELEM) {
|
||||
for (name_idx = 0; name_idx < nwnames; name_idx++) {
|
||||
|
@ -1576,6 +1664,8 @@ static void v9fs_open(void *opaque)
|
|||
} else {
|
||||
pdu_unmarshal(pdu, offset, "db", &fid, &mode);
|
||||
}
|
||||
trace_v9fs_open(pdu->tag, pdu->id, fid, mode);
|
||||
|
||||
fidp = get_fid(pdu, fid);
|
||||
if (fidp == NULL) {
|
||||
err = -ENOENT;
|
||||
|
@ -1598,10 +1688,7 @@ static void v9fs_open(void *opaque)
|
|||
err = offset;
|
||||
} else {
|
||||
if (s->proto_version == V9FS_PROTO_2000L) {
|
||||
flags = mode;
|
||||
flags &= ~(O_NOCTTY | O_ASYNC | O_CREAT);
|
||||
/* Ignore direct disk access hint until the server supports it. */
|
||||
flags &= ~O_DIRECT;
|
||||
flags = get_dotl_openflags(s, mode);
|
||||
} else {
|
||||
flags = omode_to_uflags(mode);
|
||||
}
|
||||
|
@ -1625,6 +1712,8 @@ static void v9fs_open(void *opaque)
|
|||
out:
|
||||
put_fid(pdu, fidp);
|
||||
out_nofid:
|
||||
trace_v9fs_open_return(pdu->tag, pdu->id,
|
||||
qid.type, qid.version, qid.path, iounit);
|
||||
complete_pdu(s, pdu, err);
|
||||
}
|
||||
|
||||
|
@ -1643,6 +1732,7 @@ static void v9fs_lcreate(void *opaque)
|
|||
|
||||
pdu_unmarshal(pdu, offset, "dsddd", &dfid, &name, &flags,
|
||||
&mode, &gid);
|
||||
trace_v9fs_lcreate(pdu->tag, pdu->id, dfid, flags, mode, gid);
|
||||
|
||||
fidp = get_fid(pdu, dfid);
|
||||
if (fidp == NULL) {
|
||||
|
@ -1650,8 +1740,7 @@ static void v9fs_lcreate(void *opaque)
|
|||
goto out_nofid;
|
||||
}
|
||||
|
||||
/* Ignore direct disk access hint until the server supports it. */
|
||||
flags &= ~O_DIRECT;
|
||||
flags = get_dotl_openflags(pdu->s, flags);
|
||||
err = v9fs_co_open2(pdu, fidp, &name, gid,
|
||||
flags | O_CREAT, mode, &stbuf);
|
||||
if (err < 0) {
|
||||
|
@ -1673,6 +1762,8 @@ static void v9fs_lcreate(void *opaque)
|
|||
out:
|
||||
put_fid(pdu, fidp);
|
||||
out_nofid:
|
||||
trace_v9fs_lcreate_return(pdu->tag, pdu->id,
|
||||
qid.type, qid.version, qid.path, iounit);
|
||||
complete_pdu(pdu->s, pdu, err);
|
||||
v9fs_string_free(&name);
|
||||
}
|
||||
|
@ -1688,6 +1779,8 @@ static void v9fs_fsync(void *opaque)
|
|||
V9fsState *s = pdu->s;
|
||||
|
||||
pdu_unmarshal(pdu, offset, "dd", &fid, &datasync);
|
||||
trace_v9fs_fsync(pdu->tag, pdu->id, fid, datasync);
|
||||
|
||||
fidp = get_fid(pdu, fid);
|
||||
if (fidp == NULL) {
|
||||
err = -ENOENT;
|
||||
|
@ -1712,6 +1805,7 @@ static void v9fs_clunk(void *opaque)
|
|||
V9fsState *s = pdu->s;
|
||||
|
||||
pdu_unmarshal(pdu, offset, "d", &fid);
|
||||
trace_v9fs_clunk(pdu->tag, pdu->id, fid);
|
||||
|
||||
fidp = clunk_fid(s, fid);
|
||||
if (fidp == NULL) {
|
||||
|
@ -1828,6 +1922,7 @@ static void v9fs_read(void *opaque)
|
|||
V9fsState *s = pdu->s;
|
||||
|
||||
pdu_unmarshal(pdu, offset, "dqd", &fid, &off, &max_count);
|
||||
trace_v9fs_read(pdu->tag, pdu->id, fid, off, max_count);
|
||||
|
||||
fidp = get_fid(pdu, fid);
|
||||
if (fidp == NULL) {
|
||||
|
@ -1886,6 +1981,7 @@ static void v9fs_read(void *opaque)
|
|||
out:
|
||||
put_fid(pdu, fidp);
|
||||
out_nofid:
|
||||
trace_v9fs_read_return(pdu->tag, pdu->id, count, err);
|
||||
complete_pdu(s, pdu, err);
|
||||
}
|
||||
|
||||
|
@ -1970,6 +2066,8 @@ static void v9fs_readdir(void *opaque)
|
|||
|
||||
pdu_unmarshal(pdu, offset, "dqd", &fid, &initial_offset, &max_count);
|
||||
|
||||
trace_v9fs_readdir(pdu->tag, pdu->id, fid, initial_offset, max_count);
|
||||
|
||||
fidp = get_fid(pdu, fid);
|
||||
if (fidp == NULL) {
|
||||
retval = -EINVAL;
|
||||
|
@ -1995,6 +2093,7 @@ static void v9fs_readdir(void *opaque)
|
|||
out:
|
||||
put_fid(pdu, fidp);
|
||||
out_nofid:
|
||||
trace_v9fs_readdir_return(pdu->tag, pdu->id, count, retval);
|
||||
complete_pdu(s, pdu, retval);
|
||||
}
|
||||
|
||||
|
@ -2059,6 +2158,7 @@ static void v9fs_write(void *opaque)
|
|||
V9fsState *s = pdu->s;
|
||||
|
||||
pdu_unmarshal(pdu, offset, "dqdv", &fid, &off, &count, sg, &cnt);
|
||||
trace_v9fs_write(pdu->tag, pdu->id, fid, off, count, cnt);
|
||||
|
||||
fidp = get_fid(pdu, fid);
|
||||
if (fidp == NULL) {
|
||||
|
@ -2105,6 +2205,7 @@ static void v9fs_write(void *opaque)
|
|||
out:
|
||||
put_fid(pdu, fidp);
|
||||
out_nofid:
|
||||
trace_v9fs_write_return(pdu->tag, pdu->id, total, err);
|
||||
complete_pdu(s, pdu, err);
|
||||
}
|
||||
|
||||
|
@ -2129,6 +2230,8 @@ static void v9fs_create(void *opaque)
|
|||
pdu_unmarshal(pdu, offset, "dsdbs", &fid, &name,
|
||||
&perm, &mode, &extension);
|
||||
|
||||
trace_v9fs_create(pdu->tag, pdu->id, fid, name.data, perm, mode);
|
||||
|
||||
fidp = get_fid(pdu, fid);
|
||||
if (fidp == NULL) {
|
||||
err = -EINVAL;
|
||||
|
@ -2262,6 +2365,8 @@ static void v9fs_create(void *opaque)
|
|||
out:
|
||||
put_fid(pdu, fidp);
|
||||
out_nofid:
|
||||
trace_v9fs_create_return(pdu->tag, pdu->id,
|
||||
qid.type, qid.version, qid.path, iounit);
|
||||
complete_pdu(pdu->s, pdu, err);
|
||||
v9fs_string_free(&name);
|
||||
v9fs_string_free(&extension);
|
||||
|
@ -2282,6 +2387,7 @@ static void v9fs_symlink(void *opaque)
|
|||
size_t offset = 7;
|
||||
|
||||
pdu_unmarshal(pdu, offset, "dssd", &dfid, &name, &symname, &gid);
|
||||
trace_v9fs_symlink(pdu->tag, pdu->id, dfid, name.data, symname.data, gid);
|
||||
|
||||
dfidp = get_fid(pdu, dfid);
|
||||
if (dfidp == NULL) {
|
||||
|
@ -2298,6 +2404,8 @@ static void v9fs_symlink(void *opaque)
|
|||
out:
|
||||
put_fid(pdu, dfidp);
|
||||
out_nofid:
|
||||
trace_v9fs_symlink_return(pdu->tag, pdu->id,
|
||||
qid.type, qid.version, qid.path);
|
||||
complete_pdu(pdu->s, pdu, err);
|
||||
v9fs_string_free(&name);
|
||||
v9fs_string_free(&symname);
|
||||
|
@ -2312,6 +2420,7 @@ static void v9fs_flush(void *opaque)
|
|||
V9fsState *s = pdu->s;
|
||||
|
||||
pdu_unmarshal(pdu, offset, "w", &tag);
|
||||
trace_v9fs_flush(pdu->tag, pdu->id, tag);
|
||||
|
||||
QLIST_FOREACH(cancel_pdu, &s->active_list, next) {
|
||||
if (cancel_pdu->tag == tag) {
|
||||
|
@ -2342,6 +2451,7 @@ static void v9fs_link(void *opaque)
|
|||
int err = 0;
|
||||
|
||||
pdu_unmarshal(pdu, offset, "dds", &dfid, &oldfid, &name);
|
||||
trace_v9fs_link(pdu->tag, pdu->id, dfid, oldfid, name.data);
|
||||
|
||||
dfidp = get_fid(pdu, dfid);
|
||||
if (dfidp == NULL) {
|
||||
|
@ -2375,6 +2485,7 @@ static void v9fs_remove(void *opaque)
|
|||
V9fsPDU *pdu = opaque;
|
||||
|
||||
pdu_unmarshal(pdu, offset, "d", &fid);
|
||||
trace_v9fs_remove(pdu->tag, pdu->id, fid);
|
||||
|
||||
fidp = get_fid(pdu, fid);
|
||||
if (fidp == NULL) {
|
||||
|
@ -2382,7 +2493,7 @@ static void v9fs_remove(void *opaque)
|
|||
goto out_nofid;
|
||||
}
|
||||
/* if fs driver is not path based, return EOPNOTSUPP */
|
||||
if (!pdu->s->ctx.flags & PATHNAME_FSCONTEXT) {
|
||||
if (!(pdu->s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT)) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto out_err;
|
||||
}
|
||||
|
@ -2417,6 +2528,7 @@ static void v9fs_unlinkat(void *opaque)
|
|||
V9fsPDU *pdu = opaque;
|
||||
|
||||
pdu_unmarshal(pdu, offset, "dsd", &dfid, &name, &flags);
|
||||
flags = dotl_to_at_flags(flags);
|
||||
|
||||
dfidp = get_fid(pdu, dfid);
|
||||
if (dfidp == NULL) {
|
||||
|
@ -2528,7 +2640,7 @@ static void v9fs_rename(void *opaque)
|
|||
}
|
||||
BUG_ON(fidp->fid_type != P9_FID_NONE);
|
||||
/* if fs driver is not path based, return EOPNOTSUPP */
|
||||
if (!pdu->s->ctx.flags & PATHNAME_FSCONTEXT) {
|
||||
if (!(pdu->s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT)) {
|
||||
err = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
|
@ -2601,7 +2713,7 @@ static int v9fs_complete_renameat(V9fsPDU *pdu, int32_t olddirfid,
|
|||
if (err < 0) {
|
||||
goto out;
|
||||
}
|
||||
if (s->ctx.flags & PATHNAME_FSCONTEXT) {
|
||||
if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) {
|
||||
/* Only for path based fid we need to do the below fixup */
|
||||
v9fs_fix_fid_paths(pdu, &olddirfidp->path, old_name,
|
||||
&newdirfidp->path, new_name);
|
||||
|
@ -2653,6 +2765,8 @@ static void v9fs_wstat(void *opaque)
|
|||
V9fsState *s = pdu->s;
|
||||
|
||||
pdu_unmarshal(pdu, offset, "dwS", &fid, &unused, &v9stat);
|
||||
trace_v9fs_wstat(pdu->tag, pdu->id, fid,
|
||||
v9stat.mode, v9stat.atime, v9stat.mtime);
|
||||
|
||||
fidp = get_fid(pdu, fid);
|
||||
if (fidp == NULL) {
|
||||
|
@ -2821,6 +2935,7 @@ static void v9fs_mknod(void *opaque)
|
|||
|
||||
pdu_unmarshal(pdu, offset, "dsdddd", &fid, &name, &mode,
|
||||
&major, &minor, &gid);
|
||||
trace_v9fs_mknod(pdu->tag, pdu->id, fid, mode, major, minor);
|
||||
|
||||
fidp = get_fid(pdu, fid);
|
||||
if (fidp == NULL) {
|
||||
|
@ -2838,6 +2953,7 @@ static void v9fs_mknod(void *opaque)
|
|||
out:
|
||||
put_fid(pdu, fidp);
|
||||
out_nofid:
|
||||
trace_v9fs_mknod_return(pdu->tag, pdu->id, qid.type, qid.version, qid.path);
|
||||
complete_pdu(s, pdu, err);
|
||||
v9fs_string_free(&name);
|
||||
}
|
||||
|
@ -2865,6 +2981,10 @@ static void v9fs_lock(void *opaque)
|
|||
pdu_unmarshal(pdu, offset, "dbdqqds", &fid, &flock->type,
|
||||
&flock->flags, &flock->start, &flock->length,
|
||||
&flock->proc_id, &flock->client_id);
|
||||
|
||||
trace_v9fs_lock(pdu->tag, pdu->id, fid,
|
||||
flock->type, flock->start, flock->length);
|
||||
|
||||
status = P9_LOCK_ERROR;
|
||||
|
||||
/* We support only block flag now (that too ignored currently) */
|
||||
|
@ -2887,6 +3007,7 @@ out:
|
|||
out_nofid:
|
||||
err = offset;
|
||||
err += pdu_marshal(pdu, offset, "b", status);
|
||||
trace_v9fs_lock_return(pdu->tag, pdu->id, status);
|
||||
complete_pdu(s, pdu, err);
|
||||
v9fs_string_free(&flock->client_id);
|
||||
g_free(flock);
|
||||
|
@ -2911,6 +3032,9 @@ static void v9fs_getlock(void *opaque)
|
|||
&glock->start, &glock->length, &glock->proc_id,
|
||||
&glock->client_id);
|
||||
|
||||
trace_v9fs_getlock(pdu->tag, pdu->id, fid,
|
||||
glock->type, glock->start, glock->length);
|
||||
|
||||
fidp = get_fid(pdu, fid);
|
||||
if (fidp == NULL) {
|
||||
err = -ENOENT;
|
||||
|
@ -2920,7 +3044,7 @@ static void v9fs_getlock(void *opaque)
|
|||
if (err < 0) {
|
||||
goto out;
|
||||
}
|
||||
glock->type = F_UNLCK;
|
||||
glock->type = P9_LOCK_TYPE_UNLCK;
|
||||
offset += pdu_marshal(pdu, offset, "bqqds", glock->type,
|
||||
glock->start, glock->length, glock->proc_id,
|
||||
&glock->client_id);
|
||||
|
@ -2928,6 +3052,9 @@ static void v9fs_getlock(void *opaque)
|
|||
out:
|
||||
put_fid(pdu, fidp);
|
||||
out_nofid:
|
||||
trace_v9fs_getlock_return(pdu->tag, pdu->id, glock->type, glock->start,
|
||||
glock->length, glock->proc_id);
|
||||
|
||||
complete_pdu(s, pdu, err);
|
||||
v9fs_string_free(&glock->client_id);
|
||||
g_free(glock);
|
||||
|
@ -2948,6 +3075,8 @@ static void v9fs_mkdir(void *opaque)
|
|||
|
||||
pdu_unmarshal(pdu, offset, "dsdd", &fid, &name, &mode, &gid);
|
||||
|
||||
trace_v9fs_mkdir(pdu->tag, pdu->id, fid, name.data, mode, gid);
|
||||
|
||||
fidp = get_fid(pdu, fid);
|
||||
if (fidp == NULL) {
|
||||
err = -ENOENT;
|
||||
|
@ -2963,6 +3092,8 @@ static void v9fs_mkdir(void *opaque)
|
|||
out:
|
||||
put_fid(pdu, fidp);
|
||||
out_nofid:
|
||||
trace_v9fs_mkdir_return(pdu->tag, pdu->id,
|
||||
qid.type, qid.version, qid.path, err);
|
||||
complete_pdu(pdu->s, pdu, err);
|
||||
v9fs_string_free(&name);
|
||||
}
|
||||
|
@ -2980,6 +3111,8 @@ static void v9fs_xattrwalk(void *opaque)
|
|||
V9fsState *s = pdu->s;
|
||||
|
||||
pdu_unmarshal(pdu, offset, "dds", &fid, &newfid, &name);
|
||||
trace_v9fs_xattrwalk(pdu->tag, pdu->id, fid, newfid, name.data);
|
||||
|
||||
file_fidp = get_fid(pdu, fid);
|
||||
if (file_fidp == NULL) {
|
||||
err = -ENOENT;
|
||||
|
@ -3056,6 +3189,7 @@ out:
|
|||
put_fid(pdu, xattr_fidp);
|
||||
}
|
||||
out_nofid:
|
||||
trace_v9fs_xattrwalk_return(pdu->tag, pdu->id, size);
|
||||
complete_pdu(s, pdu, err);
|
||||
v9fs_string_free(&name);
|
||||
}
|
||||
|
@ -3075,6 +3209,7 @@ static void v9fs_xattrcreate(void *opaque)
|
|||
|
||||
pdu_unmarshal(pdu, offset, "dsqd",
|
||||
&fid, &name, &size, &flags);
|
||||
trace_v9fs_xattrcreate(pdu->tag, pdu->id, fid, name.data, size, flags);
|
||||
|
||||
file_fidp = get_fid(pdu, fid);
|
||||
if (file_fidp == NULL) {
|
||||
|
@ -3111,6 +3246,7 @@ static void v9fs_readlink(void *opaque)
|
|||
V9fsFidState *fidp;
|
||||
|
||||
pdu_unmarshal(pdu, offset, "d", &fid);
|
||||
trace_v9fs_readlink(pdu->tag, pdu->id, fid);
|
||||
fidp = get_fid(pdu, fid);
|
||||
if (fidp == NULL) {
|
||||
err = -ENOENT;
|
||||
|
@ -3128,6 +3264,7 @@ static void v9fs_readlink(void *opaque)
|
|||
out:
|
||||
put_fid(pdu, fidp);
|
||||
out_nofid:
|
||||
trace_v9fs_readlink_return(pdu->tag, pdu->id, target.data);
|
||||
complete_pdu(pdu->s, pdu, err);
|
||||
}
|
||||
|
||||
|
@ -3179,9 +3316,6 @@ static void submit_pdu(V9fsState *s, V9fsPDU *pdu)
|
|||
Coroutine *co;
|
||||
CoroutineEntry *handler;
|
||||
|
||||
if (debug_9p_pdu) {
|
||||
pprint_pdu(pdu);
|
||||
}
|
||||
if (pdu->id >= ARRAY_SIZE(pdu_co_handlers) ||
|
||||
(pdu_co_handlers[pdu->id] == NULL)) {
|
||||
handler = v9fs_op_not_supp;
|
||||
|
|
|
@ -352,6 +352,35 @@ typedef struct V9fsMkState {
|
|||
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
|
||||
|
@ -393,21 +422,21 @@ static inline size_t do_pdu_unpack(void *dst, struct iovec *sg, int sg_count,
|
|||
|
||||
static inline void v9fs_path_write_lock(V9fsState *s)
|
||||
{
|
||||
if (s->ctx.flags & PATHNAME_FSCONTEXT) {
|
||||
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.flags & PATHNAME_FSCONTEXT) {
|
||||
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.flags & PATHNAME_FSCONTEXT) {
|
||||
if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) {
|
||||
qemu_co_rwlock_unlock(&s->rename_lock);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,11 +83,6 @@
|
|||
/* Flags track per-device state like workarounds for quirks in older guests. */
|
||||
#define VIRTIO_PCI_FLAG_BUS_MASTER_BUG (1 << 0)
|
||||
|
||||
/* Performance improves when virtqueue kick processing is decoupled from the
|
||||
* vcpu thread using ioeventfd for some devices. */
|
||||
#define VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT 1
|
||||
#define VIRTIO_PCI_FLAG_USE_IOEVENTFD (1 << VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT)
|
||||
|
||||
/* QEMU doesn't strictly need write barriers since everything runs in
|
||||
* lock-step. We'll leave the calls to wmb() in though to make it obvious for
|
||||
* KVM or if kqemu gets SMP support.
|
||||
|
|
|
@ -18,6 +18,11 @@
|
|||
#include "virtio-net.h"
|
||||
#include "virtio-serial.h"
|
||||
|
||||
/* Performance improves when virtqueue kick processing is decoupled from the
|
||||
* vcpu thread using ioeventfd for some devices. */
|
||||
#define VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT 1
|
||||
#define VIRTIO_PCI_FLAG_USE_IOEVENTFD (1 << VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT)
|
||||
|
||||
typedef struct {
|
||||
PCIDevice pci_dev;
|
||||
VirtIODevice *vdev;
|
||||
|
|
|
@ -165,11 +165,11 @@ static QemuOptsList qemu_chardev_opts = {
|
|||
|
||||
QemuOptsList qemu_fsdev_opts = {
|
||||
.name = "fsdev",
|
||||
.implied_opt_name = "fstype",
|
||||
.implied_opt_name = "fsdriver",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(qemu_fsdev_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = "fstype",
|
||||
.name = "fsdriver",
|
||||
.type = QEMU_OPT_STRING,
|
||||
}, {
|
||||
.name = "path",
|
||||
|
@ -177,6 +177,9 @@ QemuOptsList qemu_fsdev_opts = {
|
|||
}, {
|
||||
.name = "security_model",
|
||||
.type = QEMU_OPT_STRING,
|
||||
}, {
|
||||
.name = "writeout",
|
||||
.type = QEMU_OPT_STRING,
|
||||
},
|
||||
{ /*End of list */ }
|
||||
},
|
||||
|
@ -184,11 +187,11 @@ QemuOptsList qemu_fsdev_opts = {
|
|||
|
||||
QemuOptsList qemu_virtfs_opts = {
|
||||
.name = "virtfs",
|
||||
.implied_opt_name = "fstype",
|
||||
.implied_opt_name = "fsdriver",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(qemu_virtfs_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = "fstype",
|
||||
.name = "fsdriver",
|
||||
.type = QEMU_OPT_STRING,
|
||||
}, {
|
||||
.name = "path",
|
||||
|
@ -199,6 +202,9 @@ QemuOptsList qemu_virtfs_opts = {
|
|||
}, {
|
||||
.name = "security_model",
|
||||
.type = QEMU_OPT_STRING,
|
||||
}, {
|
||||
.name = "writeout",
|
||||
.type = QEMU_OPT_STRING,
|
||||
},
|
||||
|
||||
{ /*End of list */ }
|
||||
|
|
124
qemu-options.hx
124
qemu-options.hx
|
@ -522,73 +522,103 @@ possible drivers and properties, use @code{-device ?} and
|
|||
@code{-device @var{driver},?}.
|
||||
ETEXI
|
||||
|
||||
DEFHEADING()
|
||||
|
||||
DEFHEADING(File system options:)
|
||||
|
||||
DEF("fsdev", HAS_ARG, QEMU_OPTION_fsdev,
|
||||
"-fsdev local,id=id,path=path,security_model=[mapped|passthrough|none]\n",
|
||||
"-fsdev fsdriver,id=id,path=path,[security_model={mapped|passthrough|none}]\n"
|
||||
" [,writeout=immediate]\n",
|
||||
QEMU_ARCH_ALL)
|
||||
|
||||
STEXI
|
||||
|
||||
The general form of a File system device option is:
|
||||
@table @option
|
||||
|
||||
@item -fsdev @var{fstype} ,id=@var{id} [,@var{options}]
|
||||
@item -fsdev @var{fsdriver},id=@var{id},path=@var{path},[security_model=@var{security_model}][,writeout=@var{writeout}]
|
||||
@findex -fsdev
|
||||
Fstype is one of:
|
||||
@option{local},
|
||||
The specific Fstype will determine the applicable options.
|
||||
|
||||
Options to each backend are described below.
|
||||
|
||||
@item -fsdev local ,id=@var{id} ,path=@var{path} ,security_model=@var{security_model}
|
||||
|
||||
Create a file-system-"device" for local-filesystem.
|
||||
|
||||
@option{local} is only available on Linux.
|
||||
|
||||
@option{path} specifies the path to be exported. @option{path} is required.
|
||||
|
||||
@option{security_model} specifies the security model to be followed.
|
||||
@option{security_model} is required.
|
||||
|
||||
Define a new file system device. Valid options are:
|
||||
@table @option
|
||||
@item @var{fsdriver}
|
||||
This option specifies the fs driver backend to use.
|
||||
Currently "local" and "handle" file system drivers are supported.
|
||||
@item id=@var{id}
|
||||
Specifies identifier for this device
|
||||
@item path=@var{path}
|
||||
Specifies the export path for the file system device. Files under
|
||||
this path will be available to the 9p client on the guest.
|
||||
@item security_model=@var{security_model}
|
||||
Specifies the security model to be used for this export path.
|
||||
Supported security models are "passthrough", "mapped" and "none".
|
||||
In "passthrough" security model, files are stored using the same
|
||||
credentials as they are created on the guest. This requires qemu
|
||||
to run as root. In "mapped" security model, some of the file
|
||||
attributes like uid, gid, mode bits and link target are stored as
|
||||
file attributes. Directories exported by this security model cannot
|
||||
interact with other unix tools. "none" security model is same as
|
||||
passthrough except the sever won't report failures if it fails to
|
||||
set file attributes like ownership. Security model is mandatory
|
||||
only for local fsdriver. Other fsdrivers (like handle) don't take
|
||||
security model as a parameter.
|
||||
@item writeout=@var{writeout}
|
||||
This is an optional argument. The only supported value is "immediate".
|
||||
This means that host page cache will be used to read and write data but
|
||||
write notification will be sent to the guest only when the data has been
|
||||
reported as written by the storage subsystem.
|
||||
@end table
|
||||
|
||||
-fsdev option is used along with -device driver "virtio-9p-pci".
|
||||
@item -device virtio-9p-pci,fsdev=@var{id},mount_tag=@var{mount_tag}
|
||||
Options for virtio-9p-pci driver are:
|
||||
@table @option
|
||||
@item fsdev=@var{id}
|
||||
Specifies the id value specified along with -fsdev option
|
||||
@item mount_tag=@var{mount_tag}
|
||||
Specifies the tag name to be used by the guest to mount this export point
|
||||
@end table
|
||||
|
||||
ETEXI
|
||||
|
||||
DEFHEADING()
|
||||
|
||||
DEFHEADING(Virtual File system pass-through options:)
|
||||
|
||||
DEF("virtfs", HAS_ARG, QEMU_OPTION_virtfs,
|
||||
"-virtfs local,path=path,mount_tag=tag,security_model=[mapped|passthrough|none]\n",
|
||||
"-virtfs local,path=path,mount_tag=tag,security_model=[mapped|passthrough|none]\n"
|
||||
" [,writeout=immediate]\n",
|
||||
QEMU_ARCH_ALL)
|
||||
|
||||
STEXI
|
||||
|
||||
The general form of a Virtual File system pass-through option is:
|
||||
@table @option
|
||||
|
||||
@item -virtfs @var{fstype} [,@var{options}]
|
||||
@item -virtfs @var{fsdriver},path=@var{path},mount_tag=@var{mount_tag},security_model=@var{security_model}[,writeout=@var{writeout}]
|
||||
@findex -virtfs
|
||||
Fstype is one of:
|
||||
@option{local},
|
||||
The specific Fstype will determine the applicable options.
|
||||
|
||||
Options to each backend are described below.
|
||||
|
||||
@item -virtfs local ,path=@var{path} ,mount_tag=@var{mount_tag} ,security_model=@var{security_model}
|
||||
|
||||
Create a Virtual file-system-pass through for local-filesystem.
|
||||
|
||||
@option{local} is only available on Linux.
|
||||
|
||||
@option{path} specifies the path to be exported. @option{path} is required.
|
||||
|
||||
@option{security_model} specifies the security model to be followed.
|
||||
@option{security_model} is required.
|
||||
|
||||
|
||||
@option{mount_tag} specifies the tag with which the exported file is mounted.
|
||||
@option{mount_tag} is required.
|
||||
|
||||
The general form of a Virtual File system pass-through options are:
|
||||
@table @option
|
||||
@item @var{fsdriver}
|
||||
This option specifies the fs driver backend to use.
|
||||
Currently "local" and "handle" file system drivers are supported.
|
||||
@item id=@var{id}
|
||||
Specifies identifier for this device
|
||||
@item path=@var{path}
|
||||
Specifies the export path for the file system device. Files under
|
||||
this path will be available to the 9p client on the guest.
|
||||
@item security_model=@var{security_model}
|
||||
Specifies the security model to be used for this export path.
|
||||
Supported security models are "passthrough", "mapped" and "none".
|
||||
In "passthrough" security model, files are stored using the same
|
||||
credentials as they are created on the guest. This requires qemu
|
||||
to run as root. In "mapped" security model, some of the file
|
||||
attributes like uid, gid, mode bits and link target are stored as
|
||||
file attributes. Directories exported by this security model cannot
|
||||
interact with other unix tools. "none" security model is same as
|
||||
passthrough except the sever won't report failures if it fails to
|
||||
set file attributes like ownership. Security model is mandatory only
|
||||
for local fsdriver. Other fsdrivers (like handle) don't take security
|
||||
model as a parameter.
|
||||
@item writeout=@var{writeout}
|
||||
This is an optional argument. The only supported value is "immediate".
|
||||
This means that host page cache will be used to read and write data but
|
||||
write notification will be sent to the guest only when the data has been
|
||||
reported as written by the storage subsystem.
|
||||
@end table
|
||||
ETEXI
|
||||
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
#!/usr/bin/env python
|
||||
# Pretty print 9p simpletrace log
|
||||
# Usage: ./analyse-9p-simpletrace <trace-events> <trace-pid>
|
||||
#
|
||||
# Author: Harsh Prateek Bora
|
||||
|
||||
import simpletrace
|
||||
|
||||
class VirtFSRequestTracker(simpletrace.Analyzer):
|
||||
def begin(self):
|
||||
print "Pretty printing 9p simpletrace log ..."
|
||||
|
||||
def complete_pdu(self, tag, id, err):
|
||||
print "ERROR (tag =", tag, ", id =", id, ",err =", err, ")"
|
||||
|
||||
def v9fs_version(self, tag, id, msize, version):
|
||||
print "TVERSION (tag =", tag, ", msize =", msize, ", version =", version, ")"
|
||||
|
||||
def v9fs_version_return(self, tag, id, msize, version):
|
||||
print "RVERSION (tag =", tag, ", msize =", msize, ", version =", version, ")"
|
||||
|
||||
def v9fs_attach(self, tag, id, fid, afid, uname, aname):
|
||||
print "TATTACH (tag =", tag, ", fid =", fid, ", afid =", afid, ", uname =", uname, ", aname =", aname, ")"
|
||||
|
||||
def v9fs_attach_return(self, tag, id, type, verison, path):
|
||||
print "RATTACH (tag =", tag, ", qid={type =", type, ", version =", version, ", path =", path, "})"
|
||||
|
||||
def v9fs_stat(self, tag, id, fid):
|
||||
print "TSTAT (tag =", tag, ", fid =", fid, ")"
|
||||
|
||||
def v9fs_stat_return(self, tag, id, mode, atime, mtime, length):
|
||||
print "RSTAT (tag =", tag, ", mode =", mode, ", atime =", atime, ", mtime =", mtime, ", length =", length, ")"
|
||||
|
||||
def v9fs_getattr(self, tag, id, fid, request_mask):
|
||||
print "TGETATTR (tag =", tag, ", fid =", fid, ", request_mask =", hex(request_mask), ")"
|
||||
|
||||
def v9fs_getattr_return(self, tag, id, result_mask, mode, uid, gid):
|
||||
print "RGETATTR (tag =", tag, ", result_mask =", hex(result_mask), ", mode =", oct(mode), ", uid =", uid, ", gid =", gid, ")"
|
||||
|
||||
def v9fs_walk(self, tag, id, fid, newfid, nwnames):
|
||||
print "TWALK (tag =", tag, ", fid =", fid, ", newfid =", newfid, ", nwnames =", nwnames, ")"
|
||||
|
||||
def v9fs_walk_return(self, tag, id, nwnames, qids):
|
||||
print "RWALK (tag =", tag, ", nwnames =", nwnames, ", qids =", hex(qids), ")"
|
||||
|
||||
def v9fs_open(self, tag, id, fid, mode):
|
||||
print "TOPEN (tag =", tag, ", fid =", fid, ", mode =", oct(mode), ")"
|
||||
|
||||
def v9fs_open_return(self, tag, id, type, version, path, iounit):
|
||||
print "ROPEN (tag =", tag, ", qid={type =", type, ", version =", version, ", path =", path, "}, iounit =", iounit, ")"
|
||||
|
||||
def v9fs_lcreate(self, tag, id, dfid, flags, mode, gid):
|
||||
print "TLCREATE (tag =", tag, ", dfid =", dfid, ", flags =", oct(flags), ", mode =", oct(mode), ", gid =", gid, ")"
|
||||
|
||||
def v9fs_lcreate_return(self, id, type, version, path, iounit):
|
||||
print "RLCREATE (tag =", tag, ", qid={type =", type, ", version =", version, ", path =", path, "}, iounit =", iounit, ")"
|
||||
|
||||
def v9fs_fsync(self, tag, id, fid, datasync):
|
||||
print "TFSYNC (tag =", tag, ", fid =", fid, ", datasync =", datasync, ")"
|
||||
|
||||
def v9fs_clunk(self, tag, id, fid):
|
||||
print "TCLUNK (tag =", tag, ", fid =", fid, ")"
|
||||
|
||||
def v9fs_read(self, tag, id, fid, off, max_count):
|
||||
print "TREAD (tag =", tag, ", fid =", fid, ", off =", off, ", max_count =", max_count, ")"
|
||||
|
||||
def v9fs_read_return(self, tag, id, count, err):
|
||||
print "RREAD (tag =", tag, ", count =", count, ", err =", err, ")"
|
||||
|
||||
def v9fs_readdir(self, tag, id, fid, offset, max_count):
|
||||
print "TREADDIR (tag =", tag, ", fid =", fid, ", offset =", offset, ", max_count =", max_count, ")"
|
||||
|
||||
def v9fs_readdir_return(self, tag, id, count, retval):
|
||||
print "RREADDIR (tag =", tag, ", count =", count, ", retval =", retval, ")"
|
||||
|
||||
def v9fs_write(self, tag, id, fid, off, count, cnt):
|
||||
print "TWRITE (tag =", tag, ", fid =", fid, ", off =", off, ", count =", count, ", cnt =", cnt, ")"
|
||||
|
||||
def v9fs_write_return(self, tag, id, total, err):
|
||||
print "RWRITE (tag =", tag, ", total =", total, ", err =", err, ")"
|
||||
|
||||
def v9fs_create(self, tag, id, fid, perm, name, mode):
|
||||
print "TCREATE (tag =", tag, ", fid =", fid, ", perm =", oct(perm), ", name =", name, ", mode =", oct(mode), ")"
|
||||
|
||||
def v9fs_create_return(self, tag, id, type, verison, path, iounit):
|
||||
print "RCREATE (tag =", tag, ", qid={type =", type, ", version =", version, ", path =", path, "}, iounit =", iounit, ")"
|
||||
|
||||
def v9fs_symlink(self, tag, id, fid, name, symname, gid):
|
||||
print "TSYMLINK (tag =", tag, ", fid =", fid, ", name =", name, ", symname =", symname, ", gid =", gid, ")"
|
||||
|
||||
def v9fs_symlink_return(self, tag, id, type, version, path):
|
||||
print "RSYMLINK (tag =", tag, ", qid={type =", type, ", version =", version, ", path =", path, "})"
|
||||
|
||||
def v9fs_flush(self, tag, id, flush_tag):
|
||||
print "TFLUSH (tag =", tag, ", flush_tag =", flush_tag, ")"
|
||||
|
||||
def v9fs_link(self, tag, id, dfid, oldfid, name):
|
||||
print "TLINK (tag =", tag, ", dfid =", dfid, ", oldfid =", oldfid, ", name =", name, ")"
|
||||
|
||||
def v9fs_remove(self, tag, id, fid):
|
||||
print "TREMOVE (tag =", tag, ", fid =", fid, ")"
|
||||
|
||||
def v9fs_wstat(self, tag, id, fid, mode, atime, mtime):
|
||||
print "TWSTAT (tag =", tag, ", fid =", fid, ", mode =", oct(mode), ", atime =", atime, "mtime =", mtime, ")"
|
||||
|
||||
def v9fs_mknod(self, tag, id, fid, mode, major, minor):
|
||||
print "TMKNOD (tag =", tag, ", fid =", fid, ", mode =", oct(mode), ", major =", major, ", minor =", minor, ")"
|
||||
|
||||
def v9fs_lock(self, tag, id, fid, type, start, length):
|
||||
print "TLOCK (tag =", tag, ", fid =", fid, "type =", type, ", start =", start, ", length =", length, ")"
|
||||
|
||||
def v9fs_lock_return(self, tag, id, status):
|
||||
print "RLOCK (tag =", tag, ", status =", status, ")"
|
||||
|
||||
def v9fs_getlock(self, tag, id, fid, type, start, length):
|
||||
print "TGETLOCK (tag =", tag, ", fid =", fid, "type =", type, ", start =", start, ", length =", length, ")"
|
||||
|
||||
def v9fs_getlock_return(self, tag, id, type, start, length, proc_id):
|
||||
print "RGETLOCK (tag =", tag, "type =", type, ", start =", start, ", length =", length, ", proc_id =", proc_id, ")"
|
||||
|
||||
def v9fs_mkdir(self, tag, id, fid, name, mode, gid):
|
||||
print "TMKDIR (tag =", tag, ", fid =", fid, ", name =", name, ", mode =", mode, ", gid =", gid, ")"
|
||||
|
||||
def v9fs_mkdir_return(self, tag, id, type, version, path, err):
|
||||
print "RMKDIR (tag =", tag, ", qid={type =", type, ", version =", version, ", path =", path, "}, err =", err, ")"
|
||||
|
||||
def v9fs_xattrwalk(self, tag, id, fid, newfid, name):
|
||||
print "TXATTRWALK (tag =", tag, ", fid =", fid, ", newfid =", newfid, ", xattr name =", name, ")"
|
||||
|
||||
def v9fs_xattrwalk_return(self, tag, id, size):
|
||||
print "RXATTRWALK (tag =", tag, ", xattrsize =", size, ")"
|
||||
|
||||
def v9fs_xattrcreate(self, tag, id, fid, name, size, flags):
|
||||
print "TXATTRCREATE (tag =", tag, ", fid =", fid, ", name =", name, ", xattrsize =", size, ", flags =", flags, ")"
|
||||
|
||||
def v9fs_readlink(self, tag, id, fid):
|
||||
print "TREADLINK (tag =", tag, ", fid =", fid, ")"
|
||||
|
||||
def v9fs_readlink_return(self, tag, id, target):
|
||||
print "RREADLINK (tag =", tag, ", target =", target, ")"
|
||||
|
||||
simpletrace.run(VirtFSRequestTracker())
|
46
trace-events
46
trace-events
|
@ -552,3 +552,49 @@ open_eth_reg_read(uint32_t addr, uint32_t v) "MAC[%02x] -> %08x"
|
|||
open_eth_reg_write(uint32_t addr, uint32_t v) "MAC[%02x] <- %08x"
|
||||
open_eth_desc_read(uint32_t addr, uint32_t v) "DESC[%04x] -> %08x"
|
||||
open_eth_desc_write(uint32_t addr, uint32_t v) "DESC[%04x] <- %08x"
|
||||
|
||||
# hw/9pfs/virtio-9p.c
|
||||
complete_pdu(uint16_t tag, uint8_t id, int err) "tag %d id %d err %d"
|
||||
v9fs_version(uint16_t tag, uint8_t id, int32_t msize, char* version) "tag %d id %d msize %d version %s"
|
||||
v9fs_version_return(uint16_t tag, uint8_t id, int32_t msize, char* version) "tag %d id %d msize %d version %s"
|
||||
v9fs_attach(uint16_t tag, uint8_t id, int32_t fid, int32_t afid, char* uname, char* aname) "tag %d id %d fid %d afid %d aname %s"
|
||||
v9fs_attach_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path) "tag %d id %d type %d version %d path %"PRId64""
|
||||
v9fs_stat(uint16_t tag, uint8_t id, int32_t fid) "tag %d id %d fid %d"
|
||||
v9fs_stat_return(uint16_t tag, uint8_t id, int32_t mode, int32_t atime, int32_t mtime, int64_t length) "tag %d id %d stat={mode %d atime %d mtime %d length %"PRId64"}"
|
||||
v9fs_getattr(uint16_t tag, uint8_t id, int32_t fid, uint64_t request_mask) "tag %d id %d fid %d request_mask %"PRIu64""
|
||||
v9fs_getattr_return(uint16_t tag, uint8_t id, uint64_t result_mask, uint32_t mode, uint32_t uid, uint32_t gid) "tag %d id %d getattr={result_mask %"PRId64" mode %u uid %u gid %u}"
|
||||
v9fs_walk(uint16_t tag, uint8_t id, int32_t fid, int32_t newfid, uint16_t nwnames) "tag %d id %d fid %d newfid %d nwnames %d"
|
||||
v9fs_walk_return(uint16_t tag, uint8_t id, uint16_t nwnames, void* qids) "tag %d id %d nwnames %d qids %p"
|
||||
v9fs_open(uint16_t tag, uint8_t id, int32_t fid, int32_t mode) "tag %d id %d fid %d mode %d"
|
||||
v9fs_open_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int iounit) "tag %d id %d qid={type %d version %d path %"PRId64"} iounit %d"
|
||||
v9fs_lcreate(uint16_t tag, uint8_t id, int32_t dfid, int32_t flags, int32_t mode, uint32_t gid) "tag %d id %d dfid %d flags %d mode %d gid %u"
|
||||
v9fs_lcreate_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int32_t iounit) "tag %d id %d qid={type %d version %d path %"PRId64"} iounit %d"
|
||||
v9fs_fsync(uint16_t tag, uint8_t id, int32_t fid, int datasync) "tag %d id %d fid %d datasync %d"
|
||||
v9fs_clunk(uint16_t tag, uint8_t id, int32_t fid) "tag %d id %d fid %d"
|
||||
v9fs_read(uint16_t tag, uint8_t id, int32_t fid, int64_t off, int32_t max_count) "tag %d id %d fid %d off %"PRId64" max_count %d"
|
||||
v9fs_read_return(uint16_t tag, uint8_t id, int32_t count, ssize_t err) "tag %d id %d count %d err %zd"
|
||||
v9fs_readdir(uint16_t tag, uint8_t id, int32_t fid, int64_t offset, int32_t max_count) "tag %d id %d fid %d offset %"PRId64" max_count %d"
|
||||
v9fs_readdir_return(uint16_t tag, uint8_t id, int32_t count, ssize_t retval) "tag %d id %d count %d retval %zd"
|
||||
v9fs_write(uint16_t tag, uint8_t id, int32_t fid, int64_t off, int32_t count, int cnt) "tag %d id %d fid %d off %"PRId64" count %d cnt %d"
|
||||
v9fs_write_return(uint16_t tag, uint8_t id, int32_t total, ssize_t err) "tag %d id %d total %d err %zd"
|
||||
v9fs_create(uint16_t tag, uint8_t id, int32_t fid, char* name, int32_t perm, int8_t mode) "tag %d id %d fid %d name %s perm %d mode %d"
|
||||
v9fs_create_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int iounit) "tag %d id %d qid={type %d version %d path %"PRId64"} iounit %d"
|
||||
v9fs_symlink(uint16_t tag, uint8_t id, int32_t fid, char* name, char* symname, uint32_t gid) "tag %d id %d fid %d name %s symname %s gid %u"
|
||||
v9fs_symlink_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path) "tag %d id %d qid={type %d version %d path %"PRId64"}"
|
||||
v9fs_flush(uint16_t tag, uint8_t id, int16_t flush_tag) "tag %d id %d flush_tag %d"
|
||||
v9fs_link(uint16_t tag, uint8_t id, int32_t dfid, int32_t oldfid, char* name) "tag %d id %d dfid %d oldfid %d name %s"
|
||||
v9fs_remove(uint16_t tag, uint8_t id, int32_t fid) "tag %d id %d fid %d"
|
||||
v9fs_wstat(uint16_t tag, uint8_t id, int32_t fid, int32_t mode, int32_t atime, int32_t mtime) "tag %d id %d fid %d stat={mode %d atime %d mtime}"
|
||||
v9fs_mknod(uint16_t tag, uint8_t id, int32_t fid, int mode, int major, int minor) "tag %d id %d fid %d mode %d major %d minor %d"
|
||||
v9fs_mknod_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path) "tag %d id %d qid={type %d version %d path %"PRId64"}"
|
||||
v9fs_lock(uint16_t tag, uint8_t id, int32_t fid, uint8_t type, uint64_t start, uint64_t length) "tag %d id %d fid %d type %d start %"PRIu64" length %"PRIu64""
|
||||
v9fs_lock_return(uint16_t tag, uint8_t id, int8_t status) "tag %d id %d status %d"
|
||||
v9fs_getlock(uint16_t tag, uint8_t id, int32_t fid, uint8_t type, uint64_t start, uint64_t length)"tag %d id %d fid %d type %d start %"PRIu64" length %"PRIu64""
|
||||
v9fs_getlock_return(uint16_t tag, uint8_t id, uint8_t type, uint64_t start, uint64_t length, uint32_t proc_id) "tag %d id %d type %d start %"PRIu64" length %"PRIu64" proc_id %u"
|
||||
v9fs_mkdir(uint16_t tag, uint8_t id, int32_t fid, char* name, int mode, uint32_t gid) "tag %d id %d fid %d name %s mode %d"
|
||||
v9fs_mkdir_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int err) "tag %d id %d qid={type %d version %d path %"PRId64"}"
|
||||
v9fs_xattrwalk(uint16_t tag, uint8_t id, int32_t fid, int32_t newfid, char* name) "tag %d id %d fid %d newfid %d name %s"
|
||||
v9fs_xattrwalk_return(uint16_t tag, uint8_t id, int64_t size) "tag %d id %d size %"PRId64""
|
||||
v9fs_xattrcreate(uint16_t tag, uint8_t id, int32_t fid, char* name, int64_t size, int flags) "tag %d id %d fid %d name %s size %"PRId64" flags %d"
|
||||
v9fs_readlink(uint16_t tag, uint8_t id, int32_t fid) "tag %d id %d fid %d"
|
||||
v9fs_readlink_return(uint16_t tag, uint8_t id, char* target) "tag %d id %d name %s"
|
||||
|
|
24
vl.c
24
vl.c
|
@ -2783,6 +2783,7 @@ int main(int argc, char **argv, char **envp)
|
|||
case QEMU_OPTION_virtfs: {
|
||||
QemuOpts *fsdev;
|
||||
QemuOpts *device;
|
||||
const char *writeout;
|
||||
|
||||
olist = qemu_find_opts("virtfs");
|
||||
if (!olist) {
|
||||
|
@ -2795,16 +2796,14 @@ int main(int argc, char **argv, char **envp)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
if (qemu_opt_get(opts, "fstype") == NULL ||
|
||||
if (qemu_opt_get(opts, "fsdriver") == NULL ||
|
||||
qemu_opt_get(opts, "mount_tag") == NULL ||
|
||||
qemu_opt_get(opts, "path") == NULL ||
|
||||
qemu_opt_get(opts, "security_model") == NULL) {
|
||||
fprintf(stderr, "Usage: -virtfs fstype,path=/share_path/,"
|
||||
"security_model=[mapped|passthrough|none],"
|
||||
qemu_opt_get(opts, "path") == NULL) {
|
||||
fprintf(stderr, "Usage: -virtfs fsdriver,path=/share_path/,"
|
||||
"[security_model={mapped|passthrough|none}],"
|
||||
"mount_tag=tag.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fsdev = qemu_opts_create(qemu_find_opts("fsdev"),
|
||||
qemu_opt_get(opts, "mount_tag"), 1);
|
||||
if (!fsdev) {
|
||||
|
@ -2812,7 +2811,18 @@ int main(int argc, char **argv, char **envp)
|
|||
qemu_opt_get(opts, "mount_tag"));
|
||||
exit(1);
|
||||
}
|
||||
qemu_opt_set(fsdev, "fstype", qemu_opt_get(opts, "fstype"));
|
||||
|
||||
writeout = qemu_opt_get(opts, "writeout");
|
||||
if (writeout) {
|
||||
#ifdef CONFIG_SYNC_FILE_RANGE
|
||||
qemu_opt_set(fsdev, "writeout", writeout);
|
||||
#else
|
||||
fprintf(stderr, "writeout=immediate not supported on "
|
||||
"this platform\n");
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
qemu_opt_set(fsdev, "fsdriver", qemu_opt_get(opts, "fsdriver"));
|
||||
qemu_opt_set(fsdev, "path", qemu_opt_get(opts, "path"));
|
||||
qemu_opt_set(fsdev, "security_model",
|
||||
qemu_opt_get(opts, "security_model"));
|
||||
|
|
Loading…
Reference in New Issue