aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Kurz <groug@kaod.org>2025-03-12 16:29:30 +0100
committerChristian Schoenebeck <qemu_oss@crudebyte.com>2025-05-05 11:28:29 +0200
commit371a269ff8ce561c28e4fa03bb49e4940f990637 (patch)
tree42713e4b60379d25f0006ed08760d7926deb6023
parent0c798dd52355f3489b29bba0dfd7df0e24cfa1dd (diff)
downloadqemu-371a269ff8ce561c28e4fa03bb49e4940f990637.zip
qemu-371a269ff8ce561c28e4fa03bb49e4940f990637.tar.gz
qemu-371a269ff8ce561c28e4fa03bb49e4940f990637.tar.bz2
9pfs: Introduce futimens file op
Add an futimens operation to the fs driver and use if when a fid has a valid file descriptor. This is required to support more cases where the client wants to do an action on an unlinked file which it still has an open file decriptor for. Only 9P2000.L was considered. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Christian Schoenebeck <qemu_oss@crudebyte.com> Message-Id: <20250312152933.383967-5-groug@kaod.org> Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
-rw-r--r--fsdev/file-op-9p.h2
-rw-r--r--hw/9pfs/9p-local.c9
-rw-r--r--hw/9pfs/9p-synth.c8
-rw-r--r--hw/9pfs/9p-util.h1
-rw-r--r--hw/9pfs/9p.c6
-rw-r--r--hw/9pfs/cofs.c19
-rw-r--r--hw/9pfs/coth.h2
7 files changed, 46 insertions, 1 deletions
diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index 26ba143..b9dae8c 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -129,6 +129,8 @@ struct FileOperations {
int (*chown)(FsContext *, V9fsPath *, FsCred *);
int (*mknod)(FsContext *, V9fsPath *, const char *, FsCred *);
int (*utimensat)(FsContext *, V9fsPath *, const struct timespec *);
+ int (*futimens)(FsContext *ctx, int fid_type, V9fsFidOpenState *fs,
+ const struct timespec *times);
int (*remove)(FsContext *, const char *);
int (*symlink)(FsContext *, const char *, V9fsPath *,
const char *, FsCred *);
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index 0b33da8..31e2162 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -1100,6 +1100,14 @@ out:
return ret;
}
+static int local_futimens(FsContext *s, int fid_type, V9fsFidOpenState *fs,
+ const struct timespec *times)
+{
+ int fd = local_fid_fd(fid_type, fs);
+
+ return qemu_futimens(fd, times);
+}
+
static int local_unlinkat_common(FsContext *ctx, int dirfd, const char *name,
int flags)
{
@@ -1626,4 +1634,5 @@ FileOperations local_ops = {
.unlinkat = local_unlinkat,
.has_valid_file_handle = local_has_valid_file_handle,
.ftruncate = local_ftruncate,
+ .futimens = local_futimens,
};
diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c
index 3d28afc..9cd1884 100644
--- a/hw/9pfs/9p-synth.c
+++ b/hw/9pfs/9p-synth.c
@@ -424,6 +424,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 = ENOSYS;
+ return -1;
+}
+
static int synth_remove(FsContext *ctx, const char *path)
{
errno = EPERM;
@@ -664,4 +671,5 @@ FileOperations synth_ops = {
.unlinkat = synth_unlinkat,
.has_valid_file_handle = synth_has_valid_file_handle,
.ftruncate = synth_ftruncate,
+ .futimens = synth_futimens,
};
diff --git a/hw/9pfs/9p-util.h b/hw/9pfs/9p-util.h
index 7bc4ec8..a1924fe 100644
--- a/hw/9pfs/9p-util.h
+++ b/hw/9pfs/9p-util.h
@@ -103,6 +103,7 @@ static inline int errno_to_dotl(int err) {
#define qemu_renameat renameat
#define qemu_utimensat utimensat
#define qemu_unlinkat unlinkat
+#define qemu_futimens futimens
static inline void close_preserve_errno(int fd)
{
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index c96f2d2..b22df3a 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -1727,7 +1727,11 @@ static void coroutine_fn v9fs_setattr(void *opaque)
} else {
times[1].tv_nsec = UTIME_OMIT;
}
- err = v9fs_co_utimensat(pdu, &fidp->path, times);
+ if (fid_has_valid_file_handle(pdu->s, fidp)) {
+ err = v9fs_co_futimens(pdu, fidp, times);
+ } else {
+ err = v9fs_co_utimensat(pdu, &fidp->path, times);
+ }
if (err < 0) {
goto out;
}
diff --git a/hw/9pfs/cofs.c b/hw/9pfs/cofs.c
index 893466f..12fa8c9 100644
--- a/hw/9pfs/cofs.c
+++ b/hw/9pfs/cofs.c
@@ -139,6 +139,25 @@ int coroutine_fn v9fs_co_utimensat(V9fsPDU *pdu, V9fsPath *path,
return err;
}
+int coroutine_fn 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 coroutine_fn v9fs_co_chown(V9fsPDU *pdu, V9fsPath *path, uid_t uid,
gid_t gid)
{
diff --git a/hw/9pfs/coth.h b/hw/9pfs/coth.h
index 62e922d..7906fa7 100644
--- a/hw/9pfs/coth.h
+++ b/hw/9pfs/coth.h
@@ -71,6 +71,8 @@ int coroutine_fn v9fs_co_statfs(V9fsPDU *, V9fsPath *, struct statfs *);
int coroutine_fn v9fs_co_lstat(V9fsPDU *, V9fsPath *, struct stat *);
int coroutine_fn v9fs_co_chmod(V9fsPDU *, V9fsPath *, mode_t);
int coroutine_fn v9fs_co_utimensat(V9fsPDU *, V9fsPath *, struct timespec [2]);
+int coroutine_fn v9fs_co_futimens(V9fsPDU *pdu, V9fsFidState *fidp,
+ struct timespec times[2]);
int coroutine_fn v9fs_co_chown(V9fsPDU *, V9fsPath *, uid_t, gid_t);
int coroutine_fn v9fs_co_truncate(V9fsPDU *, V9fsPath *, off_t);
int coroutine_fn v9fs_co_ftruncate(V9fsPDU *pdu, V9fsFidState *fidp,