This allows flistxattr() in the guest to stay functional even if the file was unlinked.
Signed-off-by: Greg Kurz <gr...@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)