提交 066ae4f8 编写于 作者: P Peter Maydell

Merge remote-tracking branch 'remotes/gkurz/tags/for-upstream' into staging

Various bugfixes and code cleanups. Most notably, it fixes metadata handling in
mapped-file security mode (especially for the virtfs root).

# gpg: Signature made Tue 30 May 2017 14:36:22 BST
# gpg:                using DSA key 0x02FC3AEB0101DBC2
# gpg: Good signature from "Greg Kurz <groug@kaod.org>"
# gpg:                 aka "Greg Kurz <groug@free.fr>"
# gpg:                 aka "Greg Kurz <gkurz@linux.vnet.ibm.com>"
# gpg:                 aka "Gregory Kurz (Groug) <groug@free.fr>"
# gpg:                 aka "[jpeg image of size 3330]"
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 2BD4 3B44 535E C0A7 9894  DBA2 02FC 3AEB 0101 DBC2

* remotes/gkurz/tags/for-upstream:
  9pfs: local: metadata file for the VirtFS root
  9pfs: local: simplify file opening
  9pfs: local: resolve special directories in paths
  9pfs: check return value of v9fs_co_name_to_path()
  util: drop old utimensat() compat code
  9pfs: assume utimensat() and futimens() are present
  fsdev: fix virtfs-proxy-helper cwd
  9pfs: local: fix unlink of alien files in mapped-file mode
  9pfs: drop pdu_push_and_notify()
  fsdev: don't allow unknown format in marshal/unmarshal
  virtio-9p/xen-9p: move 9p specific bits to core 9p code
