From: "M. Mohan Kumar" <mo...@in.ibm.com> Add xattr support for proxy FS
Signed-off-by: M. Mohan Kumar <mo...@in.ibm.com> --- hw/9pfs/proxy.h | 4 ++ hw/9pfs/virtfs-proxy-helper.c | 60 ++++++++++++++++++++ hw/9pfs/virtio-9p-proxy.c | 121 ++++++++++++++++++++++++++++++++++++++--- 3 files changed, 176 insertions(+), 9 deletions(-) diff --git a/hw/9pfs/proxy.h b/hw/9pfs/proxy.h index 557a8f4..fdfa651 100644 --- a/hw/9pfs/proxy.h +++ b/hw/9pfs/proxy.h @@ -30,6 +30,10 @@ enum { T_UTIME, T_RENAME, T_REMOVE, + T_LGETXATTR, + T_LLISTXATTR, + T_LSETXATTR, + T_LREMOVEXATTR, }; #endif diff --git a/hw/9pfs/virtfs-proxy-helper.c b/hw/9pfs/virtfs-proxy-helper.c index 845e3c6..78669d0 100644 --- a/hw/9pfs/virtfs-proxy-helper.c +++ b/hw/9pfs/virtfs-proxy-helper.c @@ -18,6 +18,7 @@ #include "bswap.h" #include <sys/socket.h> #include <sys/vfs.h> +#include <attr/xattr.h> #include "qemu-common.h" #include "virtio-9p.h" #include "hw/9pfs/proxy.h" @@ -426,6 +427,8 @@ static int process_requests(int sock) int size, mode, uid, gid; struct timespec spec[2]; uint64_t offset; + V9fsString name, value; + int flags; iovec.iov_base = g_malloc(BUFF_SZ); iovec.iov_len = BUFF_SZ; @@ -526,6 +529,49 @@ static int process_requests(int sock) } v9fs_string_free(&path); break; + case T_LGETXATTR: + if (size) { + response = g_malloc(size); + } + v9fs_unmarshal(&iovec, 1, 0, "ssd", &path, &name, &size); + retval = lgetxattr(path.data, name.data, response, size); + if (retval < 0) { + retval = -errno; + } + v9fs_string_free(&path); + v9fs_string_free(&name); + break; + case T_LLISTXATTR: + if (size) { + response = g_malloc(size); + } + v9fs_unmarshal(&iovec, 1, 0, "sd", &path, &size); + retval = llistxattr(path.data, response, size); + if (retval < 0) { + retval = -errno; + } + v9fs_string_free(&path); + break; + case T_LSETXATTR: + v9fs_unmarshal(&iovec, 1, 0, "sssdd", &path, &name, &value, &size, + &flags); + retval = lsetxattr(path.data, name.data, value.data, size, flags); + if (retval < 0) { + retval = -errno; + } + v9fs_string_free(&path); + v9fs_string_free(&name); + v9fs_string_free(&value); + break; + case T_LREMOVEXATTR: + v9fs_unmarshal(&iovec, 1, 0, "ss", &path, &name); + retval = lremovexattr(path.data, name.data); + if (retval < 0) { + retval = -errno; + } + v9fs_string_free(&path); + v9fs_string_free(&name); + break; default: goto error; break; @@ -545,6 +591,8 @@ static int process_requests(int sock) case T_UTIME: case T_RENAME: case T_REMOVE: + case T_LSETXATTR: + case T_LREMOVEXATTR: sendfd(sock, retval, valid_fd); break; case T_LSTAT: @@ -555,6 +603,18 @@ static int process_requests(int sock) goto error; } break; + case T_LGETXATTR: + case T_LLISTXATTR: + /* send only size of xattr attribute as per request */ + if (!size) { + socket_write(sock, &retval, sizeof(retval)); + } else { /* send value of xattr 'name' */ + if (send_response(sock, retval, response) < 0) { + do_perror("send_response"); + goto error; + } + } + break; default: break; } diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c index 47419dd..143a784 100644 --- a/hw/9pfs/virtio-9p-proxy.c +++ b/hw/9pfs/virtio-9p-proxy.c @@ -101,9 +101,10 @@ 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; + int msg_size, size = 0; struct timespec spec[2]; uint64_t offset; + V9fsString *name, *value; qemu_mutex_lock(&proxy->mutex); @@ -258,6 +259,46 @@ 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_LGETXATTR: + path = va_arg(ap, V9fsString *); + name = va_arg(ap, V9fsString *); + size = va_arg(ap, int); + header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "ssd", path, + name, size); + header.type = T_LGETXATTR; + v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size); + header.size += sizeof(header); + break; + case T_LLISTXATTR: + path = va_arg(ap, V9fsString *); + size = va_arg(ap, int); + header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "sd", + path, size); + header.type = T_LLISTXATTR; + v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size); + header.size += sizeof(header); + break; + case T_LSETXATTR: + path = va_arg(ap, V9fsString *); + name = va_arg(ap, V9fsString *); + value = va_arg(ap, V9fsString *); + size = va_arg(ap, int); + flags = va_arg(ap, int); + header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "sssdd", + path, name, value, size, flags); + header.type = T_LSETXATTR; + v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size); + header.size += sizeof(header); + break; + case T_LREMOVEXATTR: + path = va_arg(ap, V9fsString *); + name = va_arg(ap, V9fsString *); + header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "ss", + path, name); + header.type = T_LREMOVEXATTR; + 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; @@ -286,6 +327,8 @@ static int v9fs_request(V9fsProxy *proxy, int type, case T_TRUNCATE: case T_UTIME: case T_REMOVE: + case T_LSETXATTR: + case T_LREMOVEXATTR: retval = v9fs_receivefd(proxy->sockfd, &sock_error); if (sock_error) { goto close_error; @@ -308,6 +351,24 @@ static int v9fs_request(V9fsProxy *proxy, int type, } retval = 0; /* success */ break; + case T_LGETXATTR: + case T_LLISTXATTR: + if (!size) { + if (read(proxy->sockfd, &retval, sizeof(int)) < 0) { + retval = -errno; + } + } else { + retval = read(proxy->sockfd, &msg_size, sizeof(msg_size)); + 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; + } + } + break; } qemu_mutex_unlock(&proxy->mutex); return retval; @@ -661,29 +722,71 @@ static int proxy_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf) static ssize_t proxy_lgetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name, void *value, size_t size) { - errno = EOPNOTSUPP; - return -1; + int retval; + V9fsString xname; + + v9fs_string_init(&xname); + v9fs_string_sprintf(&xname, "%s", name); + retval = v9fs_request(ctx->private, T_LGETXATTR, value, "ssd", + fs_path, &xname, size); + if (retval < 0) { + errno = -retval; + } + v9fs_string_free(&xname); + return retval; } static ssize_t proxy_llistxattr(FsContext *ctx, V9fsPath *fs_path, void *value, size_t size) { - errno = EOPNOTSUPP; - return -1; + int retval; + retval = v9fs_request(ctx->private, T_LLISTXATTR, value, "sd", + fs_path, size); + if (retval < 0) { + errno = -retval; + } + return retval; } static int proxy_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name, void *value, size_t size, int flags) { - errno = EOPNOTSUPP; - return -1; + int retval; + V9fsString xname, xvalue; + + v9fs_string_init(&xname); + v9fs_string_sprintf(&xname, "%s", name); + + v9fs_string_init(&xvalue); + xvalue.size = size; + xvalue.data = g_malloc(size); + memcpy(xvalue.data, value, size); + + retval = v9fs_request(ctx->private, T_LSETXATTR, value, "sssdd", + fs_path, xname, xvalue, size, flags); + if (retval < 0) { + errno = -retval; + } + v9fs_string_free(&xname); + v9fs_string_free(&xvalue); + return retval; } static int proxy_lremovexattr(FsContext *ctx, V9fsPath *fs_path, const char *name) { - errno = EOPNOTSUPP; - return -1; + int retval; + V9fsString xname; + + v9fs_string_init(&xname); + v9fs_string_sprintf(&xname, "%s", name); + retval = v9fs_request(ctx->private, T_LREMOVEXATTR, NULL, "ss", + fs_path, &xname); + if (retval < 0) { + errno = -retval; + } + v9fs_string_free(&xname); + return retval; } static int proxy_name_to_path(FsContext *ctx, V9fsPath *dir_path, -- 1.7.6