diff mbox

[07/13] 9p: introduce futimens file op

Message ID 146702051386.5764.5880031092636948315.stgit@bahia.lan (mailing list archive)
State New, archived
Headers show

Commit Message

Greg Kurz June 27, 2016, 9:41 a.m. UTC
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 mbox

Patch

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