diff options
author | Ricardo M. Correia <[email protected]> | 2010-08-26 10:21:44 -0700 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2010-08-31 08:38:45 -0700 |
commit | 4d58b69de8a6e2dc77b73e113d2c7847d389f456 (patch) | |
tree | e3473ee2961614fe57e32c86ca0cb05c4fad537c /lib/libzpool/kernel.c | |
parent | 235db0aceaa01638d3cd7d041ac968c3faa3a691 (diff) |
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 <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Diffstat (limited to 'lib/libzpool/kernel.c')
-rw-r--r-- | lib/libzpool/kernel.c | 26 |
1 files changed, 17 insertions, 9 deletions
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); } |