aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/file-op-9p.h2
-rw-r--r--hw/virtio-9p-debug.c4
-rw-r--r--hw/virtio-9p-local.c12
-rw-r--r--hw/virtio-9p-xattr.c3
-rw-r--r--hw/virtio-9p.c11
-rw-r--r--oslib-posix.c48
-rw-r--r--qemu-os-posix.h12
7 files changed, 80 insertions, 12 deletions
diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h
index 21d60b5855..c7731c2993 100644
--- a/hw/file-op-9p.h
+++ b/hw/file-op-9p.h
@@ -86,7 +86,7 @@ typedef struct FileOperations
int (*fstat)(FsContext *, int, struct stat *);
int (*rename)(FsContext *, const char *, const char *);
int (*truncate)(FsContext *, const char *, off_t);
- int (*fsync)(FsContext *, int);
+ int (*fsync)(FsContext *, int, int);
int (*statfs)(FsContext *s, const char *path, struct statfs *stbuf);
ssize_t (*lgetxattr)(FsContext *, const char *,
const char *, void *, size_t);
diff --git a/hw/virtio-9p-debug.c b/hw/virtio-9p-debug.c
index cff5b07297..6b18842fd4 100644
--- a/hw/virtio-9p-debug.c
+++ b/hw/virtio-9p-debug.c
@@ -552,8 +552,8 @@ void pprint_pdu(V9fsPDU *pdu)
break;
case P9_TLINK:
fprintf(llogfile, "TLINK: (");
- pprint_int32(pdu, 0, &offset, "fid");
- pprint_str(pdu, 0, &offset, ", oldpath");
+ pprint_int32(pdu, 0, &offset, "dfid");
+ pprint_int32(pdu, 0, &offset, ", fid");
pprint_str(pdu, 0, &offset, ", newpath");
break;
case P9_RLINK:
diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index 0d520201b4..a8e7525bf6 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -480,9 +480,9 @@ static int local_chown(FsContext *fs_ctx, const char *path, FsCred *credp)
}
static int local_utimensat(FsContext *s, const char *path,
- const struct timespec *buf)
+ const struct timespec *buf)
{
- return utimensat(AT_FDCWD, rpath(s, path), buf, AT_SYMLINK_NOFOLLOW);
+ return qemu_utimensat(AT_FDCWD, rpath(s, path), buf, AT_SYMLINK_NOFOLLOW);
}
static int local_remove(FsContext *ctx, const char *path)
@@ -490,9 +490,13 @@ static int local_remove(FsContext *ctx, const char *path)
return remove(rpath(ctx, path));
}
-static int local_fsync(FsContext *ctx, int fd)
+static int local_fsync(FsContext *ctx, int fd, int datasync)
{
- return fsync(fd);
+ if (datasync) {
+ return qemu_fdatasync(fd);
+ } else {
+ return fsync(fd);
+ }
}
static int local_statfs(FsContext *s, const char *path, struct statfs *stbuf)
diff --git a/hw/virtio-9p-xattr.c b/hw/virtio-9p-xattr.c
index 175f372c39..1aab081de2 100644
--- a/hw/virtio-9p-xattr.c
+++ b/hw/virtio-9p-xattr.c
@@ -73,6 +73,9 @@ ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
/* Get the actual len */
xattr_len = llistxattr(rpath(ctx, path), value, 0);
+ if (xattr_len <= 0) {
+ return xattr_len;
+ }
/* Now fetch the xattr and find the actual size */
orig_value = qemu_malloc(xattr_len);
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index daade77ed9..7c59988a51 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -248,9 +248,9 @@ static int v9fs_do_remove(V9fsState *s, V9fsString *path)
return s->ops->remove(&s->ctx, path->data);
}
-static int v9fs_do_fsync(V9fsState *s, int fd)
+static int v9fs_do_fsync(V9fsState *s, int fd, int datasync)
{
- return s->ops->fsync(&s->ctx, fd);
+ return s->ops->fsync(&s->ctx, fd, datasync);
}
static int v9fs_do_statfs(V9fsState *s, V9fsString *path, struct statfs *stbuf)
@@ -1868,16 +1868,17 @@ static void v9fs_fsync(V9fsState *s, V9fsPDU *pdu)
int32_t fid;
size_t offset = 7;
V9fsFidState *fidp;
+ int datasync;
int err;
- pdu_unmarshal(pdu, offset, "d", &fid);
+ pdu_unmarshal(pdu, offset, "dd", &fid, &datasync);
fidp = lookup_fid(s, fid);
if (fidp == NULL) {
err = -ENOENT;
v9fs_post_do_fsync(s, pdu, err);
return;
}
- err = v9fs_do_fsync(s, fidp->fs.fd);
+ err = v9fs_do_fsync(s, fidp->fs.fd, datasync);
v9fs_post_do_fsync(s, pdu, err);
}
@@ -3001,7 +3002,7 @@ static void v9fs_wstat(V9fsState *s, V9fsPDU *pdu)
/* do we need to sync the file? */
if (donttouch_stat(&vs->v9stat)) {
- err = v9fs_do_fsync(s, vs->fidp->fs.fd);
+ err = v9fs_do_fsync(s, vs->fidp->fs.fd, 0);
v9fs_wstat_post_fsync(s, vs, err);
return;
}
diff --git a/oslib-posix.c b/oslib-posix.c
index 6e9b0c3c13..7bc5f7cf09 100644
--- a/oslib-posix.c
+++ b/oslib-posix.c
@@ -107,3 +107,51 @@ int qemu_pipe(int pipefd[2])
return ret;
}
+
+int qemu_utimensat(int dirfd, const char *path, const struct timespec *times,
+ int flags)
+{
+ struct timeval tv[2], tv_now;
+ struct stat st;
+ int i;
+#ifdef CONFIG_UTIMENSAT
+ int ret;
+
+ ret = utimensat(dirfd, path, times, flags);
+ if (ret != -1 || errno != ENOSYS) {
+ return ret;
+ }
+#endif
+ /* Fallback: use utimes() instead of utimensat() */
+
+ /* happy if special cases */
+ if (times[0].tv_nsec == UTIME_OMIT && times[1].tv_nsec == UTIME_OMIT) {
+ return 0;
+ }
+ if (times[0].tv_nsec == UTIME_NOW && times[1].tv_nsec == UTIME_NOW) {
+ return utimes(path, NULL);
+ }
+
+ /* prepare for hard cases */
+ if (times[0].tv_nsec == UTIME_NOW || times[1].tv_nsec == UTIME_NOW) {
+ gettimeofday(&tv_now, NULL);
+ }
+ if (times[0].tv_nsec == UTIME_OMIT || times[1].tv_nsec == UTIME_OMIT) {
+ stat(path, &st);
+ }
+
+ for (i = 0; i < 2; i++) {
+ if (times[i].tv_nsec == UTIME_NOW) {
+ tv[i].tv_sec = tv_now.tv_sec;
+ tv[i].tv_usec = tv_now.tv_usec;
+ } else if (times[i].tv_nsec == UTIME_OMIT) {
+ tv[i].tv_sec = (i == 0) ? st.st_atime : st.st_mtime;
+ tv[i].tv_usec = 0;
+ } else {
+ tv[i].tv_sec = times[i].tv_sec;
+ tv[i].tv_usec = times[i].tv_nsec / 1000;
+ }
+ }
+
+ return utimes(path, &tv[0]);
+}
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
index 353f87813f..81fd9ab389 100644
--- a/qemu-os-posix.h
+++ b/qemu-os-posix.h
@@ -39,4 +39,16 @@ void os_setup_post(void);
typedef struct timeval qemu_timeval;
#define qemu_gettimeofday(tp) gettimeofday(tp, NULL)
+#ifndef CONFIG_UTIMENSAT
+#ifndef UTIME_NOW
+# define UTIME_NOW ((1l << 30) - 1l)
+#endif
+#ifndef UTIME_OMIT
+# define UTIME_OMIT ((1l << 30) - 2l)
+#endif
+#endif
+typedef struct timespec qemu_timespec;
+int qemu_utimensat(int dirfd, const char *path, const qemu_timespec *times,
+ int flags);
+
#endif