Signed-off-by: NPeter Maydell <peter.maydell@linaro.org>
...@@ -3629,25 +3629,6 @@ if compile_prog "" "" ; then ...@@ -3629,25 +3629,6 @@ if compile_prog "" "" ; then
inotify1=yes inotify1=yes
fi fi
# check if utimensat and futimens are supported
utimens=no
cat > $TMPC << EOF
#define _ATFILE_SOURCE
#include <stddef.h>
#include <fcntl.h>
#include <sys/stat.h>
int main(void)
{
utimensat(AT_FDCWD, "foo", NULL, 0);
futimens(0, NULL);
return 0;
}
EOF
if compile_prog "" "" ; then
utimens=yes
fi
# check if pipe2 is there # check if pipe2 is there
pipe2=no pipe2=no
cat > $TMPC << EOF cat > $TMPC << EOF
...@@ -5434,9 +5415,6 @@ fi ...@@ -5434,9 +5415,6 @@ fi
if test "$curses" = "yes" ; then if test "$curses" = "yes" ; then
echo "CONFIG_CURSES=y" >> $config_host_mak echo "CONFIG_CURSES=y" >> $config_host_mak
fi fi
if test "$utimens" = "yes" ; then
echo "CONFIG_UTIMENSAT=y" >> $config_host_mak
fi
if test "$pipe2" = "yes" ; then if test "$pipe2" = "yes" ; then
echo "CONFIG_PIPE2=y" >> $config_host_mak echo "CONFIG_PIPE2=y" >> $config_host_mak
fi fi
......
...@@ -168,7 +168,7 @@ ssize_t v9fs_iov_vunmarshal(struct iovec *out_sg, int out_num, size_t offset, ...@@ -168,7 +168,7 @@ ssize_t v9fs_iov_vunmarshal(struct iovec *out_sg, int out_num, size_t offset,
break; break;
} }
default: default:
break; g_assert_not_reached();
} }
if (copied < 0) { if (copied < 0) {
return copied; return copied;
...@@ -281,7 +281,7 @@ ssize_t v9fs_iov_vmarshal(struct iovec *in_sg, int in_num, size_t offset, ...@@ -281,7 +281,7 @@ ssize_t v9fs_iov_vmarshal(struct iovec *in_sg, int in_num, size_t offset,
break; break;
} }
default: default:
break; g_assert_not_reached();
} }
if (copied < 0) { if (copied < 0) {
return copied; return copied;
......
...@@ -945,7 +945,8 @@ static int process_requests(int sock) ...@@ -945,7 +945,8 @@ static int process_requests(int sock)
&spec[0].tv_sec, &spec[0].tv_nsec, &spec[0].tv_sec, &spec[0].tv_nsec,
&spec[1].tv_sec, &spec[1].tv_nsec); &spec[1].tv_sec, &spec[1].tv_nsec);
if (retval > 0) { if (retval > 0) {
retval = qemu_utimens(path.data, spec); retval = utimensat(AT_FDCWD, path.data, spec,
AT_SYMLINK_NOFOLLOW);
if (retval < 0) { if (retval < 0) {
retval = -errno; retval = -errno;
} }
...@@ -1129,14 +1130,14 @@ int main(int argc, char **argv) ...@@ -1129,14 +1130,14 @@ int main(int argc, char **argv)
} }
} }
if (chdir("/") < 0) {
do_perror("chdir");
goto error;
}
if (chroot(rpath) < 0) { if (chroot(rpath) < 0) {
do_perror("chroot"); do_perror("chroot");
goto error; goto error;
} }
if (chdir("/") < 0) {
do_perror("chdir");
goto error;
}
get_version = false; get_version = false;
#ifdef FS_IOC_GETVERSION #ifdef FS_IOC_GETVERSION
......
...@@ -378,7 +378,6 @@ static int handle_utimensat(FsContext *ctx, V9fsPath *fs_path, ...@@ -378,7 +378,6 @@ static int handle_utimensat(FsContext *ctx, V9fsPath *fs_path,
const struct timespec *buf) const struct timespec *buf)
{ {
int ret; int ret;
#ifdef CONFIG_UTIMENSAT
int fd; int fd;
struct handle_data *data = (struct handle_data *)ctx->private; struct handle_data *data = (struct handle_data *)ctx->private;
...@@ -388,10 +387,6 @@ static int handle_utimensat(FsContext *ctx, V9fsPath *fs_path, ...@@ -388,10 +387,6 @@ static int handle_utimensat(FsContext *ctx, V9fsPath *fs_path,
} }
ret = futimens(fd, buf); ret = futimens(fd, buf);
close(fd); close(fd);
#else
ret = -1;
errno = ENOSYS;
#endif
return ret; return ret;
} }
......
...@@ -53,13 +53,37 @@ int local_open_nofollow(FsContext *fs_ctx, const char *path, int flags, ...@@ -53,13 +53,37 @@ int local_open_nofollow(FsContext *fs_ctx, const char *path, int flags,
mode_t mode) mode_t mode)
{ {
LocalData *data = fs_ctx->private; LocalData *data = fs_ctx->private;
int fd = data->mountfd;
/* All paths are relative to the path data->mountfd points to */
while (*path == '/') { while (*path && fd != -1) {
path++; const char *c;
int next_fd;
char *head;
/* Only relative paths without consecutive slashes */
assert(*path != '/');
head = g_strdup(path);
c = strchrnul(path, '/');
if (*c) {
/* Intermediate path element */
head[c - path] = 0;
path = c + 1;
next_fd = openat_dir(fd, head);
} else {
/* Rightmost path element */
next_fd = openat_file(fd, head, flags, mode);
path = c;
}
g_free(head);
if (fd != data->mountfd) {
close_preserve_errno(fd);
}
fd = next_fd;
} }
return relative_openat_nofollow(data->mountfd, path, flags, mode); assert(fd != data->mountfd);
return fd;
} }
int local_opendir_nofollow(FsContext *fs_ctx, const char *path) int local_opendir_nofollow(FsContext *fs_ctx, const char *path)
...@@ -83,6 +107,7 @@ static void unlinkat_preserve_errno(int dirfd, const char *path, int flags) ...@@ -83,6 +107,7 @@ static void unlinkat_preserve_errno(int dirfd, const char *path, int flags)
} }
#define VIRTFS_META_DIR ".virtfs_metadata" #define VIRTFS_META_DIR ".virtfs_metadata"
#define VIRTFS_META_ROOT_FILE VIRTFS_META_DIR "_root"
static FILE *local_fopenat(int dirfd, const char *name, const char *mode) static FILE *local_fopenat(int dirfd, const char *name, const char *mode)
{ {
...@@ -119,13 +144,17 @@ static void local_mapped_file_attr(int dirfd, const char *name, ...@@ -119,13 +144,17 @@ static void local_mapped_file_attr(int dirfd, const char *name,
char buf[ATTR_MAX]; char buf[ATTR_MAX];
int map_dirfd; int map_dirfd;
map_dirfd = openat_dir(dirfd, VIRTFS_META_DIR); if (strcmp(name, ".")) {
if (map_dirfd == -1) { map_dirfd = openat_dir(dirfd, VIRTFS_META_DIR);
return; if (map_dirfd == -1) {
} return;
}
fp = local_fopenat(map_dirfd, name, "r"); fp = local_fopenat(map_dirfd, name, "r");
close_preserve_errno(map_dirfd); close_preserve_errno(map_dirfd);
} else {
fp = local_fopenat(dirfd, VIRTFS_META_ROOT_FILE, "r");
}
if (!fp) { if (!fp) {
return; return;
} }
...@@ -203,26 +232,38 @@ static int local_set_mapped_file_attrat(int dirfd, const char *name, ...@@ -203,26 +232,38 @@ static int local_set_mapped_file_attrat(int dirfd, const char *name,
int ret; int ret;
char buf[ATTR_MAX]; char buf[ATTR_MAX];
int uid = -1, gid = -1, mode = -1, rdev = -1; int uid = -1, gid = -1, mode = -1, rdev = -1;
int map_dirfd; int map_dirfd = -1, map_fd;
bool is_root = !strcmp(name, ".");
ret = mkdirat(dirfd, VIRTFS_META_DIR, 0700);
if (ret < 0 && errno != EEXIST) { if (is_root) {
return -1; fp = local_fopenat(dirfd, VIRTFS_META_ROOT_FILE, "r");
} if (!fp) {
if (errno == ENOENT) {
map_dirfd = openat_dir(dirfd, VIRTFS_META_DIR); goto update_map_file;
if (map_dirfd == -1) { } else {
return -1; return -1;
} }
}
} else {
ret = mkdirat(dirfd, VIRTFS_META_DIR, 0700);
if (ret < 0 && errno != EEXIST) {
return -1;
}
fp = local_fopenat(map_dirfd, name, "r"); map_dirfd = openat_dir(dirfd, VIRTFS_META_DIR);
if (!fp) { if (map_dirfd == -1) {
if (errno == ENOENT) {
goto update_map_file;
} else {
close_preserve_errno(map_dirfd);
return -1; return -1;
} }
fp = local_fopenat(map_dirfd, name, "r");
if (!fp) {
if (errno == ENOENT) {
goto update_map_file;
} else {
close_preserve_errno(map_dirfd);
return -1;
}
}
} }
memset(buf, 0, ATTR_MAX); memset(buf, 0, ATTR_MAX);
while (fgets(buf, ATTR_MAX, fp)) { while (fgets(buf, ATTR_MAX, fp)) {
...@@ -240,12 +281,26 @@ static int local_set_mapped_file_attrat(int dirfd, const char *name, ...@@ -240,12 +281,26 @@ static int local_set_mapped_file_attrat(int dirfd, const char *name,
fclose(fp); fclose(fp);
update_map_file: update_map_file:
fp = local_fopenat(map_dirfd, name, "w"); if (is_root) {
close_preserve_errno(map_dirfd); fp = local_fopenat(dirfd, VIRTFS_META_ROOT_FILE, "w");
} else {
fp = local_fopenat(map_dirfd, name, "w");
/* We can't go this far with map_dirfd not being a valid file descriptor
* but some versions of gcc aren't smart enough to see it.
*/
if (map_dirfd != -1) {
close_preserve_errno(map_dirfd);
}
}
if (!fp) { if (!fp) {
return -1; return -1;
} }
map_fd = fileno(fp);
assert(map_fd != -1);
ret = fchmod(map_fd, 0600);
assert(ret == 0);
if (credp->fc_uid != -1) { if (credp->fc_uid != -1) {
uid = credp->fc_uid; uid = credp->fc_uid;
} }
...@@ -454,7 +509,8 @@ static off_t local_telldir(FsContext *ctx, V9fsFidOpenState *fs) ...@@ -454,7 +509,8 @@ static off_t local_telldir(FsContext *ctx, V9fsFidOpenState *fs)
static bool local_is_mapped_file_metadata(FsContext *fs_ctx, const char *name) static bool local_is_mapped_file_metadata(FsContext *fs_ctx, const char *name)
{ {
return !strcmp(name, VIRTFS_META_DIR); return
!strcmp(name, VIRTFS_META_DIR) || !strcmp(name, VIRTFS_META_ROOT_FILE);
} }
static struct dirent *local_readdir(FsContext *ctx, V9fsFidOpenState *fs) static struct dirent *local_readdir(FsContext *ctx, V9fsFidOpenState *fs)
...@@ -471,7 +527,7 @@ again: ...@@ -471,7 +527,7 @@ again:
entry->d_type = DT_UNKNOWN; entry->d_type = DT_UNKNOWN;
} else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { } else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
if (local_is_mapped_file_metadata(ctx, entry->d_name)) { if (local_is_mapped_file_metadata(ctx, entry->d_name)) {
/* skip the meta data directory */ /* skip the meta data */
goto again; goto again;
} }
entry->d_type = DT_UNKNOWN; entry->d_type = DT_UNKNOWN;
...@@ -992,6 +1048,14 @@ static int local_unlinkat_common(FsContext *ctx, int dirfd, const char *name, ...@@ -992,6 +1048,14 @@ static int local_unlinkat_common(FsContext *ctx, int dirfd, const char *name,
if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
int map_dirfd; int map_dirfd;
/* We need to remove the metadata as well:
* - the metadata directory if we're removing a directory
* - the metadata file in the parent's metadata directory
*
* If any of these are missing (ie, ENOENT) then we're probably
* trying to remove something that wasn't created in mapped-file
* mode. We just ignore the error.
*/
if (flags == AT_REMOVEDIR) { if (flags == AT_REMOVEDIR) {
int fd; int fd;
...@@ -999,32 +1063,20 @@ static int local_unlinkat_common(FsContext *ctx, int dirfd, const char *name, ...@@ -999,32 +1063,20 @@ static int local_unlinkat_common(FsContext *ctx, int dirfd, const char *name,
if (fd == -1) { if (fd == -1) {
goto err_out; goto err_out;
} }
/*
* If directory remove .virtfs_metadata contained in the
* directory
*/
ret = unlinkat(fd, VIRTFS_META_DIR, AT_REMOVEDIR); ret = unlinkat(fd, VIRTFS_META_DIR, AT_REMOVEDIR);
close_preserve_errno(fd); close_preserve_errno(fd);
if (ret < 0 && errno != ENOENT) { if (ret < 0 && errno != ENOENT) {
/*
* We didn't had the .virtfs_metadata file. May be file created
* in non-mapped mode ?. Ignore ENOENT.
*/
goto err_out; goto err_out;
} }
} }
/*
* Now remove the name from parent directory
* .virtfs_metadata directory.
*/
map_dirfd = openat_dir(dirfd, VIRTFS_META_DIR); map_dirfd = openat_dir(dirfd, VIRTFS_META_DIR);
ret = unlinkat(map_dirfd, name, 0); if (map_dirfd != -1) {
close_preserve_errno(map_dirfd); ret = unlinkat(map_dirfd, name, 0);
if (ret < 0 && errno != ENOENT) { close_preserve_errno(map_dirfd);
/* if (ret < 0 && errno != ENOENT) {
* We didn't had the .virtfs_metadata file. May be file created goto err_out;
* in non-mapped mode ?. Ignore ENOENT. }
*/ } else if (errno != ENOENT) {
goto err_out; goto err_out;
} }
} }
...@@ -1138,14 +1190,32 @@ static int local_name_to_path(FsContext *ctx, V9fsPath *dir_path, ...@@ -1138,14 +1190,32 @@ static int local_name_to_path(FsContext *ctx, V9fsPath *dir_path,
} }
if (dir_path) { if (dir_path) {
v9fs_path_sprintf(target, "%s/%s", dir_path->data, name); if (!strcmp(name, ".")) {
} else if (strcmp(name, "/")) { /* "." relative to "foo/bar" is "foo/bar" */
v9fs_path_sprintf(target, "%s", name); v9fs_path_copy(target, dir_path);
} else if (!strcmp(name, "..")) {
if (!strcmp(dir_path->data, ".")) {
/* ".." relative to the root is "." */
v9fs_path_sprintf(target, ".");
} else {
char *tmp = g_path_get_dirname(dir_path->data);
/* Symbolic links are resolved by the client. We can assume
* that ".." relative to "foo/bar" is equivalent to "foo"
*/
v9fs_path_sprintf(target, "%s", tmp);
g_free(tmp);
}
} else {
assert(!strchr(name, '/'));
v9fs_path_sprintf(target, "%s/%s", dir_path->data, name);
}
} else if (!strcmp(name, "/") || !strcmp(name, ".") ||
!strcmp(name, "..")) {
/* This is the root fid */
v9fs_path_sprintf(target, ".");
} else { } else {
/* We want the path of the export root to be relative, otherwise assert(!strchr(name, '/'));
* "*at()" syscalls would treat it as "/" in the host. v9fs_path_sprintf(target, "./%s", name);
*/
v9fs_path_sprintf(target, "%s", ".");
} }
return 0; return 0;
} }
......
...@@ -14,49 +14,6 @@ ...@@ -14,49 +14,6 @@
#include "qemu/xattr.h" #include "qemu/xattr.h"
#include "9p-util.h" #include "9p-util.h"
int relative_openat_nofollow(int dirfd, const char *path, int flags,
mode_t mode)
{
int fd;
fd = dup(dirfd);
if (fd == -1) {
return -1;
}
while (*path) {
const char *c;
int next_fd;
char *head;
/* Only relative paths without consecutive slashes */
assert(path[0] != '/');
head = g_strdup(path);
c = strchr(path, '/');
if (c) {
head[c - path] = 0;
next_fd = openat_dir(fd, head);
} else {
next_fd = openat_file(fd, head, flags, mode);
}
g_free(head);
if (next_fd == -1) {
close_preserve_errno(fd);
return -1;
}
close(fd);
fd = next_fd;
if (!c) {
break;
}
path = c + 1;
}
return fd;
}
ssize_t fgetxattrat_nofollow(int dirfd, const char *filename, const char *name, ssize_t fgetxattrat_nofollow(int dirfd, const char *filename, const char *name,
void *value, size_t size) void *value, size_t size)
{ {
......
...@@ -50,8 +50,6 @@ static inline int openat_file(int dirfd, const char *name, int flags, ...@@ -50,8 +50,6 @@ static inline int openat_file(int dirfd, const char *name, int flags,
return fd; return fd;
} }
int relative_openat_nofollow(int dirfd, const char *path, int flags,
mode_t mode);
ssize_t fgetxattrat_nofollow(int dirfd, const char *path, const char *name, ssize_t fgetxattrat_nofollow(int dirfd, const char *path, const char *name,
void *value, size_t size); void *value, size_t size);
int fsetxattrat_nofollow(int dirfd, const char *path, const char *name, int fsetxattrat_nofollow(int dirfd, const char *path, const char *name,
......
...@@ -65,11 +65,6 @@ ssize_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...) ...@@ -65,11 +65,6 @@ ssize_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
return ret; return ret;
} }
static void pdu_push_and_notify(V9fsPDU *pdu)
{
pdu->s->transport->push_and_notify(pdu);
}
static int omode_to_uflags(int8_t mode) static int omode_to_uflags(int8_t mode)
{ {
int ret = 0; int ret = 0;
...@@ -668,7 +663,7 @@ static void coroutine_fn pdu_complete(V9fsPDU *pdu, ssize_t len) ...@@ -668,7 +663,7 @@ static void coroutine_fn pdu_complete(V9fsPDU *pdu, ssize_t len)
pdu->size = len; pdu->size = len;
pdu->id = id; pdu->id = id;
pdu_push_and_notify(pdu); pdu->s->transport->push_and_notify(pdu);
/* Now wakeup anybody waiting in flush for this request */ /* Now wakeup anybody waiting in flush for this request */
if (!qemu_co_queue_next(&pdu->complete)) { if (!qemu_co_queue_next(&pdu->complete)) {
...@@ -2576,7 +2571,10 @@ static int coroutine_fn v9fs_complete_rename(V9fsPDU *pdu, V9fsFidState *fidp, ...@@ -2576,7 +2571,10 @@ static int coroutine_fn v9fs_complete_rename(V9fsPDU *pdu, V9fsFidState *fidp,
err = -EINVAL; err = -EINVAL;
goto out; goto out;
} }
v9fs_co_name_to_path(pdu, &dirfidp->path, name->data, &new_path); err = v9fs_co_name_to_path(pdu, &dirfidp->path, name->data, &new_path);
if (err < 0) {
goto out;
}
} else { } else {
old_name = fidp->path.data; old_name = fidp->path.data;
end = strrchr(old_name, '/'); end = strrchr(old_name, '/');
...@@ -2588,8 +2586,11 @@ static int coroutine_fn v9fs_complete_rename(V9fsPDU *pdu, V9fsFidState *fidp, ...@@ -2588,8 +2586,11 @@ static int coroutine_fn v9fs_complete_rename(V9fsPDU *pdu, V9fsFidState *fidp,
new_name = g_malloc0(end - old_name + name->size + 1); new_name = g_malloc0(end - old_name + name->size + 1);
strncat(new_name, old_name, end - old_name); strncat(new_name, old_name, end - old_name);
strncat(new_name + (end - old_name), name->data, name->size); strncat(new_name + (end - old_name), name->data, name->size);
v9fs_co_name_to_path(pdu, NULL, new_name, &new_path); err = v9fs_co_name_to_path(pdu, NULL, new_name, &new_path);
g_free(new_name); g_free(new_name);
if (err < 0) {
goto out;
}
} }
err = v9fs_co_rename(pdu, &fidp->path, &new_path); err = v9fs_co_rename(pdu, &fidp->path, &new_path);
if (err < 0) { if (err < 0) {
...@@ -2669,20 +2670,26 @@ out_nofid: ...@@ -2669,20 +2670,26 @@ out_nofid:
v9fs_string_free(&name); v9fs_string_free(&name);
} }
static void coroutine_fn v9fs_fix_fid_paths(V9fsPDU *pdu, V9fsPath *olddir, static int coroutine_fn v9fs_fix_fid_paths(V9fsPDU *pdu, V9fsPath *olddir,
V9fsString *old_name, V9fsString *old_name,
V9fsPath *newdir, V9fsPath *newdir,
V9fsString *new_name) V9fsString *new_name)
{ {
V9fsFidState *tfidp; V9fsFidState *tfidp;
V9fsPath oldpath, newpath; V9fsPath oldpath, newpath;
V9fsState *s = pdu->s; V9fsState *s = pdu->s;
int err;
v9fs_path_init(&oldpath); v9fs_path_init(&oldpath);
v9fs_path_init(&newpath); v9fs_path_init(&newpath);
v9fs_co_name_to_path(pdu, olddir, old_name->data, &oldpath); err = v9fs_co_name_to_path(pdu, olddir, old_name->data, &oldpath);
v9fs_co_name_to_path(pdu, newdir, new_name->data, &newpath); if (err < 0) {
goto out;
}
err = v9fs_co_name_to_path(pdu, newdir, new_name->data, &newpath);
if (err < 0) {
goto out;
}
/* /*
* Fixup fid's pointing to the old name to * Fixup fid's pointing to the old name to
...@@ -2694,8 +2701,10 @@ static void coroutine_fn v9fs_fix_fid_paths(V9fsPDU *pdu, V9fsPath *olddir, ...@@ -2694,8 +2701,10 @@ static void coroutine_fn v9fs_fix_fid_paths(V9fsPDU *pdu, V9fsPath *olddir,
v9fs_fix_path(&tfidp->path, &newpath, strlen(oldpath.data)); v9fs_fix_path(&tfidp->path, &newpath, strlen(oldpath.data));
} }
} }
out:
v9fs_path_free(&oldpath); v9fs_path_free(&oldpath);
v9fs_path_free(&newpath); v9fs_path_free(&newpath);
return err;
} }
static int coroutine_fn v9fs_complete_renameat(V9fsPDU *pdu, int32_t olddirfid, static int coroutine_fn v9fs_complete_renameat(V9fsPDU *pdu, int32_t olddirfid,
...@@ -2729,8 +2738,8 @@ static int coroutine_fn v9fs_complete_renameat(V9fsPDU *pdu, int32_t olddirfid, ...@@ -2729,8 +2738,8 @@ static int coroutine_fn v9fs_complete_renameat(V9fsPDU *pdu, int32_t olddirfid,
} }
if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) {
/* Only for path based fid we need to do the below fixup */ /* Only for path based fid we need to do the below fixup */
v9fs_fix_fid_paths(pdu, &olddirfidp->path, old_name, err = v9fs_fix_fid_paths(pdu, &olddirfidp->path, old_name,
&newdirfidp->path, new_name); &newdirfidp->path, new_name);
} }
out: out:
if (olddirfidp) { if (olddirfidp) {
...@@ -3446,12 +3455,16 @@ static inline bool is_read_only_op(V9fsPDU *pdu) ...@@ -3446,12 +3455,16 @@ static inline bool is_read_only_op(V9fsPDU *pdu)
} }
} }
void pdu_submit(V9fsPDU *pdu) void pdu_submit(V9fsPDU *pdu, P9MsgHeader *hdr)
{ {
Coroutine *co; Coroutine *co;
CoroutineEntry *handler; CoroutineEntry *handler;
V9fsState *s = pdu->s; V9fsState *s = pdu->s;
pdu->size = le32_to_cpu(hdr->size_le);
pdu->id = hdr->id;
pdu->tag = le16_to_cpu(hdr->tag_le);
if (pdu->id >= ARRAY_SIZE(pdu_co_handlers) || if (pdu->id >= ARRAY_SIZE(pdu_co_handlers) ||
(pdu_co_handlers[pdu->id] == NULL)) { (pdu_co_handlers[pdu->id] == NULL)) {
handler = v9fs_op_not_supp; handler = v9fs_op_not_supp;
...@@ -3462,6 +3475,8 @@ void pdu_submit(V9fsPDU *pdu) ...@@ -3462,6 +3475,8 @@ void pdu_submit(V9fsPDU *pdu)
if (is_ro_export(&s->ctx) && !is_read_only_op(pdu)) { if (is_ro_export(&s->ctx) && !is_read_only_op(pdu)) {
handler = v9fs_fs_ro; handler = v9fs_fs_ro;
} }
qemu_co_queue_init(&pdu->complete);
co = qemu_coroutine_create(handler, pdu); co = qemu_coroutine_create(handler, pdu);
qemu_coroutine_enter(co); qemu_coroutine_enter(co);
} }
......
...@@ -347,7 +347,7 @@ ssize_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...); ...@@ -347,7 +347,7 @@ ssize_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...);
ssize_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...); ssize_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...);
V9fsPDU *pdu_alloc(V9fsState *s); V9fsPDU *pdu_alloc(V9fsState *s);
void pdu_free(V9fsPDU *pdu); void pdu_free(V9fsPDU *pdu);
void pdu_submit(V9fsPDU *pdu); void pdu_submit(V9fsPDU *pdu, P9MsgHeader *hdr);
void v9fs_reset(V9fsState *s); void v9fs_reset(V9fsState *s);
struct V9fsTransport { struct V9fsTransport {
......
...@@ -70,13 +70,7 @@ static void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq) ...@@ -70,13 +70,7 @@ static void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)
goto out_free_req; goto out_free_req;
} }
pdu->size = le32_to_cpu(out.size_le); pdu_submit(pdu, &out);
pdu->id = out.id;
pdu->tag = le16_to_cpu(out.tag_le);
qemu_co_queue_init(&pdu->complete);
pdu_submit(pdu);
} }
return; return;
......
...@@ -243,14 +243,10 @@ static int xen_9pfs_receive(Xen9pfsRing *ring) ...@@ -243,14 +243,10 @@ static int xen_9pfs_receive(Xen9pfsRing *ring)
/* cannot fail, because we only handle one request per ring at a time */ /* cannot fail, because we only handle one request per ring at a time */
pdu = pdu_alloc(&ring->priv->state); pdu = pdu_alloc(&ring->priv->state);
pdu->size = le32_to_cpu(h.size_le);
pdu->id = h.id;
pdu->tag = le32_to_cpu(h.tag_le);
ring->out_size = le32_to_cpu(h.size_le); ring->out_size = le32_to_cpu(h.size_le);
ring->out_cons = cons + le32_to_cpu(h.size_le); ring->out_cons = cons + le32_to_cpu(h.size_le);
qemu_co_queue_init(&pdu->complete); pdu_submit(pdu, &h);
pdu_submit(pdu);
return 0; return 0;
} }
......
...@@ -51,17 +51,6 @@ int os_mlock(void); ...@@ -51,17 +51,6 @@ int os_mlock(void);
typedef struct timeval qemu_timeval; typedef struct timeval qemu_timeval;
#define qemu_gettimeofday(tp) gettimeofday(tp, NULL) #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_utimens(const char *path, const qemu_timespec *times);
bool is_daemonized(void); bool is_daemonized(void);
/** /**
......
...@@ -207,53 +207,6 @@ int qemu_pipe(int pipefd[2]) ...@@ -207,53 +207,6 @@ int qemu_pipe(int pipefd[2])
return ret; return ret;
} }
int qemu_utimens(const char *path, const struct timespec *times)
{
struct timeval tv[2], tv_now;
struct stat st;
int i;
#ifdef CONFIG_UTIMENSAT
int ret;
ret = utimensat(AT_FDCWD, path, times, AT_SYMLINK_NOFOLLOW);
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]);
}
char * char *
qemu_get_local_state_pathname(const char *relative_pathname) qemu_get_local_state_pathname(const char *relative_pathname)
{ {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册