Re: [Qemu-devel] idea: non-ethernet paravirtual network device

2011-07-26 Thread Sassan Panahinejad
Ok, thanks guys. I don't think I'll proceed with this idea.

Thanks
Sassan

On 26 July 2011 11:23, Hannes Reinecke h...@suse.de wrote:

 On 07/26/2011 08:04 AM, Stefan Hajnoczi wrote:

 On Mon, Jul 25, 2011 at 4:53 PM, Sassan 
 Panahinejadsas...@sassan.me.**uksas...@sassan.me.uk
  wrote:

 Here's a thought, could we improve network performance by creating a
 paravirtual network device which doesn't emulate ethernet? It shouldn't
 be
 too hard to just whack IP packets pretty much directly over a virtio
 link.
 This should improve performance when using a user host connection and
 we
 could introduce a tun host connection instead of tap for this setup.

 Does anyone have any thoughts on how worthwhile this would be? Would the
 performance improvement justify the effort involved?


 My guess is no noticable impact (if you ignore ARP requests).

 The Ethernet header is only 14 bytes or so.  We don't calculate any
 checksums at that level.  There's probably not much of a win.

  Only lots of pain to be had.
 Mainframe used to do this. But abandoned it not, thankfully.

 Problem is that you need to patch each and every tool looking at the
 packets to _not_ expecting an Ethernet header.
 And patching up DHCP is _not_ trivial.

 Cheers,

 Hannes
 --
 Dr. Hannes Reinecke   zSeries  Storage
 h...@suse.de  +49 911 74053 688
 SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
 GF: J. Hawn, J. Guild, F. Imendörffer, HRB 16746 (AG Nürnberg)




[Qemu-devel] idea: non-ethernet paravirtual network device

2011-07-25 Thread Sassan Panahinejad
Hi all,

Here's a thought, could we improve network performance by creating a
paravirtual network device which doesn't emulate ethernet? It shouldn't be
too hard to just whack IP packets pretty much directly over a virtio link.
This should improve performance when using a user host connection and we
could introduce a tun host connection instead of tap for this setup.

Does anyone have any thoughts on how worthwhile this would be? Would the
performance improvement justify the effort involved?

Thanks
Sassan


Re: [Qemu-devel] [PATCH] Clean up virtio-9p error handling code

2011-06-28 Thread Sassan Panahinejad
Hi JV,

Any progress regarding merging this patch (and the fsync patch I submitted)?
Is there anything I can do to assist/speed the process?

Thanks
Sassan


