aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fsdev/file-op-9p.h6
-rw-r--r--hw/9pfs/codir.c8
-rw-r--r--hw/9pfs/cofile.c16
-rw-r--r--hw/9pfs/cofs.c58
-rw-r--r--hw/9pfs/coxattr.c16
-rw-r--r--hw/9pfs/virtio-9p-device.c1
-rw-r--r--hw/9pfs/virtio-9p-local.c1
-rw-r--r--hw/9pfs/virtio-9p.c30
-rw-r--r--hw/9pfs/virtio-9p.h21
9 files changed, 105 insertions, 52 deletions
diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index 5221d6d798..8de8abfd5b 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -50,12 +50,18 @@ typedef struct FsCred
struct xattr_operations;
+/* FsContext flag values */
+#define PATHNAME_FSCONTEXT 0x1
+
typedef struct FsContext
{
+ int flags;
char *fs_root;
SecModel fs_sm;
uid_t uid;
struct xattr_operations **xops;
+ /* fs driver specific data */
+ void *private;
} FsContext;
typedef struct V9fsPath {
diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c
index 2c50df84c3..b379f931c0 100644
--- a/hw/9pfs/codir.c
+++ b/hw/9pfs/codir.c
@@ -76,7 +76,7 @@ int v9fs_co_mkdir(V9fsState *s, V9fsFidState *fidp, V9fsString *name,
cred.fc_mode = mode;
cred.fc_uid = uid;
cred.fc_gid = gid;
- qemu_co_rwlock_rdlock(&s->rename_lock);
+ v9fs_path_read_lock(s);
v9fs_co_run_in_worker(
{
err = s->ops->mkdir(&s->ctx, &fidp->path, name->data, &cred);
@@ -94,7 +94,7 @@ int v9fs_co_mkdir(V9fsState *s, V9fsFidState *fidp, V9fsString *name,
v9fs_path_free(&path);
}
});
- qemu_co_rwlock_unlock(&s->rename_lock);
+ v9fs_path_unlock(s);
return err;
}
@@ -102,7 +102,7 @@ int v9fs_co_opendir(V9fsState *s, V9fsFidState *fidp)
{
int err;
- qemu_co_rwlock_rdlock(&s->rename_lock);
+ v9fs_path_read_lock(s);
v9fs_co_run_in_worker(
{
fidp->fs.dir = s->ops->opendir(&s->ctx, &fidp->path);
@@ -112,7 +112,7 @@ int v9fs_co_opendir(V9fsState *s, V9fsFidState *fidp)
err = 0;
}
});
- qemu_co_rwlock_unlock(&s->rename_lock);
+ v9fs_path_unlock(s);
if (!err) {
total_open_fd++;
if (total_open_fd > open_fd_hw) {
diff --git a/hw/9pfs/cofile.c b/hw/9pfs/cofile.c
index 69fad369f3..1a99adc55f 100644
--- a/hw/9pfs/cofile.c
+++ b/hw/9pfs/cofile.c
@@ -21,7 +21,7 @@ int v9fs_co_lstat(V9fsState *s, V9fsPath *path, struct stat *stbuf)
{
int err;
- qemu_co_rwlock_rdlock(&s->rename_lock);
+ v9fs_path_read_lock(s);
v9fs_co_run_in_worker(
{
err = s->ops->lstat(&s->ctx, path, stbuf);
@@ -29,7 +29,7 @@ int v9fs_co_lstat(V9fsState *s, V9fsPath *path, struct stat *stbuf)
err = -errno;
}
});
- qemu_co_rwlock_unlock(&s->rename_lock);
+ v9fs_path_unlock(s);
return err;
}
@@ -51,7 +51,7 @@ int v9fs_co_open(V9fsState *s, V9fsFidState *fidp, int flags)
{
int err;
- qemu_co_rwlock_rdlock(&s->rename_lock);
+ v9fs_path_read_lock(s);
v9fs_co_run_in_worker(
{
fidp->fs.fd = s->ops->open(&s->ctx, &fidp->path, flags);
@@ -61,7 +61,7 @@ int v9fs_co_open(V9fsState *s, V9fsFidState *fidp, int flags)
err = 0;
}
});
- qemu_co_rwlock_unlock(&s->rename_lock);
+ v9fs_path_unlock(s);
if (!err) {
total_open_fd++;
if (total_open_fd > open_fd_hw) {
@@ -88,7 +88,7 @@ int v9fs_co_open2(V9fsState *s, V9fsFidState *fidp, V9fsString *name, gid_t gid,
* don't change. Read lock is fine because this fid cannot
* be used by any other operation.
*/
- qemu_co_rwlock_rdlock(&s->rename_lock);
+ v9fs_path_read_lock(s);
v9fs_co_run_in_worker(
{
fidp->fs.fd = s->ops->open2(&s->ctx, &fidp->path,
@@ -112,7 +112,7 @@ int v9fs_co_open2(V9fsState *s, V9fsFidState *fidp, V9fsString *name, gid_t gid,
v9fs_path_free(&path);
}
});
- qemu_co_rwlock_unlock(&s->rename_lock);
+ v9fs_path_unlock(s);
if (!err) {
total_open_fd++;
if (total_open_fd > open_fd_hw) {
@@ -160,7 +160,7 @@ int v9fs_co_link(V9fsState *s, V9fsFidState *oldfid,
{
int err;
- qemu_co_rwlock_rdlock(&s->rename_lock);
+ v9fs_path_read_lock(s);
v9fs_co_run_in_worker(
{
err = s->ops->link(&s->ctx, &oldfid->path,
@@ -169,7 +169,7 @@ int v9fs_co_link(V9fsState *s, V9fsFidState *oldfid,
err = -errno;
}
});
- qemu_co_rwlock_unlock(&s->rename_lock);
+ v9fs_path_unlock(s);
return err;
}
diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c
index 7f5220e1e6..9c3c9e9bcb 100644
--- a/hw/9pfs/cofs.c
+++ b/hw/9pfs/cofs.c
@@ -23,8 +23,7 @@ int v9fs_co_readlink(V9fsState *s, V9fsPath *path, V9fsString *buf)
ssize_t len;
buf->data = g_malloc(PATH_MAX);
- qemu_co_rwlock_rdlock(&s->rename_lock);
-
+ v9fs_path_read_lock(s);
v9fs_co_run_in_worker(
{
len = s->ops->readlink(&s->ctx, path,
@@ -37,7 +36,7 @@ int v9fs_co_readlink(V9fsState *s, V9fsPath *path, V9fsString *buf)
err = -errno;
}
});
- qemu_co_rwlock_unlock(&s->rename_lock);
+ v9fs_path_unlock(s);
if (err) {
g_free(buf->data);
buf->data = NULL;
@@ -50,7 +49,7 @@ int v9fs_co_statfs(V9fsState *s, V9fsPath *path, struct statfs *stbuf)
{
int err;
- qemu_co_rwlock_rdlock(&s->rename_lock);
+ v9fs_path_read_lock(s);
v9fs_co_run_in_worker(
{
err = s->ops->statfs(&s->ctx, path, stbuf);
@@ -58,7 +57,7 @@ int v9fs_co_statfs(V9fsState *s, V9fsPath *path, struct statfs *stbuf)
err = -errno;
}
});
- qemu_co_rwlock_unlock(&s->rename_lock);
+ v9fs_path_unlock(s);
return err;
}
@@ -69,7 +68,7 @@ int v9fs_co_chmod(V9fsState *s, V9fsPath *path, mode_t mode)
cred_init(&cred);
cred.fc_mode = mode;
- qemu_co_rwlock_rdlock(&s->rename_lock);
+ v9fs_path_read_lock(s);
v9fs_co_run_in_worker(
{
err = s->ops->chmod(&s->ctx, path, &cred);
@@ -77,7 +76,7 @@ int v9fs_co_chmod(V9fsState *s, V9fsPath *path, mode_t mode)
err = -errno;
}
});
- qemu_co_rwlock_unlock(&s->rename_lock);
+ v9fs_path_unlock(s);
return err;
}
@@ -86,7 +85,7 @@ int v9fs_co_utimensat(V9fsState *s, V9fsPath *path,
{
int err;
- qemu_co_rwlock_rdlock(&s->rename_lock);
+ v9fs_path_read_lock(s);
v9fs_co_run_in_worker(
{
err = s->ops->utimensat(&s->ctx, path, times);
@@ -94,7 +93,7 @@ int v9fs_co_utimensat(V9fsState *s, V9fsPath *path,
err = -errno;
}
});
- qemu_co_rwlock_unlock(&s->rename_lock);
+ v9fs_path_unlock(s);
return err;
}
@@ -106,7 +105,7 @@ int v9fs_co_chown(V9fsState *s, V9fsPath *path, uid_t uid, gid_t gid)
cred_init(&cred);
cred.fc_uid = uid;
cred.fc_gid = gid;
- qemu_co_rwlock_rdlock(&s->rename_lock);
+ v9fs_path_read_lock(s);
v9fs_co_run_in_worker(
{
err = s->ops->chown(&s->ctx, path, &cred);
@@ -114,7 +113,7 @@ int v9fs_co_chown(V9fsState *s, V9fsPath *path, uid_t uid, gid_t gid)
err = -errno;
}
});
- qemu_co_rwlock_unlock(&s->rename_lock);
+ v9fs_path_unlock(s);
return err;
}
@@ -122,7 +121,7 @@ int v9fs_co_truncate(V9fsState *s, V9fsPath *path, off_t size)
{
int err;
- qemu_co_rwlock_rdlock(&s->rename_lock);
+ v9fs_path_read_lock(s);
v9fs_co_run_in_worker(
{
err = s->ops->truncate(&s->ctx, path, size);
@@ -130,7 +129,7 @@ int v9fs_co_truncate(V9fsState *s, V9fsPath *path, off_t size)
err = -errno;
}
});
- qemu_co_rwlock_unlock(&s->rename_lock);
+ v9fs_path_unlock(s);
return err;
}
@@ -146,7 +145,7 @@ int v9fs_co_mknod(V9fsState *s, V9fsFidState *fidp, V9fsString *name, uid_t uid,
cred.fc_gid = gid;
cred.fc_mode = mode;
cred.fc_rdev = dev;
- qemu_co_rwlock_rdlock(&s->rename_lock);
+ v9fs_path_read_lock(s);
v9fs_co_run_in_worker(
{
err = s->ops->mknod(&s->ctx, &fidp->path, name->data, &cred);
@@ -164,7 +163,7 @@ int v9fs_co_mknod(V9fsState *s, V9fsFidState *fidp, V9fsString *name, uid_t uid,
v9fs_path_free(&path);
}
});
- qemu_co_rwlock_unlock(&s->rename_lock);
+ v9fs_path_unlock(s);
return err;
}
@@ -173,7 +172,7 @@ int v9fs_co_remove(V9fsState *s, V9fsPath *path)
{
int err;
- qemu_co_rwlock_rdlock(&s->rename_lock);
+ v9fs_path_read_lock(s);
v9fs_co_run_in_worker(
{
err = s->ops->remove(&s->ctx, path->data);
@@ -181,7 +180,7 @@ int v9fs_co_remove(V9fsState *s, V9fsPath *path)
err = -errno;
}
});
- qemu_co_rwlock_unlock(&s->rename_lock);
+ v9fs_path_unlock(s);
return err;
}
@@ -189,7 +188,7 @@ int v9fs_co_unlinkat(V9fsState *s, V9fsPath *path, V9fsString *name, int flags)
{
int err;
- qemu_co_rwlock_rdlock(&s->rename_lock);
+ v9fs_path_read_lock(s);
v9fs_co_run_in_worker(
{
err = s->ops->unlinkat(&s->ctx, path, name->data, flags);
@@ -197,7 +196,7 @@ int v9fs_co_unlinkat(V9fsState *s, V9fsPath *path, V9fsString *name, int flags)
err = -errno;
}
});
- qemu_co_rwlock_unlock(&s->rename_lock);
+ v9fs_path_unlock(s);
return err;
}
@@ -244,7 +243,7 @@ int v9fs_co_symlink(V9fsState *s, V9fsFidState *dfidp, V9fsString *name,
cred.fc_uid = dfidp->uid;
cred.fc_gid = gid;
cred.fc_mode = 0777;
- qemu_co_rwlock_rdlock(&s->rename_lock);
+ v9fs_path_read_lock(s);
v9fs_co_run_in_worker(
{
err = s->ops->symlink(&s->ctx, oldpath, &dfidp->path,
@@ -263,7 +262,7 @@ int v9fs_co_symlink(V9fsState *s, V9fsFidState *dfidp, V9fsString *name,
v9fs_path_free(&path);
}
});
- qemu_co_rwlock_unlock(&s->rename_lock);
+ v9fs_path_unlock(s);
return err;
}
@@ -275,9 +274,20 @@ int v9fs_co_name_to_path(V9fsState *s, V9fsPath *dirpath,
const char *name, V9fsPath *path)
{
int err;
- err = s->ops->name_to_path(&s->ctx, dirpath, name, path);
- if (err < 0) {
- err = -errno;
+
+ if (s->ctx.flags & PATHNAME_FSCONTEXT) {
+ err = s->ops->name_to_path(&s->ctx, dirpath, name, path);
+ if (err < 0) {
+ err = -errno;
+ }
+ } else {
+ v9fs_co_run_in_worker(
+ {
+ err = s->ops->name_to_path(&s->ctx, dirpath, name, path);
+ if (err < 0) {
+ err = -errno;
+ }
+ });
}
return err;
}
diff --git a/hw/9pfs/coxattr.c b/hw/9pfs/coxattr.c
index b723240fb9..dd2e4a5cc3 100644
--- a/hw/9pfs/coxattr.c
+++ b/hw/9pfs/coxattr.c
@@ -21,7 +21,7 @@ int v9fs_co_llistxattr(V9fsState *s, V9fsPath *path, void *value, size_t size)
{
int err;
- qemu_co_rwlock_rdlock(&s->rename_lock);
+ v9fs_path_read_lock(s);
v9fs_co_run_in_worker(
{
err = s->ops->llistxattr(&s->ctx, path, value, size);
@@ -29,7 +29,7 @@ int v9fs_co_llistxattr(V9fsState *s, V9fsPath *path, void *value, size_t size)
err = -errno;
}
});
- qemu_co_rwlock_unlock(&s->rename_lock);
+ v9fs_path_unlock(s);
return err;
}
@@ -39,7 +39,7 @@ int v9fs_co_lgetxattr(V9fsState *s, V9fsPath *path,
{
int err;
- qemu_co_rwlock_rdlock(&s->rename_lock);
+ v9fs_path_read_lock(s);
v9fs_co_run_in_worker(
{
err = s->ops->lgetxattr(&s->ctx, path,
@@ -49,7 +49,7 @@ int v9fs_co_lgetxattr(V9fsState *s, V9fsPath *path,
err = -errno;
}
});
- qemu_co_rwlock_unlock(&s->rename_lock);
+ v9fs_path_unlock(s);
return err;
}
@@ -59,7 +59,7 @@ int v9fs_co_lsetxattr(V9fsState *s, V9fsPath *path,
{
int err;
- qemu_co_rwlock_rdlock(&s->rename_lock);
+ v9fs_path_read_lock(s);
v9fs_co_run_in_worker(
{
err = s->ops->lsetxattr(&s->ctx, path,
@@ -69,7 +69,7 @@ int v9fs_co_lsetxattr(V9fsState *s, V9fsPath *path,
err = -errno;
}
});
- qemu_co_rwlock_unlock(&s->rename_lock);
+ v9fs_path_unlock(s);
return err;
}
@@ -78,7 +78,7 @@ int v9fs_co_lremovexattr(V9fsState *s, V9fsPath *path,
{
int err;
- qemu_co_rwlock_rdlock(&s->rename_lock);
+ v9fs_path_read_lock(s);
v9fs_co_run_in_worker(
{
err = s->ops->lremovexattr(&s->ctx, path, xattr_name->data);
@@ -86,6 +86,6 @@ int v9fs_co_lremovexattr(V9fsState *s, V9fsPath *path,
err = -errno;
}
});
- qemu_co_rwlock_unlock(&s->rename_lock);
+ v9fs_path_unlock(s);
return err;
}
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index 1ffe95b83b..320ed95868 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -124,6 +124,7 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
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;
diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
index 61954fefec..9559ff6550 100644
--- a/hw/9pfs/virtio-9p-local.c
+++ b/hw/9pfs/virtio-9p-local.c
@@ -647,6 +647,7 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
static int local_init(FsContext *ctx)
{
+ ctx->flags |= PATHNAME_FSCONTEXT;
return 0;
}
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index 82f1db5701..2a6895396d 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -2332,6 +2332,7 @@ out_nofid:
complete_pdu(s, pdu, err);
}
+/* Only works with path name based fid */
static void v9fs_remove(void *opaque)
{
int32_t fid;
@@ -2347,6 +2348,11 @@ static void v9fs_remove(void *opaque)
err = -EINVAL;
goto out_nofid;
}
+ /* if fs driver is not path based, return EOPNOTSUPP */
+ if (!pdu->s->ctx.flags & PATHNAME_FSCONTEXT) {
+ err = -EOPNOTSUPP;
+ goto out_err;
+ }
/*
* IF the file is unlinked, we cannot reopen
* the file later. So don't reclaim fd
@@ -2467,6 +2473,7 @@ out_nofid:
return err;
}
+/* Only works with path name based fid */
static void v9fs_rename(void *opaque)
{
int32_t fid;
@@ -2486,13 +2493,18 @@ static void v9fs_rename(void *opaque)
goto out_nofid;
}
BUG_ON(fidp->fid_type != P9_FID_NONE);
-
- qemu_co_rwlock_wrlock(&s->rename_lock);
+ /* if fs driver is not path based, return EOPNOTSUPP */
+ if (!pdu->s->ctx.flags & PATHNAME_FSCONTEXT) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+ v9fs_path_write_lock(s);
err = v9fs_complete_rename(s, fidp, newdirfid, &name);
- qemu_co_rwlock_unlock(&s->rename_lock);
+ v9fs_path_unlock(s);
if (!err) {
err = offset;
}
+out:
put_fid(s, fidp);
out_nofid:
complete_pdu(s, pdu, err);
@@ -2553,9 +2565,11 @@ static int v9fs_complete_renameat(V9fsState *s, int32_t olddirfid,
if (err < 0) {
goto out;
}
- /* Only for path based fid we need to do the below fixup */
- v9fs_fix_fid_paths(s, &olddirfidp->path, old_name,
- &newdirfidp->path, new_name);
+ if (s->ctx.flags & PATHNAME_FSCONTEXT) {
+ /* Only for path based fid we need to do the below fixup */
+ v9fs_fix_fid_paths(s, &olddirfidp->path, old_name,
+ &newdirfidp->path, new_name);
+ }
out:
if (olddirfidp) {
put_fid(s, olddirfidp);
@@ -2578,9 +2592,9 @@ static void v9fs_renameat(void *opaque)
pdu_unmarshal(pdu, offset, "dsds", &olddirfid,
&old_name, &newdirfid, &new_name);
- qemu_co_rwlock_wrlock(&s->rename_lock);
+ v9fs_path_write_lock(s);
err = v9fs_complete_renameat(s, olddirfid, &old_name, newdirfid, &new_name);
- qemu_co_rwlock_unlock(&s->rename_lock);
+ v9fs_path_unlock(s);
if (!err) {
err = offset;
}
diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
index 8c7c3f0571..80147d4131 100644
--- a/hw/9pfs/virtio-9p.h
+++ b/hw/9pfs/virtio-9p.h
@@ -388,6 +388,27 @@ static inline size_t do_pdu_unpack(void *dst, struct iovec *sg, int sg_count,
return pdu_packunpack(dst, sg, sg_count, offset, size, 0);
}
+static inline void v9fs_path_write_lock(V9fsState *s)
+{
+ if (s->ctx.flags & PATHNAME_FSCONTEXT) {
+ qemu_co_rwlock_wrlock(&s->rename_lock);
+ }
+}
+
+static inline void v9fs_path_read_lock(V9fsState *s)
+{
+ if (s->ctx.flags & PATHNAME_FSCONTEXT) {
+ qemu_co_rwlock_rdlock(&s->rename_lock);
+ }
+}
+
+static inline void v9fs_path_unlock(V9fsState *s)
+{
+ if (s->ctx.flags & PATHNAME_FSCONTEXT) {
+ qemu_co_rwlock_unlock(&s->rename_lock);
+ }
+}
+
extern void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq);
extern void virtio_9p_set_fd_limit(void);
extern void v9fs_reclaim_fd(V9fsState *s);