Patchwork Fix bug with virtio-9p xattr functions return values

login
register
mail settings
Submitter jvrao
Date May 2, 2011, 10:41 p.m.
Message ID <4DBF3313.7040203@linux.vnet.ibm.com>
Download mbox | patch
Permalink /patch/93721/
State New
Headers show

Comments

jvrao - May 2, 2011, 10:41 p.m.
On 04/28/2011 06:48 AM, Sassan Panahinejad wrote:
> Several functions in virtio-9p-xattr.c are passing the return value of the associated host system call back to the client instead of errno.
> Since this value is -1 for any error (which, when received in the guest app as errno, indicates "operation not permitted") it is causing guest applications to fail in cases where the operation is not supported by the host.
> This causes a number of problems with dpkg and with install.
> This patch fixes the bug and returns the correct value, which means that guest applications are able to handle the error correctly.
>
> Signed-off-by: Sassan Panahinejad<sassan@sassan.me.uk>
The motivation and direction of this change is correct but unfortunately 
this is little bigger than
what is being identified here. This problem is not just limited to 
xattrs.  Unfortunately this is all over the place.

If you look at the post* functions of say, v9fs_do_lgetxattr( which is 
nothing but local_lgetxattr)
it tries to capture errno.
v9fs_post_xattr_getvalue()
v9fs_post_lxattr_check()
etc.

But this is not always the case say, in v9fs_xattr_fid_clunk()
retval = v9fs_do_lsetxattr(retval = v9fs_do_lsetxattr()).
So the plan is to change this from top to bottom. Starting from the 
virtio-9p.c to the virtio-9p-local.c
to other files and functions.
Just as you did, we need to push the errno to the source of the system 
call and from then on,
just use the function return values populated up. There should not be 
any errno references
other than immediately after the systemcall().  Something like below.
But I will be posting an initial patch which moves all the errno into 
v9fs_do*()
and then into local.c . It will be great if you want to take this all 
the way. :)