On 8 June 2011 17:21, Sassan Panahinejad sas...@sassan.me.uk wrote:

 In a lot of cases, the handling of errors was quite ugly.
 This patch moves reading of errno to immediately after the system calls and
 passes it up through the system more cleanly.
 Also, in the case of the xattr functions (and possibly others), completely
 the wrong error was being returned.


 This patch is created against your 9p-coroutine-bh branch, as requested.
 Sorry for the delay, I was unexpectedly required to work abroad for 2 weeks.

 Signed-off-by: Sassan Panahinejad sas...@sassan.me.uk

 ---
  fsdev/file-op-9p.h|4 +-
  hw/9pfs/codir.c   |   14 +
  hw/9pfs/virtio-9p-local.c |  123
 +
  hw/9pfs/virtio-9p-xattr.c |   21 +++-
  4 files changed, 90 insertions(+), 72 deletions(-)

 diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
 index af9daf7..3d9575b 100644
 --- a/fsdev/file-op-9p.h
 +++ b/fsdev/file-op-9p.h
 @@ -73,12 +73,12 @@ 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 *);
 off_t (*telldir)(FsContext *, DIR *);
 -struct dirent *(*readdir)(FsContext *, DIR *);
 +int (*readdir)(FsContext *, DIR *, struct dirent **);
 void (*seekdir)(FsContext *, DIR *, off_t);
 ssize_t (*preadv)(FsContext *, int, const struct iovec *, int, off_t);
 ssize_t (*pwritev)(FsContext *, int, const struct iovec *, int, off_t);
 diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c
 index 110289f..acbbb39 100644
 --- a/hw/9pfs/codir.c
 +++ b/hw/9pfs/codir.c
 @@ -25,12 +25,7 @@ int v9fs_co_readdir(V9fsState *s, V9fsFidState *fidp,
 struct dirent **dent)
 {
 errno = 0;
 /*FIXME!! need to switch to readdir_r */
 -*dent = s-ops-readdir(s-ctx, fidp-fs.dir);
 -if (!*dent  errno) {
 -err = -errno;
 -} else {
 -err = 0;
 -}
 +err = s-ops-readdir(s-ctx, fidp-fs.dir, dent);
 });
 return err;
  }
 @@ -93,12 +88,7 @@ int v9fs_co_opendir(V9fsState *s, V9fsFidState *fidp)

 v9fs_co_run_in_worker(
 {
 -dir = s-ops-opendir(s-ctx, fidp-path.data);
 -if (!dir) {
 -err = -errno;
 -} else {
 -err = 0;
 -}
 +err = s-ops-opendir(s-ctx, fidp-path.data, dir);
 });
 fidp-fs.dir = dir;
 return err;
 diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
 index 77904c3..65f35eb 100644
 --- a/hw/9pfs/virtio-9p-local.c
 +++ b/hw/9pfs/virtio-9p-local.c
 @@ -28,7 +28,7 @@ static int local_lstat(FsContext *fs_ctx, const char
 *path, struct stat *stbuf)
 char buffer[PATH_MAX];
 err =  lstat(rpath(fs_ctx, path, buffer), stbuf);
  if (err) {
 -return err;
 +return -errno;
 }
 if (fs_ctx-fs_sm == SM_MAPPED) {
 /* Actual credentials are part of extended attrs */
 @@ -53,7 +53,7 @@ static int local_lstat(FsContext *fs_ctx, const char
 *path, struct stat *stbuf)
  stbuf-st_rdev = tmp_dev;
 }
 }
 -return err;
 +return 0;
  }

  static int local_set_xattr(const char *path, FsCred *credp)
 @@ -63,28 +63,28 @@ static int local_set_xattr(const char *path, FsCred
 *credp)
  err = setxattr(path, user.virtfs.uid, credp-fc_uid,
 sizeof(uid_t),
 0);
 if (err) {
 -return err;
 +return -errno;
 }
 }
 if (credp-fc_gid != -1) {
 err = setxattr(path, user.virtfs.gid, credp-fc_gid,
 sizeof(gid_t),
 0);
 if (err) {
 -return err;
 +return -errno;
 }
 }
 if (credp-fc_mode != -1) {
 err = setxattr(path, user.virtfs.mode, credp-fc_mode,
 sizeof(mode_t), 0);
 if (err) {
 -return err;
 +return -errno;
 }
 }
 if (credp-fc_rdev != -1) {
 err = setxattr(path, user.virtfs.rdev, credp-fc_rdev,
 sizeof(dev_t), 0);
 if (err) {
 -return err;
 +return -errno;
 }
 }
 return 0;
 @@ -95,7 +95,7 @@ static int local_post_create_passthrough(FsContext
 *fs_ctx, const char *path,
  {
 char buffer[PATH_MAX];
 if (chmod(rpath(fs_ctx, path, buffer), credp-fc_mode  0)  0) {
 -return -1;
 +return -errno;
 }
 if (lchown(rpath(fs_ctx, path, buffer), credp-fc_uid

Re: [Qemu-devel] [PATCH] Clean up virtio-9p error handling code

2011-06-28 Thread Sassan Panahinejad
On 28 June 2011 15:22, Venkateswararao Jujjuri jv...@linux.vnet.ibm.comwrote:

 **
 On 06/28/2011 05:25 AM, Sassan Panahinejad wrote:

 Hi JV,

 Any progress regarding merging this patch (and the fsync patch I
 submitted)?
 Is there anything I can do to assist/speed the process?

 Sussan, Thanks for the ping. :)

 Everything is on hold waiting for 0.15 tag; Including threading/coroutine
 patches.
 As soon as we go in with the coroutines, you can just rebase your patch and
 we should be
 ready to go. I am waiting too. :-D

Thanks for the info :)


 Thanks,
 JV



 Thanks
 Sassan


 On 8 June 2011 17:21, Sassan Panahinejad sas...@sassan.me.uk wrote:

 In a lot of cases, the handling of errors was quite ugly.
 This patch moves reading of errno to immediately after the system calls
 and passes it up through the system more cleanly.
 Also, in the case of the xattr functions (and possibly others), completely
 the wrong error was being returned.


  This patch is created against your 9p-coroutine-bh branch, as requested.
 Sorry for the delay, I was unexpectedly required to work abroad for 2 weeks.

 Signed-off-by: Sassan Panahinejad sas...@sassan.me.uk

 ---
  fsdev/file-op-9p.h|4 +-
   hw/9pfs/codir.c   |   14 +
  hw/9pfs/virtio-9p-local.c |  123
 +
   hw/9pfs/virtio-9p-xattr.c |   21 +++-
  4 files changed, 90 insertions(+), 72 deletions(-)

 diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
  index af9daf7..3d9575b 100644
 --- a/fsdev/file-op-9p.h
 +++ b/fsdev/file-op-9p.h
 @@ -73,12 +73,12 @@ 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 *);
 off_t (*telldir)(FsContext *, DIR *);
 -struct dirent *(*readdir)(FsContext *, DIR *);
 +int (*readdir)(FsContext *, DIR *, struct dirent **);
 void (*seekdir)(FsContext *, DIR *, off_t);
 ssize_t (*preadv)(FsContext *, int, const struct iovec *, int, off_t);
 ssize_t (*pwritev)(FsContext *, int, const struct iovec *, int,
 off_t);
  diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c
 index 110289f..acbbb39 100644
 --- a/hw/9pfs/codir.c
 +++ b/hw/9pfs/codir.c
 @@ -25,12 +25,7 @@ int v9fs_co_readdir(V9fsState *s, V9fsFidState *fidp,
 struct dirent **dent)
 {
 errno = 0;
 /*FIXME!! need to switch to readdir_r */
 -*dent = s-ops-readdir(s-ctx, fidp-fs.dir);
 -if (!*dent  errno) {
 -err = -errno;
 -} else {
 -err = 0;
 -}
 +err = s-ops-readdir(s-ctx, fidp-fs.dir, dent);
 });
 return err;
  }
 @@ -93,12 +88,7 @@ int v9fs_co_opendir(V9fsState *s, V9fsFidState *fidp)

 v9fs_co_run_in_worker(
 {
 -dir = s-ops-opendir(s-ctx, fidp-path.data);
 -if (!dir) {
 -err = -errno;
 -} else {
 -err = 0;
 -}
 +err = s-ops-opendir(s-ctx, fidp-path.data, dir);
 });
 fidp-fs.dir = dir;
 return err;
 diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
  index 77904c3..65f35eb 100644
 --- a/hw/9pfs/virtio-9p-local.c
 +++ b/hw/9pfs/virtio-9p-local.c
  @@ -28,7 +28,7 @@ static int local_lstat(FsContext *fs_ctx, const char
 *path, struct stat *stbuf)
 char buffer[PATH_MAX];
 err =  lstat(rpath(fs_ctx, path, buffer), stbuf);
  if (err) {
 -return err;
 +return -errno;
 }
 if (fs_ctx-fs_sm == SM_MAPPED) {
 /* Actual credentials are part of extended attrs */
  @@ -53,7 +53,7 @@ static int local_lstat(FsContext *fs_ctx, const char
 *path, struct stat *stbuf)
  stbuf-st_rdev = tmp_dev;
 }
 }
 -return err;
 +return 0;
  }

  static int local_set_xattr(const char *path, FsCred *credp)
  @@ -63,28 +63,28 @@ static int local_set_xattr(const char *path, FsCred
 *credp)
  err = setxattr(path, user.virtfs.uid, credp-fc_uid,
 sizeof(uid_t),
 0);
 if (err) {
 -return err;
 +return -errno;
 }
 }
 if (credp-fc_gid != -1) {
 err = setxattr(path, user.virtfs.gid, credp-fc_gid,
 sizeof(gid_t),
 0);
 if (err) {
 -return err;
 +return -errno;
 }
 }
 if (credp-fc_mode != -1) {
 err = setxattr(path, user.virtfs.mode, credp-fc_mode,
 sizeof(mode_t), 0);
 if (err) {
 -return err;
 +return -errno;
 }
 }
 if (credp-fc_rdev != -1) {
 err = setxattr(path, user.virtfs.rdev, credp-fc_rdev,
 sizeof

[Qemu-devel] [PATCH] Clean up virtio-9p error handling code

2011-06-08 Thread Sassan Panahinejad
In a lot of cases, the handling of errors was quite ugly.
This patch moves reading of errno to immediately after the system calls and 
passes it up through the system more cleanly.
Also, in the case of the xattr functions (and possibly others), completely the 
wrong error was being returned.


This patch is created against your 9p-coroutine-bh branch, as requested. Sorry 
for the delay, I was unexpectedly required to work abroad for 2 weeks.

Signed-off-by: Sassan Panahinejad sas...@sassan.me.uk

---
 fsdev/file-op-9p.h|4 +-
 hw/9pfs/codir.c   |   14 +
 hw/9pfs/virtio-9p-local.c |  123 +
 hw/9pfs/virtio-9p-xattr.c |   21 +++-
 4 files changed, 90 insertions(+), 72 deletions(-)

diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index af9daf7..3d9575b 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -73,12 +73,12 @@ 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 *);
 off_t (*telldir)(FsContext *, DIR *);
-struct dirent *(*readdir)(FsContext *, DIR *);
+int (*readdir)(FsContext *, DIR *, struct dirent **);
 void (*seekdir)(FsContext *, DIR *, off_t);
 ssize_t (*preadv)(FsContext *, int, const struct iovec *, int, off_t);
 ssize_t (*pwritev)(FsContext *, int, const struct iovec *, int, off_t);
diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c
index 110289f..acbbb39 100644
--- a/hw/9pfs/codir.c
+++ b/hw/9pfs/codir.c
@@ -25,12 +25,7 @@ int v9fs_co_readdir(V9fsState *s, V9fsFidState *fidp, struct 
dirent **dent)
 {
 errno = 0;
 /*FIXME!! need to switch to readdir_r */
-*dent = s-ops-readdir(s-ctx, fidp-fs.dir);
-if (!*dent  errno) {
-err = -errno;
-} else {
-err = 0;
-}
+err = s-ops-readdir(s-ctx, fidp-fs.dir, dent);
 });
 return err;
 }
