From: Ricardo M. Correia Date: Thu, 26 Aug 2010 17:21:44 +0000 (-0700) Subject: Fix vn_open/vn_rdwr error handling X-Git-Tag: zfs-0.5.1~63 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4d58b69de8a6e2dc77b73e113d2c7847d389f456;p=zfs Fix vn_open/vn_rdwr 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 ef264061f..adbe6ba08 100644 --- a/lib/libzpool/kernel.c +++ b/lib/libzpool/kernel.c @@ -328,6 +328,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 @@ -376,8 +377,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); @@ -415,26 +417,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); }