func: static int v9fs_request(V9fsProxy *proxy, int type,
  
                          void *response, const char *fmt, ...)
  
  {
  
      dev_t rdev;
  
      va_list ap;
  
      int size = 0;
  
      int retval = 0;
  
      uint64_t offset;
  
      ProxyHeader header = { 0, 0};
  
      struct timespec spec[2];
  
      int flags, mode, uid, gid;
  
      V9fsString *name, *value;
  
      V9fsString *path, *oldpath;
  
      struct iovec *iovec = NULL, *reply = NULL;
  
  
  
      qemu_mutex_lock(&proxy->mutex);
  
  
  
      if (proxy->sockfd == -1) {
  
          retval = -EIO;
  
          goto err_out;
  
      }
  
      iovec = &proxy->out_iovec;
  
      reply = &proxy->in_iovec;
  
      va_start(ap, fmt);
  
      switch (type) {
  
      case T_OPEN:
  
          path = va_arg(ap, V9fsString *);
  
          flags = va_arg(ap, int);
  
          retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sd", path, flags);
  
          if (retval > 0) {
  
              header.size = retval;
  
              header.type = T_OPEN;
  
          }
  
          break;
  
      case T_CREATE:
  
          path = va_arg(ap, V9fsString *);
  
          flags = va_arg(ap, int);
  
          mode = va_arg(ap, int);
  
          uid = va_arg(ap, int);
  
          gid = va_arg(ap, int);
  
          retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sdddd", path,
  
                                      flags, mode, uid, gid);
  
          if (retval > 0) {
  
              header.size = retval;
  
              header.type = T_CREATE;
  
          }
  
          break;
  
      case T_MKNOD:
  
          path = va_arg(ap, V9fsString *);
  
          mode = va_arg(ap, int);
  
          rdev = va_arg(ap, long int);
  
          uid = va_arg(ap, int);
  
          gid = va_arg(ap, int);
  
          retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ddsdq",
  
                                      uid, gid, path, mode, rdev);
  
          if (retval > 0) {
  
              header.size = retval;
  
              header.type = T_MKNOD;
  
          }
  
          break;
  
      case T_MKDIR:
  
          path = va_arg(ap, V9fsString *);
  
          mode = va_arg(ap, int);
  
          uid = va_arg(ap, int);
  
          gid = va_arg(ap, int);
  
          retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ddsd",
  
                                      uid, gid, path, mode);
  
          if (retval > 0) {
  
              header.size = retval;
  
              header.type = T_MKDIR;
  
          }
  
          break;
  
      case T_SYMLINK:
  
          oldpath = va_arg(ap, V9fsString *);
  
          path = va_arg(ap, V9fsString *);
  
          uid = va_arg(ap, int);
  
          gid = va_arg(ap, int);
  
          retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ddss",
  
                                      uid, gid, oldpath, path);
  
          if (retval > 0) {
  
              header.size = retval;
  
              header.type = T_SYMLINK;
  
          }
  
          break;
  
      case T_LINK:
  
          oldpath = va_arg(ap, V9fsString *);
  
          path = va_arg(ap, V9fsString *);
  
          retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ss",
  
                                      oldpath, path);
  
          if (retval > 0) {
  
              header.size = retval;
  
              header.type = T_LINK;
  
          }
  
          break;
  
      case T_LSTAT:
  
          path = va_arg(ap, V9fsString *);
  
          retval = proxy_marshal(iovec, PROXY_HDR_SZ, "s", path);
  
          if (retval > 0) {
  
              header.size = retval;
  
              header.type = T_LSTAT;
  
          }
  
          break;
  
      case T_READLINK:
  
          path = va_arg(ap, V9fsString *);
  
          size = va_arg(ap, int);
  
          retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sd", path, size);
  
          if (retval > 0) {
  
              header.size = retval;
  
              header.type = T_READLINK;
  
          }
  
          break;
  
      case T_STATFS:
  
          path = va_arg(ap, V9fsString *);
  
          retval = proxy_marshal(iovec, PROXY_HDR_SZ, "s", path);
  
          if (retval > 0) {
  
              header.size = retval;
  
              header.type = T_STATFS;
  
          }
  
          break;
  
      case T_CHMOD:
  
          path = va_arg(ap, V9fsString *);
  
          mode = va_arg(ap, int);
  
          retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sd", path, mode);
  
          if (retval > 0) {
  
              header.size = retval;
  
              header.type = T_CHMOD;
  
          }
  
          break;
  
      case T_CHOWN:
  
          path = va_arg(ap, V9fsString *);
  
          uid = va_arg(ap, int);
  
          gid = va_arg(ap, int);
  
          retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sdd", path, uid, gid);
  
          if (retval > 0) {
  
              header.size = retval;
  
              header.type = T_CHOWN;
  
          }
  
          break;
  
      case T_TRUNCATE:
  
          path = va_arg(ap, V9fsString *);
  
          offset = va_arg(ap, uint64_t);
  
          retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sq", path, offset);
  
          if (retval > 0) {
  
              header.size = retval;
  
              header.type = T_TRUNCATE;
  
          }
  
          break;
  
      case T_UTIME:
  
          path = va_arg(ap, V9fsString *);
  
          spec[0].tv_sec = va_arg(ap, long);
  
          spec[0].tv_nsec = va_arg(ap, long);
  
          spec[1].tv_sec = va_arg(ap, long);
  
          spec[1].tv_nsec = va_arg(ap, long);
  
          retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sqqqq", path,
  
                                      spec[0].tv_sec, spec[1].tv_nsec,
  
                                      spec[1].tv_sec, spec[1].tv_nsec);
  
          if (retval > 0) {
  
              header.size = retval;
  
              header.type = T_UTIME;
  
          }
  
          break;
  
      case T_RENAME:
  
          oldpath = va_arg(ap, V9fsString *);
  
          path = va_arg(ap, V9fsString *);
  
          retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ss", oldpath, path);
  
          if (retval > 0) {
  
              header.size = retval;
  
              header.type = T_RENAME;
  
          }
  
          break;
  
      case T_REMOVE:
  
          path = va_arg(ap, V9fsString *);
  
          retval = proxy_marshal(iovec, PROXY_HDR_SZ, "s", path);
  
          if (retval > 0) {
  
              header.size = retval;
  
              header.type = T_REMOVE;
  
          }
  
          break;
  
      case T_LGETXATTR:
  
          size = va_arg(ap, int);
  
          path = va_arg(ap, V9fsString *);
  
          name = va_arg(ap, V9fsString *);
  
          retval = proxy_marshal(iovec, PROXY_HDR_SZ,
  
                                      "dss", size, path, name);
  
          if (retval > 0) {
  
              header.size = retval;
  
              header.type = T_LGETXATTR;
  
          }
  
          break;
  
      case T_LLISTXATTR:
  
          size = va_arg(ap, int);
  
          path = va_arg(ap, V9fsString *);
  
          retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ds", size, path);
  
          if (retval > 0) {
  
              header.size = retval;
  
              header.type = T_LLISTXATTR;
  
          }
  
          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);
  
          retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sssdd",
  
                                      path, name, value, size, flags);
  
          if (retval > 0) {
  
              header.size = retval;
  
              header.type = T_LSETXATTR;
  
          }
  
          break;
  
      case T_LREMOVEXATTR:
  
          path = va_arg(ap, V9fsString *);
  
          name = va_arg(ap, V9fsString *);
  
          retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ss", path, name);
  
          if (retval > 0) {
  
              header.size = retval;
  
              header.type = T_LREMOVEXATTR;
  
          }
  
          break;
  
      case T_GETVERSION:
  
          path = va_arg(ap, V9fsString *);
  
          retval = proxy_marshal(iovec, PROXY_HDR_SZ, "s", path);
  
          if (retval > 0) {
  
              header.size = retval;
  
              header.type = T_GETVERSION;
  
          }
  
          break;
  
      default:
  
          error_report("Invalid type %d", type);
  
          retval = -EINVAL;
  
          break;
  
      }
  
      va_end(ap);
  
  
  
      if (retval < 0) {
  
          goto err_out;
  
      }
  
  
  
      /* marshal the header details */
  
      proxy_marshal(iovec, 0, "dd", header.type, header.size);
  
      header.size += PROXY_HDR_SZ;
  
  
  
      retval = qemu_write_full(proxy->sockfd, iovec->iov_base, header.size);
  
      if (retval != header.size) {
  
          goto close_error;
  
      }
  
  
  
      switch (type) {
  
      case T_OPEN:
  
      case T_CREATE:
  
          /*
  
           * A file descriptor is returned as response for
  
           * T_OPEN,T_CREATE on success
  
           */
  
          if (v9fs_receivefd(proxy->sockfd, &retval) < 0) {
  
              goto close_error;
  
          }
  
          break;
  
      case T_MKNOD:
  
      case T_MKDIR:
  
      case T_SYMLINK:
  
      case T_LINK:
  
      case T_CHMOD:
  
      case T_CHOWN:
  
      case T_RENAME:
  
      case T_TRUNCATE:
  
      case T_UTIME:
  
      case T_REMOVE:
  
      case T_LSETXATTR:
  
      case T_LREMOVEXATTR:
  
          if (v9fs_receive_status(proxy, reply, &retval) < 0) {
  
              goto close_error;
  
          }
  
          break;
  
      case T_LSTAT:
  
      case T_READLINK:
  
      case T_STATFS:
  
      case T_GETVERSION:
  
          if (v9fs_receive_response(proxy, type, &retval, response) < 0) {
  
              goto close_error;
  
          }
  
          break;
  
      case T_LGETXATTR:
  
      case T_LLISTXATTR:
  
          if (!size) {
  
              if (v9fs_receive_status(proxy, reply, &retval) < 0) {
  
                  goto close_error;
  
              }
  
          } else {
  
              if (v9fs_receive_response(proxy, type, &retval, response) < 0) {
  
                  goto close_error;
  
              }
  
          }
  
          break;
  
      }
  
  
  
  err_out:
  
      qemu_mutex_unlock(&proxy->mutex);
  
      return retval;
  
  
  
  close_error:
  
      close(proxy->sockfd);
  
      proxy->sockfd = -1;
  
      qemu_mutex_unlock(&proxy->mutex);
  
      return -EIO;
  
  }
  