@@ -93,12 +88,7 @@ int v9fs_co_opendir(V9fsState *s, V9fsFidState *fidp)
 
 v9fs_co_run_in_worker(
 {
-dir = s-ops-opendir(s-ctx, fidp-path.data);
-if (!dir) {
-err = -errno;
-} else {
-err = 0;
-}
+err = s-ops-opendir(s-ctx, fidp-path.data, dir);
 });
 fidp-fs.dir = dir;
 return err;
diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
index 77904c3..65f35eb 100644
--- a/hw/9pfs/virtio-9p-local.c
+++ b/hw/9pfs/virtio-9p-local.c
@@ -28,7 +28,7 @@ static int local_lstat(FsContext *fs_ctx, const char *path, 
struct stat *stbuf)
 char buffer[PATH_MAX];
 err =  lstat(rpath(fs_ctx, path, buffer), stbuf);
 if (err) {
-return err;
+return -errno;
 }
 if (fs_ctx-fs_sm == SM_MAPPED) {
 /* Actual credentials are part of extended attrs */
@@ -53,7 +53,7 @@ static int local_lstat(FsContext *fs_ctx, const char *path, 
struct stat *stbuf)
 stbuf-st_rdev = tmp_dev;
 }
 }
-return err;
+return 0;
 }
 
 static int local_set_xattr(const char *path, FsCred *credp)
@@ -63,28 +63,28 @@ static int local_set_xattr(const char *path, FsCred *credp)
 err = setxattr(path, user.virtfs.uid, credp-fc_uid, sizeof(uid_t),
 0);
 if (err) {
-return err;
+return -errno;
 }
 }
 if (credp-fc_gid != -1) {
 err = setxattr(path, user.virtfs.gid, credp-fc_gid, sizeof(gid_t),
 0);
 if (err) {
-return err;
+return -errno;
 }
 }
 if (credp-fc_mode != -1) {
 err = setxattr(path, user.virtfs.mode, credp-fc_mode,
 sizeof(mode_t), 0);
 if (err) {
-return err;
+return -errno;
 }
 }
 if (credp-fc_rdev != -1) {
 err = setxattr(path, user.virtfs.rdev, credp-fc_rdev,
 sizeof(dev_t), 0);
 if (err) {
-return err;
+return -errno;
 }
 }
 return 0;
