Patchwork [10/13] hw/9pfs: xattr interfaces in proxy filesystem driver

login
register
mail settings
Submitter Mohan Kumar M
Date Oct. 31, 2011, 8:53 p.m.
Message ID <1320094412-19091-11-git-send-email-mohan@in.ibm.com>
Download mbox | patch
Permalink /patch/122960/
State New
Headers show

Comments

Mohan Kumar M - Oct. 31, 2011, 8:53 p.m.
From: "M. Mohan Kumar" <mohan@in.ibm.com>

Add xattr support for proxy FS

Signed-off-by: M. Mohan Kumar <mohan@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(-)

Patch

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,