From 62a0ac8f221a0d82ae198c3b12ebbfd3eb39566c Mon Sep 17 00:00:00 2001 From: "Ricardo M. Correia" Date: Wed, 10 Mar 2010 09:53:53 -0800 Subject: [PATCH] Fix some incorrect error handling. In vn_open(), if fstat64() returned an error, the real errno was being obscured by calling close(). Add error handling for both pwrite64() calls in vn_rdwr(). --- .topdeps | 1 + .topmsg | 12 ++++++++++++ lib/libzpool/kernel.c | 26 +++++++++++++++++--------- 3 files changed, 30 insertions(+), 9 deletions(-) create mode 100644 .topdeps create mode 100644 .topmsg diff --git a/.topdeps b/.topdeps new file mode 100644 index 0000000000..1f7391f92b --- /dev/null +++ b/.topdeps @@ -0,0 +1 @@ +master diff --git a/.topmsg b/.topmsg new file mode 100644 index 0000000000..8a0394a0c7 --- /dev/null +++ b/.topmsg @@ -0,0 +1,12 @@ +From: Ricardo M. Correia +Subject: [PATCH] fix error handling + +Fix some incorrect error handling. + +1) In vn_open(), if fstat64() returned an error, the real errno +was being obscured by calling close(). + +2) Add error handling for both pwrite64() calls in vn_rdwr(). + +Signed-off-by: Ricardo M. Correia +Signed-off-by: Brian Behlendorf diff --git a/lib/libzpool/kernel.c b/lib/libzpool/kernel.c index 89108fe5b2..af4329a4dc 100644 --- a/lib/libzpool/kernel.c +++ b/lib/libzpool/kernel.c @@ -325,6 +325,7 @@ vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3) int old_umask; char realpath[MAXPATHLEN]; struct stat64 st; + int err; /* * If we're accessing a real disk from userland, we need to use @@ -373,8 +374,9 @@ vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3) return (errno); if (fstat64(fd, &st) == -1) { + err = errno; close(fd); - return (errno); + return (err); } (void) fcntl(fd, F_SETFD, FD_CLOEXEC); @@ -412,26 +414,32 @@ int vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset, int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp) { - ssize_t iolen, split; + ssize_t rc, done = 0, split; if (uio == UIO_READ) { - iolen = pread64(vp->v_fd, addr, len, offset); + rc = pread64(vp->v_fd, addr, len, offset); } else { /* * To simulate partial disk writes, we split writes into two * system calls so that the process can be killed in between. */ split = (len > 0 ? rand() % len : 0); - iolen = pwrite64(vp->v_fd, addr, split, offset); - iolen += pwrite64(vp->v_fd, (char *)addr + split, - len - split, offset + split); + rc = pwrite64(vp->v_fd, addr, split, offset); + if (rc != -1) { + done = rc; + rc = pwrite64(vp->v_fd, (char *)addr + split, + len - split, offset + split); + } } - if (iolen == -1) + if (rc == -1) return (errno); + + done += rc; + if (residp) - *residp = len - iolen; - else if (iolen != len) + *residp = len - done; + else if (done != len) return (EIO); return (0); }