summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRicardo M. Correia <[email protected]>2010-08-26 10:21:44 -0700
committerBrian Behlendorf <[email protected]>2010-08-31 08:38:45 -0700
commit4d58b69de8a6e2dc77b73e113d2c7847d389f456 (patch)
treee3473ee2961614fe57e32c86ca0cb05c4fad537c
parent235db0aceaa01638d3cd7d041ac968c3faa3a691 (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]>
-rw-r--r--lib/libzpool/kernel.c26
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);
}