@@ -95,7 +95,7 @@ static int local_post_create_passthrough(FsContext *fs_ctx, 
const char *path,
 {
 char buffer[PATH_MAX];
 if (chmod(rpath(fs_ctx, path, buffer), credp-fc_mode  0)  0) {
-return -1;
+return -errno;
 }
 if (lchown(rpath(fs_ctx, path, buffer), credp-fc_uid,
 credp-fc_gid)  0) {
@@ -104,7 +104,7 @@ static int local_post_create_passthrough(FsContext *fs_ctx, 
const char *path,
  * using security model none. Ignore the error
  */
 if (fs_ctx-fs_sm != SM_NONE) {
-return -1;
+return -errno

[Qemu-devel] [PATCH] Clean up virtio-9p error handling code

2011-05-15 Thread Sassan Panahinejad
In a lot of cases, the handling of errors was quite ugly.
This patch moves reading of errno to immediately after the system calls and 
passes it up through the system more cleanly.
Also, in the case of the xattr functions (and possibly others), completely the 
wrong error was being returned.

Signed-off-by: Sassan Panahinejad sas...@sassan.me.uk
---
 fsdev/file-op-9p.h|4 +-
 hw/9pfs/virtio-9p-local.c |  123 +
 hw/9pfs/virtio-9p-xattr.c |   21 ++-
 hw/9pfs/virtio-9p.c   |  150 -
 4 files changed, 128 insertions(+), 170 deletions(-)

diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index 126e60e..81a822a 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -73,12 +73,12 @@ 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 *);
 off_t (*telldir)(FsContext *, DIR *);
-struct dirent *(*readdir)(FsContext *, DIR *);
+int (*readdir)(FsContext *, DIR *, struct dirent **);
 void (*seekdir)(FsContext *, DIR *, off_t);
 ssize_t (*preadv)(FsContext *, int, const struct iovec *, int, off_t);
 ssize_t (*pwritev)(FsContext *, int, const struct iovec *, int, off_t);
diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
index 0a015de..de2597d 100644
--- a/hw/9pfs/virtio-9p-local.c
+++ b/hw/9pfs/virtio-9p-local.c
@@ -26,7 +26,7 @@ static int local_lstat(FsContext *fs_ctx, const char *path, 
struct stat *stbuf)
 int err;
 err =  lstat(rpath(fs_ctx, path), stbuf);
 if (err) {
-return err;
+return -errno;
 }
 if (fs_ctx-fs_sm == SM_MAPPED) {
 /* Actual credentials are part of extended attrs */
@@ -51,7 +51,7 @@ static int local_lstat(FsContext *fs_ctx, const char *path, 
struct stat *stbuf)
 stbuf-st_rdev = tmp_dev;
 }
 }
-return err;
+return 0;
 }
 
 static int local_set_xattr(const char *path, FsCred *credp)
@@ -61,28 +61,28 @@ static int local_set_xattr(const char *path, FsCred *credp)
 err = setxattr(path, user.virtfs.uid, credp-fc_uid, sizeof(uid_t),
 0);
 if (err) {
-return err;
+return -errno;
 }
 }
 if (credp-fc_gid != -1) {
 err = setxattr(path, user.virtfs.gid, credp-fc_gid, sizeof(gid_t),
 0);
 if (err) {
-return err;
+return -errno;
 }
 }
 if (credp-fc_mode != -1) {
 err = setxattr(path, user.virtfs.mode, credp-fc_mode,
 sizeof(mode_t), 0);
 if (err) {
-return err;
+return -errno;
 }
 }
 if (credp-fc_rdev != -1) {
 err = setxattr(path, user.virtfs.rdev, credp-fc_rdev,
 sizeof(dev_t), 0);
 if (err) {
-return err;
+return -errno;
 }
 }
 return 0;
@@ -92,7 +92,7 @@ static int local_post_create_passthrough(FsContext *fs_ctx, 
const char *path,
 FsCred *credp)
 {
 if (chmod(rpath(fs_ctx, path), credp-fc_mode  0)  0) {
-return -1;
+return -errno;
 }
 if (lchown(rpath(fs_ctx, path), credp-fc_uid, credp-fc_gid)  0) {
 /*
@@ -100,7 +100,7 @@ static int local_post_create_passthrough(FsContext *fs_ctx, 
const char *path,
  * using security model none. Ignore the error
  */
 if (fs_ctx-fs_sm != SM_NONE) {
-return -1;
+return -errno;
 }
 }
 return 0;
@@ -114,38 +114,40 @@ static ssize_t local_readlink(FsContext *fs_ctx, const 
char *path,
 int fd;
 fd = open(rpath(fs_ctx, path), O_RDONLY);
 if (fd == -1) {
-return -1;
+return -errno;
 }
 do {
 tsize = read(fd, (void *)buf, bufsz);
 } while (tsize == -1  errno == EINTR);
 close(fd);
-return tsize;
+return tsize == -1 ? -errno : tsize;
 } else if ((fs_ctx-fs_sm == SM_PASSTHROUGH) ||
(fs_ctx-fs_sm == SM_NONE)) {
 tsize = readlink(rpath(fs_ctx, path), buf, bufsz);
 }
-return tsize;
+return tsize == -1 ? -errno : tsize;
 }
 
 static int local_close(FsContext *ctx, int fd)
 {
-return close(fd);
+return close(fd) == -1 ? -errno : 0;
 }
 
 static int local_closedir(FsContext *ctx, DIR *dir)
 {
-return closedir(dir);
+return closedir(dir) == -1 ? -errno : 0;
 }
 
 static int local_open(FsContext *ctx, const char *path, int flags)
 {
-return open(rpath(ctx, path), flags);
+int ret = open(rpath(ctx, path), flags);
+return ret == -1 ? -errno : ret

[Qemu-devel] [PATCH] Clean up virtio-9p error handling code

2011-05-08 Thread Sassan Panahinejad
In a lot of cases, the handling of errors was quite ugly.
This patch moves reading of errno to immediately after the system calls and 
passes it up through the system more cleanly.
Also, in the case of the xattr functions (and possibly others), completely the 
wrong error was being returned.
---
 fsdev/file-op-9p.h|4 +-
 hw/9pfs/virtio-9p-local.c |  121 
 hw/9pfs/virtio-9p-xattr.c |   21 ++-
 hw/9pfs/virtio-9p.c   |  150 +++-
 4 files changed, 125 insertions(+), 171 deletions(-)

diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index 126e60e..81a822a 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -73,12 +73,12 @@ 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 *);
 off_t (*telldir)(FsContext *, DIR *);
-struct dirent *(*readdir)(FsContext *, DIR *);
+int (*readdir)(FsContext *, DIR *, struct dirent **);
 void (*seekdir)(FsContext *, DIR *, off_t);
 ssize_t (*preadv)(FsContext *, int, const struct iovec *, int, off_t);
 ssize_t (*pwritev)(FsContext *, int, const struct iovec *, int, off_t);
diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
index 0a015de..afaff78 100644
--- a/hw/9pfs/virtio-9p-local.c
+++ b/hw/9pfs/virtio-9p-local.c
@@ -26,7 +26,7 @@ static int local_lstat(FsContext *fs_ctx, const char *path, 
struct stat *stbuf)
 int err;
 err =  lstat(rpath(fs_ctx, path), stbuf);
 if (err) {
-return err;
+return -errno;
 }
 if (fs_ctx-fs_sm == SM_MAPPED) {
 /* Actual credentials are part of extended attrs */
@@ -51,7 +51,7 @@ static int local_lstat(FsContext *fs_ctx, const char *path, 
struct stat *stbuf)
 stbuf-st_rdev = tmp_dev;
 }
 }
