@@ -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;
};
@@ -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,
};
@@ -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,
};
@@ -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,
};
@@ -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,
};
@@ -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;
@@ -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
@@ -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)
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(-) ------------------------------------------------------------------------------ Attend Shape: An AT&T Tech Expo July 15-16. Meet us at AT&T Park in San Francisco, CA to explore cutting-edge tech and listen to tech luminaries present their vision of the future. This family event has something for everyone, including kids. Get more information and register today. http://sdm.link/attshape