* [Qemu-devel] [PATCH 00/13] 9p: reconcile virtfs with unlinked files
@ 2016-06-27 9:40 Greg Kurz
2016-06-27 9:41 ` [Qemu-devel] [PATCH 01/13] 9p: synth: drop v9fs_ prefix Greg Kurz
` (13 more replies)
0 siblings, 14 replies; 16+ messages in thread
From: Greg Kurz @ 2016-06-27 9:40 UTC (permalink / raw)
To: qemu-devel
Cc: Eric Van Hensbergen, v9fs-developer, Aneesh Kumar K.V, Greg Kurz
This series addresses a long standing issue in 9p, where most syscalls
accessing file attributes out of file descriptor stop to work in the
guest when the file gets unlinked:
open("./test.txt", O_RDWR|O_CREAT, 0666) = 4
unlink("./test.txt") = 0
fstat(4, 0x3fffc22108d0) = -1 ENOENT (No such file or directory)
ftruncate(4, 0) = -1 ENOENT (No such file or directory)
utimensat(4, NULL, NULL, 0) = -1 ENOENT (No such file or directory)
fgetxattr(4, "user.greg", NULL, 0) = -1 ENOENT (No such file or directory)
flistxattr(4, NULL, 0) = -1 ENOENT (No such file or directory)
fchmod(4, 0) = -1 ENOENT (No such file or directory)
fchown(4, -1, -1) = -1 ENOENT (No such file or directory)
There is also another case where ftruncate() unexpectedly fails:
open("./test.txt", O_RDWR|O_CREAT, 0666) = 4
chmod("./test.txt", 0) = 0
ftruncate(4, 0) = -1 EACCES (Permission denied)
Since the open+unlink sequence is widely used in applications, these
failures are really a problem, and does not encourage people to using
9p mounts.
The root cause for all these errors is that QEMU uses path based syscalls to
implement 9p operations on file attributes, even if the fid has an open fd.
This series adds new file ops to the internal fsdev API, following the example
of already existing fstat, so that backends can access the fid file descriptor
and pass it to ftruncate(), fchmod() and friends.
This can be tested with a linux guest, provided the 9p client in the kernel is
fixed with the following patches, to ensure it passes open fids (fid associated
to a valid file descriptor) to the 9p server in QEMU.
https://sourceforge.net/p/v9fs/mailman/message/35175775/
With this series and the patched guest kernel, all the failures mentionned
above no longer occur.
---
Greg Kurz (13):
9p: synth: drop v9fs_ prefix
9p: factour out duplicate code from local_fstat() and local_lstat()
9p: introduce the v9fs_get_fd_fid() helper
9p: getattr: use fstat if we have a fd
9p: introduce ftruncate file op
oslib: support futimens() if available
9p: introduce futimens file op
9p: add a fd argument to xattr helpers
9p: introduce fchown file op
9p: introduce fchmod file op
9p: xattr fid to reference file fid
9p: introduce fgetxattr file op
9p: introduce flistxattr file op
fsdev/file-op-9p.h | 9 ++
hw/9pfs/9p-handle.c | 85 ++++++++++++---
hw/9pfs/9p-local.c | 213 ++++++++++++++++++++++++++++----------
hw/9pfs/9p-posix-acl.c | 80 ++++++++++----
hw/9pfs/9p-proxy.c | 78 ++++++++++++--
hw/9pfs/9p-synth.c | 249 +++++++++++++++++++++++++++------------------
hw/9pfs/9p-xattr-user.c | 41 +++++--
hw/9pfs/9p-xattr.c | 35 ++++--
hw/9pfs/9p-xattr.h | 67 +++++++-----
hw/9pfs/9p.c | 189 +++++++++++++++++++++++++++++-----
hw/9pfs/9p.h | 3 +
hw/9pfs/cofs.c | 79 ++++++++++++++
hw/9pfs/coth.h | 7 +
hw/9pfs/coxattr.c | 42 ++++++++
include/sysemu/os-posix.h | 1
util/oslib-posix.c | 10 ++
16 files changed, 896 insertions(+), 292 deletions(-)
--
Greg
^ permalink raw reply [flat|nested] 16+ messages in thread
* [Qemu-devel] [PATCH 01/13] 9p: synth: drop v9fs_ prefix
2016-06-27 9:40 [Qemu-devel] [PATCH 00/13] 9p: reconcile virtfs with unlinked files Greg Kurz
@ 2016-06-27 9:41 ` Greg Kurz
2016-06-30 11:45 ` Cédric Le Goater
2016-06-27 9:41 ` [Qemu-devel] [PATCH 02/13] 9p: factour out duplicate code from local_fstat() and local_lstat() Greg Kurz
` (12 subsequent siblings)
13 siblings, 1 reply; 16+ messages in thread
From: Greg Kurz @ 2016-06-27 9:41 UTC (permalink / raw)
To: qemu-devel
Cc: Eric Van Hensbergen, v9fs-developer, Aneesh Kumar K.V, Greg Kurz
To have shorter lines and be consistent with other fs devices.
Signed-off-by: Greg Kurz <groug@kaod.org>
---
hw/9pfs/9p-synth.c | 200 ++++++++++++++++++++++++++--------------------------
1 file changed, 100 insertions(+), 100 deletions(-)
diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c
index 73c8be816bbb..4b6d4e6a3f1c 100644
--- a/hw/9pfs/9p-synth.c
+++ b/hw/9pfs/9p-synth.c
@@ -21,19 +21,19 @@
#include "qemu/cutils.h"
/* Root node for synth file system */
-static V9fsSynthNode v9fs_synth_root = {
+static V9fsSynthNode synth_root = {
.name = "/",
.actual_attr = {
.mode = 0555 | S_IFDIR,
.nlink = 1,
},
- .attr = &v9fs_synth_root.actual_attr,
+ .attr = &synth_root.actual_attr,
};
-static QemuMutex v9fs_synth_mutex;
-static int v9fs_synth_node_count;
+static QemuMutex synth_mutex;
+static int synth_node_count;
/* set to 1 when the synth fs is ready */
-static int v9fs_synth_fs;
+static int synth_fs;
static V9fsSynthNode *v9fs_add_dir_node(V9fsSynthNode *parent, int mode,
const char *name,
@@ -69,16 +69,16 @@ int qemu_v9fs_synth_mkdir(V9fsSynthNode *parent, int mode,
int ret;
V9fsSynthNode *node, *tmp;
- if (!v9fs_synth_fs) {
+ if (!synth_fs) {
return EAGAIN;
}
if (!name || (strlen(name) >= NAME_MAX)) {
return EINVAL;
}
if (!parent) {
- parent = &v9fs_synth_root;
+ parent = &synth_root;
}
- qemu_mutex_lock(&v9fs_synth_mutex);
+ qemu_mutex_lock(&synth_mutex);
QLIST_FOREACH(tmp, &parent->child, sibling) {
if (!strcmp(tmp->name, name)) {
ret = EEXIST;
@@ -86,7 +86,7 @@ int qemu_v9fs_synth_mkdir(V9fsSynthNode *parent, int mode,
}
}
/* Add the name */
- node = v9fs_add_dir_node(parent, mode, name, NULL, v9fs_synth_node_count++);
+ node = v9fs_add_dir_node(parent, mode, name, NULL, synth_node_count++);
v9fs_add_dir_node(node, parent->attr->mode, "..",
parent->attr, parent->attr->inode);
v9fs_add_dir_node(node, node->attr->mode, ".",
@@ -94,7 +94,7 @@ int qemu_v9fs_synth_mkdir(V9fsSynthNode *parent, int mode,
*result = node;
ret = 0;
err_out:
- qemu_mutex_unlock(&v9fs_synth_mutex);
+ qemu_mutex_unlock(&synth_mutex);
return ret;
}
@@ -105,17 +105,17 @@ int qemu_v9fs_synth_add_file(V9fsSynthNode *parent, int mode,
int ret;
V9fsSynthNode *node, *tmp;
- if (!v9fs_synth_fs) {
+ if (!synth_fs) {
return EAGAIN;
}
if (!name || (strlen(name) >= NAME_MAX)) {
return EINVAL;
}
if (!parent) {
- parent = &v9fs_synth_root;
+ parent = &synth_root;
}
- qemu_mutex_lock(&v9fs_synth_mutex);
+ qemu_mutex_lock(&synth_mutex);
QLIST_FOREACH(tmp, &parent->child, sibling) {
if (!strcmp(tmp->name, name)) {
ret = EEXIST;
@@ -126,7 +126,7 @@ int qemu_v9fs_synth_add_file(V9fsSynthNode *parent, int mode,
mode = ((mode & 0777) | S_IFREG);
node = g_malloc0(sizeof(V9fsSynthNode));
node->attr = &node->actual_attr;
- node->attr->inode = v9fs_synth_node_count++;
+ node->attr->inode = synth_node_count++;
node->attr->nlink = 1;
node->attr->read = read;
node->attr->write = write;
@@ -136,11 +136,11 @@ int qemu_v9fs_synth_add_file(V9fsSynthNode *parent, int mode,
QLIST_INSERT_HEAD_RCU(&parent->child, node, sibling);
ret = 0;
err_out:
- qemu_mutex_unlock(&v9fs_synth_mutex);
+ qemu_mutex_unlock(&synth_mutex);
return ret;
}
-static void v9fs_synth_fill_statbuf(V9fsSynthNode *node, struct stat *stbuf)
+static void synth_fill_statbuf(V9fsSynthNode *node, struct stat *stbuf)
{
stbuf->st_dev = 0;
stbuf->st_ino = node->attr->inode;
@@ -157,24 +157,24 @@ static void v9fs_synth_fill_statbuf(V9fsSynthNode *node, struct stat *stbuf)
stbuf->st_ctime = 0;
}
-static int v9fs_synth_lstat(FsContext *fs_ctx,
+static int synth_lstat(FsContext *fs_ctx,
V9fsPath *fs_path, struct stat *stbuf)
{
V9fsSynthNode *node = *(V9fsSynthNode **)fs_path->data;
- v9fs_synth_fill_statbuf(node, stbuf);
+ synth_fill_statbuf(node, stbuf);
return 0;
}
-static int v9fs_synth_fstat(FsContext *fs_ctx, int fid_type,
+static int synth_fstat(FsContext *fs_ctx, int fid_type,
V9fsFidOpenState *fs, struct stat *stbuf)
{
V9fsSynthOpenState *synth_open = fs->private;
- v9fs_synth_fill_statbuf(synth_open->node, stbuf);
+ synth_fill_statbuf(synth_open->node, stbuf);
return 0;
}
-static int v9fs_synth_opendir(FsContext *ctx,
+static int synth_opendir(FsContext *ctx,
V9fsPath *fs_path, V9fsFidOpenState *fs)
{
V9fsSynthOpenState *synth_open;
@@ -187,7 +187,7 @@ static int v9fs_synth_opendir(FsContext *ctx,
return 0;
}
-static int v9fs_synth_closedir(FsContext *ctx, V9fsFidOpenState *fs)
+static int synth_closedir(FsContext *ctx, V9fsFidOpenState *fs)
{
V9fsSynthOpenState *synth_open = fs->private;
V9fsSynthNode *node = synth_open->node;
@@ -198,24 +198,24 @@ static int v9fs_synth_closedir(FsContext *ctx, V9fsFidOpenState *fs)
return 0;
}
-static off_t v9fs_synth_telldir(FsContext *ctx, V9fsFidOpenState *fs)
+static off_t synth_telldir(FsContext *ctx, V9fsFidOpenState *fs)
{
V9fsSynthOpenState *synth_open = fs->private;
return synth_open->offset;
}
-static void v9fs_synth_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
+static void synth_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
{
V9fsSynthOpenState *synth_open = fs->private;
synth_open->offset = off;
}
-static void v9fs_synth_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
+static void synth_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
{
- v9fs_synth_seekdir(ctx, fs, 0);
+ synth_seekdir(ctx, fs, 0);
}
-static void v9fs_synth_direntry(V9fsSynthNode *node,
+static void synth_direntry(V9fsSynthNode *node,
struct dirent *entry, off_t off)
{
strcpy(entry->d_name, node->name);
@@ -223,7 +223,7 @@ static void v9fs_synth_direntry(V9fsSynthNode *node,
entry->d_off = off + 1;
}
-static struct dirent *v9fs_synth_get_dentry(V9fsSynthNode *dir,
+static struct dirent *synth_get_dentry(V9fsSynthNode *dir,
struct dirent *entry, off_t off)
{
int i = 0;
@@ -242,23 +242,23 @@ static struct dirent *v9fs_synth_get_dentry(V9fsSynthNode *dir,
/* end of directory */
return NULL;
}
- v9fs_synth_direntry(node, entry, off);
+ synth_direntry(node, entry, off);
return entry;
}
-static struct dirent *v9fs_synth_readdir(FsContext *ctx, V9fsFidOpenState *fs)
+static struct dirent *synth_readdir(FsContext *ctx, V9fsFidOpenState *fs)
{
struct dirent *entry;
V9fsSynthOpenState *synth_open = fs->private;
V9fsSynthNode *node = synth_open->node;
- entry = v9fs_synth_get_dentry(node, &synth_open->dent, synth_open->offset);
+ entry = synth_get_dentry(node, &synth_open->dent, synth_open->offset);
if (entry) {
synth_open->offset++;
}
return entry;
}
-static int v9fs_synth_open(FsContext *ctx, V9fsPath *fs_path,
+static int synth_open(FsContext *ctx, V9fsPath *fs_path,
int flags, V9fsFidOpenState *fs)
{
V9fsSynthOpenState *synth_open;
@@ -271,7 +271,7 @@ static int v9fs_synth_open(FsContext *ctx, V9fsPath *fs_path,
return 0;
}
-static int v9fs_synth_open2(FsContext *fs_ctx, V9fsPath *dir_path,
+static int synth_open2(FsContext *fs_ctx, V9fsPath *dir_path,
const char *name, int flags,
FsCred *credp, V9fsFidOpenState *fs)
{
@@ -279,7 +279,7 @@ static int v9fs_synth_open2(FsContext *fs_ctx, V9fsPath *dir_path,
return -1;
}
-static int v9fs_synth_close(FsContext *ctx, V9fsFidOpenState *fs)
+static int synth_close(FsContext *ctx, V9fsFidOpenState *fs)
{
V9fsSynthOpenState *synth_open = fs->private;
V9fsSynthNode *node = synth_open->node;
@@ -290,7 +290,7 @@ static int v9fs_synth_close(FsContext *ctx, V9fsFidOpenState *fs)
return 0;
}
-static ssize_t v9fs_synth_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
+static ssize_t synth_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
const struct iovec *iov,
int iovcnt, off_t offset)
{
@@ -314,7 +314,7 @@ static ssize_t v9fs_synth_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
return count;
}
-static ssize_t v9fs_synth_preadv(FsContext *ctx, V9fsFidOpenState *fs,
+static ssize_t synth_preadv(FsContext *ctx, V9fsFidOpenState *fs,
const struct iovec *iov,
int iovcnt, off_t offset)
{
@@ -338,112 +338,112 @@ static ssize_t v9fs_synth_preadv(FsContext *ctx, V9fsFidOpenState *fs,
return count;
}
-static int v9fs_synth_truncate(FsContext *ctx, V9fsPath *path, off_t offset)
+static int synth_truncate(FsContext *ctx, V9fsPath *path, off_t offset)
{
errno = ENOSYS;
return -1;
}
-static int v9fs_synth_chmod(FsContext *fs_ctx, V9fsPath *path, FsCred *credp)
+static int synth_chmod(FsContext *fs_ctx, V9fsPath *path, FsCred *credp)
{
errno = EPERM;
return -1;
}
-static int v9fs_synth_mknod(FsContext *fs_ctx, V9fsPath *path,
+static int synth_mknod(FsContext *fs_ctx, V9fsPath *path,
const char *buf, FsCred *credp)
{
errno = EPERM;
return -1;
}
-static int v9fs_synth_mkdir(FsContext *fs_ctx, V9fsPath *path,
+static int synth_mkdir(FsContext *fs_ctx, V9fsPath *path,
const char *buf, FsCred *credp)
{
errno = EPERM;
return -1;
}
-static ssize_t v9fs_synth_readlink(FsContext *fs_ctx, V9fsPath *path,
+static ssize_t synth_readlink(FsContext *fs_ctx, V9fsPath *path,
char *buf, size_t bufsz)
{
errno = ENOSYS;
return -1;
}
-static int v9fs_synth_symlink(FsContext *fs_ctx, const char *oldpath,
+static int synth_symlink(FsContext *fs_ctx, const char *oldpath,
V9fsPath *newpath, const char *buf, FsCred *credp)
{
errno = EPERM;
return -1;
}
-static int v9fs_synth_link(FsContext *fs_ctx, V9fsPath *oldpath,
+static int synth_link(FsContext *fs_ctx, V9fsPath *oldpath,
V9fsPath *newpath, const char *buf)
{
errno = EPERM;
return -1;
}
-static int v9fs_synth_rename(FsContext *ctx, const char *oldpath,
+static int synth_rename(FsContext *ctx, const char *oldpath,
const char *newpath)
{
errno = EPERM;
return -1;
}
-static int v9fs_synth_chown(FsContext *fs_ctx, V9fsPath *path, FsCred *credp)
+static int synth_chown(FsContext *fs_ctx, V9fsPath *path, FsCred *credp)
{
errno = EPERM;
return -1;
}
-static int v9fs_synth_utimensat(FsContext *fs_ctx, V9fsPath *path,
+static int synth_utimensat(FsContext *fs_ctx, V9fsPath *path,
const struct timespec *buf)
{
errno = EPERM;
return 0;
}
-static int v9fs_synth_remove(FsContext *ctx, const char *path)
+static int synth_remove(FsContext *ctx, const char *path)
{
errno = EPERM;
return -1;
}
-static int v9fs_synth_fsync(FsContext *ctx, int fid_type,
+static int synth_fsync(FsContext *ctx, int fid_type,
V9fsFidOpenState *fs, int datasync)
{
errno = ENOSYS;
return 0;
}
-static int v9fs_synth_statfs(FsContext *s, V9fsPath *fs_path,
+static int synth_statfs(FsContext *s, V9fsPath *fs_path,
struct statfs *stbuf)
{
stbuf->f_type = 0xABCD;
stbuf->f_bsize = 512;
stbuf->f_blocks = 0;
- stbuf->f_files = v9fs_synth_node_count;
+ stbuf->f_files = synth_node_count;
stbuf->f_namelen = NAME_MAX;
return 0;
}
-static ssize_t v9fs_synth_lgetxattr(FsContext *ctx, V9fsPath *path,
+static ssize_t synth_lgetxattr(FsContext *ctx, V9fsPath *path,
const char *name, void *value, size_t size)
{
errno = ENOTSUP;
return -1;
}
-static ssize_t v9fs_synth_llistxattr(FsContext *ctx, V9fsPath *path,
+static ssize_t synth_llistxattr(FsContext *ctx, V9fsPath *path,
void *value, size_t size)
{
errno = ENOTSUP;
return -1;
}
-static int v9fs_synth_lsetxattr(FsContext *ctx, V9fsPath *path,
+static int synth_lsetxattr(FsContext *ctx, V9fsPath *path,
const char *name, void *value,
size_t size, int flags)
{
@@ -451,14 +451,14 @@ static int v9fs_synth_lsetxattr(FsContext *ctx, V9fsPath *path,
return -1;
}
-static int v9fs_synth_lremovexattr(FsContext *ctx,
+static int synth_lremovexattr(FsContext *ctx,
V9fsPath *path, const char *name)
{
errno = ENOTSUP;
return -1;
}
-static int v9fs_synth_name_to_path(FsContext *ctx, V9fsPath *dir_path,
+static int synth_name_to_path(FsContext *ctx, V9fsPath *dir_path,
const char *name, V9fsPath *target)
{
V9fsSynthNode *node;
@@ -471,7 +471,7 @@ static int v9fs_synth_name_to_path(FsContext *ctx, V9fsPath *dir_path,
}
if (!dir_path) {
- dir_node = &v9fs_synth_root;
+ dir_node = &synth_root;
} else {
dir_node = *(V9fsSynthNode **)dir_path->data;
}
@@ -500,7 +500,7 @@ out:
return 0;
}
-static int v9fs_synth_renameat(FsContext *ctx, V9fsPath *olddir,
+static int synth_renameat(FsContext *ctx, V9fsPath *olddir,
const char *old_name, V9fsPath *newdir,
const char *new_name)
{
@@ -508,62 +508,62 @@ static int v9fs_synth_renameat(FsContext *ctx, V9fsPath *olddir,
return -1;
}
-static int v9fs_synth_unlinkat(FsContext *ctx, V9fsPath *dir,
+static int synth_unlinkat(FsContext *ctx, V9fsPath *dir,
const char *name, int flags)
{
errno = EPERM;
return -1;
}
-static int v9fs_synth_init(FsContext *ctx)
+static int synth_init(FsContext *ctx)
{
- QLIST_INIT(&v9fs_synth_root.child);
- qemu_mutex_init(&v9fs_synth_mutex);
+ QLIST_INIT(&synth_root.child);
+ qemu_mutex_init(&synth_mutex);
/* Add "." and ".." entries for root */
- v9fs_add_dir_node(&v9fs_synth_root, v9fs_synth_root.attr->mode,
- "..", v9fs_synth_root.attr, v9fs_synth_root.attr->inode);
- v9fs_add_dir_node(&v9fs_synth_root, v9fs_synth_root.attr->mode,
- ".", v9fs_synth_root.attr, v9fs_synth_root.attr->inode);
+ v9fs_add_dir_node(&synth_root, synth_root.attr->mode,
+ "..", synth_root.attr, synth_root.attr->inode);
+ v9fs_add_dir_node(&synth_root, synth_root.attr->mode,
+ ".", synth_root.attr, synth_root.attr->inode);
/* Mark the subsystem is ready for use */
- v9fs_synth_fs = 1;
+ synth_fs = 1;
return 0;
}
FileOperations synth_ops = {
- .init = v9fs_synth_init,
- .lstat = v9fs_synth_lstat,
- .readlink = v9fs_synth_readlink,
- .close = v9fs_synth_close,
- .closedir = v9fs_synth_closedir,
- .open = v9fs_synth_open,
- .opendir = v9fs_synth_opendir,
- .rewinddir = v9fs_synth_rewinddir,
- .telldir = v9fs_synth_telldir,
- .readdir = v9fs_synth_readdir,
- .seekdir = v9fs_synth_seekdir,
- .preadv = v9fs_synth_preadv,
- .pwritev = v9fs_synth_pwritev,
- .chmod = v9fs_synth_chmod,
- .mknod = v9fs_synth_mknod,
- .mkdir = v9fs_synth_mkdir,
- .fstat = v9fs_synth_fstat,
- .open2 = v9fs_synth_open2,
- .symlink = v9fs_synth_symlink,
- .link = v9fs_synth_link,
- .truncate = v9fs_synth_truncate,
- .rename = v9fs_synth_rename,
- .chown = v9fs_synth_chown,
- .utimensat = v9fs_synth_utimensat,
- .remove = v9fs_synth_remove,
- .fsync = v9fs_synth_fsync,
- .statfs = v9fs_synth_statfs,
- .lgetxattr = v9fs_synth_lgetxattr,
- .llistxattr = v9fs_synth_llistxattr,
- .lsetxattr = v9fs_synth_lsetxattr,
- .lremovexattr = v9fs_synth_lremovexattr,
- .name_to_path = v9fs_synth_name_to_path,
- .renameat = v9fs_synth_renameat,
- .unlinkat = v9fs_synth_unlinkat,
+ .init = synth_init,
+ .lstat = synth_lstat,
+ .readlink = synth_readlink,
+ .close = synth_close,
+ .closedir = synth_closedir,
+ .open = synth_open,
+ .opendir = synth_opendir,
+ .rewinddir = synth_rewinddir,
+ .telldir = synth_telldir,
+ .readdir = synth_readdir,
+ .seekdir = synth_seekdir,
+ .preadv = synth_preadv,
+ .pwritev = synth_pwritev,
+ .chmod = synth_chmod,
+ .mknod = synth_mknod,
+ .mkdir = synth_mkdir,
+ .fstat = synth_fstat,
+ .open2 = synth_open2,
+ .symlink = synth_symlink,
+ .link = synth_link,
+ .truncate = synth_truncate,
+ .rename = synth_rename,
+ .chown = synth_chown,
+ .utimensat = synth_utimensat,
+ .remove = synth_remove,
+ .fsync = synth_fsync,
+ .statfs = synth_statfs,
+ .lgetxattr = synth_lgetxattr,
+ .llistxattr = synth_llistxattr,
+ .lsetxattr = synth_lsetxattr,
+ .lremovexattr = synth_lremovexattr,
+ .name_to_path = synth_name_to_path,
+ .renameat = synth_renameat,
+ .unlinkat = synth_unlinkat,
};
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] [PATCH 02/13] 9p: factour out duplicate code from local_fstat() and local_lstat()
2016-06-27 9:40 [Qemu-devel] [PATCH 00/13] 9p: reconcile virtfs with unlinked files Greg Kurz
2016-06-27 9:41 ` [Qemu-devel] [PATCH 01/13] 9p: synth: drop v9fs_ prefix Greg Kurz
@ 2016-06-27 9:41 ` Greg Kurz
2016-06-27 9:41 ` [Qemu-devel] [PATCH 03/13] 9p: introduce the v9fs_get_fd_fid() helper Greg Kurz
` (11 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Greg Kurz @ 2016-06-27 9:41 UTC (permalink / raw)
To: qemu-devel
Cc: Eric Van Hensbergen, v9fs-developer, Aneesh Kumar K.V, Greg Kurz
This does not change functionality.
Signed-off-by: Greg Kurz <groug@kaod.org>
---
hw/9pfs/9p-local.c | 68 +++++++++++++++++++++++++++-------------------------
1 file changed, 35 insertions(+), 33 deletions(-)
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index 3f271fcbd2c5..b363711fe2f0 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -117,36 +117,55 @@ static void local_mapped_file_attr(FsContext *ctx, const char *path,
fclose(fp);
}
-static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
+static int local_do_getxattr(int fd, const char *path,
+ const char *name, void *value, size_t size)
{
- int err;
- char *buffer;
- char *path = fs_path->data;
-
- buffer = rpath(fs_ctx, path);
- err = lstat(buffer, stbuf);
- if (err) {
- goto err_out;
+ if (path) {
+ return getxattr(path, name, value, size);
+ } else {
+ return fgetxattr(fd, name, value, size);
}
- if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
+}
+
+static void local_mapped_attr(int fd, char *path, struct stat *stbuf)
+{
/* Actual credentials are part of extended attrs */
uid_t tmp_uid;
gid_t tmp_gid;
mode_t tmp_mode;
dev_t tmp_dev;
- if (getxattr(buffer, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) {
+
+ if (local_do_getxattr(fd, path, "user.virtfs.uid", &tmp_uid,
+ sizeof(uid_t)) > 0) {
stbuf->st_uid = le32_to_cpu(tmp_uid);
}
- if (getxattr(buffer, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) {
+ if (local_do_getxattr(fd, path, "user.virtfs.gid", &tmp_gid,
+ sizeof(gid_t)) > 0) {
stbuf->st_gid = le32_to_cpu(tmp_gid);
}
- if (getxattr(buffer, "user.virtfs.mode",
- &tmp_mode, sizeof(mode_t)) > 0) {
+ if (local_do_getxattr(fd, path, "user.virtfs.mode", &tmp_mode,
+ sizeof(mode_t)) > 0) {
stbuf->st_mode = le32_to_cpu(tmp_mode);
}
- if (getxattr(buffer, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) {
+ if (local_do_getxattr(fd, path, "user.virtfs.rdev", &tmp_dev,
+ sizeof(dev_t)) > 0) {
stbuf->st_rdev = le64_to_cpu(tmp_dev);
}
+}
+
+static int local_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
+{
+ int err;
+ char *buffer;
+ char *path = fs_path->data;
+
+ buffer = rpath(fs_ctx, path);
+ err = lstat(buffer, stbuf);
+ if (err) {
+ goto err_out;
+ }
+ if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
+ local_mapped_attr(-1, buffer, stbuf);
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
local_mapped_file_attr(fs_ctx, path, stbuf);
}
@@ -622,24 +641,7 @@ static int local_fstat(FsContext *fs_ctx, int fid_type,
return err;
}
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
- /* Actual credentials are part of extended attrs */
- uid_t tmp_uid;
- gid_t tmp_gid;
- mode_t tmp_mode;
- dev_t tmp_dev;
-
- if (fgetxattr(fd, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) {
- stbuf->st_uid = le32_to_cpu(tmp_uid);
- }
- if (fgetxattr(fd, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) {
- stbuf->st_gid = le32_to_cpu(tmp_gid);
- }
- if (fgetxattr(fd, "user.virtfs.mode", &tmp_mode, sizeof(mode_t)) > 0) {
- stbuf->st_mode = le32_to_cpu(tmp_mode);
- }
- if (fgetxattr(fd, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) {
- stbuf->st_rdev = le64_to_cpu(tmp_dev);
- }
+ local_mapped_attr(fd, NULL, stbuf);
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
errno = EOPNOTSUPP;
return -1;
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] [PATCH 03/13] 9p: introduce the v9fs_get_fd_fid() helper
2016-06-27 9:40 [Qemu-devel] [PATCH 00/13] 9p: reconcile virtfs with unlinked files Greg Kurz
2016-06-27 9:41 ` [Qemu-devel] [PATCH 01/13] 9p: synth: drop v9fs_ prefix Greg Kurz
2016-06-27 9:41 ` [Qemu-devel] [PATCH 02/13] 9p: factour out duplicate code from local_fstat() and local_lstat() Greg Kurz
@ 2016-06-27 9:41 ` Greg Kurz
2016-06-27 9:41 ` [Qemu-devel] [PATCH 04/13] 9p: getattr: use fstat if we have a fd Greg Kurz
` (10 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Greg Kurz @ 2016-06-27 9:41 UTC (permalink / raw)
To: qemu-devel
Cc: Eric Van Hensbergen, v9fs-developer, Aneesh Kumar K.V, Greg Kurz
This will be used by all file descriptor based ops.
Signed-off-by: Greg Kurz <groug@kaod.org>
---
hw/9pfs/9p-handle.c | 12 ++----------
hw/9pfs/9p-local.c | 12 ++----------
hw/9pfs/9p-proxy.c | 12 ++----------
hw/9pfs/9p.c | 13 +++++++++++++
hw/9pfs/9p.h | 2 ++
5 files changed, 21 insertions(+), 30 deletions(-)
diff --git a/hw/9pfs/9p-handle.c b/hw/9pfs/9p-handle.c
index 3d77594f9245..2e741535df24 100644
--- a/hw/9pfs/9p-handle.c
+++ b/hw/9pfs/9p-handle.c
@@ -259,11 +259,7 @@ static int handle_fstat(FsContext *fs_ctx, int fid_type,
{
int fd;
- if (fid_type == P9_FID_DIR) {
- fd = dirfd(fs->dir.stream);
- } else {
- fd = fs->fd;
- }
+ fd = v9fs_get_fd_fid(fid_type, fs);
return fstat(fd, stbuf);
}
@@ -406,11 +402,7 @@ static int handle_fsync(FsContext *ctx, int fid_type,
{
int fd;
- if (fid_type == P9_FID_DIR) {
- fd = dirfd(fs->dir.stream);
- } else {
- fd = fs->fd;
- }
+ fd = v9fs_get_fd_fid(fid_type, fs);
if (datasync) {
return qemu_fdatasync(fd);
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index b363711fe2f0..6804c6558b8e 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -630,11 +630,7 @@ static int local_fstat(FsContext *fs_ctx, int fid_type,
{
int err, fd;
- if (fid_type == P9_FID_DIR) {
- fd = dirfd(fs->dir.stream);
- } else {
- fd = fs->fd;
- }
+ fd = v9fs_get_fd_fid(fid_type, fs);
err = fstat(fd, stbuf);
if (err) {
@@ -1001,11 +997,7 @@ static int local_fsync(FsContext *ctx, int fid_type,
{
int fd;
- if (fid_type == P9_FID_DIR) {
- fd = dirfd(fs->dir.stream);
- } else {
- fd = fs->fd;
- }
+ fd = v9fs_get_fd_fid(fid_type, fs);
if (datasync) {
return qemu_fdatasync(fd);
diff --git a/hw/9pfs/9p-proxy.c b/hw/9pfs/9p-proxy.c
index f265501eac1d..d78ff7b1bd8d 100644
--- a/hw/9pfs/9p-proxy.c
+++ b/hw/9pfs/9p-proxy.c
@@ -788,11 +788,7 @@ static int proxy_fstat(FsContext *fs_ctx, int fid_type,
{
int fd;
- if (fid_type == P9_FID_DIR) {
- fd = dirfd(fs->dir.stream);
- } else {
- fd = fs->fd;
- }
+ fd = v9fs_get_fd_fid(fid_type, fs);
return fstat(fd, stbuf);
}
@@ -933,11 +929,7 @@ static int proxy_fsync(FsContext *ctx, int fid_type,
{
int fd;
- if (fid_type == P9_FID_DIR) {
- fd = dirfd(fs->dir.stream);
- } else {
- fd = fs->fd;
- }
+ fd = v9fs_get_fd_fid(fid_type, fs);
if (datasync) {
return qemu_fdatasync(fd);
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 9acff9293c60..626d4aa8ebb6 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -240,6 +240,19 @@ static int v9fs_reopen_fid(V9fsPDU *pdu, V9fsFidState *f)
return err;
}
+int v9fs_get_fd_fid(int fid_type, V9fsFidOpenState *fs)
+{
+ int fd = -1;
+
+ if (fid_type == P9_FID_DIR) {
+ fd = dirfd(fs->dir.stream);
+ } else if (fid_type == P9_FID_FILE) {
+ fd = fs->fd;
+ }
+
+ return fd;
+}
+
static V9fsFidState *get_fid(V9fsPDU *pdu, int32_t fid)
{
int err;
diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h
index d2030fdf56e9..d0ccc0089771 100644
--- a/hw/9pfs/9p.h
+++ b/hw/9pfs/9p.h
@@ -202,6 +202,8 @@ union V9fsFidOpenState {
void *private;
};
+extern int v9fs_get_fd_fid(int fid_type, V9fsFidOpenState *fs);
+
struct V9fsFidState
{
int fid_type;
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] [PATCH 04/13] 9p: getattr: use fstat if we have a fd
2016-06-27 9:40 [Qemu-devel] [PATCH 00/13] 9p: reconcile virtfs with unlinked files Greg Kurz
` (2 preceding siblings ...)
2016-06-27 9:41 ` [Qemu-devel] [PATCH 03/13] 9p: introduce the v9fs_get_fd_fid() helper Greg Kurz
@ 2016-06-27 9:41 ` Greg Kurz
2016-06-27 9:41 ` [Qemu-devel] [PATCH 05/13] 9p: introduce ftruncate file op Greg Kurz
` (9 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Greg Kurz @ 2016-06-27 9:41 UTC (permalink / raw)
To: qemu-devel
Cc: Eric Van Hensbergen, v9fs-developer, Aneesh Kumar K.V, Greg Kurz
If we have an opened fd, it is better to call fstat() as the underlying
file may have been unlinked and lstat() will fail.
The fid_has_file() helper will be used by other file descriptor based ops.
Signed-off-by: Greg Kurz <groug@kaod.org>
---
hw/9pfs/9p.c | 36 +++++++++++++++++++++++++++++++++---
1 file changed, 33 insertions(+), 3 deletions(-)
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 626d4aa8ebb6..3301cef0980d 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -253,6 +253,23 @@ int v9fs_get_fd_fid(int fid_type, V9fsFidOpenState *fs)
return fd;
}
+static bool fid_has_file(V9fsFidState *fidp)
+{
+ int fid_type = fidp->fid_type;
+
+ if (fid_type == P9_FID_DIR) {
+ if (fidp->fs.dir.stream) {
+ return true;
+ }
+ } else if (fid_type == P9_FID_FILE) {
+ if (fidp->fs.fd > -1) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
static V9fsFidState *get_fid(V9fsPDU *pdu, int32_t fid)
{
int err;
@@ -1044,6 +1061,19 @@ out_nofid:
v9fs_string_free(&aname);
}
+static int v9fs_do_stat(V9fsPDU *pdu, V9fsFidState *fidp, struct stat *stbuf)
+{
+ int retval;
+
+ if (fid_has_file(fidp)) {
+ retval = v9fs_co_fstat(pdu, fidp, stbuf);
+ } else {
+ retval = v9fs_co_lstat(pdu, &fidp->path, stbuf);
+ }
+
+ return retval;
+}
+
static void v9fs_stat(void *opaque)
{
int32_t fid;
@@ -1065,7 +1095,7 @@ static void v9fs_stat(void *opaque)
err = -ENOENT;
goto out_nofid;
}
- err = v9fs_co_lstat(pdu, &fidp->path, &stbuf);
+ err = v9fs_do_stat(pdu, fidp, &stbuf);
if (err < 0) {
goto out;
}
@@ -1115,7 +1145,7 @@ static void v9fs_getattr(void *opaque)
* Currently we only support BASIC fields in stat, so there is no
* need to look at request_mask.
*/
- retval = v9fs_co_lstat(pdu, &fidp->path, &stbuf);
+ retval = v9fs_do_stat(pdu, fidp, &stbuf);
if (retval < 0) {
goto out;
}
@@ -2674,7 +2704,7 @@ static void v9fs_wstat(void *opaque)
}
if (v9stat.mode != -1) {
uint32_t v9_mode;
- err = v9fs_co_lstat(pdu, &fidp->path, &stbuf);
+ err = v9fs_do_stat(pdu, fidp, &stbuf);
if (err < 0) {
goto out;
}
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] [PATCH 05/13] 9p: introduce ftruncate file op
2016-06-27 9:40 [Qemu-devel] [PATCH 00/13] 9p: reconcile virtfs with unlinked files Greg Kurz
` (3 preceding siblings ...)
2016-06-27 9:41 ` [Qemu-devel] [PATCH 04/13] 9p: getattr: use fstat if we have a fd Greg Kurz
@ 2016-06-27 9:41 ` Greg Kurz
2016-06-27 9:41 ` [Qemu-devel] [PATCH 06/13] oslib: support futimens() if available Greg Kurz
` (8 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Greg Kurz @ 2016-06-27 9:41 UTC (permalink / raw)
To: qemu-devel
Cc: Eric Van Hensbergen, v9fs-developer, Aneesh Kumar K.V, Greg Kurz
This patch adds a ftruncate operation to the fsdev API. It is then used if
we have an open fd, so that ftruncate() in the guest is functional even
if the file was unlinked or its file permissions would cause truncate() to
fail.
Signed-off-by: Greg Kurz <groug@kaod.org>
---
fsdev/file-op-9p.h | 1 +
hw/9pfs/9p-handle.c | 15 +++++++++++++++
hw/9pfs/9p-local.c | 15 +++++++++++++++
hw/9pfs/9p-proxy.c | 14 ++++++++++++++
hw/9pfs/9p-synth.c | 8 ++++++++
hw/9pfs/9p.c | 17 +++++++++++++++--
hw/9pfs/cofs.c | 18 ++++++++++++++++++
hw/9pfs/coth.h | 1 +
8 files changed, 87 insertions(+), 2 deletions(-)
diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index 55614949740d..930bcc623f8b 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -140,6 +140,7 @@ struct FileOperations
int (*renameat)(FsContext *ctx, V9fsPath *olddir, const char *old_name,
V9fsPath *newdir, const char *new_name);
int (*unlinkat)(FsContext *ctx, V9fsPath *dir, const char *name, int flags);
+ int (*ftruncate)(FsContext *, int, V9fsFidOpenState *, off_t);
void *opaque;
};
diff --git a/hw/9pfs/9p-handle.c b/hw/9pfs/9p-handle.c
index 2e741535df24..e48e48a7145d 100644
--- a/hw/9pfs/9p-handle.c
+++ b/hw/9pfs/9p-handle.c
@@ -349,6 +349,20 @@ static int handle_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
return ret;
}
+static int handle_ftruncate(FsContext *ctx, int fid_type, V9fsFidOpenState *fs,
+ off_t size)
+{
+ int fd;
+
+ if (fid_type == P9_FID_DIR) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ fd = v9fs_get_fd_fid(fid_type, fs);
+ return ftruncate(fd, size);
+}
+
static int handle_rename(FsContext *ctx, const char *oldpath,
const char *newpath)
{
@@ -696,4 +710,5 @@ FileOperations handle_ops = {
.name_to_path = handle_name_to_path,
.renameat = handle_renameat,
.unlinkat = handle_unlinkat,
+ .ftruncate = handle_ftruncate,
};
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index 6804c6558b8e..b4c31c49da69 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -874,6 +874,20 @@ static int local_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
return ret;
}
+static int local_ftruncate(FsContext *ctx, int fid_type, V9fsFidOpenState *fs,
+ off_t size)
+{
+ int fd;
+
+ if (fid_type == P9_FID_DIR) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ fd = v9fs_get_fd_fid(fid_type, fs);
+ return ftruncate(fd, size);
+}
+
static int local_rename(FsContext *ctx, const char *oldpath,
const char *newpath)
{
@@ -1275,4 +1289,5 @@ FileOperations local_ops = {
.name_to_path = local_name_to_path,
.renameat = local_renameat,
.unlinkat = local_unlinkat,
+ .ftruncate = local_ftruncate,
};
diff --git a/hw/9pfs/9p-proxy.c b/hw/9pfs/9p-proxy.c
index d78ff7b1bd8d..9abcc201bd67 100644
--- a/hw/9pfs/9p-proxy.c
+++ b/hw/9pfs/9p-proxy.c
@@ -864,6 +864,19 @@ static int proxy_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
return 0;
}
+static int proxy_ftruncate(FsContext *ctx, int fid_type, V9fsFidOpenState *fs,
+ off_t size)
+{
+ int fd;
+
+ if (fid_type == P9_FID_DIR) {
+ return -EINVAL;
+ }
+
+ fd = v9fs_get_fd_fid(fid_type, fs);
+ return ftruncate(fd, size);
+}
+
static int proxy_rename(FsContext *ctx, const char *oldpath,
const char *newpath)
{
@@ -1207,4 +1220,5 @@ FileOperations proxy_ops = {
.name_to_path = proxy_name_to_path,
.renameat = proxy_renameat,
.unlinkat = proxy_unlinkat,
+ .ftruncate = proxy_ftruncate,
};
diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c
index 4b6d4e6a3f1c..70c71ce305c9 100644
--- a/hw/9pfs/9p-synth.c
+++ b/hw/9pfs/9p-synth.c
@@ -344,6 +344,13 @@ static int synth_truncate(FsContext *ctx, V9fsPath *path, off_t offset)
return -1;
}
+static int synth_ftruncate(FsContext *ctx, int fid_type, V9fsFidOpenState *fs,
+ off_t size)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
static int synth_chmod(FsContext *fs_ctx, V9fsPath *path, FsCred *credp)
{
errno = EPERM;
@@ -566,4 +573,5 @@ FileOperations synth_ops = {
.name_to_path = synth_name_to_path,
.renameat = synth_renameat,
.unlinkat = synth_unlinkat,
+ .ftruncate = synth_ftruncate,
};
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 3301cef0980d..3aa4c8e22ed9 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -1181,6 +1181,19 @@ out_nofid:
pdu_complete(pdu, retval);
}
+static int v9fs_do_truncate(V9fsPDU *pdu, V9fsFidState *fidp, off_t size)
+{
+ int err;
+
+ if (fid_has_file(fidp)) {
+ err = v9fs_co_ftruncate(pdu, fidp, size);
+ } else {
+ err = v9fs_co_truncate(pdu, &fidp->path, size);
+ }
+
+ return err;
+}
+
/* Attribute flags */
#define P9_ATTR_MODE (1 << 0)
#define P9_ATTR_UID (1 << 1)
@@ -1266,7 +1279,7 @@ static void v9fs_setattr(void *opaque)
}
}
if (v9iattr.valid & (P9_ATTR_SIZE)) {
- err = v9fs_co_truncate(pdu, &fidp->path, v9iattr.size);
+ err = v9fs_do_truncate(pdu, fidp, v9iattr.size);
if (err < 0) {
goto out;
}
@@ -2754,7 +2767,7 @@ static void v9fs_wstat(void *opaque)
}
}
if (v9stat.length != -1) {
- err = v9fs_co_truncate(pdu, &fidp->path, v9stat.length);
+ err = v9fs_do_truncate(pdu, fidp, v9stat.length);
if (err < 0) {
goto out;
}
diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c
index 70f584fcbd21..969c24730cb0 100644
--- a/hw/9pfs/cofs.c
+++ b/hw/9pfs/cofs.c
@@ -177,6 +177,24 @@ int v9fs_co_truncate(V9fsPDU *pdu, V9fsPath *path, off_t size)
return err;
}
+int v9fs_co_ftruncate(V9fsPDU *pdu, V9fsFidState *fidp, off_t size)
+{
+ int err;
+ V9fsState *s = pdu->s;
+
+ if (v9fs_request_cancelled(pdu)) {
+ return -EINTR;
+ }
+ v9fs_co_run_in_worker(
+ {
+ err = s->ops->ftruncate(&s->ctx, fidp->fid_type, &fidp->fs, size);
+ if (err < 0) {
+ err = -errno;
+ }
+ });
+ return err;
+}
+
int v9fs_co_mknod(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name, uid_t uid,
gid_t gid, dev_t dev, mode_t mode, struct stat *stbuf)
{
diff --git a/hw/9pfs/coth.h b/hw/9pfs/coth.h
index 5b02a63ad9fd..4f493ad29ec4 100644
--- a/hw/9pfs/coth.h
+++ b/hw/9pfs/coth.h
@@ -94,5 +94,6 @@ 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);
+extern int v9fs_co_ftruncate(V9fsPDU *, V9fsFidState *, off_t);
#endif
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] [PATCH 06/13] oslib: support futimens() if available
2016-06-27 9:40 [Qemu-devel] [PATCH 00/13] 9p: reconcile virtfs with unlinked files Greg Kurz
` (4 preceding siblings ...)
2016-06-27 9:41 ` [Qemu-devel] [PATCH 05/13] 9p: introduce ftruncate file op Greg Kurz
@ 2016-06-27 9:41 ` Greg Kurz
2016-06-27 9:41 ` [Qemu-devel] [PATCH 07/13] 9p: introduce futimens file op Greg Kurz
` (7 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Greg Kurz @ 2016-06-27 9:41 UTC (permalink / raw)
To: qemu-devel
Cc: Eric Van Hensbergen, v9fs-developer, Aneesh Kumar K.V, Greg Kurz
Signed-off-by: Greg Kurz <groug@kaod.org>
---
hw/9pfs/9p-handle.c | 7 +------
include/sysemu/os-posix.h | 1 +
util/oslib-posix.c | 10 ++++++++++
3 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/hw/9pfs/9p-handle.c b/hw/9pfs/9p-handle.c
index e48e48a7145d..197c2c7efbb5 100644
--- a/hw/9pfs/9p-handle.c
+++ b/hw/9pfs/9p-handle.c
@@ -388,7 +388,6 @@ static int handle_utimensat(FsContext *ctx, V9fsPath *fs_path,
const struct timespec *buf)
{
int ret;
-#ifdef CONFIG_UTIMENSAT
int fd;
struct handle_data *data = (struct handle_data *)ctx->private;
@@ -396,12 +395,8 @@ static int handle_utimensat(FsContext *ctx, V9fsPath *fs_path,
if (fd < 0) {
return fd;
}
- ret = futimens(fd, buf);
+ ret = qemu_futimens(fd, buf);
close(fd);
-#else
- ret = -1;
- errno = ENOSYS;
-#endif
return ret;
}
diff --git a/include/sysemu/os-posix.h b/include/sysemu/os-posix.h
index 9c7dfdfbec69..c2b2288bb3bf 100644
--- a/include/sysemu/os-posix.h
+++ b/include/sysemu/os-posix.h
@@ -57,6 +57,7 @@ typedef struct timeval qemu_timeval;
#endif
typedef struct timespec qemu_timespec;
int qemu_utimens(const char *path, const qemu_timespec *times);
+int qemu_futimens(int fd, const qemu_timespec *times);
bool is_daemonized(void);
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index e2e1d4d39f59..3c9de4ad1d71 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -187,6 +187,16 @@ int qemu_pipe(int pipefd[2])
return ret;
}
+int qemu_futimens(int fd, const struct timespec *times)
+{
+#ifdef CONFIG_UTIMENSAT
+ return futimens(fd, times);
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
int qemu_utimens(const char *path, const struct timespec *times)
{
struct timeval tv[2], tv_now;
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] [PATCH 07/13] 9p: introduce futimens file op
2016-06-27 9:40 [Qemu-devel] [PATCH 00/13] 9p: reconcile virtfs with unlinked files Greg Kurz
` (5 preceding siblings ...)
2016-06-27 9:41 ` [Qemu-devel] [PATCH 06/13] oslib: support futimens() if available Greg Kurz
@ 2016-06-27 9:41 ` Greg Kurz
2016-06-27 9:42 ` [Qemu-devel] [PATCH 08/13] 9p: add a fd argument to xattr helpers Greg Kurz
` (6 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Greg Kurz @ 2016-06-27 9:41 UTC (permalink / raw)
To: qemu-devel
Cc: Eric Van Hensbergen, v9fs-developer, Aneesh Kumar K.V, Greg Kurz
This allows futimens() in the guest to stay functional even if the file
was unlinked.
Signed-off-by: Greg Kurz <groug@kaod.org>
---
fsdev/file-op-9p.h | 2 ++
hw/9pfs/9p-handle.c | 10 ++++++++++
hw/9pfs/9p-local.c | 10 ++++++++++
hw/9pfs/9p-proxy.c | 10 ++++++++++
hw/9pfs/9p-synth.c | 8 ++++++++
hw/9pfs/9p.c | 18 ++++++++++++++++--
hw/9pfs/cofs.c | 18 ++++++++++++++++++
hw/9pfs/coth.h | 1 +
8 files changed, 75 insertions(+), 2 deletions(-)
diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index 930bcc623f8b..811ca234cf86 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -141,6 +141,8 @@ struct FileOperations
V9fsPath *newdir, const char *new_name);
int (*unlinkat)(FsContext *ctx, V9fsPath *dir, const char *name, int flags);
int (*ftruncate)(FsContext *, int, V9fsFidOpenState *, off_t);
+ int (*futimens)(FsContext *, int, V9fsFidOpenState *,
+ const struct timespec *);
void *opaque;
};
diff --git a/hw/9pfs/9p-handle.c b/hw/9pfs/9p-handle.c
index 197c2c7efbb5..382b4d57927a 100644
--- a/hw/9pfs/9p-handle.c
+++ b/hw/9pfs/9p-handle.c
@@ -400,6 +400,15 @@ static int handle_utimensat(FsContext *ctx, V9fsPath *fs_path,
return ret;
}
+static int handle_futimens(FsContext *s, int fid_type, V9fsFidOpenState *fs,
+ const struct timespec *buf)
+{
+ int fd;
+
+ fd = v9fs_get_fd_fid(fid_type, fs);
+ return qemu_futimens(fd, buf);
+}
+
static int handle_remove(FsContext *ctx, const char *path)
{
errno = EOPNOTSUPP;
@@ -706,4 +715,5 @@ FileOperations handle_ops = {
.renameat = handle_renameat,
.unlinkat = handle_unlinkat,
.ftruncate = handle_ftruncate,
+ .futimens = handle_futimens,
};
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index b4c31c49da69..46ac7aab7c47 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -953,6 +953,15 @@ static int local_utimensat(FsContext *s, V9fsPath *fs_path,
return ret;
}
+static int local_futimens(FsContext *s, int fid_type, V9fsFidOpenState *fs,
+ const struct timespec *buf)
+{
+ int fd;
+
+ fd = v9fs_get_fd_fid(fid_type, fs);
+ return qemu_futimens(fd, buf);
+}
+
static int local_remove(FsContext *ctx, const char *path)
{
int err;
@@ -1290,4 +1299,5 @@ FileOperations local_ops = {
.renameat = local_renameat,
.unlinkat = local_unlinkat,
.ftruncate = local_ftruncate,
+ .futimens = local_futimens,
};
diff --git a/hw/9pfs/9p-proxy.c b/hw/9pfs/9p-proxy.c
index 9abcc201bd67..cbc94b645852 100644
--- a/hw/9pfs/9p-proxy.c
+++ b/hw/9pfs/9p-proxy.c
@@ -923,6 +923,15 @@ static int proxy_utimensat(FsContext *s, V9fsPath *fs_path,
return retval;
}
+static int proxy_futimens(FsContext *s, int fid_type, V9fsFidOpenState *fs,
+ const struct timespec *buf)
+{
+ int fd;
+
+ fd = v9fs_get_fd_fid(fid_type, fs);
+ return qemu_futimens(fd, buf);
+}
+
static int proxy_remove(FsContext *ctx, const char *path)
{
int retval;
@@ -1221,4 +1230,5 @@ FileOperations proxy_ops = {
.renameat = proxy_renameat,
.unlinkat = proxy_unlinkat,
.ftruncate = proxy_ftruncate,
+ .futimens = proxy_futimens,
};
diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c
index 70c71ce305c9..c4770792a79f 100644
--- a/hw/9pfs/9p-synth.c
+++ b/hw/9pfs/9p-synth.c
@@ -412,6 +412,13 @@ static int synth_utimensat(FsContext *fs_ctx, V9fsPath *path,
return 0;
}
+static int synth_futimens(FsContext *fs_ctx, int fid_type, V9fsFidOpenState *fs,
+ const struct timespec *buf)
+{
+ errno = EPERM;
+ return -1;
+}
+
static int synth_remove(FsContext *ctx, const char *path)
{
errno = EPERM;
@@ -574,4 +581,5 @@ FileOperations synth_ops = {
.renameat = synth_renameat,
.unlinkat = synth_unlinkat,
.ftruncate = synth_ftruncate,
+ .futimens = synth_futimens,
};
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 3aa4c8e22ed9..97dba6190809 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -1194,6 +1194,20 @@ static int v9fs_do_truncate(V9fsPDU *pdu, V9fsFidState *fidp, off_t size)
return err;
}
+static int v9fs_do_utimens(V9fsPDU *pdu, V9fsFidState *fidp,
+ struct timespec times[2])
+{
+ int err;
+
+ if (fid_has_file(fidp)) {
+ err = v9fs_co_futimens(pdu, fidp, times);
+ } else {
+ err = v9fs_co_utimensat(pdu, &fidp->path, times);
+ }
+
+ return err;
+}
+
/* Attribute flags */
#define P9_ATTR_MODE (1 << 0)
#define P9_ATTR_UID (1 << 1)
@@ -1254,7 +1268,7 @@ static void v9fs_setattr(void *opaque)
} else {
times[1].tv_nsec = UTIME_OMIT;
}
- err = v9fs_co_utimensat(pdu, &fidp->path, times);
+ err = v9fs_do_utimens(pdu, fidp, times);
if (err < 0) {
goto out;
}
@@ -2749,7 +2763,7 @@ static void v9fs_wstat(void *opaque)
} else {
times[1].tv_nsec = UTIME_OMIT;
}
- err = v9fs_co_utimensat(pdu, &fidp->path, times);
+ err = v9fs_do_utimens(pdu, fidp, times);
if (err < 0) {
goto out;
}
diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c
index 969c24730cb0..1ed9c298f98d 100644
--- a/hw/9pfs/cofs.c
+++ b/hw/9pfs/cofs.c
@@ -133,6 +133,24 @@ int v9fs_co_utimensat(V9fsPDU *pdu, V9fsPath *path,
return err;
}
+int v9fs_co_futimens(V9fsPDU *pdu, V9fsFidState *fidp, struct timespec times[2])
+{
+ int err;
+ V9fsState *s = pdu->s;
+
+ if (v9fs_request_cancelled(pdu)) {
+ return -EINTR;
+ }
+ v9fs_co_run_in_worker(
+ {
+ err = s->ops->futimens(&s->ctx, fidp->fid_type, &fidp->fs, times);
+ if (err < 0) {
+ err = -errno;
+ }
+ });
+ return err;
+}
+
int v9fs_co_chown(V9fsPDU *pdu, V9fsPath *path, uid_t uid, gid_t gid)
{
int err;
diff --git a/hw/9pfs/coth.h b/hw/9pfs/coth.h
index 4f493ad29ec4..c4e90059f00c 100644
--- a/hw/9pfs/coth.h
+++ b/hw/9pfs/coth.h
@@ -95,5 +95,6 @@ extern int v9fs_co_name_to_path(V9fsPDU *, V9fsPath *,
extern int v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t,
V9fsStatDotl *v9stat);
extern int v9fs_co_ftruncate(V9fsPDU *, V9fsFidState *, off_t);
+extern int v9fs_co_futimens(V9fsPDU *, V9fsFidState *, struct timespec [2]);
#endif
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] [PATCH 08/13] 9p: add a fd argument to xattr helpers
2016-06-27 9:40 [Qemu-devel] [PATCH 00/13] 9p: reconcile virtfs with unlinked files Greg Kurz
` (6 preceding siblings ...)
2016-06-27 9:41 ` [Qemu-devel] [PATCH 07/13] 9p: introduce futimens file op Greg Kurz
@ 2016-06-27 9:42 ` Greg Kurz
2016-06-27 9:42 ` [Qemu-devel] [PATCH 09/13] 9p: introduce fchown file op Greg Kurz
` (5 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Greg Kurz @ 2016-06-27 9:42 UTC (permalink / raw)
To: qemu-devel
Cc: Eric Van Hensbergen, v9fs-developer, Aneesh Kumar K.V, Greg Kurz
This patch adds the plumbing to be able to use fgetxattr(), fsetxattr(),
flistxattr() and fremovexattr().
It does not change any functionality.
Signed-off-by: Greg Kurz <groug@kaod.org>
---
hw/9pfs/9p-local.c | 44 +++++++++++++++++---------
hw/9pfs/9p-posix-acl.c | 80 ++++++++++++++++++++++++++++++++---------------
hw/9pfs/9p-xattr-user.c | 41 ++++++++++++++++--------
hw/9pfs/9p-xattr.c | 35 +++++++++++++--------
hw/9pfs/9p-xattr.h | 67 ++++++++++++++++++++++++---------------
5 files changed, 172 insertions(+), 95 deletions(-)
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index 46ac7aab7c47..873bd4b9d997 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -269,34 +269,48 @@ err_out:
return ret;
}
-static int local_set_xattr(const char *path, FsCred *credp)
+static int local_do_setxattr(int fd, const char *path,
+ const char *name, void *value, size_t size)
+{
+ if (path) {
+ return setxattr(path, name, value, size, 0);
+ } else {
+ return fsetxattr(fd, name, value, size, 0);
+ }
+}
+
+static int local_set_xattr(int fd, const char *path, FsCred *credp)
{
int err;
if (credp->fc_uid != -1) {
uint32_t tmp_uid = cpu_to_le32(credp->fc_uid);
- err = setxattr(path, "user.virtfs.uid", &tmp_uid, sizeof(uid_t), 0);
+ err = local_do_setxattr(fd, path, "user.virtfs.uid", &tmp_uid,
+ sizeof(uid_t));
if (err) {
return err;
}
}
if (credp->fc_gid != -1) {
uint32_t tmp_gid = cpu_to_le32(credp->fc_gid);
- err = setxattr(path, "user.virtfs.gid", &tmp_gid, sizeof(gid_t), 0);
+ err = local_do_setxattr(fd, path, "user.virtfs.gid", &tmp_gid,
+ sizeof(gid_t));
if (err) {
return err;
}
}
if (credp->fc_mode != -1) {
uint32_t tmp_mode = cpu_to_le32(credp->fc_mode);
- err = setxattr(path, "user.virtfs.mode", &tmp_mode, sizeof(mode_t), 0);
+ err = local_do_setxattr(fd, path, "user.virtfs.mode", &tmp_mode,
+ sizeof(mode_t));
if (err) {
return err;
}
}
if (credp->fc_rdev != -1) {
uint64_t tmp_rdev = cpu_to_le64(credp->fc_rdev);
- err = setxattr(path, "user.virtfs.rdev", &tmp_rdev, sizeof(dev_t), 0);
+ err = local_do_setxattr(fd, path, "user.virtfs.rdev", &tmp_rdev,
+ sizeof(dev_t));
if (err) {
return err;
}
@@ -489,7 +503,7 @@ static int local_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
buffer = rpath(fs_ctx, path);
- ret = local_set_xattr(buffer, credp);
+ ret = local_set_xattr(-1, buffer, credp);
g_free(buffer);
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
return local_set_mapped_file_attr(fs_ctx, path, credp);
@@ -522,7 +536,7 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
if (err == -1) {
goto out;
}
- err = local_set_xattr(buffer, credp);
+ err = local_set_xattr(-1, buffer, credp);
if (err == -1) {
serrno = errno;
goto err_end;
@@ -584,7 +598,7 @@ static int local_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
goto out;
}
credp->fc_mode = credp->fc_mode|S_IFDIR;
- err = local_set_xattr(buffer, credp);
+ err = local_set_xattr(-1, buffer, credp);
if (err == -1) {
serrno = errno;
goto err_end;
@@ -674,7 +688,7 @@ static int local_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
}
credp->fc_mode = credp->fc_mode|S_IFREG;
/* Set cleint credentials in xattr */
- err = local_set_xattr(buffer, credp);
+ err = local_set_xattr(-1, buffer, credp);
if (err == -1) {
serrno = errno;
goto err_end;
@@ -760,7 +774,7 @@ static int local_symlink(FsContext *fs_ctx, const char *oldpath,
close(fd);
/* Set cleint credentials in symlink's xattr */
credp->fc_mode = credp->fc_mode|S_IFLNK;
- err = local_set_xattr(buffer, credp);
+ err = local_set_xattr(-1, buffer, credp);
if (err == -1) {
serrno = errno;
goto err_end;
@@ -932,7 +946,7 @@ static int local_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
g_free(buffer);
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
buffer = rpath(fs_ctx, path);
- ret = local_set_xattr(buffer, credp);
+ ret = local_set_xattr(-1, buffer, credp);
g_free(buffer);
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
return local_set_mapped_file_attr(fs_ctx, path, credp);
@@ -1046,7 +1060,7 @@ static ssize_t local_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
{
char *path = fs_path->data;
- return v9fs_get_xattr(ctx, path, name, value, size);
+ return v9fs_get_xattr(ctx, -1, path, name, value, size);
}
static ssize_t local_llistxattr(FsContext *ctx, V9fsPath *fs_path,
@@ -1054,7 +1068,7 @@ static ssize_t local_llistxattr(FsContext *ctx, V9fsPath *fs_path,
{
char *path = fs_path->data;
- return v9fs_list_xattr(ctx, path, value, size);
+ return v9fs_list_xattr(ctx, -1, path, value, size);
}
static int local_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name,
@@ -1062,7 +1076,7 @@ static int local_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name,
{
char *path = fs_path->data;
- return v9fs_set_xattr(ctx, path, name, value, size, flags);
+ return v9fs_set_xattr(ctx, -1, path, name, value, size, flags);
}
static int local_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
@@ -1070,7 +1084,7 @@ static int local_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
{
char *path = fs_path->data;
- return v9fs_remove_xattr(ctx, path, name);
+ return v9fs_remove_xattr(ctx, -1, path, name);
}
static int local_name_to_path(FsContext *ctx, V9fsPath *dir_path,
diff --git a/hw/9pfs/9p-posix-acl.c b/hw/9pfs/9p-posix-acl.c
index ec003181cd33..287e8cf68396 100644
--- a/hw/9pfs/9p-posix-acl.c
+++ b/hw/9pfs/9p-posix-acl.c
@@ -22,19 +22,23 @@
#define ACL_ACCESS "system.posix_acl_access"
#define ACL_DEFAULT "system.posix_acl_default"
-static ssize_t mp_pacl_getxattr(FsContext *ctx, const char *path,
+static ssize_t mp_pacl_getxattr(FsContext *ctx, int fd, const char *path,
const char *name, void *value, size_t size)
{
char *buffer;
ssize_t ret;
- buffer = rpath(ctx, path);
- ret = lgetxattr(buffer, MAP_ACL_ACCESS, value, size);
- g_free(buffer);
+ if (path) {
+ buffer = rpath(ctx, path);
+ ret = lgetxattr(buffer, MAP_ACL_ACCESS, value, size);
+ g_free(buffer);
+ } else {
+ ret = fgetxattr(fd, MAP_ACL_ACCESS, value, size);
+ }
return ret;
}
-static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
+static ssize_t mp_pacl_listxattr(FsContext *ctx, int fd, const char *path,
char *name, void *value, size_t osize)
{
ssize_t len = sizeof(ACL_ACCESS);
@@ -53,26 +57,36 @@ static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
return 0;
}
-static int mp_pacl_setxattr(FsContext *ctx, const char *path, const char *name,
- void *value, size_t size, int flags)
+static int mp_pacl_setxattr(FsContext *ctx, int fd, const char *path,
+ const char *name, void *value, size_t size,
+ int flags)
{
char *buffer;
int ret;
- buffer = rpath(ctx, path);
- ret = lsetxattr(buffer, MAP_ACL_ACCESS, value, size, flags);
- g_free(buffer);
+ if (path) {
+ buffer = rpath(ctx, path);
+ ret = lsetxattr(buffer, MAP_ACL_ACCESS, value, size, flags);
+ g_free(buffer);
+ } else {
+ ret = fsetxattr(fd, MAP_ACL_ACCESS, value, size, flags);
+ }
return ret;
}
-static int mp_pacl_removexattr(FsContext *ctx,
+static int mp_pacl_removexattr(FsContext *ctx, int fd,
const char *path, const char *name)
{
int ret;
char *buffer;
- buffer = rpath(ctx, path);
- ret = lremovexattr(buffer, MAP_ACL_ACCESS);
+ if (path) {
+ buffer = rpath(ctx, path);
+ ret = lremovexattr(buffer, MAP_ACL_ACCESS);
+ } else {
+ buffer = NULL;
+ ret = fremovexattr(fd, MAP_ACL_ACCESS);
+ }
if (ret == -1 && errno == ENODATA) {
/*
* We don't get ENODATA error when trying to remove a
@@ -86,19 +100,23 @@ static int mp_pacl_removexattr(FsContext *ctx,
return ret;
}
-static ssize_t mp_dacl_getxattr(FsContext *ctx, const char *path,
+static ssize_t mp_dacl_getxattr(FsContext *ctx, int fd, const char *path,
const char *name, void *value, size_t size)
{
char *buffer;
ssize_t ret;
- buffer = rpath(ctx, path);
- ret = lgetxattr(buffer, MAP_ACL_DEFAULT, value, size);
- g_free(buffer);
+ if (path) {
+ buffer = rpath(ctx, path);
+ ret = lgetxattr(buffer, MAP_ACL_DEFAULT, value, size);
+ g_free(buffer);
+ } else {
+ ret = fgetxattr(fd, MAP_ACL_DEFAULT, value, size);
+ }
return ret;
}
-static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
+static ssize_t mp_dacl_listxattr(FsContext *ctx, int fd, const char *path,
char *name, void *value, size_t osize)
{
ssize_t len = sizeof(ACL_DEFAULT);
@@ -117,26 +135,36 @@ static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
return 0;
}
-static int mp_dacl_setxattr(FsContext *ctx, const char *path, const char *name,
- void *value, size_t size, int flags)
+static int mp_dacl_setxattr(FsContext *ctx, int fd, const char *path,
+ const char *name, void *value, size_t size,
+ int flags)
{
char *buffer;
int ret;
- buffer = rpath(ctx, path);
- ret = lsetxattr(buffer, MAP_ACL_DEFAULT, value, size, flags);
- g_free(buffer);
+ if (path) {
+ buffer = rpath(ctx, path);
+ ret = lsetxattr(buffer, MAP_ACL_DEFAULT, value, size, flags);
+ g_free(buffer);
+ } else {
+ ret = fsetxattr(fd, MAP_ACL_DEFAULT, value, size, flags);
+ }
return ret;
}
-static int mp_dacl_removexattr(FsContext *ctx,
+static int mp_dacl_removexattr(FsContext *ctx, int fd,
const char *path, const char *name)
{
int ret;
char *buffer;
- buffer = rpath(ctx, path);
- ret = lremovexattr(buffer, MAP_ACL_DEFAULT);
+ if (path) {
+ buffer = rpath(ctx, path);
+ ret = lremovexattr(buffer, MAP_ACL_DEFAULT);
+ } else {
+ buffer = NULL;
+ ret = fremovexattr(fd, MAP_ACL_DEFAULT);
+ }
if (ret == -1 && errno == ENODATA) {
/*
* We don't get ENODATA error when trying to remove a
diff --git a/hw/9pfs/9p-xattr-user.c b/hw/9pfs/9p-xattr-user.c
index f87530c8b526..aa93ab926da9 100644
--- a/hw/9pfs/9p-xattr-user.c
+++ b/hw/9pfs/9p-xattr-user.c
@@ -17,7 +17,7 @@
#include "9p-xattr.h"
-static ssize_t mp_user_getxattr(FsContext *ctx, const char *path,
+static ssize_t mp_user_getxattr(FsContext *ctx, int fd, const char *path,
const char *name, void *value, size_t size)
{
char *buffer;
@@ -31,13 +31,17 @@ static ssize_t mp_user_getxattr(FsContext *ctx, const char *path,
errno = ENOATTR;
return -1;
}
- buffer = rpath(ctx, path);
- ret = lgetxattr(buffer, name, value, size);
- g_free(buffer);
+ if (path) {
+ buffer = rpath(ctx, path);
+ ret = lgetxattr(buffer, name, value, size);
+ g_free(buffer);
+ } else {
+ ret = fgetxattr(fd, name, value, size);
+ }
return ret;
}
-static ssize_t mp_user_listxattr(FsContext *ctx, const char *path,
+static ssize_t mp_user_listxattr(FsContext *ctx, int fd, const char *path,
char *name, void *value, size_t size)
{
int name_size = strlen(name) + 1;
@@ -70,8 +74,9 @@ static ssize_t mp_user_listxattr(FsContext *ctx, const char *path,
return name_size;
}
-static int mp_user_setxattr(FsContext *ctx, const char *path, const char *name,
- void *value, size_t size, int flags)
+static int mp_user_setxattr(FsContext *ctx, int fd, const char *path,
+ const char *name, void *value, size_t size,
+ int flags)
{
char *buffer;
int ret;
@@ -84,13 +89,17 @@ static int mp_user_setxattr(FsContext *ctx, const char *path, const char *name,
errno = EACCES;
return -1;
}
- buffer = rpath(ctx, path);
- ret = lsetxattr(buffer, name, value, size, flags);
- g_free(buffer);
+ if (path) {
+ buffer = rpath(ctx, path);
+ ret = lsetxattr(buffer, name, value, size, flags);
+ g_free(buffer);
+ } else {
+ ret = fsetxattr(fd, name, value, size, flags);
+ }
return ret;
}
-static int mp_user_removexattr(FsContext *ctx,
+static int mp_user_removexattr(FsContext *ctx, int fd,
const char *path, const char *name)
{
char *buffer;
@@ -104,9 +113,13 @@ static int mp_user_removexattr(FsContext *ctx,
errno = EACCES;
return -1;
}
- buffer = rpath(ctx, path);
- ret = lremovexattr(buffer, name);
- g_free(buffer);
+ if (path) {
+ buffer = rpath(ctx, path);
+ ret = lremovexattr(buffer, name);
+ g_free(buffer);
+ } else {
+ ret = fremovexattr(fd, name);
+ }
return ret;
}
diff --git a/hw/9pfs/9p-xattr.c b/hw/9pfs/9p-xattr.c
index 5d8595ed932a..cd8c634b6364 100644
--- a/hw/9pfs/9p-xattr.c
+++ b/hw/9pfs/9p-xattr.c
@@ -29,18 +29,18 @@ static XattrOperations *get_xattr_operations(XattrOperations **h,
return NULL;
}
-ssize_t v9fs_get_xattr(FsContext *ctx, const char *path,
+ssize_t v9fs_get_xattr(FsContext *ctx, int fd, const char *path,
const char *name, void *value, size_t size)
{
XattrOperations *xops = get_xattr_operations(ctx->xops, name);
if (xops) {
- return xops->getxattr(ctx, path, name, value, size);
+ return xops->getxattr(ctx, fd, path, name, value, size);
}
errno = EOPNOTSUPP;
return -1;
}
-ssize_t pt_listxattr(FsContext *ctx, const char *path,
+ssize_t pt_listxattr(FsContext *ctx, int fd, const char *path,
char *name, void *value, size_t size)
{
int name_size = strlen(name) + 1;
@@ -63,7 +63,7 @@ ssize_t pt_listxattr(FsContext *ctx, const char *path,
* Get the list and pass to each layer to find out whether
* to send the data or not
*/
-ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
+ssize_t v9fs_list_xattr(FsContext *ctx, int fd, const char *path,
void *value, size_t vsize)
{
ssize_t size = 0;
@@ -74,8 +74,13 @@ ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
ssize_t xattr_len, parsed_len = 0, attr_len;
/* Get the actual len */
- buffer = rpath(ctx, path);
- xattr_len = llistxattr(buffer, value, 0);
+ if (path) {
+ buffer = rpath(ctx, path);
+ xattr_len = llistxattr(buffer, value, 0);
+ } else {
+ buffer = NULL;
+ xattr_len = flistxattr(fd, value, 0);
+ }
if (xattr_len <= 0) {
g_free(buffer);
return xattr_len;
@@ -83,7 +88,11 @@ ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
/* Now fetch the xattr and find the actual size */
orig_value = g_malloc(xattr_len);
- xattr_len = llistxattr(buffer, orig_value, xattr_len);
+ if (path) {
+ xattr_len = llistxattr(buffer, orig_value, xattr_len);
+ } else {
+ xattr_len = flistxattr(fd, orig_value, xattr_len);
+ }
g_free(buffer);
/* store the orig pointer */
@@ -95,9 +104,9 @@ ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
}
if (!value) {
- size += xops->listxattr(ctx, path, orig_value, value, vsize);
+ size += xops->listxattr(ctx, fd, path, orig_value, value, vsize);
} else {
- size = xops->listxattr(ctx, path, orig_value, value, vsize);
+ size = xops->listxattr(ctx, fd, path, orig_value, value, vsize);
if (size < 0) {
goto err_out;
}
@@ -119,24 +128,24 @@ err_out:
return size;
}
-int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name,
+int v9fs_set_xattr(FsContext *ctx, int fd, const char *path, const char *name,
void *value, size_t size, int flags)
{
XattrOperations *xops = get_xattr_operations(ctx->xops, name);
if (xops) {
- return xops->setxattr(ctx, path, name, value, size, flags);
+ return xops->setxattr(ctx, fd, path, name, value, size, flags);
}
errno = EOPNOTSUPP;
return -1;
}
-int v9fs_remove_xattr(FsContext *ctx,
+int v9fs_remove_xattr(FsContext *ctx, int fd,
const char *path, const char *name)
{
XattrOperations *xops = get_xattr_operations(ctx->xops, name);
if (xops) {
- return xops->removexattr(ctx, path, name);
+ return xops->removexattr(ctx, fd, path, name);
}
errno = EOPNOTSUPP;
return -1;
diff --git a/hw/9pfs/9p-xattr.h b/hw/9pfs/9p-xattr.h
index 4d39a20262ad..dacb423c0968 100644
--- a/hw/9pfs/9p-xattr.h
+++ b/hw/9pfs/9p-xattr.h
@@ -18,13 +18,13 @@
typedef struct xattr_operations
{
const char *name;
- ssize_t (*getxattr)(FsContext *ctx, const char *path,
+ ssize_t (*getxattr)(FsContext *ctx, int fd, const char *path,
const char *name, void *value, size_t size);
- ssize_t (*listxattr)(FsContext *ctx, const char *path,
+ ssize_t (*listxattr)(FsContext *ctx, int fd, const char *path,
char *name, void *value, size_t size);
- int (*setxattr)(FsContext *ctx, const char *path, const char *name,
+ int (*setxattr)(FsContext *ctx, int fd, const char *path, const char *name,
void *value, size_t size, int flags);
- int (*removexattr)(FsContext *ctx,
+ int (*removexattr)(FsContext *ctx, int fd,
const char *path, const char *name);
} XattrOperations;
@@ -41,54 +41,67 @@ extern XattrOperations *mapped_xattr_ops[];
extern XattrOperations *passthrough_xattr_ops[];
extern XattrOperations *none_xattr_ops[];
-ssize_t v9fs_get_xattr(FsContext *ctx, const char *path, const char *name,
- void *value, size_t size);
-ssize_t v9fs_list_xattr(FsContext *ctx, const char *path, void *value,
+ssize_t v9fs_get_xattr(FsContext *ctx, int fd, const char *path,
+ const char *name, void *value, size_t size);
+ssize_t v9fs_list_xattr(FsContext *ctx, int fd, const char *path, void *value,
size_t vsize);
-int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name,
+int v9fs_set_xattr(FsContext *ctx, int fd, const char *path, const char *name,
void *value, size_t size, int flags);
-int v9fs_remove_xattr(FsContext *ctx, const char *path, const char *name);
-ssize_t pt_listxattr(FsContext *ctx, const char *path, char *name, void *value,
- size_t size);
+int v9fs_remove_xattr(FsContext *ctx, int fd, const char *path,
+ const char *name);
+ssize_t pt_listxattr(FsContext *ctx, int fd, const char *path, char *name,
+ void *value, size_t size);
-static inline ssize_t pt_getxattr(FsContext *ctx, const char *path,
+static inline ssize_t pt_getxattr(FsContext *ctx, int fd, const char *path,
const char *name, void *value, size_t size)
{
char *buffer;
ssize_t ret;
- buffer = rpath(ctx, path);
- ret = lgetxattr(buffer, name, value, size);
- g_free(buffer);
+ if (path) {
+ buffer = rpath(ctx, path);
+ ret = lgetxattr(buffer, name, value, size);
+ g_free(buffer);
+ } else {
+ ret = fgetxattr(fd, name, value, size);
+ }
return ret;
}
-static inline int pt_setxattr(FsContext *ctx, const char *path,
+static inline int pt_setxattr(FsContext *ctx, int fd, const char *path,
const char *name, void *value,
size_t size, int flags)
{
char *buffer;
int ret;
- buffer = rpath(ctx, path);
- ret = lsetxattr(buffer, name, value, size, flags);
- g_free(buffer);
+ if (path) {
+ buffer = rpath(ctx, path);
+ ret = lsetxattr(buffer, name, value, size, flags);
+ g_free(buffer);
+ } else {
+ ret = fsetxattr(fd, name, value, size, flags);
+ }
return ret;
}
-static inline int pt_removexattr(FsContext *ctx,
+static inline int pt_removexattr(FsContext *ctx, int fd,
const char *path, const char *name)
{
char *buffer;
int ret;
- buffer = rpath(ctx, path);
- ret = lremovexattr(path, name);
- g_free(buffer);
+ if (path) {
+ buffer = rpath(ctx, path);
+ ret = lremovexattr(path, name);
+ g_free(buffer);
+ } else {
+ ret = fremovexattr(fd, name);
+ }
return ret;
}
-static inline ssize_t notsup_getxattr(FsContext *ctx, const char *path,
+static inline ssize_t notsup_getxattr(FsContext *ctx, int fd, const char *path,
const char *name, void *value,
size_t size)
{
@@ -96,7 +109,7 @@ static inline ssize_t notsup_getxattr(FsContext *ctx, const char *path,
return -1;
}
-static inline int notsup_setxattr(FsContext *ctx, const char *path,
+static inline int notsup_setxattr(FsContext *ctx, int fd, const char *path,
const char *name, void *value,
size_t size, int flags)
{
@@ -104,13 +117,13 @@ static inline int notsup_setxattr(FsContext *ctx, const char *path,
return -1;
}
-static inline ssize_t notsup_listxattr(FsContext *ctx, const char *path,
+static inline ssize_t notsup_listxattr(FsContext *ctx, int fd, const char *path,
char *name, void *value, size_t size)
{
return 0;
}
-static inline int notsup_removexattr(FsContext *ctx,
+static inline int notsup_removexattr(FsContext *ctx, int fd,
const char *path, const char *name)
{
errno = ENOTSUP;
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] [PATCH 09/13] 9p: introduce fchown file op
2016-06-27 9:40 [Qemu-devel] [PATCH 00/13] 9p: reconcile virtfs with unlinked files Greg Kurz
` (7 preceding siblings ...)
2016-06-27 9:42 ` [Qemu-devel] [PATCH 08/13] 9p: add a fd argument to xattr helpers Greg Kurz
@ 2016-06-27 9:42 ` Greg Kurz
2016-06-27 9:42 ` [Qemu-devel] [PATCH 10/13] 9p: introduce fchmod " Greg Kurz
` (4 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Greg Kurz @ 2016-06-27 9:42 UTC (permalink / raw)
To: qemu-devel
Cc: Eric Van Hensbergen, v9fs-developer, Aneesh Kumar K.V, Greg Kurz
This allows fchown() in the guest to stay functional even if the file
was unlinked.
Signed-off-by: Greg Kurz <groug@kaod.org>
---
fsdev/file-op-9p.h | 1 +
hw/9pfs/9p-handle.c | 10 ++++++++++
hw/9pfs/9p-local.c | 22 ++++++++++++++++++++++
hw/9pfs/9p-proxy.c | 10 ++++++++++
hw/9pfs/9p-synth.c | 8 ++++++++
hw/9pfs/9p.c | 18 +++++++++++++++---
hw/9pfs/cofs.c | 22 ++++++++++++++++++++++
hw/9pfs/coth.h | 1 +
8 files changed, 89 insertions(+), 3 deletions(-)
diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index 811ca234cf86..1c15d6efdaea 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -143,6 +143,7 @@ struct FileOperations
int (*ftruncate)(FsContext *, int, V9fsFidOpenState *, off_t);
int (*futimens)(FsContext *, int, V9fsFidOpenState *,
const struct timespec *);
+ int (*fchown)(FsContext *, int, V9fsFidOpenState *, FsCred *);
void *opaque;
};
diff --git a/hw/9pfs/9p-handle.c b/hw/9pfs/9p-handle.c
index 382b4d57927a..7e8e776cdab0 100644
--- a/hw/9pfs/9p-handle.c
+++ b/hw/9pfs/9p-handle.c
@@ -384,6 +384,15 @@ static int handle_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
return ret;
}
+static int handle_fchown(FsContext *fs_ctx, int fid_type, V9fsFidOpenState *fs,
+ FsCred *credp)
+{
+ int fd;
+
+ fd = v9fs_get_fd_fid(fid_type, fs);
+ return fchown(fd, credp->fc_uid, credp->fc_gid);
+}
+
static int handle_utimensat(FsContext *ctx, V9fsPath *fs_path,
const struct timespec *buf)
{
@@ -716,4 +725,5 @@ FileOperations handle_ops = {
.unlinkat = handle_unlinkat,
.ftruncate = handle_ftruncate,
.futimens = handle_futimens,
+ .fchown = handle_fchown,
};
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index 873bd4b9d997..bc8d3bff1308 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -954,6 +954,27 @@ static int local_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
return ret;
}
+static int local_fchown(FsContext *fs_ctx, int fid_type, V9fsFidOpenState *fs,
+ FsCred *credp)
+{
+ int ret = -1;
+ int fd;
+
+ fd = v9fs_get_fd_fid(fid_type, fs);
+
+ if ((credp->fc_uid == -1 && credp->fc_gid == -1) ||
+ (fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
+ (fs_ctx->export_flags & V9FS_SM_NONE)) {
+ ret = fchown(fd, credp->fc_uid, credp->fc_gid);
+ } else if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
+ ret = local_set_xattr(fd, NULL, credp);
+ } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+ return ret;
+}
+
static int local_utimensat(FsContext *s, V9fsPath *fs_path,
const struct timespec *buf)
{
@@ -1314,4 +1335,5 @@ FileOperations local_ops = {
.unlinkat = local_unlinkat,
.ftruncate = local_ftruncate,
.futimens = local_futimens,
+ .fchown = local_fchown,
};
diff --git a/hw/9pfs/9p-proxy.c b/hw/9pfs/9p-proxy.c
index cbc94b645852..8f2e27c6f8e4 100644
--- a/hw/9pfs/9p-proxy.c
+++ b/hw/9pfs/9p-proxy.c
@@ -909,6 +909,15 @@ static int proxy_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
return retval;
}
+static int proxy_fchown(FsContext *fs_ctx, int fid_type, V9fsFidOpenState *fs,
+ FsCred *credp)
+{
+ int fd;
+
+ fd = v9fs_get_fd_fid(fid_type, fs);
+ return fchown(fd, credp->fc_uid, credp->fc_gid);
+}
+
static int proxy_utimensat(FsContext *s, V9fsPath *fs_path,
const struct timespec *buf)
{
@@ -1231,4 +1240,5 @@ FileOperations proxy_ops = {
.unlinkat = proxy_unlinkat,
.ftruncate = proxy_ftruncate,
.futimens = proxy_futimens,
+ .fchown = proxy_fchown,
};
diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c
index c4770792a79f..b0f9b0cd67f6 100644
--- a/hw/9pfs/9p-synth.c
+++ b/hw/9pfs/9p-synth.c
@@ -405,6 +405,13 @@ static int synth_chown(FsContext *fs_ctx, V9fsPath *path, FsCred *credp)
return -1;
}
+static int synth_fchown(FsContext *fs_ctx, int fid_type, V9fsFidOpenState *fs,
+ FsCred *credp)
+{
+ errno = EPERM;
+ return -1;
+}
+
static int synth_utimensat(FsContext *fs_ctx, V9fsPath *path,
const struct timespec *buf)
{
@@ -582,4 +589,5 @@ FileOperations synth_ops = {
.unlinkat = synth_unlinkat,
.ftruncate = synth_ftruncate,
.futimens = synth_futimens,
+ .fchown = synth_fchown,
};
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 97dba6190809..351bbdde4748 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -1208,6 +1208,19 @@ static int v9fs_do_utimens(V9fsPDU *pdu, V9fsFidState *fidp,
return err;
}
+static int v9fs_do_chown(V9fsPDU *pdu, V9fsFidState *fidp, uid_t uid, gid_t gid)
+{
+ int err;
+
+ if (fid_has_file(fidp)) {
+ err = v9fs_co_fchown(pdu, fidp, uid, gid);
+ } else {
+ err = v9fs_co_chown(pdu, &fidp->path, uid, gid);
+ }
+
+ return err;
+}
+
/* Attribute flags */
#define P9_ATTR_MODE (1 << 0)
#define P9_ATTR_UID (1 << 1)
@@ -1286,8 +1299,7 @@ static void v9fs_setattr(void *opaque)
if (!(v9iattr.valid & P9_ATTR_GID)) {
v9iattr.gid = -1;
}
- err = v9fs_co_chown(pdu, &fidp->path, v9iattr.uid,
- v9iattr.gid);
+ err = v9fs_do_chown(pdu, fidp, v9iattr.uid, v9iattr.gid);
if (err < 0) {
goto out;
}
@@ -2769,7 +2781,7 @@ static void v9fs_wstat(void *opaque)
}
}
if (v9stat.n_gid != -1 || v9stat.n_uid != -1) {
- err = v9fs_co_chown(pdu, &fidp->path, v9stat.n_uid, v9stat.n_gid);
+ err = v9fs_do_chown(pdu, fidp, v9stat.n_uid, v9stat.n_gid);
if (err < 0) {
goto out;
}
diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c
index 1ed9c298f98d..4e8fbbe2b24e 100644
--- a/hw/9pfs/cofs.c
+++ b/hw/9pfs/cofs.c
@@ -175,6 +175,28 @@ int v9fs_co_chown(V9fsPDU *pdu, V9fsPath *path, uid_t uid, gid_t gid)
return err;
}
+int v9fs_co_fchown(V9fsPDU *pdu, V9fsFidState *fidp, uid_t uid, gid_t gid)
+{
+ int err;
+ FsCred cred;
+ V9fsState *s = pdu->s;
+
+ if (v9fs_request_cancelled(pdu)) {
+ return -EINTR;
+ }
+ cred_init(&cred);
+ cred.fc_uid = uid;
+ cred.fc_gid = gid;
+ v9fs_co_run_in_worker(
+ {
+ err = s->ops->fchown(&s->ctx, fidp->fid_type, &fidp->fs, &cred);
+ if (err < 0) {
+ err = -errno;
+ }
+ });
+ return err;
+}
+
int v9fs_co_truncate(V9fsPDU *pdu, V9fsPath *path, off_t size)
{
int err;
diff --git a/hw/9pfs/coth.h b/hw/9pfs/coth.h
index c4e90059f00c..7050298f7170 100644
--- a/hw/9pfs/coth.h
+++ b/hw/9pfs/coth.h
@@ -96,5 +96,6 @@ extern int v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t,
V9fsStatDotl *v9stat);
extern int v9fs_co_ftruncate(V9fsPDU *, V9fsFidState *, off_t);
extern int v9fs_co_futimens(V9fsPDU *, V9fsFidState *, struct timespec [2]);
+extern int v9fs_co_fchown(V9fsPDU *, V9fsFidState *, uid_t, gid_t);
#endif
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] [PATCH 10/13] 9p: introduce fchmod file op
2016-06-27 9:40 [Qemu-devel] [PATCH 00/13] 9p: reconcile virtfs with unlinked files Greg Kurz
` (8 preceding siblings ...)
2016-06-27 9:42 ` [Qemu-devel] [PATCH 09/13] 9p: introduce fchown file op Greg Kurz
@ 2016-06-27 9:42 ` Greg Kurz
2016-06-27 9:42 ` [Qemu-devel] [PATCH 11/13] 9p: xattr fid to reference file fid Greg Kurz
` (3 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Greg Kurz @ 2016-06-27 9:42 UTC (permalink / raw)
To: qemu-devel
Cc: Eric Van Hensbergen, v9fs-developer, Aneesh Kumar K.V, Greg Kurz
This allows fchmod() in the guest to stay functional even if the file
was unlinked.
Signed-off-by: Greg Kurz <groug@kaod.org>
---
fsdev/file-op-9p.h | 1 +
hw/9pfs/9p-handle.c | 10 ++++++++++
hw/9pfs/9p-local.c | 21 +++++++++++++++++++++
hw/9pfs/9p-proxy.c | 10 ++++++++++
hw/9pfs/9p-synth.c | 8 ++++++++
hw/9pfs/9p.c | 20 ++++++++++++++++----
hw/9pfs/cofs.c | 21 +++++++++++++++++++++
hw/9pfs/coth.h | 1 +
8 files changed, 88 insertions(+), 4 deletions(-)
diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index 1c15d6efdaea..8094d2c6c438 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -144,6 +144,7 @@ struct FileOperations
int (*futimens)(FsContext *, int, V9fsFidOpenState *,
const struct timespec *);
int (*fchown)(FsContext *, int, V9fsFidOpenState *, FsCred *);
+ int (*fchmod)(FsContext *, int, V9fsFidOpenState *, FsCred *);
void *opaque;
};
diff --git a/hw/9pfs/9p-handle.c b/hw/9pfs/9p-handle.c
index 7e8e776cdab0..f345217aa8e1 100644
--- a/hw/9pfs/9p-handle.c
+++ b/hw/9pfs/9p-handle.c
@@ -218,6 +218,15 @@ static int handle_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
return ret;
}
+static int handle_fchmod(FsContext *fs_ctx, int fid_type, V9fsFidOpenState *fs,
+ FsCred *credp)
+{
+ int fd;
+
+ fd = v9fs_get_fd_fid(fid_type, fs);
+ return fchmod(fd, credp->fc_mode);
+}
+
static int handle_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
const char *name, FsCred *credp)
{
@@ -726,4 +735,5 @@ FileOperations handle_ops = {
.ftruncate = handle_ftruncate,
.futimens = handle_futimens,
.fchown = handle_fchown,
+ .fchmod = handle_fchmod,
};
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index bc8d3bff1308..e51c58037266 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -516,6 +516,26 @@ static int local_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
return ret;
}
+static int local_fchmod(FsContext *fs_ctx, int fid_type, V9fsFidOpenState *fs,
+ FsCred *credp)
+{
+ int ret = -1;
+ int fd;
+
+ fd = v9fs_get_fd_fid(fid_type, fs);
+
+ if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
+ ret = local_set_xattr(fd, NULL, credp);
+ } else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
+ errno = ENOTSUP;
+ return -1;
+ } else if ((fs_ctx->export_flags & V9FS_SM_PASSTHROUGH) ||
+ (fs_ctx->export_flags & V9FS_SM_NONE)) {
+ ret = fchmod(fd, credp->fc_mode);
+ }
+ return ret;
+}
+
static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
const char *name, FsCred *credp)
{
@@ -1336,4 +1356,5 @@ FileOperations local_ops = {
.ftruncate = local_ftruncate,
.futimens = local_futimens,
.fchown = local_fchown,
+ .fchmod = local_fchmod,
};
diff --git a/hw/9pfs/9p-proxy.c b/hw/9pfs/9p-proxy.c
index 8f2e27c6f8e4..dec4a861a073 100644
--- a/hw/9pfs/9p-proxy.c
+++ b/hw/9pfs/9p-proxy.c
@@ -743,6 +743,15 @@ static int proxy_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
return retval;
}
+static int proxy_fchmod(FsContext *fs_ctx, int fid_type, V9fsFidOpenState *fs,
+ FsCred *credp)
+{
+ int fd;
+
+ fd = v9fs_get_fd_fid(fid_type, fs);
+ return fchmod(fd, credp->fc_mode);
+}
+
static int proxy_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
const char *name, FsCred *credp)
{
@@ -1241,4 +1250,5 @@ FileOperations proxy_ops = {
.ftruncate = proxy_ftruncate,
.futimens = proxy_futimens,
.fchown = proxy_fchown,
+ .fchmod = proxy_fchmod,
};
diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c
index b0f9b0cd67f6..ec2e301de8c6 100644
--- a/hw/9pfs/9p-synth.c
+++ b/hw/9pfs/9p-synth.c
@@ -357,6 +357,13 @@ static int synth_chmod(FsContext *fs_ctx, V9fsPath *path, FsCred *credp)
return -1;
}
+static int synth_fchmod(FsContext *fs_ctx, int fid_type, V9fsFidOpenState *fs,
+ FsCred *credp)
+{
+ errno = EPERM;
+ return -1;
+}
+
static int synth_mknod(FsContext *fs_ctx, V9fsPath *path,
const char *buf, FsCred *credp)
{
@@ -590,4 +597,5 @@ FileOperations synth_ops = {
.ftruncate = synth_ftruncate,
.futimens = synth_futimens,
.fchown = synth_fchown,
+ .fchmod = synth_fchmod,
};
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 351bbdde4748..8824b71f364b 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -1221,6 +1221,19 @@ static int v9fs_do_chown(V9fsPDU *pdu, V9fsFidState *fidp, uid_t uid, gid_t gid)
return err;
}
+static int v9fs_do_chmod(V9fsPDU *pdu, V9fsFidState *fidp, mode_t mode)
+{
+ int err;
+
+ if (fid_has_file(fidp)) {
+ err = v9fs_co_fchmod(pdu, fidp, mode);
+ } else {
+ err = v9fs_co_chmod(pdu, &fidp->path, mode);
+ }
+
+ return err;
+}
+
/* Attribute flags */
#define P9_ATTR_MODE (1 << 0)
#define P9_ATTR_UID (1 << 1)
@@ -1254,7 +1267,7 @@ static void v9fs_setattr(void *opaque)
goto out_nofid;
}
if (v9iattr.valid & P9_ATTR_MODE) {
- err = v9fs_co_chmod(pdu, &fidp->path, v9iattr.mode);
+ err = v9fs_do_chmod(pdu, fidp, v9iattr.mode);
if (err < 0) {
goto out;
}
@@ -2754,9 +2767,8 @@ static void v9fs_wstat(void *opaque)
err = -EIO;
goto out;
}
- err = v9fs_co_chmod(pdu, &fidp->path,
- v9mode_to_mode(v9stat.mode,
- &v9stat.extension));
+ err = v9fs_do_chmod(pdu, fidp, v9mode_to_mode(v9stat.mode,
+ &v9stat.extension));
if (err < 0) {
goto out;
}
diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c
index 4e8fbbe2b24e..779997dc0e33 100644
--- a/hw/9pfs/cofs.c
+++ b/hw/9pfs/cofs.c
@@ -112,6 +112,27 @@ int v9fs_co_chmod(V9fsPDU *pdu, V9fsPath *path, mode_t mode)
return err;
}
+int v9fs_co_fchmod(V9fsPDU *pdu, V9fsFidState *fidp, mode_t mode)
+{
+ int err;
+ FsCred cred;
+ V9fsState *s = pdu->s;
+
+ if (v9fs_request_cancelled(pdu)) {
+ return -EINTR;
+ }
+ cred_init(&cred);
+ cred.fc_mode = mode;
+ v9fs_co_run_in_worker(
+ {
+ err = s->ops->fchmod(&s->ctx, fidp->fid_type, &fidp->fs, &cred);
+ if (err < 0) {
+ err = -errno;
+ }
+ });
+ return err;
+}
+
int v9fs_co_utimensat(V9fsPDU *pdu, V9fsPath *path,
struct timespec times[2])
{
diff --git a/hw/9pfs/coth.h b/hw/9pfs/coth.h
index 7050298f7170..ee819a7eed54 100644
--- a/hw/9pfs/coth.h
+++ b/hw/9pfs/coth.h
@@ -97,5 +97,6 @@ extern int v9fs_co_st_gen(V9fsPDU *pdu, V9fsPath *path, mode_t,
extern int v9fs_co_ftruncate(V9fsPDU *, V9fsFidState *, off_t);
extern int v9fs_co_futimens(V9fsPDU *, V9fsFidState *, struct timespec [2]);
extern int v9fs_co_fchown(V9fsPDU *, V9fsFidState *, uid_t, gid_t);
+extern int v9fs_co_fchmod(V9fsPDU *, V9fsFidState *, mode_t);
#endif
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] [PATCH 11/13] 9p: xattr fid to reference file fid
2016-06-27 9:40 [Qemu-devel] [PATCH 00/13] 9p: reconcile virtfs with unlinked files Greg Kurz
` (9 preceding siblings ...)
2016-06-27 9:42 ` [Qemu-devel] [PATCH 10/13] 9p: introduce fchmod " Greg Kurz
@ 2016-06-27 9:42 ` Greg Kurz
2016-06-27 9:42 ` [Qemu-devel] [PATCH 12/13] 9p: introduce fgetxattr file op Greg Kurz
` (2 subsequent siblings)
13 siblings, 0 replies; 16+ messages in thread
From: Greg Kurz @ 2016-06-27 9:42 UTC (permalink / raw)
To: qemu-devel
Cc: Eric Van Hensbergen, v9fs-developer, Aneesh Kumar K.V, Greg Kurz
The flistxattr() and fgetxattr() syscalls in the guest are implementend
with XATTRWALK. In v9fs_xattrwalk(), we then create a xattr fid to
hold the the file path, and retrieve the xattr from the fs backend with
llistxattr() or lgetxattr().
This patch brings file descriptor support to fids with type P9_FID_XATTR,
so that the backend can use flistxattr() and fgetxattr(). This is done by
keeping a reference to the original fid until the xattr fid gets clunked.
Xattr fids created during XATTRCREATE (setxattr/removexattr in the guest),
are not affected: the guest does not provide the related open fid and we
have no reference to keep. In this case, the xattr operation will continue
to be based on the path.
Signed-off-by: Greg Kurz <groug@kaod.org>
---
hw/9pfs/9p.c | 28 ++++++++++++++++++++++++----
hw/9pfs/9p.h | 1 +
2 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 8824b71f364b..d02f95634b97 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -248,6 +248,12 @@ int v9fs_get_fd_fid(int fid_type, V9fsFidOpenState *fs)
fd = dirfd(fs->dir.stream);
} else if (fid_type == P9_FID_FILE) {
fd = fs->fd;
+ } else if (fid_type == P9_FID_XATTR) {
+ V9fsFidState *fidp = fs->xattr.file;
+
+ if (fidp) {
+ return v9fs_get_fd_fid(fidp->fid_type, &fidp->fs);
+ }
}
return fd;
@@ -265,6 +271,12 @@ static bool fid_has_file(V9fsFidState *fidp)
if (fidp->fs.fd > -1) {
return true;
}
+ } else if (fid_type == P9_FID_XATTR) {
+ V9fsFidState *file = fidp->fs.xattr.file;
+
+ if (file) {
+ return fid_has_file(file);
+ }
}
return false;
@@ -368,6 +380,8 @@ free_value:
return retval;
}
+static int put_fid(V9fsPDU *pdu, V9fsFidState *fidp);
+
static int free_fid(V9fsPDU *pdu, V9fsFidState *fidp)
{
int retval = 0;
@@ -382,7 +396,13 @@ static int free_fid(V9fsPDU *pdu, V9fsFidState *fidp)
retval = v9fs_co_closedir(pdu, &fidp->fs);
}
} else if (fidp->fid_type == P9_FID_XATTR) {
+ V9fsFidState *file_fidp = fidp->fs.xattr.file;
+
retval = v9fs_xattr_fid_clunk(pdu, fidp);
+ if (file_fidp) {
+ fidp->fs.xattr.file = NULL;
+ put_fid(pdu, file_fidp);
+ }
}
v9fs_path_free(&fidp->path);
g_free(fidp);
@@ -3125,6 +3145,10 @@ static void v9fs_xattrwalk(void *opaque)
goto out;
}
v9fs_path_copy(&xattr_fidp->path, &file_fidp->path);
+ xattr_fidp->fid_type = P9_FID_XATTR;
+ xattr_fidp->fs.xattr.copied_len = -1;
+ xattr_fidp->fs.xattr.file = file_fidp;
+ file_fidp->ref++;
if (name.data == NULL) {
/*
* listxattr request. Get the size first
@@ -3139,8 +3163,6 @@ static void v9fs_xattrwalk(void *opaque)
* Read the xattr value
*/
xattr_fidp->fs.xattr.len = size;
- xattr_fidp->fid_type = P9_FID_XATTR;
- xattr_fidp->fs.xattr.copied_len = -1;
if (size) {
xattr_fidp->fs.xattr.value = g_malloc(size);
err = v9fs_co_llistxattr(pdu, &xattr_fidp->path,
@@ -3172,8 +3194,6 @@ static void v9fs_xattrwalk(void *opaque)
* Read the xattr value
*/
xattr_fidp->fs.xattr.len = size;
- xattr_fidp->fid_type = P9_FID_XATTR;
- xattr_fidp->fs.xattr.copied_len = -1;
if (size) {
xattr_fidp->fs.xattr.value = g_malloc(size);
err = v9fs_co_lgetxattr(pdu, &xattr_fidp->path,
diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h
index d0ccc0089771..0b9db6bd8c38 100644
--- a/hw/9pfs/9p.h
+++ b/hw/9pfs/9p.h
@@ -164,6 +164,7 @@ typedef struct V9fsXattr
void *value;
V9fsString name;
int flags;
+ V9fsFidState *file;
} V9fsXattr;
typedef struct V9fsDir {
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] [PATCH 12/13] 9p: introduce fgetxattr file op
2016-06-27 9:40 [Qemu-devel] [PATCH 00/13] 9p: reconcile virtfs with unlinked files Greg Kurz
` (10 preceding siblings ...)
2016-06-27 9:42 ` [Qemu-devel] [PATCH 11/13] 9p: xattr fid to reference file fid Greg Kurz
@ 2016-06-27 9:42 ` Greg Kurz
2016-06-27 9:42 ` [Qemu-devel] [PATCH 13/13] 9p: introduce flistxattr " Greg Kurz
2016-07-04 12:40 ` [Qemu-devel] [PATCH 00/13] 9p: reconcile virtfs with unlinked files Greg Kurz
13 siblings, 0 replies; 16+ messages in thread
From: Greg Kurz @ 2016-06-27 9:42 UTC (permalink / raw)
To: qemu-devel
Cc: Eric Van Hensbergen, v9fs-developer, Aneesh Kumar K.V, Greg Kurz
This allows fgetxattr() in the guest to stay functional even if the file
was unlinked.
Signed-off-by: Greg Kurz <groug@kaod.org>
---
fsdev/file-op-9p.h | 2 ++
hw/9pfs/9p-handle.c | 11 +++++++++++
hw/9pfs/9p-local.c | 11 +++++++++++
hw/9pfs/9p-proxy.c | 12 ++++++++++++
hw/9pfs/9p-synth.c | 9 +++++++++
hw/9pfs/9p.c | 21 +++++++++++++++------
hw/9pfs/coth.h | 2 ++
hw/9pfs/coxattr.c | 22 ++++++++++++++++++++++
8 files changed, 84 insertions(+), 6 deletions(-)
diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index 8094d2c6c438..683596797b51 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -145,6 +145,8 @@ struct FileOperations
const struct timespec *);
int (*fchown)(FsContext *, int, V9fsFidOpenState *, FsCred *);
int (*fchmod)(FsContext *, int, V9fsFidOpenState *, FsCred *);
+ ssize_t (*fgetxattr)(FsContext *, int, V9fsFidOpenState *,
+ const char *, void *, size_t);
void *opaque;
};
diff --git a/hw/9pfs/9p-handle.c b/hw/9pfs/9p-handle.c
index f345217aa8e1..3153acff663c 100644
--- a/hw/9pfs/9p-handle.c
+++ b/hw/9pfs/9p-handle.c
@@ -477,6 +477,16 @@ static ssize_t handle_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
return ret;
}
+static ssize_t handle_fgetxattr(FsContext *ctx, int fid_type,
+ V9fsFidOpenState *fs, const char *name,
+ void *value, size_t size)
+{
+ int fd;
+
+ fd = v9fs_get_fd_fid(fid_type, fs);
+ return fgetxattr(fd, name, value, size);
+}
+
static ssize_t handle_llistxattr(FsContext *ctx, V9fsPath *fs_path,
void *value, size_t size)
{
@@ -736,4 +746,5 @@ FileOperations handle_ops = {
.futimens = handle_futimens,
.fchown = handle_fchown,
.fchmod = handle_fchmod,
+ .fgetxattr = handle_fgetxattr,
};
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index e51c58037266..206849a3ed83 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -1104,6 +1104,16 @@ static ssize_t local_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
return v9fs_get_xattr(ctx, -1, path, name, value, size);
}
+static ssize_t local_fgetxattr(FsContext *ctx, int fid_type,
+ V9fsFidOpenState *fs, const char *name,
+ void *value, size_t size)
+{
+ int fd;
+
+ fd = v9fs_get_fd_fid(fid_type, fs);
+ return v9fs_get_xattr(ctx, fd, NULL, name, value, size);
+}
+
static ssize_t local_llistxattr(FsContext *ctx, V9fsPath *fs_path,
void *value, size_t size)
{
@@ -1357,4 +1367,5 @@ FileOperations local_ops = {
.futimens = local_futimens,
.fchown = local_fchown,
.fchmod = local_fchmod,
+ .fgetxattr = local_fgetxattr,
};
diff --git a/hw/9pfs/9p-proxy.c b/hw/9pfs/9p-proxy.c
index dec4a861a073..074799027873 100644
--- a/hw/9pfs/9p-proxy.c
+++ b/hw/9pfs/9p-proxy.c
@@ -17,6 +17,7 @@
#include "qemu/error-report.h"
#include "fsdev/qemu-fsdev.h"
#include "9p-proxy.h"
+#include "qemu/xattr.h"
typedef struct V9fsProxy {
int sockfd;
@@ -1006,6 +1007,16 @@ static ssize_t proxy_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
return retval;
}
+static ssize_t proxy_fgetxattr(FsContext *ctx, int fid_type,
+ V9fsFidOpenState *fs, const char *name,
+ void *value, size_t size)
+{
+ int fd;
+
+ fd = v9fs_get_fd_fid(fid_type, fs);
+ return fgetxattr(fd, name, value, size);
+}
+
static ssize_t proxy_llistxattr(FsContext *ctx, V9fsPath *fs_path,
void *value, size_t size)
{
@@ -1251,4 +1262,5 @@ FileOperations proxy_ops = {
.futimens = proxy_futimens,
.fchown = proxy_fchown,
.fchmod = proxy_fchmod,
+ .fgetxattr = proxy_fgetxattr,
};
diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c
index ec2e301de8c6..24505fc2f621 100644
--- a/hw/9pfs/9p-synth.c
+++ b/hw/9pfs/9p-synth.c
@@ -464,6 +464,14 @@ static ssize_t synth_lgetxattr(FsContext *ctx, V9fsPath *path,
return -1;
}
+static ssize_t synth_fgetxattr(FsContext *ctx, int fid_type,
+ V9fsFidOpenState *fs, const char *name,
+ void *value, size_t size)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
static ssize_t synth_llistxattr(FsContext *ctx, V9fsPath *path,
void *value, size_t size)
{
@@ -598,4 +606,5 @@ FileOperations synth_ops = {
.futimens = synth_futimens,
.fchown = synth_fchown,
.fchmod = synth_fchmod,
+ .fgetxattr = synth_fgetxattr,
};
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index d02f95634b97..435100f85be3 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -3115,6 +3115,16 @@ out_nofid:
v9fs_string_free(&name);
}
+static int v9fs_do_getxattr(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name,
+ void *value, size_t size)
+{
+ if (fid_has_file(fidp)) {
+ return v9fs_co_fgetxattr(pdu, fidp, name, value, size);
+ } else {
+ return v9fs_co_lgetxattr(pdu, &fidp->path, name, value, size);
+ }
+}
+
static void v9fs_xattrwalk(void *opaque)
{
int64_t size;
@@ -3181,10 +3191,9 @@ static void v9fs_xattrwalk(void *opaque)
} else {
/*
* specific xattr fid. We check for xattr
- * presence also collect the xattr size
+ * presence also collect the xattr size.
*/
- size = v9fs_co_lgetxattr(pdu, &xattr_fidp->path,
- &name, NULL, 0);
+ size = v9fs_do_getxattr(pdu, xattr_fidp, &name, NULL, 0);
if (size < 0) {
err = size;
clunk_fid(s, xattr_fidp->fid);
@@ -3196,9 +3205,9 @@ static void v9fs_xattrwalk(void *opaque)
xattr_fidp->fs.xattr.len = size;
if (size) {
xattr_fidp->fs.xattr.value = g_malloc(size);
- err = v9fs_co_lgetxattr(pdu, &xattr_fidp->path,
- &name, xattr_fidp->fs.xattr.value,
- xattr_fidp->fs.xattr.len);
+ err = v9fs_do_getxattr(pdu, xattr_fidp, &name,
+ xattr_fidp->fs.xattr.value,
+ xattr_fidp->fs.xattr.len);
if (err < 0) {
clunk_fid(s, xattr_fidp->fid);
goto out;
diff --git a/hw/9pfs/coth.h b/hw/9pfs/coth.h
index ee819a7eed54..2e507939d01d 100644
--- a/hw/9pfs/coth.h
+++ b/hw/9pfs/coth.h
@@ -98,5 +98,7 @@ extern int v9fs_co_ftruncate(V9fsPDU *, V9fsFidState *, off_t);
extern int v9fs_co_futimens(V9fsPDU *, V9fsFidState *, struct timespec [2]);
extern int v9fs_co_fchown(V9fsPDU *, V9fsFidState *, uid_t, gid_t);
extern int v9fs_co_fchmod(V9fsPDU *, V9fsFidState *, mode_t);
+extern int v9fs_co_fgetxattr(V9fsPDU *, V9fsFidState *, V9fsString *, void *,
+ size_t);
#endif
diff --git a/hw/9pfs/coxattr.c b/hw/9pfs/coxattr.c
index 133c4ead37b6..72e3f38fb371 100644
--- a/hw/9pfs/coxattr.c
+++ b/hw/9pfs/coxattr.c
@@ -61,6 +61,28 @@ int v9fs_co_lgetxattr(V9fsPDU *pdu, V9fsPath *path,
return err;
}
+int v9fs_co_fgetxattr(V9fsPDU *pdu, V9fsFidState *fidp,
+ V9fsString *xattr_name,
+ void *value, size_t size)
+{
+ int err;
+ V9fsState *s = pdu->s;
+
+ if (v9fs_request_cancelled(pdu)) {
+ return -EINTR;
+ }
+ v9fs_co_run_in_worker(
+ {
+ err = s->ops->fgetxattr(&s->ctx, fidp->fid_type, &fidp->fs,
+ xattr_name->data,
+ value, size);
+ if (err < 0) {
+ err = -errno;
+ }
+ });
+ return err;
+}
+
int v9fs_co_lsetxattr(V9fsPDU *pdu, V9fsPath *path,
V9fsString *xattr_name, void *value,
size_t size, int flags)
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] [PATCH 13/13] 9p: introduce flistxattr file op
2016-06-27 9:40 [Qemu-devel] [PATCH 00/13] 9p: reconcile virtfs with unlinked files Greg Kurz
` (11 preceding siblings ...)
2016-06-27 9:42 ` [Qemu-devel] [PATCH 12/13] 9p: introduce fgetxattr file op Greg Kurz
@ 2016-06-27 9:42 ` Greg Kurz
2016-07-04 12:40 ` [Qemu-devel] [PATCH 00/13] 9p: reconcile virtfs with unlinked files Greg Kurz
13 siblings, 0 replies; 16+ messages in thread
From: Greg Kurz @ 2016-06-27 9:42 UTC (permalink / raw)
To: qemu-devel
Cc: Eric Van Hensbergen, v9fs-developer, Aneesh Kumar K.V, Greg Kurz
This allows flistxattr() in the guest to stay functional even if the file
was unlinked.
Signed-off-by: Greg Kurz <groug@kaod.org>
---
fsdev/file-op-9p.h | 2 ++
hw/9pfs/9p-handle.c | 10 ++++++++++
hw/9pfs/9p-local.c | 10 ++++++++++
hw/9pfs/9p-proxy.c | 10 ++++++++++
hw/9pfs/9p-synth.c | 8 ++++++++
hw/9pfs/9p.c | 18 ++++++++++++++----
hw/9pfs/coth.h | 1 +
hw/9pfs/coxattr.c | 20 ++++++++++++++++++++
8 files changed, 75 insertions(+), 4 deletions(-)
diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index 683596797b51..e23908d98764 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -147,6 +147,8 @@ struct FileOperations
int (*fchmod)(FsContext *, int, V9fsFidOpenState *, FsCred *);
ssize_t (*fgetxattr)(FsContext *, int, V9fsFidOpenState *,
const char *, void *, size_t);
+ ssize_t (*flistxattr)(FsContext *, int, V9fsFidOpenState *,
+ void *, size_t);
void *opaque;
};
diff --git a/hw/9pfs/9p-handle.c b/hw/9pfs/9p-handle.c
index 3153acff663c..d17d9a8ff008 100644
--- a/hw/9pfs/9p-handle.c
+++ b/hw/9pfs/9p-handle.c
@@ -502,6 +502,15 @@ static ssize_t handle_llistxattr(FsContext *ctx, V9fsPath *fs_path,
return ret;
}
+static ssize_t handle_flistxattr(FsContext *ctx, int fid_type,
+ V9fsFidOpenState *fs, void *value, size_t size)
+{
+ int fd;
+
+ fd = v9fs_get_fd_fid(fid_type, fs);
+ return flistxattr(fd, value, size);
+}
+
static int handle_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name,
void *value, size_t size, int flags)
{
@@ -747,4 +756,5 @@ FileOperations handle_ops = {
.fchown = handle_fchown,
.fchmod = handle_fchmod,
.fgetxattr = handle_fgetxattr,
+ .flistxattr = handle_flistxattr,
};
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index 206849a3ed83..3a1caeccdf00 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -1122,6 +1122,15 @@ static ssize_t local_llistxattr(FsContext *ctx, V9fsPath *fs_path,
return v9fs_list_xattr(ctx, -1, path, value, size);
}
+static ssize_t local_flistxattr(FsContext *ctx, int fid_type,
+ V9fsFidOpenState *fs, void *value, size_t size)
+{
+ int fd;
+
+ fd = v9fs_get_fd_fid(fid_type, fs);
+ return v9fs_list_xattr(ctx, fd, NULL, value, size);
+}
+
static int local_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name,
void *value, size_t size, int flags)
{
@@ -1368,4 +1377,5 @@ FileOperations local_ops = {
.fchown = local_fchown,
.fchmod = local_fchmod,
.fgetxattr = local_fgetxattr,
+ .flistxattr = local_flistxattr,
};
diff --git a/hw/9pfs/9p-proxy.c b/hw/9pfs/9p-proxy.c
index 074799027873..94ee76f1fbf6 100644
--- a/hw/9pfs/9p-proxy.c
+++ b/hw/9pfs/9p-proxy.c
@@ -1029,6 +1029,15 @@ static ssize_t proxy_llistxattr(FsContext *ctx, V9fsPath *fs_path,
return retval;
}
+static ssize_t proxy_flistxattr(FsContext *ctx, int fid_type,
+ V9fsFidOpenState *fs, void *value, size_t size)
+{
+ int fd;
+
+ fd = v9fs_get_fd_fid(fid_type, fs);
+ return flistxattr(fd, value, size);
+}
+
static int proxy_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name,
void *value, size_t size, int flags)
{
@@ -1263,4 +1272,5 @@ FileOperations proxy_ops = {
.fchown = proxy_fchown,
.fchmod = proxy_fchmod,
.fgetxattr = proxy_fgetxattr,
+ .flistxattr = proxy_flistxattr,
};
diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c
index 24505fc2f621..9cd098914d08 100644
--- a/hw/9pfs/9p-synth.c
+++ b/hw/9pfs/9p-synth.c
@@ -479,6 +479,13 @@ static ssize_t synth_llistxattr(FsContext *ctx, V9fsPath *path,
return -1;
}
+static ssize_t synth_flistxattr(FsContext *ctx, int fid_type,
+ V9fsFidOpenState *fs, void *value, size_t size)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
static int synth_lsetxattr(FsContext *ctx, V9fsPath *path,
const char *name, void *value,
size_t size, int flags)
@@ -607,4 +614,5 @@ FileOperations synth_ops = {
.fchown = synth_fchown,
.fchmod = synth_fchmod,
.fgetxattr = synth_fgetxattr,
+ .flistxattr = synth_flistxattr,
};
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 435100f85be3..14aee2e749d8 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -3125,6 +3125,16 @@ static int v9fs_do_getxattr(V9fsPDU *pdu, V9fsFidState *fidp, V9fsString *name,
}
}
+static int v9fs_do_listxattr(V9fsPDU *pdu, V9fsFidState *fidp, void *value,
+ size_t size)
+{
+ if (fid_has_file(fidp)) {
+ return v9fs_co_flistxattr(pdu, fidp, value, size);
+ } else {
+ return v9fs_co_llistxattr(pdu, &fidp->path, value, size);
+ }
+}
+
static void v9fs_xattrwalk(void *opaque)
{
int64_t size;
@@ -3163,7 +3173,7 @@ static void v9fs_xattrwalk(void *opaque)
/*
* listxattr request. Get the size first
*/
- size = v9fs_co_llistxattr(pdu, &xattr_fidp->path, NULL, 0);
+ size = v9fs_do_listxattr(pdu, xattr_fidp, NULL, 0);
if (size < 0) {
err = size;
clunk_fid(s, xattr_fidp->fid);
@@ -3175,9 +3185,9 @@ static void v9fs_xattrwalk(void *opaque)
xattr_fidp->fs.xattr.len = size;
if (size) {
xattr_fidp->fs.xattr.value = g_malloc(size);
- err = v9fs_co_llistxattr(pdu, &xattr_fidp->path,
- xattr_fidp->fs.xattr.value,
- xattr_fidp->fs.xattr.len);
+ err = v9fs_do_listxattr(pdu, xattr_fidp,
+ xattr_fidp->fs.xattr.value,
+ xattr_fidp->fs.xattr.len);
if (err < 0) {
clunk_fid(s, xattr_fidp->fid);
goto out;
diff --git a/hw/9pfs/coth.h b/hw/9pfs/coth.h
index 2e507939d01d..ddb061d91ed3 100644
--- a/hw/9pfs/coth.h
+++ b/hw/9pfs/coth.h
@@ -100,5 +100,6 @@ extern int v9fs_co_fchown(V9fsPDU *, V9fsFidState *, uid_t, gid_t);
extern int v9fs_co_fchmod(V9fsPDU *, V9fsFidState *, mode_t);
extern int v9fs_co_fgetxattr(V9fsPDU *, V9fsFidState *, V9fsString *, void *,
size_t);
+extern int v9fs_co_flistxattr(V9fsPDU *, V9fsFidState *, void *, size_t);
#endif
diff --git a/hw/9pfs/coxattr.c b/hw/9pfs/coxattr.c
index 72e3f38fb371..f4944e6abae3 100644
--- a/hw/9pfs/coxattr.c
+++ b/hw/9pfs/coxattr.c
@@ -37,6 +37,26 @@ int v9fs_co_llistxattr(V9fsPDU *pdu, V9fsPath *path, void *value, size_t size)
return err;
}
+int v9fs_co_flistxattr(V9fsPDU *pdu, V9fsFidState *fidp, void *value,
+ size_t size)
+{
+ int err;
+ V9fsState *s = pdu->s;
+
+ if (v9fs_request_cancelled(pdu)) {
+ return -EINTR;
+ }
+ v9fs_co_run_in_worker(
+ {
+ err = s->ops->flistxattr(&s->ctx, fidp->fid_type, &fidp->fs, value,
+ size);
+ if (err < 0) {
+ err = -errno;
+ }
+ });
+ return err;
+}
+
int v9fs_co_lgetxattr(V9fsPDU *pdu, V9fsPath *path,
V9fsString *xattr_name,
void *value, size_t size)
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [Qemu-devel] [PATCH 01/13] 9p: synth: drop v9fs_ prefix
2016-06-27 9:41 ` [Qemu-devel] [PATCH 01/13] 9p: synth: drop v9fs_ prefix Greg Kurz
@ 2016-06-30 11:45 ` Cédric Le Goater
0 siblings, 0 replies; 16+ messages in thread
From: Cédric Le Goater @ 2016-06-30 11:45 UTC (permalink / raw)
To: Greg Kurz, qemu-devel
Cc: Eric Van Hensbergen, v9fs-developer, Aneesh Kumar K.V
On 06/27/2016 11:41 AM, Greg Kurz wrote:
> To have shorter lines and be consistent with other fs devices.
>
> Signed-off-by: Greg Kurz <groug@kaod.org>
Acked-by: Cédric Le Goater <clg@kaod.org>
> ---
> hw/9pfs/9p-synth.c | 200 ++++++++++++++++++++++++++--------------------------
> 1 file changed, 100 insertions(+), 100 deletions(-)
>
> diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c
> index 73c8be816bbb..4b6d4e6a3f1c 100644
> --- a/hw/9pfs/9p-synth.c
> +++ b/hw/9pfs/9p-synth.c
> @@ -21,19 +21,19 @@
> #include "qemu/cutils.h"
>
> /* Root node for synth file system */
> -static V9fsSynthNode v9fs_synth_root = {
> +static V9fsSynthNode synth_root = {
> .name = "/",
> .actual_attr = {
> .mode = 0555 | S_IFDIR,
> .nlink = 1,
> },
> - .attr = &v9fs_synth_root.actual_attr,
> + .attr = &synth_root.actual_attr,
> };
>
> -static QemuMutex v9fs_synth_mutex;
> -static int v9fs_synth_node_count;
> +static QemuMutex synth_mutex;
> +static int synth_node_count;
> /* set to 1 when the synth fs is ready */
> -static int v9fs_synth_fs;
> +static int synth_fs;
>
> static V9fsSynthNode *v9fs_add_dir_node(V9fsSynthNode *parent, int mode,
> const char *name,
> @@ -69,16 +69,16 @@ int qemu_v9fs_synth_mkdir(V9fsSynthNode *parent, int mode,
> int ret;
> V9fsSynthNode *node, *tmp;
>
> - if (!v9fs_synth_fs) {
> + if (!synth_fs) {
> return EAGAIN;
> }
> if (!name || (strlen(name) >= NAME_MAX)) {
> return EINVAL;
> }
> if (!parent) {
> - parent = &v9fs_synth_root;
> + parent = &synth_root;
> }
> - qemu_mutex_lock(&v9fs_synth_mutex);
> + qemu_mutex_lock(&synth_mutex);
> QLIST_FOREACH(tmp, &parent->child, sibling) {
> if (!strcmp(tmp->name, name)) {
> ret = EEXIST;
> @@ -86,7 +86,7 @@ int qemu_v9fs_synth_mkdir(V9fsSynthNode *parent, int mode,
> }
> }
> /* Add the name */
> - node = v9fs_add_dir_node(parent, mode, name, NULL, v9fs_synth_node_count++);
> + node = v9fs_add_dir_node(parent, mode, name, NULL, synth_node_count++);
> v9fs_add_dir_node(node, parent->attr->mode, "..",
> parent->attr, parent->attr->inode);
> v9fs_add_dir_node(node, node->attr->mode, ".",
> @@ -94,7 +94,7 @@ int qemu_v9fs_synth_mkdir(V9fsSynthNode *parent, int mode,
> *result = node;
> ret = 0;
> err_out:
> - qemu_mutex_unlock(&v9fs_synth_mutex);
> + qemu_mutex_unlock(&synth_mutex);
> return ret;
> }
>
> @@ -105,17 +105,17 @@ int qemu_v9fs_synth_add_file(V9fsSynthNode *parent, int mode,
> int ret;
> V9fsSynthNode *node, *tmp;
>
> - if (!v9fs_synth_fs) {
> + if (!synth_fs) {
> return EAGAIN;
> }
> if (!name || (strlen(name) >= NAME_MAX)) {
> return EINVAL;
> }
> if (!parent) {
> - parent = &v9fs_synth_root;
> + parent = &synth_root;
> }
>
> - qemu_mutex_lock(&v9fs_synth_mutex);
> + qemu_mutex_lock(&synth_mutex);
> QLIST_FOREACH(tmp, &parent->child, sibling) {
> if (!strcmp(tmp->name, name)) {
> ret = EEXIST;
> @@ -126,7 +126,7 @@ int qemu_v9fs_synth_add_file(V9fsSynthNode *parent, int mode,
> mode = ((mode & 0777) | S_IFREG);
> node = g_malloc0(sizeof(V9fsSynthNode));
> node->attr = &node->actual_attr;
> - node->attr->inode = v9fs_synth_node_count++;
> + node->attr->inode = synth_node_count++;
> node->attr->nlink = 1;
> node->attr->read = read;
> node->attr->write = write;
> @@ -136,11 +136,11 @@ int qemu_v9fs_synth_add_file(V9fsSynthNode *parent, int mode,
> QLIST_INSERT_HEAD_RCU(&parent->child, node, sibling);
> ret = 0;
> err_out:
> - qemu_mutex_unlock(&v9fs_synth_mutex);
> + qemu_mutex_unlock(&synth_mutex);
> return ret;
> }
>
> -static void v9fs_synth_fill_statbuf(V9fsSynthNode *node, struct stat *stbuf)
> +static void synth_fill_statbuf(V9fsSynthNode *node, struct stat *stbuf)
> {
> stbuf->st_dev = 0;
> stbuf->st_ino = node->attr->inode;
> @@ -157,24 +157,24 @@ static void v9fs_synth_fill_statbuf(V9fsSynthNode *node, struct stat *stbuf)
> stbuf->st_ctime = 0;
> }
>
> -static int v9fs_synth_lstat(FsContext *fs_ctx,
> +static int synth_lstat(FsContext *fs_ctx,
> V9fsPath *fs_path, struct stat *stbuf)
> {
> V9fsSynthNode *node = *(V9fsSynthNode **)fs_path->data;
>
> - v9fs_synth_fill_statbuf(node, stbuf);
> + synth_fill_statbuf(node, stbuf);
> return 0;
> }
>
> -static int v9fs_synth_fstat(FsContext *fs_ctx, int fid_type,
> +static int synth_fstat(FsContext *fs_ctx, int fid_type,
> V9fsFidOpenState *fs, struct stat *stbuf)
> {
> V9fsSynthOpenState *synth_open = fs->private;
> - v9fs_synth_fill_statbuf(synth_open->node, stbuf);
> + synth_fill_statbuf(synth_open->node, stbuf);
> return 0;
> }
>
> -static int v9fs_synth_opendir(FsContext *ctx,
> +static int synth_opendir(FsContext *ctx,
> V9fsPath *fs_path, V9fsFidOpenState *fs)
> {
> V9fsSynthOpenState *synth_open;
> @@ -187,7 +187,7 @@ static int v9fs_synth_opendir(FsContext *ctx,
> return 0;
> }
>
> -static int v9fs_synth_closedir(FsContext *ctx, V9fsFidOpenState *fs)
> +static int synth_closedir(FsContext *ctx, V9fsFidOpenState *fs)
> {
> V9fsSynthOpenState *synth_open = fs->private;
> V9fsSynthNode *node = synth_open->node;
> @@ -198,24 +198,24 @@ static int v9fs_synth_closedir(FsContext *ctx, V9fsFidOpenState *fs)
> return 0;
> }
>
> -static off_t v9fs_synth_telldir(FsContext *ctx, V9fsFidOpenState *fs)
> +static off_t synth_telldir(FsContext *ctx, V9fsFidOpenState *fs)
> {
> V9fsSynthOpenState *synth_open = fs->private;
> return synth_open->offset;
> }
>
> -static void v9fs_synth_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
> +static void synth_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
> {
> V9fsSynthOpenState *synth_open = fs->private;
> synth_open->offset = off;
> }
>
> -static void v9fs_synth_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
> +static void synth_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
> {
> - v9fs_synth_seekdir(ctx, fs, 0);
> + synth_seekdir(ctx, fs, 0);
> }
>
> -static void v9fs_synth_direntry(V9fsSynthNode *node,
> +static void synth_direntry(V9fsSynthNode *node,
> struct dirent *entry, off_t off)
> {
> strcpy(entry->d_name, node->name);
> @@ -223,7 +223,7 @@ static void v9fs_synth_direntry(V9fsSynthNode *node,
> entry->d_off = off + 1;
> }
>
> -static struct dirent *v9fs_synth_get_dentry(V9fsSynthNode *dir,
> +static struct dirent *synth_get_dentry(V9fsSynthNode *dir,
> struct dirent *entry, off_t off)
> {
> int i = 0;
> @@ -242,23 +242,23 @@ static struct dirent *v9fs_synth_get_dentry(V9fsSynthNode *dir,
> /* end of directory */
> return NULL;
> }
> - v9fs_synth_direntry(node, entry, off);
> + synth_direntry(node, entry, off);
> return entry;
> }
>
> -static struct dirent *v9fs_synth_readdir(FsContext *ctx, V9fsFidOpenState *fs)
> +static struct dirent *synth_readdir(FsContext *ctx, V9fsFidOpenState *fs)
> {
> struct dirent *entry;
> V9fsSynthOpenState *synth_open = fs->private;
> V9fsSynthNode *node = synth_open->node;
> - entry = v9fs_synth_get_dentry(node, &synth_open->dent, synth_open->offset);
> + entry = synth_get_dentry(node, &synth_open->dent, synth_open->offset);
> if (entry) {
> synth_open->offset++;
> }
> return entry;
> }
>
> -static int v9fs_synth_open(FsContext *ctx, V9fsPath *fs_path,
> +static int synth_open(FsContext *ctx, V9fsPath *fs_path,
> int flags, V9fsFidOpenState *fs)
> {
> V9fsSynthOpenState *synth_open;
> @@ -271,7 +271,7 @@ static int v9fs_synth_open(FsContext *ctx, V9fsPath *fs_path,
> return 0;
> }
>
> -static int v9fs_synth_open2(FsContext *fs_ctx, V9fsPath *dir_path,
> +static int synth_open2(FsContext *fs_ctx, V9fsPath *dir_path,
> const char *name, int flags,
> FsCred *credp, V9fsFidOpenState *fs)
> {
> @@ -279,7 +279,7 @@ static int v9fs_synth_open2(FsContext *fs_ctx, V9fsPath *dir_path,
> return -1;
> }
>
> -static int v9fs_synth_close(FsContext *ctx, V9fsFidOpenState *fs)
> +static int synth_close(FsContext *ctx, V9fsFidOpenState *fs)
> {
> V9fsSynthOpenState *synth_open = fs->private;
> V9fsSynthNode *node = synth_open->node;
> @@ -290,7 +290,7 @@ static int v9fs_synth_close(FsContext *ctx, V9fsFidOpenState *fs)
> return 0;
> }
>
> -static ssize_t v9fs_synth_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
> +static ssize_t synth_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
> const struct iovec *iov,
> int iovcnt, off_t offset)
> {
> @@ -314,7 +314,7 @@ static ssize_t v9fs_synth_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
> return count;
> }
>
> -static ssize_t v9fs_synth_preadv(FsContext *ctx, V9fsFidOpenState *fs,
> +static ssize_t synth_preadv(FsContext *ctx, V9fsFidOpenState *fs,
> const struct iovec *iov,
> int iovcnt, off_t offset)
> {
> @@ -338,112 +338,112 @@ static ssize_t v9fs_synth_preadv(FsContext *ctx, V9fsFidOpenState *fs,
> return count;
> }
>
> -static int v9fs_synth_truncate(FsContext *ctx, V9fsPath *path, off_t offset)
> +static int synth_truncate(FsContext *ctx, V9fsPath *path, off_t offset)
> {
> errno = ENOSYS;
> return -1;
> }
>
> -static int v9fs_synth_chmod(FsContext *fs_ctx, V9fsPath *path, FsCred *credp)
> +static int synth_chmod(FsContext *fs_ctx, V9fsPath *path, FsCred *credp)
> {
> errno = EPERM;
> return -1;
> }
>
> -static int v9fs_synth_mknod(FsContext *fs_ctx, V9fsPath *path,
> +static int synth_mknod(FsContext *fs_ctx, V9fsPath *path,
> const char *buf, FsCred *credp)
> {
> errno = EPERM;
> return -1;
> }
>
> -static int v9fs_synth_mkdir(FsContext *fs_ctx, V9fsPath *path,
> +static int synth_mkdir(FsContext *fs_ctx, V9fsPath *path,
> const char *buf, FsCred *credp)
> {
> errno = EPERM;
> return -1;
> }
>
> -static ssize_t v9fs_synth_readlink(FsContext *fs_ctx, V9fsPath *path,
> +static ssize_t synth_readlink(FsContext *fs_ctx, V9fsPath *path,
> char *buf, size_t bufsz)
> {
> errno = ENOSYS;
> return -1;
> }
>
> -static int v9fs_synth_symlink(FsContext *fs_ctx, const char *oldpath,
> +static int synth_symlink(FsContext *fs_ctx, const char *oldpath,
> V9fsPath *newpath, const char *buf, FsCred *credp)
> {
> errno = EPERM;
> return -1;
> }
>
> -static int v9fs_synth_link(FsContext *fs_ctx, V9fsPath *oldpath,
> +static int synth_link(FsContext *fs_ctx, V9fsPath *oldpath,
> V9fsPath *newpath, const char *buf)
> {
> errno = EPERM;
> return -1;
> }
>
> -static int v9fs_synth_rename(FsContext *ctx, const char *oldpath,
> +static int synth_rename(FsContext *ctx, const char *oldpath,
> const char *newpath)
> {
> errno = EPERM;
> return -1;
> }
>
> -static int v9fs_synth_chown(FsContext *fs_ctx, V9fsPath *path, FsCred *credp)
> +static int synth_chown(FsContext *fs_ctx, V9fsPath *path, FsCred *credp)
> {
> errno = EPERM;
> return -1;
> }
>
> -static int v9fs_synth_utimensat(FsContext *fs_ctx, V9fsPath *path,
> +static int synth_utimensat(FsContext *fs_ctx, V9fsPath *path,
> const struct timespec *buf)
> {
> errno = EPERM;
> return 0;
> }
>
> -static int v9fs_synth_remove(FsContext *ctx, const char *path)
> +static int synth_remove(FsContext *ctx, const char *path)
> {
> errno = EPERM;
> return -1;
> }
>
> -static int v9fs_synth_fsync(FsContext *ctx, int fid_type,
> +static int synth_fsync(FsContext *ctx, int fid_type,
> V9fsFidOpenState *fs, int datasync)
> {
> errno = ENOSYS;
> return 0;
> }
>
> -static int v9fs_synth_statfs(FsContext *s, V9fsPath *fs_path,
> +static int synth_statfs(FsContext *s, V9fsPath *fs_path,
> struct statfs *stbuf)
> {
> stbuf->f_type = 0xABCD;
> stbuf->f_bsize = 512;
> stbuf->f_blocks = 0;
> - stbuf->f_files = v9fs_synth_node_count;
> + stbuf->f_files = synth_node_count;
> stbuf->f_namelen = NAME_MAX;
> return 0;
> }
>
> -static ssize_t v9fs_synth_lgetxattr(FsContext *ctx, V9fsPath *path,
> +static ssize_t synth_lgetxattr(FsContext *ctx, V9fsPath *path,
> const char *name, void *value, size_t size)
> {
> errno = ENOTSUP;
> return -1;
> }
>
> -static ssize_t v9fs_synth_llistxattr(FsContext *ctx, V9fsPath *path,
> +static ssize_t synth_llistxattr(FsContext *ctx, V9fsPath *path,
> void *value, size_t size)
> {
> errno = ENOTSUP;
> return -1;
> }
>
> -static int v9fs_synth_lsetxattr(FsContext *ctx, V9fsPath *path,
> +static int synth_lsetxattr(FsContext *ctx, V9fsPath *path,
> const char *name, void *value,
> size_t size, int flags)
> {
> @@ -451,14 +451,14 @@ static int v9fs_synth_lsetxattr(FsContext *ctx, V9fsPath *path,
> return -1;
> }
>
> -static int v9fs_synth_lremovexattr(FsContext *ctx,
> +static int synth_lremovexattr(FsContext *ctx,
> V9fsPath *path, const char *name)
> {
> errno = ENOTSUP;
> return -1;
> }
>
> -static int v9fs_synth_name_to_path(FsContext *ctx, V9fsPath *dir_path,
> +static int synth_name_to_path(FsContext *ctx, V9fsPath *dir_path,
> const char *name, V9fsPath *target)
> {
> V9fsSynthNode *node;
> @@ -471,7 +471,7 @@ static int v9fs_synth_name_to_path(FsContext *ctx, V9fsPath *dir_path,
>
> }
> if (!dir_path) {
> - dir_node = &v9fs_synth_root;
> + dir_node = &synth_root;
> } else {
> dir_node = *(V9fsSynthNode **)dir_path->data;
> }
> @@ -500,7 +500,7 @@ out:
> return 0;
> }
>
> -static int v9fs_synth_renameat(FsContext *ctx, V9fsPath *olddir,
> +static int synth_renameat(FsContext *ctx, V9fsPath *olddir,
> const char *old_name, V9fsPath *newdir,
> const char *new_name)
> {
> @@ -508,62 +508,62 @@ static int v9fs_synth_renameat(FsContext *ctx, V9fsPath *olddir,
> return -1;
> }
>
> -static int v9fs_synth_unlinkat(FsContext *ctx, V9fsPath *dir,
> +static int synth_unlinkat(FsContext *ctx, V9fsPath *dir,
> const char *name, int flags)
> {
> errno = EPERM;
> return -1;
> }
>
> -static int v9fs_synth_init(FsContext *ctx)
> +static int synth_init(FsContext *ctx)
> {
> - QLIST_INIT(&v9fs_synth_root.child);
> - qemu_mutex_init(&v9fs_synth_mutex);
> + QLIST_INIT(&synth_root.child);
> + qemu_mutex_init(&synth_mutex);
>
> /* Add "." and ".." entries for root */
> - v9fs_add_dir_node(&v9fs_synth_root, v9fs_synth_root.attr->mode,
> - "..", v9fs_synth_root.attr, v9fs_synth_root.attr->inode);
> - v9fs_add_dir_node(&v9fs_synth_root, v9fs_synth_root.attr->mode,
> - ".", v9fs_synth_root.attr, v9fs_synth_root.attr->inode);
> + v9fs_add_dir_node(&synth_root, synth_root.attr->mode,
> + "..", synth_root.attr, synth_root.attr->inode);
> + v9fs_add_dir_node(&synth_root, synth_root.attr->mode,
> + ".", synth_root.attr, synth_root.attr->inode);
>
> /* Mark the subsystem is ready for use */
> - v9fs_synth_fs = 1;
> + synth_fs = 1;
> return 0;
> }
>
> FileOperations synth_ops = {
> - .init = v9fs_synth_init,
> - .lstat = v9fs_synth_lstat,
> - .readlink = v9fs_synth_readlink,
> - .close = v9fs_synth_close,
> - .closedir = v9fs_synth_closedir,
> - .open = v9fs_synth_open,
> - .opendir = v9fs_synth_opendir,
> - .rewinddir = v9fs_synth_rewinddir,
> - .telldir = v9fs_synth_telldir,
> - .readdir = v9fs_synth_readdir,
> - .seekdir = v9fs_synth_seekdir,
> - .preadv = v9fs_synth_preadv,
> - .pwritev = v9fs_synth_pwritev,
> - .chmod = v9fs_synth_chmod,
> - .mknod = v9fs_synth_mknod,
> - .mkdir = v9fs_synth_mkdir,
> - .fstat = v9fs_synth_fstat,
> - .open2 = v9fs_synth_open2,
> - .symlink = v9fs_synth_symlink,
> - .link = v9fs_synth_link,
> - .truncate = v9fs_synth_truncate,
> - .rename = v9fs_synth_rename,
> - .chown = v9fs_synth_chown,
> - .utimensat = v9fs_synth_utimensat,
> - .remove = v9fs_synth_remove,
> - .fsync = v9fs_synth_fsync,
> - .statfs = v9fs_synth_statfs,
> - .lgetxattr = v9fs_synth_lgetxattr,
> - .llistxattr = v9fs_synth_llistxattr,
> - .lsetxattr = v9fs_synth_lsetxattr,
> - .lremovexattr = v9fs_synth_lremovexattr,
> - .name_to_path = v9fs_synth_name_to_path,
> - .renameat = v9fs_synth_renameat,
> - .unlinkat = v9fs_synth_unlinkat,
> + .init = synth_init,
> + .lstat = synth_lstat,
> + .readlink = synth_readlink,
> + .close = synth_close,
> + .closedir = synth_closedir,
> + .open = synth_open,
> + .opendir = synth_opendir,
> + .rewinddir = synth_rewinddir,
> + .telldir = synth_telldir,
> + .readdir = synth_readdir,
> + .seekdir = synth_seekdir,
> + .preadv = synth_preadv,
> + .pwritev = synth_pwritev,
> + .chmod = synth_chmod,
> + .mknod = synth_mknod,
> + .mkdir = synth_mkdir,
> + .fstat = synth_fstat,
> + .open2 = synth_open2,
> + .symlink = synth_symlink,
> + .link = synth_link,
> + .truncate = synth_truncate,
> + .rename = synth_rename,
> + .chown = synth_chown,
> + .utimensat = synth_utimensat,
> + .remove = synth_remove,
> + .fsync = synth_fsync,
> + .statfs = synth_statfs,
> + .lgetxattr = synth_lgetxattr,
> + .llistxattr = synth_llistxattr,
> + .lsetxattr = synth_lsetxattr,
> + .lremovexattr = synth_lremovexattr,
> + .name_to_path = synth_name_to_path,
> + .renameat = synth_renameat,
> + .unlinkat = synth_unlinkat,
> };
>
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Qemu-devel] [PATCH 00/13] 9p: reconcile virtfs with unlinked files
2016-06-27 9:40 [Qemu-devel] [PATCH 00/13] 9p: reconcile virtfs with unlinked files Greg Kurz
` (12 preceding siblings ...)
2016-06-27 9:42 ` [Qemu-devel] [PATCH 13/13] 9p: introduce flistxattr " Greg Kurz
@ 2016-07-04 12:40 ` Greg Kurz
13 siblings, 0 replies; 16+ messages in thread
From: Greg Kurz @ 2016-07-04 12:40 UTC (permalink / raw)
To: qemu-devel; +Cc: Eric Van Hensbergen, v9fs-developer, Aneesh Kumar K.V
Aneesh,
Can you review this series please, and maybe provide feedback on the
patches for the linux client ?
Thanks.
--
Greg
On Mon, 27 Jun 2016 11:40:55 +0200
Greg Kurz <groug@kaod.org> wrote:
> This series addresses a long standing issue in 9p, where most syscalls
> accessing file attributes out of file descriptor stop to work in the
> guest when the file gets unlinked:
>
> open("./test.txt", O_RDWR|O_CREAT, 0666) = 4
> unlink("./test.txt") = 0
> fstat(4, 0x3fffc22108d0) = -1 ENOENT (No such file or directory)
> ftruncate(4, 0) = -1 ENOENT (No such file or directory)
> utimensat(4, NULL, NULL, 0) = -1 ENOENT (No such file or directory)
> fgetxattr(4, "user.greg", NULL, 0) = -1 ENOENT (No such file or directory)
> flistxattr(4, NULL, 0) = -1 ENOENT (No such file or directory)
> fchmod(4, 0) = -1 ENOENT (No such file or directory)
> fchown(4, -1, -1) = -1 ENOENT (No such file or directory)
>
> There is also another case where ftruncate() unexpectedly fails:
>
> open("./test.txt", O_RDWR|O_CREAT, 0666) = 4
> chmod("./test.txt", 0) = 0
> ftruncate(4, 0) = -1 EACCES (Permission denied)
>
> Since the open+unlink sequence is widely used in applications, these
> failures are really a problem, and does not encourage people to using
> 9p mounts.
>
> The root cause for all these errors is that QEMU uses path based syscalls to
> implement 9p operations on file attributes, even if the fid has an open fd.
>
> This series adds new file ops to the internal fsdev API, following the example
> of already existing fstat, so that backends can access the fid file descriptor
> and pass it to ftruncate(), fchmod() and friends.
>
> This can be tested with a linux guest, provided the 9p client in the kernel is
> fixed with the following patches, to ensure it passes open fids (fid associated
> to a valid file descriptor) to the 9p server in QEMU.
>
> https://sourceforge.net/p/v9fs/mailman/message/35175775/
>
> With this series and the patched guest kernel, all the failures mentionned
> above no longer occur.
>
> ---
>
> Greg Kurz (13):
> 9p: synth: drop v9fs_ prefix
> 9p: factour out duplicate code from local_fstat() and local_lstat()
> 9p: introduce the v9fs_get_fd_fid() helper
> 9p: getattr: use fstat if we have a fd
> 9p: introduce ftruncate file op
> oslib: support futimens() if available
> 9p: introduce futimens file op
> 9p: add a fd argument to xattr helpers
> 9p: introduce fchown file op
> 9p: introduce fchmod file op
> 9p: xattr fid to reference file fid
> 9p: introduce fgetxattr file op
> 9p: introduce flistxattr file op
>
>
> fsdev/file-op-9p.h | 9 ++
> hw/9pfs/9p-handle.c | 85 ++++++++++++---
> hw/9pfs/9p-local.c | 213 ++++++++++++++++++++++++++++----------
> hw/9pfs/9p-posix-acl.c | 80 ++++++++++----
> hw/9pfs/9p-proxy.c | 78 ++++++++++++--
> hw/9pfs/9p-synth.c | 249 +++++++++++++++++++++++++++------------------
> hw/9pfs/9p-xattr-user.c | 41 +++++--
> hw/9pfs/9p-xattr.c | 35 ++++--
> hw/9pfs/9p-xattr.h | 67 +++++++-----
> hw/9pfs/9p.c | 189 +++++++++++++++++++++++++++++-----
> hw/9pfs/9p.h | 3 +
> hw/9pfs/cofs.c | 79 ++++++++++++++
> hw/9pfs/coth.h | 7 +
> hw/9pfs/coxattr.c | 42 ++++++++
> include/sysemu/os-posix.h | 1
> util/oslib-posix.c | 10 ++
> 16 files changed, 896 insertions(+), 292 deletions(-)
>
> --
> Greg
>
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2016-07-04 12:40 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-06-27 9:40 [Qemu-devel] [PATCH 00/13] 9p: reconcile virtfs with unlinked files Greg Kurz
2016-06-27 9:41 ` [Qemu-devel] [PATCH 01/13] 9p: synth: drop v9fs_ prefix Greg Kurz
2016-06-30 11:45 ` Cédric Le Goater
2016-06-27 9:41 ` [Qemu-devel] [PATCH 02/13] 9p: factour out duplicate code from local_fstat() and local_lstat() Greg Kurz
2016-06-27 9:41 ` [Qemu-devel] [PATCH 03/13] 9p: introduce the v9fs_get_fd_fid() helper Greg Kurz
2016-06-27 9:41 ` [Qemu-devel] [PATCH 04/13] 9p: getattr: use fstat if we have a fd Greg Kurz
2016-06-27 9:41 ` [Qemu-devel] [PATCH 05/13] 9p: introduce ftruncate file op Greg Kurz
2016-06-27 9:41 ` [Qemu-devel] [PATCH 06/13] oslib: support futimens() if available Greg Kurz
2016-06-27 9:41 ` [Qemu-devel] [PATCH 07/13] 9p: introduce futimens file op Greg Kurz
2016-06-27 9:42 ` [Qemu-devel] [PATCH 08/13] 9p: add a fd argument to xattr helpers Greg Kurz
2016-06-27 9:42 ` [Qemu-devel] [PATCH 09/13] 9p: introduce fchown file op Greg Kurz
2016-06-27 9:42 ` [Qemu-devel] [PATCH 10/13] 9p: introduce fchmod " Greg Kurz
2016-06-27 9:42 ` [Qemu-devel] [PATCH 11/13] 9p: xattr fid to reference file fid Greg Kurz
2016-06-27 9:42 ` [Qemu-devel] [PATCH 12/13] 9p: introduce fgetxattr file op Greg Kurz
2016-06-27 9:42 ` [Qemu-devel] [PATCH 13/13] 9p: introduce flistxattr " Greg Kurz
2016-07-04 12:40 ` [Qemu-devel] [PATCH 00/13] 9p: reconcile virtfs with unlinked files Greg Kurz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).