> ---
>   hw/virtio-9p-xattr.c |   21 ++++++++++++++++++---
>   1 files changed, 18 insertions(+), 3 deletions(-)
>
> diff --git a/hw/virtio-9p-xattr.c b/hw/virtio-9p-xattr.c
> index 1aab081..fd6d892 100644
> --- a/hw/virtio-9p-xattr.c
> +++ b/hw/virtio-9p-xattr.c
> @@ -32,9 +32,14 @@ static XattrOperations *get_xattr_operations(XattrOperations **h,
>   ssize_t v9fs_get_xattr(FsContext *ctx, const char *path,
>                          const char *name, void *value, size_t size)
>   {
> +    int ret;
>       XattrOperations *xops = get_xattr_operations(ctx->xops, name);
>       if (xops) {
> -        return xops->getxattr(ctx, path, name, value, size);
> +        ret = xops->getxattr(ctx, path, name, value, size);
> +        if (ret<  0) {
> +            return -errno;
> +        }
> +        return ret;
>       }
>       errno = -EOPNOTSUPP;
>       return -1;
> @@ -117,9 +122,14 @@ err_out:
>   int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name,
>                      void *value, size_t size, int flags)
>   {
> +    int ret;
>       XattrOperations *xops = get_xattr_operations(ctx->xops, name);
>       if (xops) {
> -        return xops->setxattr(ctx, path, name, value, size, flags);
> +        ret = xops->setxattr(ctx, path, name, value, size, flags);
> +        if (ret<  0) {
> +            return -errno;
> +        }
> +        return ret;
>       }
>       errno = -EOPNOTSUPP;
>       return -1;
> @@ -129,9 +139,14 @@ int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name,
>   int v9fs_remove_xattr(FsContext *ctx,
>                         const char *path, const char *name)
>   {
> +    int ret;
>       XattrOperations *xops = get_xattr_operations(ctx->xops, name);
>       if (xops) {
> -        return xops->removexattr(ctx, path, name);
> +        ret = xops->removexattr(ctx, path, name);
> +        if (ret<  0) {
> +            return -errno;
> +        }
> +        return ret;
>       }
>       errno = -EOPNOTSUPP;
>       return -1;

Patch

diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
index 0a015de..1674f40 100644
--- a/hw/9pfs/virtio-9p-local.c
+++ b/hw/9pfs/virtio-9p-local.c
@@ -143,9 +143,10 @@  static int local_open(FsContext *ctx, const char 
*path, int
      return open(rpath(ctx, path), flags);
  }

-static DIR *local_opendir(FsContext *ctx, const char *path)
+static int local_opendir(FsContext *ctx, const char *path, DIR **dir)
  {
-    return opendir(rpath(ctx, path));
+    *dir = opendir(rpath(ctx, path));
+    return *dir ? 0 : -errno;
  }

  static void local_rewinddir(FsContext *ctx, DIR *dir)
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index b5fc52b..7d88f48 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -110,9 +110,9 @@  static int v9fs_do_open(V9fsState *s, V9fsString 
*path, int
      return s->ops->open(&s->ctx, path->data, flags);
  }

-static DIR *v9fs_do_opendir(V9fsState *s, V9fsString *path)
+static int v9fs_do_opendir(V9fsState *s, V9fsString *path, DIR **dir)
  {
-    return s->ops->opendir(&s->ctx, path->data);
+    return s->ops->opendir(&s->ctx, path->data, dir);
  }

  static void v9fs_do_rewinddir(V9fsState *s, DIR *dir)
@@ -1665,8 +1665,7 @@  static int32_t get_iounit(V9fsState *s, V9fsString 
*name)

  static void v9fs_open_post_opendir(V9fsState *s, V9fsOpenState *vs, 
int err)
  {
-    if (vs->fidp->fs.dir == NULL) {
-        err = -errno;
+    if (err < 0) {
          goto out;
      }
      vs->fidp->fid_type = P9_FID_DIR;
@@ -1714,7 +1713,7 @@  static void v9fs_open_post_lstat(V9fsState *s, 
V9fsOpenSta
      stat_to_qid(&vs->stbuf, &vs->qid);

      if (S_ISDIR(vs->stbuf.st_mode)) {
-        vs->fidp->fs.dir = v9fs_do_opendir(s, &vs->fidp->path);
+        err = v9fs_do_opendir(s, &vs->fidp->path, &vs->fidp->fs.dir);
          v9fs_open_post_opendir(s, vs, err);
      } else {
          if (s->proto_version == V9FS_PROTO_2000L) {
@@ -2397,9 +2396,6 @@  static void v9fs_create_post_perms(V9fsState *s, 
V9fsCreat
  static void v9fs_create_post_opendir(V9fsState *s, V9fsCreateState *vs,
                                                                      
int err)
  {
-    if (!vs->fidp->fs.dir) {
-        err = -errno;
-    }
      vs->fidp->fid_type = P9_FID_DIR;
      v9fs_post_create(s, vs, err);
  }
@@ -2412,7 +2408,7 @@  static void v9fs_create_post_dir_lstat(V9fsState 
*s, V9fsC
          goto out;
      }

-    vs->fidp->fs.dir = v9fs_do_opendir(s, &vs->fullname);
+    err = v9fs_do_opendir(s, &vs->fullname, &vs->fidp->fs.dir);
      v9fs_create_post_opendir(s, vs, err);
      return;

diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h
index 126e60e..dc95824 100644
--- a/hw/file-op-9p.h
+++ b/hw/file-op-9p.h
@@ -73,7 +73,7 @@  typedef struct FileOperations
      int (*setuid)(FsContext *, uid_t);
      int (*close)(FsContext *, int);
      int (*closedir)(FsContext *, DIR *);
-    DIR *(*opendir)(FsContext *, const char *);
+    int (*opendir)(FsContext *, const char *, DIR **);
      int (*open)(FsContext *, const char *, int);
      int (*open2)(FsContext *, const char *, int, FsCred *);
      void (*rewinddir)(FsContext *, DIR *);