-return err;
+return 0;
 }
 
 static int local_set_xattr(const char *path, FsCred *credp)
@@ -61,28 +61,28 @@ static int local_set_xattr(const char *path, FsCred *credp)
 err = setxattr(path, user.virtfs.uid, credp-fc_uid, sizeof(uid_t),
 0);
 if (err) {
-return err;
+return -errno;
 }
 }
 if (credp-fc_gid != -1) {
 err = setxattr(path, user.virtfs.gid, credp-fc_gid, sizeof(gid_t),
 0);
 if (err) {
-return err;
+return -errno;
 }
 }
 if (credp-fc_mode != -1) {
 err = setxattr(path, user.virtfs.mode, credp-fc_mode,
 sizeof(mode_t), 0);
 if (err) {
-return err;
+return -errno;
 }
 }
 if (credp-fc_rdev != -1) {
 err = setxattr(path, user.virtfs.rdev, credp-fc_rdev,
 sizeof(dev_t), 0);
 if (err) {
-return err;
+return -errno;
 }
 }
 return 0;
@@ -92,7 +92,7 @@ static int local_post_create_passthrough(FsContext *fs_ctx, 
const char *path,
 FsCred *credp)
 {
 if (chmod(rpath(fs_ctx, path), credp-fc_mode  0)  0) {
-return -1;
+return -errno;
 }
 if (lchown(rpath(fs_ctx, path), credp-fc_uid, credp-fc_gid)  0) {
 /*
@@ -100,7 +100,7 @@ static int local_post_create_passthrough(FsContext *fs_ctx, 
const char *path,
  * using security model none. Ignore the error
  */
 if (fs_ctx-fs_sm != SM_NONE) {
-return -1;
+return -errno;
 }
 }
 return 0;
@@ -114,38 +114,40 @@ static ssize_t local_readlink(FsContext *fs_ctx, const 
char *path,
 int fd;
 fd = open(rpath(fs_ctx, path), O_RDONLY);
 if (fd == -1) {
-return -1;
+return -errno;
 }
 do {
 tsize = read(fd, (void *)buf, bufsz);
 } while (tsize == -1  errno == EINTR);
 close(fd);
-return tsize;
+return tsize = 0 ? tsize : -errno;
 } else if ((fs_ctx-fs_sm == SM_PASSTHROUGH) ||
(fs_ctx-fs_sm == SM_NONE)) {
 tsize = readlink(rpath(fs_ctx, path), buf, bufsz);
 }
-return tsize;
+return tsize = 0 ? tsize : -errno;
 }
 
 static int local_close(FsContext *ctx, int fd)
 {
-return close(fd);
+return close(fd) ? -errno : 0;
 }
 
 static int local_closedir(FsContext *ctx, DIR *dir)
 {
-return closedir(dir);
+return closedir(dir) ? -errno : 0;
 }
 
 static int local_open(FsContext *ctx, const char *path, int flags)
 {
-return open(rpath(ctx, path), flags);
+int ret = open(rpath(ctx, path), flags);
+return ret = 0 ? ret : -errno;
 }
 
-static DIR *local_opendir(FsContext *ctx, const char *path)
+static int 

Re: [Qemu-devel] Bug in virtio-9p when fstatting an fd referring to a file that no longer exists

2011-05-03 Thread Sassan Panahinejad
On 2 May 2011 16:47, Venkateswararao Jujjuri jv...@linux.vnet.ibm.comwrote:

  On 04/28/2011 09:51 AM, Sassan Panahinejad wrote:

 This thread seems relevant:
 http://www.mail-archive.com/linux-fsdevel@vger.kernel.org/msg09159.html
 Unless things have changed, it looks like the problem is in the client
 kernel (although note that there isn't support in qemu, even if the client
 did send an fid associated with an open file!).
 Any thoughts on a workaround for this?


 Hrm, I don't see any workaround for this. May be we should add TFSTAT for
 dotl? or add a flag to
 TSTAT?


It's definitely a tricky problem. I can't think of how to go about dealing
with it.
Probably worth looking into how nfs deals with it (and also looking into
what happens when communicating between two native plan9 systems). I'll
start reading.

Thanks
Sassan



 Copying the v9fs.

 Thanks,
 JV





 Thanks
 Sassan

 On 28 April 2011 17:13, Sassan Panahinejad sas...@sassan.me.uk wrote:

 It should be possible for guest applications to fstat a file for which
 they have a valid file descriptor, even if the file has been removed.
 Demonstrated by the code sample below (fstat reports no such file or
 directory).
 Strangely it seems that reading from a file in this state works fine (and
 when both are run, the server receives a different fid for each).
 On any other filesystem, the code runs correctly. On our 9p filesystem it
 fails.
 Many applications (including bash) depend on this working correctly.
 I will continue investigating, but any thoughts anyone has on the subject
 would be appreciated.


 Thanks
 Sassan


 #include stdio.h
 #include unistd.h
 #include fcntl.h
 #include sys/types.h
 #include sys/stat.h


 int main(void)
 {
 int ret;
 struct stat statbuf;
 int fd = open(test.txt, O_RDWR | O_CREAT, 0666);
 if (fd  0) {
 printf(open failed: %m\n);
 return 1;
 }
 ret = write(fd, test1\n, 6);
 if (ret  0) {
 printf(write1 failed: %m\n);
 return 1;
 }
 ret = unlink(test.txt);
 if (ret  0) {
 printf(unlink failed: %m\n);
 return 1;
 }
 ret = fstat(fd, statbuf);
 if (ret  0) {
 printf(fstat failed: %m\n);
 return 1;
 }
 return 0;
 }






