Patchwork [08/13] hw/9pfs: Add stat/readlink/statfs for proxy FS

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

Comments

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


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

Patch

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,