Add xattr support for proxy FS Signed-off-by: M. Mohan Kumar <mo...@in.ibm.com> --- fsdev/virtfs-proxy-helper.c | 78 ++++++++++++++++++++++++++++- hw/9pfs/virtio-9p-proxy.c | 119 +++++++++++++++++++++++++++++++++++++++---- hw/9pfs/virtio-9p-proxy.h | 4 ++ 3 files changed, 190 insertions(+), 11 deletions(-)
diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c index ded0ead..ccd7ed8 100644 --- a/fsdev/virtfs-proxy-helper.c +++ b/fsdev/virtfs-proxy-helper.c @@ -29,6 +29,7 @@ #include <sys/socket.h> #include <sys/vfs.h> #include <sys/stat.h> +#include <attr/xattr.h> #include "qemu-common.h" #include "virtio-9p-marshal.h" #include "hw/9pfs/virtio-9p-proxy.h" @@ -283,6 +284,50 @@ static int send_response(int sock, struct iovec *iovec, int size) return 0; } +static int do_getxattr(int type, struct iovec *iovec, struct iovec *out_iovec) +{ + int size = 0, offset, retval; + V9fsString path, name, xattr; + + v9fs_string_init(&xattr); + + offset = HDR_SZ; + offset += proxy_unmarshal(iovec, 1, HDR_SZ, "ds", &size, &path); + if (size) { + xattr.data = g_malloc(size); + xattr.size = size; + } + switch (type) { + case T_LGETXATTR: + proxy_unmarshal(iovec, 1, offset, "s", &name); + retval = lgetxattr(path.data, name.data, xattr.data, size); + if (retval < 0) { + retval = -errno; + v9fs_string_free(&name); + goto error; + } + v9fs_string_free(&name); + break; + case T_LLISTXATTR: + retval = llistxattr(path.data, xattr.data, size); + if (retval < 0) { + retval = -errno; + goto error; + } + break; + } + + if (!size) { + proxy_marshal(out_iovec, 1, HDR_SZ, "d", retval); + retval = sizeof(retval); + } else { + retval = proxy_marshal(out_iovec, 1, HDR_SZ, "s", &xattr); + } +error: + v9fs_string_free(&path); + return retval; +} + static void stat_to_prstat(ProxyStat *pr_stat, struct stat *stat) { memset(pr_stat, 0, sizeof(*pr_stat)); @@ -499,9 +544,10 @@ static int process_requests(int sock) int mode, uid, gid; struct timespec spec[2]; int type, retval = 0; + V9fsString name, value; V9fsString oldpath, path; struct iovec in_iovec, out_iovec; - int size = 0; + int size = 0, flags; in_iovec.iov_base = g_malloc(BUFF_SZ); in_iovec.iov_len = BUFF_SZ; @@ -595,6 +641,32 @@ static int process_requests(int sock) } v9fs_string_free(&path); break; + case T_LGETXATTR: + case T_LLISTXATTR: + size = do_getxattr(type, &in_iovec, &out_iovec); + break; + case T_LSETXATTR: + proxy_unmarshal(&in_iovec, 1, HDR_SZ, + "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: + proxy_unmarshal(&in_iovec, 1, + HDR_SZ, "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; @@ -616,11 +688,15 @@ static int process_requests(int sock) case T_UTIME: case T_RENAME: case T_REMOVE: + case T_LSETXATTR: + case T_LREMOVEXATTR: send_status(sock, &out_iovec, retval); break; case T_LSTAT: case T_STATFS: case T_READLINK: + case T_LGETXATTR: + case T_LLISTXATTR: if (send_response(sock, &out_iovec, size) < 0) { goto error; } diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c index aefdc61..f672ac3 100644 --- a/hw/9pfs/virtio-9p-proxy.c +++ b/hw/9pfs/virtio-9p-proxy.c @@ -136,7 +136,7 @@ static void prstat_to_stat(struct stat *stbuf, ProxyStat *prstat) * size of errno/response is given by header.size */ static int v9fs_receive_response(V9fsProxy *proxy, int type, - int *sock_error, void *response) + int *sock_error, int size, void *response) { int retval, error; ProxyHeader header; @@ -196,6 +196,19 @@ static int v9fs_receive_response(V9fsProxy *proxy, int type, v9fs_string_free(&target); break; } + case T_LGETXATTR: + case T_LLISTXATTR: { + V9fsString xattr; + if (!size) { + proxy_unmarshal(reply, 1, HDR_SZ, "d", &size); + return size; + } else { + proxy_unmarshal(reply, 1, HDR_SZ, "s", &xattr); + memcpy(response, xattr.data, xattr.size); + v9fs_string_free(&xattr); + } + break; + } default: *sock_error = 1; return -1; @@ -244,6 +257,7 @@ static int v9fs_request(V9fsProxy *proxy, int type, int size = 0; struct timespec spec[2]; uint64_t offset; + V9fsString *name, *value; qemu_mutex_lock(&proxy->mutex); @@ -398,6 +412,44 @@ static int v9fs_request(V9fsProxy *proxy, int type, proxy_marshal(iovec, 1, 0, "dd", header.type, header.size); header.size += HDR_SZ; break; + case T_LGETXATTR: + size = va_arg(ap, int); + path = va_arg(ap, V9fsString *); + name = va_arg(ap, V9fsString *); + header.size = proxy_marshal(iovec, 1, HDR_SZ, "dss", size, + path, name); + header.type = T_LGETXATTR; + proxy_marshal(iovec, 1, 0, "dd", header.type, header.size); + header.size += HDR_SZ; + break; + case T_LLISTXATTR: + size = va_arg(ap, int); + path = va_arg(ap, V9fsString *); + header.size = proxy_marshal(iovec, 1, HDR_SZ, "ds", size, path); + header.type = T_LLISTXATTR; + proxy_marshal(iovec, 1, 0, "dd", header.type, header.size); + header.size += HDR_SZ; + 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 = proxy_marshal(iovec, 1, HDR_SZ, "sssdd", + path, name, value, size, flags); + header.type = T_LSETXATTR; + proxy_marshal(iovec, 1, 0, "dd", header.type, header.size); + header.size += HDR_SZ; + break; + case T_LREMOVEXATTR: + path = va_arg(ap, V9fsString *); + name = va_arg(ap, V9fsString *); + header.size = proxy_marshal(iovec, 1, HDR_SZ, "ss", path, name); + header.type = T_LREMOVEXATTR; + proxy_marshal(iovec, 1, 0, "dd", header.type, header.size); + header.size += HDR_SZ; + break; default: error_report("Invalid type %d\n", type); va_end(ap); @@ -433,6 +485,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_receive_status(proxy, &sock_error, reply); if (sock_error) { goto close_error; @@ -441,7 +495,10 @@ static int v9fs_request(V9fsProxy *proxy, int type, case T_LSTAT: case T_READLINK: case T_STATFS: - retval = v9fs_receive_response(proxy, type, &sock_error, response); + case T_LGETXATTR: + case T_LLISTXATTR: + retval = v9fs_receive_response(proxy, type, &sock_error, size, + response); if (sock_error) { goto close_error; } @@ -807,29 +864,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, "dss", size, + fs_path, &xname); + v9fs_string_free(&xname); + if (retval < 0) { + errno = -retval; + } + 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, "ds", size, + fs_path); + 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); + v9fs_string_free(&xname); + v9fs_string_free(&xvalue); + if (retval < 0) { + errno = -retval; + } + 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); + v9fs_string_free(&xname); + if (retval < 0) { + errno = -retval; + } + return retval; } static int proxy_name_to_path(FsContext *ctx, V9fsPath *dir_path, diff --git a/hw/9pfs/virtio-9p-proxy.h b/hw/9pfs/virtio-9p-proxy.h index ef8a0f3..4c691a8 100644 --- a/hw/9pfs/virtio-9p-proxy.h +++ b/hw/9pfs/virtio-9p-proxy.h @@ -39,6 +39,10 @@ enum { T_UTIME, T_RENAME, T_REMOVE, + T_LGETXATTR, + T_LLISTXATTR, + T_LSETXATTR, + T_LREMOVEXATTR, }; typedef struct { -- 1.7.6