Re: [Qemu-devel] [PATCH] Fix bug with virtio-9p rename

2011-04-28 Thread Sassan Panahinejad
Malahal Naineni's patch Stop renaming files with similar name! (posted
since this one) also fixes this bug.
I don't mind which one gets merged, as long as the bug gets fixed ;)

Sassan


On 27 April 2011 19:30, Sassan Panahinejad sas...@sassan.me.uk wrote:

 After renaming a file, any existing references to the file are updated.
 However, in addition to this, it would update any files whos names began
 with that of the file being moved.
 Therefore when renaming somefile.txt to somefile.txt-old, any references to
 somefile.txt-new became somefile.txt-old-new.
 This breaks debconf and probably many other applications.
 This patch fixes the problem. Now only files exactly matching, or files
 which are a subdirectory of a directory being moved are affected.

 Signed-off-by: Sassan Panahinejad sas...@sassan.me.uk
 ---
  hw/virtio-9p.c |9 -
  1 files changed, 8 insertions(+), 1 deletions(-)

 diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
 index 2530f6d..a2f096d 100644
 --- a/hw/virtio-9p.c
 +++ b/hw/virtio-9p.c
 @@ -2810,8 +2810,15 @@ static int v9fs_complete_rename(V9fsState *s,
 V9fsRenameState *vs)
 */
 continue;
 }
 +/*
 +* Fix the name if
 +* A: The file is the one we're moving
 +* Or B: The file is a subdirectory of one we're moving
 +*/
 if (!strncmp(vs-fidp-path.data, fidp-path.data,
 -strlen(vs-fidp-path.data))) {
 +strlen(vs-fidp-path.data)) 
 +(strlen(vs-fidp-path.data) ==
 strlen(fidp-path.data) ||
 +fidp-path.data[strlen(vs-fidp-path.data)] == '/'))
 {
 /* replace the name */
 v9fs_fix_path(fidp-path, vs-name,
   strlen(vs-fidp-path.data));
 --
 1.7.0.4




[Qemu-devel] [PATCH] Fix bug with virtio-9p xattr functions return values

2011-04-28 Thread Sassan Panahinejad
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 sas...@sassan.me.uk
---
 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;
-- 
1.7.0.4




[Qemu-devel] Bug in virtio-9p when fstatting an fd referring to a file that no longer exists

2011-04-28 Thread Sassan Panahinejad
It should be possible for guest applications to fstat a file for which they
have a valid file descriptor, even if the file has been removed.
Demonstrated by the code sample below (fstat reports no such file or
directory).
Strangely it seems that reading from a file in this state works fine (and
when both are run, the server receives a different fid for each).
On any other filesystem, the code runs correctly. On our 9p filesystem it
fails.
Many applications (including bash) depend on this working correctly.
I will continue investigating, but any thoughts anyone has on the subject
would be appreciated.


Thanks
Sassan


#include stdio.h
#include unistd.h
#include fcntl.h
#include sys/types.h
#include sys/stat.h


int main(void)
{
int ret;
struct stat statbuf;
int fd = open(test.txt, O_RDWR | O_CREAT, 0666);
if (fd  0) {
printf(open failed: %m\n);
return 1;
}
ret = write(fd, test1\n, 6);
if (ret  0) {
printf(write1 failed: %m\n);
return 1;
}
ret = unlink(test.txt);
if (ret  0) {
printf(unlink failed: %m\n);
return 1;
}
ret = fstat(fd, statbuf);
if (ret  0) {
printf(fstat failed: %m\n);
return 1;
}
return 0;
}


Re: [Qemu-devel] Bug in virtio-9p when fstatting an fd referring to a file that no longer exists

2011-04-28 Thread Sassan Panahinejad
This thread seems relevant:
http://www.mail-archive.com/linux-fsdevel@vger.kernel.org/msg09159.html
Unless things have changed, it looks like the problem is in the client
kernel (although note that there isn't support in qemu, even if the client
did send an fid associated with an open file!).
Any thoughts on a workaround for this?


Thanks
Sassan

On 28 April 2011 17:13, Sassan Panahinejad sas...@sassan.me.uk wrote:

 It should be possible for guest applications to fstat a file for which they
 have a valid file descriptor, even if the file has been removed.
 Demonstrated by the code sample below (fstat reports no such file or
 directory).
 Strangely it seems that reading from a file in this state works fine (and
 when both are run, the server receives a different fid for each).
 On any other filesystem, the code runs correctly. On our 9p filesystem it
 fails.
 Many applications (including bash) depend on this working correctly.
 I will continue investigating, but any thoughts anyone has on the subject
 would be appreciated.


 Thanks
 Sassan


 #include stdio.h
 #include unistd.h
 #include fcntl.h
 #include sys/types.h
 #include sys/stat.h


 int main(void)
 {
 int ret;
 struct stat statbuf;
 int fd = open(test.txt, O_RDWR | O_CREAT, 0666);
 if (fd  0) {
 printf(open failed: %m\n);
 return 1;
 }
 ret = write(fd, test1\n, 6);
 if (ret  0) {
 printf(write1 failed: %m\n);
 return 1;
 }
 ret = unlink(test.txt);
 if (ret  0) {
 printf(unlink failed: %m\n);
 return 1;
 }
 ret = fstat(fd, statbuf);
 if (ret  0) {
 printf(fstat failed: %m\n);
 return 1;
 }
 return 0;
 }



[Qemu-devel] [PATCH] Fix bug with virtio-9p fsync

2011-04-27 Thread Sassan Panahinejad
JV: I hope I have correctly understood your description of how lock/getlock 
should behave.

v9fs_fsync and possibly others break when asked to operate on a directory.
It does not check fid_type to see if it is operating on a directory and 
therefore accesses the wrong element of the fs union.
This error can result in guest applications failing (in my case it was dpkg).
This patch fixes the issue and implements correct behaviour for fsync, wstat, 
lock and getlock.

Signed-off-by: Sassan Panahinejad sas...@sassan.me.uk
---
 hw/virtio-9p.c |   36 
 1 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 7e29535..2530f6d 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -1875,7 +1875,13 @@ static void v9fs_fsync(V9fsState *s, V9fsPDU *pdu)
 v9fs_post_do_fsync(s, pdu, err);
 return;
 }
