From: "M. Mohan Kumar" <mo...@in.ibm.com>
Signed-off-by: M. Mohan Kumar <mo...@in.ibm.com> --- hw/9pfs/proxy.h | 3 ++ hw/9pfs/virtfs-proxy-helper.c | 81 ++++++++++++++++++++++++++++++++++++++++- hw/9pfs/virtio-9p-proxy.c | 67 +++++++++++++++++++++++++++++++--- 3 files changed, 144 insertions(+), 7 deletions(-) diff --git a/hw/9pfs/proxy.h b/hw/9pfs/proxy.h index 5564eb5..5a13b5f 100644 --- a/hw/9pfs/proxy.h +++ b/hw/9pfs/proxy.h @@ -21,6 +21,9 @@ enum { T_MKDIR, T_SYMLINK, T_LINK, + T_LSTAT, + T_READLINK, + T_STATFS, }; #endif diff --git a/hw/9pfs/virtfs-proxy-helper.c b/hw/9pfs/virtfs-proxy-helper.c index 82aa267..9fa4a30 100644 --- a/hw/9pfs/virtfs-proxy-helper.c +++ b/hw/9pfs/virtfs-proxy-helper.c @@ -17,6 +17,7 @@ #include <stdarg.h> #include "bswap.h" #include <sys/socket.h> +#include <sys/vfs.h> #include "qemu-common.h" #include "virtio-9p.h" #include "hw/9pfs/proxy.h" @@ -268,6 +269,59 @@ static int setfsugid(int uid, int gid) } /* + * send response in two parts + * 1) Size of the response + * 2) Response + * If there was a error send -errno only + */ +static int send_response(int sock, int size, char *response) +{ + int retval; + retval = socket_write(sock, &size, sizeof(size)); + if (retval > 0 && size > 0) { + retval = socket_write(sock, response, size); + } + if (size > 0) { + g_free(response); + } + return retval; +} + +static int do_stat(int type, struct iovec *iovec, char **response) +{ + V9fsString path; + int size = 0, retval = -1; + + v9fs_unmarshal(iovec, 1, 0, "s", &path); + + switch (type) { + case T_LSTAT: + size = sizeof(struct stat); + *response = g_malloc(size); + retval = lstat(path.data, (struct stat *)*response); + break; + case T_STATFS: + size = sizeof(struct statfs); + *response = g_malloc(size); + retval = statfs(path.data, (struct statfs *)*response); + break; + default: + retval = -EOPNOTSUPP; + goto error; + } + + if (retval < 0) { + retval = -errno; + g_free(*response); + } else { + retval = size; + } +error: + v9fs_string_free(&path); + return retval; +} + +/* * create a other filesystem objects and send 0 on success * return -errno on error */ @@ -368,6 +422,8 @@ static int process_requests(int sock) struct iovec iovec; int valid_fd; V9fsString oldpath, path; + char *response = NULL; + int size; iovec.iov_base = g_malloc(BUFF_SZ); iovec.iov_len = BUFF_SZ; @@ -401,6 +457,22 @@ static int process_requests(int sock) v9fs_string_free(&oldpath); v9fs_string_free(&path); break; + case T_LSTAT: + case T_STATFS: + retval = do_stat(type, &iovec, &response); + break; + case T_READLINK: + response = g_malloc(size); + v9fs_unmarshal(&iovec, 1, 0, "sd", &path, &size); + retval = readlink(path.data, response, size); + if (retval > 0) { + response[retval++] = '\0'; + } else { + retval = -errno; + g_free(response); + } + v9fs_string_free(&path); + break; default: goto error; break; @@ -416,11 +488,18 @@ static int process_requests(int sock) case T_LINK: sendfd(sock, retval, valid_fd); break; + case T_LSTAT: + case T_READLINK: + case T_STATFS: + if (send_response(sock, retval, response) < 0) { + do_perror("send_response"); + goto error; + } + break; default: break; } } - (void)socket_write; error: g_free(iovec.iov_base); return -1; diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c index 5f5eb35..1328e59 100644 --- a/hw/9pfs/virtio-9p-proxy.c +++ b/hw/9pfs/virtio-9p-proxy.c @@ -101,6 +101,7 @@ static int v9fs_request(V9fsProxy *proxy, int type, int sock_error, flags, mode, uid, gid; struct iovec *iovec = NULL; dev_t rdev; + int msg_size, size; qemu_mutex_lock(&proxy->mutex); @@ -175,6 +176,29 @@ static int v9fs_request(V9fsProxy *proxy, int type, v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size); header.size += sizeof(header); break; + case T_LSTAT: + path = va_arg(ap, V9fsString *); + header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "s", path); + header.type = T_LSTAT; + v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size); + header.size += sizeof(header); + break; + case T_READLINK: + path = va_arg(ap, V9fsString *); + size = va_arg(ap, int); + header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "sd", + path, size); + header.type = T_READLINK; + v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size); + header.size += sizeof(header); + break; + case T_STATFS: + path = va_arg(ap, V9fsString *); + header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "s", path); + header.type = T_STATFS; + v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size); + header.size += sizeof(header); + break; default: fprintf(stderr, "Invalid type %d\n", type); goto close_error; @@ -202,6 +226,23 @@ static int v9fs_request(V9fsProxy *proxy, int type, goto close_error; } break; + case T_LSTAT: + case T_READLINK: + case T_STATFS: + retval = read(proxy->sockfd, &msg_size, sizeof(msg_size)); + if (retval != sizeof(msg_size)) { + goto close_error; + } + if (msg_size < 0) { + qemu_mutex_unlock(&proxy->mutex); + return msg_size; + } + retval = read(proxy->sockfd, response, msg_size); + if (retval != msg_size) { + goto close_error; + } + retval = 0; /* success */ + break; } qemu_mutex_unlock(&proxy->mutex); return retval; @@ -215,15 +256,25 @@ error: static int proxy_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf) { - errno = EOPNOTSUPP; - return -1; + int retval; + retval = v9fs_request(fs_ctx->private, T_LSTAT, stbuf, "s", fs_path); + if (retval < 0) { + errno = -retval; + } + return retval; } static ssize_t proxy_readlink(FsContext *fs_ctx, V9fsPath *fs_path, char *buf, size_t bufsz) { - errno = EOPNOTSUPP; - return -1; + int retval; + retval = v9fs_request(fs_ctx->private, T_READLINK, buf, "sd", + fs_path, bufsz); + if (retval < 0) { + errno = -retval; + return -1; + } + return strlen(buf); } static int proxy_close(FsContext *ctx, V9fsFidOpenState *fs) @@ -489,8 +540,12 @@ static int proxy_fsync(FsContext *ctx, V9fsFidOpenState *fs, int datasync) static int proxy_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf) { - errno = EOPNOTSUPP; - return -1; + int retval; + retval = v9fs_request(s->private, T_STATFS, stbuf, "s", fs_path); + if (retval < 0) { + errno = -retval; + } + return retval; } static ssize_t proxy_lgetxattr(FsContext *ctx, V9fsPath *fs_path, -- 1.7.6