-err = v9fs_do_fsync(s, fidp-fs.fd, datasync);
+if (fidp-fid_type == P9_FID_FILE) {
+err = v9fs_do_fsync(s, fidp-fs.fd, datasync);
+} else if (fidp-fid_type == P9_FID_DIR) {
+err = v9fs_do_fsync(s, dirfd(fidp-fs.dir), datasync);
+} else {
+err = -EINVAL;
+}
 v9fs_post_do_fsync(s, pdu, err);
 }
 
@@ -2999,7 +3005,13 @@ static void v9fs_wstat(V9fsState *s, V9fsPDU *pdu)
 
 /* do we need to sync the file? */
 if (donttouch_stat(vs-v9stat)) {
-err = v9fs_do_fsync(s, vs-fidp-fs.fd, 0);
+if (vs-fidp-fid_type == P9_FID_FILE) {
+err = v9fs_do_fsync(s, vs-fidp-fs.fd, 0);
+} else if (vs-fidp-fid_type == P9_FID_DIR) {
+err = v9fs_do_fsync(s, dirfd(vs-fidp-fs.dir), 0);
+} else {
+err = -EINVAL;
+}
 v9fs_wstat_post_fsync(s, vs, err);
 return;
 }
@@ -3199,7 +3211,15 @@ static void v9fs_lock(V9fsState *s, V9fsPDU *pdu)
 goto out;
 }
 
-err = v9fs_do_fstat(s, vs-fidp-fs.fd, vs-stbuf);
+if (vs-fidp-fid_type == P9_FID_FILE) {
+err = v9fs_do_fstat(s, vs-fidp-fs.fd, vs-stbuf);
+} else if (vs-fidp-fid_type == P9_FID_DIR) {
+err = -EISDIR;
+goto out;
+} else {
+err = -EINVAL;
+goto out;
+}
 if (err  0) {
 err = -errno;
 goto out;
@@ -3237,7 +3257,15 @@ static void v9fs_getlock(V9fsState *s, V9fsPDU *pdu)
 goto out;
 }
 
-err = v9fs_do_fstat(s, vs-fidp-fs.fd, vs-stbuf);
+if (vs-fidp-fid_type == P9_FID_FILE) {
+err = v9fs_do_fstat(s, vs-fidp-fs.fd, vs-stbuf);
+} else if (vs-fidp-fid_type == P9_FID_DIR) {
+err = -EISDIR;
+goto out;
+} else {
+err = -EINVAL;
+goto out;
+}
 if (err  0) {
 err = -errno;
 goto out;
-- 
1.7.0.4




[Qemu-devel] [PATCH] Fix bug with virtio-9p rename

2011-04-27 Thread Sassan Panahinejad
After renaming a file, any existing references to the file are updated.
However, in addition to this, it would update any files whos names began with 
that of the file being moved.
Therefore when renaming somefile.txt to somefile.txt-old, any references to 
somefile.txt-new became somefile.txt-old-new.
This breaks debconf and probably many other applications.
This patch fixes the problem. Now only files exactly matching, or files which 
are a subdirectory of a directory being moved are affected.

Signed-off-by: Sassan Panahinejad sas...@sassan.me.uk
---
 hw/virtio-9p.c |9 -
 1 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 2530f6d..a2f096d 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -2810,8 +2810,15 @@ static int v9fs_complete_rename(V9fsState *s, 
V9fsRenameState *vs)
 */
 continue;
 }
+/*
+* Fix the name if
+* A: The file is the one we're moving
+* Or B: The file is a subdirectory of one we're moving
+*/
 if (!strncmp(vs-fidp-path.data, fidp-path.data,
-strlen(vs-fidp-path.data))) {
+strlen(vs-fidp-path.data)) 
+(strlen(vs-fidp-path.data) == strlen(fidp-path.data) ||
+fidp-path.data[strlen(vs-fidp-path.data)] == '/')) {
 /* replace the name */
 v9fs_fix_path(fidp-path, vs-name,
   strlen(vs-fidp-path.data));
-- 
1.7.0.4




[Qemu-devel] [PATCH] Fix bug with virtio-9p fsync

2011-04-26 Thread Sassan Panahinejad
v9fs_fsync and possibly others break when asked to operate on a directory.
It does not check fid_type to see if it is operating on a directory and 
therefore accesses the wrong element of the fs union.
This error can result in guest applications failing (in my case it was dpkg).
This patch fixes the issue, although there may be other, similar bugs in 
virtio-9p.

Signed-off-by: Sassan Panahinejad sas...@sassan.me.uk
---
 hw/virtio-9p.c |6 +-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 7e29535..cc4fdc8 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -1875,7 +1875,11 @@ static void v9fs_fsync(V9fsState *s, V9fsPDU *pdu)
 v9fs_post_do_fsync(s, pdu, err);
 return;
 }
-err = v9fs_do_fsync(s, fidp-fs.fd, datasync);
+if (fidp-fid_type == P9_FID_DIR) {
+err = v9fs_do_fsync(s, dirfd(fidp-fs.dir), datasync);
+} else {
+err = v9fs_do_fsync(s, fidp-fs.fd, datasync);
+}
 v9fs_post_do_fsync(s, pdu, err);
 }
 
-- 
1.7.0.4




Re: [Qemu-devel] [PATCH] Fix bug with virtio-9p fsync

2011-04-26 Thread Sassan Panahinejad
On 26 April 2011 13:58, Stefan Hajnoczi stefa...@gmail.com wrote:

 What about P9_FID_XATTR, seems like we have the same issue there too?

 wstat, lock, and getlock need closer auditing and perhaps fixing.

 Stefan


Sorry, forgot to hit reply-to-all.

Yes, it is probable that those functions will suffer from the same bug.
I will have to study XATTR and see how that will be affected. I don't know
whether it is possible for these functions to be called for XATTR, and if it
is then I do not know the proper way to handle it.
Perhaps we should have some function or macro to obtain the correct FD from
an fidp structure, which could be used for fsync, wstat, lock and getlock?

Sassan


[Qemu-devel] [PATCH] Fix bug with virtio-9p fsync

2011-04-26 Thread Sassan Panahinejad
v9fs_fsync and possibly others break when asked to operate on a directory.
It does not check fid_type to see if it is operating on a directory and 
therefore accesses the wrong element of the fs union.
This error can result in guest applications failing (in my case it was dpkg).
This patch fixes the issue, although there may be other, similar bugs in 
virtio-9p.

Signed-off-by: Sassan Panahinejad sas...@sassan.me.uk
---

Here I've implemented it as a function. If you'd prefer a macro or inline 
function then let me know.

Thanks
Sassan

 hw/virtio-9p.c |   43 +--
 1 files changed, 37 insertions(+), 6 deletions(-)

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 7e29535..26be0fc 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -1860,6 +1860,18 @@ static void v9fs_post_do_fsync(V9fsState *s, V9fsPDU 
*pdu, int err)
 complete_pdu(s, pdu, err);
 }
 
+static int v9fs_get_fd(V9fsFidState *fidp) 
+{
+switch (fidp-fid_type) {
+case P9_FID_FILE: 
+return fidp-fs.fd;
+case P9_FID_DIR: 
+return dirfd(fidp-fs.dir);
+default:
+return -1;
+}
+}
+
 static void v9fs_fsync(V9fsState *s, V9fsPDU *pdu)
 {
 int32_t fid;
@@ -1867,6 +1879,7 @@ static void v9fs_fsync(V9fsState *s, V9fsPDU *pdu)
 V9fsFidState *fidp;
 int datasync;
 int err;
+int fd;
 
 pdu_unmarshal(pdu, offset, dd, fid, datasync);
 fidp = lookup_fid(s, fid);
@@ -1875,7 +1888,11 @@ static void v9fs_fsync(V9fsState *s, V9fsPDU *pdu)
 v9fs_post_do_fsync(s, pdu, err);
 return;
 }
-err = v9fs_do_fsync(s, fidp-fs.fd, datasync);
+if ((fd = v9fs_get_fd(fidp)) = 0) {
+err = v9fs_do_fsync(s, fd, datasync);
+} else {
+   err = -EINVAL;
+}
 v9fs_post_do_fsync(s, pdu, err);
 }
 
@@ -2984,6 +3001,7 @@ static void v9fs_wstat(V9fsState *s, V9fsPDU *pdu)
 int32_t fid;
 V9fsWstatState *vs;
 int err = 0;
+int fd;
 
 vs = qemu_malloc(sizeof(*vs));
 vs-pdu = pdu;
@@ -2999,7 +3017,10 @@ static void v9fs_wstat(V9fsState *s, V9fsPDU *pdu)
 
 /* do we need to sync the file? */
 if (donttouch_stat(vs-v9stat)) {
-err = v9fs_do_fsync(s, vs-fidp-fs.fd, 0);
+if ((fd = v9fs_get_fd(vs-fidp)) = 0) {
+err = v9fs_do_fsync(s, fd, 0);
+} else
+err = -EINVAL;
 v9fs_wstat_post_fsync(s, vs, err);
 return;
 }
@@ -3176,6 +3197,7 @@ static void v9fs_lock(V9fsState *s, V9fsPDU *pdu)
 {
 int32_t fid, err = 0;
 V9fsLockState *vs;
+int fd;
 
 vs = qemu_mallocz(sizeof(*vs));
 vs-pdu = pdu;
@@ -3198,8 +3220,12 @@ static void v9fs_lock(V9fsState *s, V9fsPDU *pdu)
 err = -ENOENT;
 goto out;
 }
-
-err = v9fs_do_fstat(s, vs-fidp-fs.fd, vs-stbuf);
+if ((fd = v9fs_get_fd(vs-fidp)) = 0) {
+err = v9fs_do_fstat(s, fd, vs-stbuf);
+} else {
+err = -EINVAL;
+goto out;
+}
 if (err  0) {
 err = -errno;
 goto out;
@@ -3221,6 +3247,7 @@ static void v9fs_getlock(V9fsState *s, V9fsPDU *pdu)
 {
 int32_t fid, err = 0;
 V9fsGetlockState *vs;
+int fd;
 
 vs = qemu_mallocz(sizeof(*vs));
 vs-pdu = pdu;
@@ -3236,8 +3263,12 @@ static void v9fs_getlock(V9fsState *s, V9fsPDU *pdu)
 err = -ENOENT;
 goto out;
 }
-
-err = v9fs_do_fstat(s, vs-fidp-fs.fd, vs-stbuf);
+if ((fd = v9fs_get_fd(vs-fidp)) = 0) {
+err = v9fs_do_fstat(s, fd, vs-stbuf);
+} else {
+err = -EINVAL;
+goto out;
+}
 if (err  0) {
 err = -errno;
 goto out;
-- 
1.7.0.4




[Qemu-devel] [PATCH] Fix bug with virtio-9p fsync

2011-04-25 Thread Sassan Panahinejad
v9fs_fsync and possibly others break when asked to operate on a directory.
It does not check fid_type to see if it is operating on a directory and 
therefore accesses the wrong element of the fs union.
This error can result in guest applications failing (in my case it was dpkg).
This patch fixes the issue, although there may be other, similar bugs in 
virtio-9p.
---
 hw/virtio-9p.c |5 -
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 7e29535..09fb5da 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -1875,7 +1875,10 @@ static void v9fs_fsync(V9fsState *s, V9fsPDU *pdu)
 v9fs_post_do_fsync(s, pdu, err);
 return;
 }
-err = v9fs_do_fsync(s, fidp-fs.fd, datasync);
+if (fidp-fid_type == P9_FID_DIR)
+err = v9fs_do_fsync(s, dirfd(fidp-fs.dir), datasync);
+else
+err = v9fs_do_fsync(s, fidp-fs.fd, datasync);
 v9fs_post_do_fsync(s, pdu, err);
 }
 
-- 
1.7.0.4