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 <Ricardo.M.Correia@Sun.COM>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
This commit is contained in:
Ricardo M. Correia 2010-08-26 10:21:44 -07:00 committed by Brian Behlendorf
parent 235db0acea
commit 4d58b69de8

View File

@ -328,6 +328,7 @@ vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
int old_umask; int old_umask;
char realpath[MAXPATHLEN]; char realpath[MAXPATHLEN];
struct stat64 st; struct stat64 st;
int err;
/* /*
* If we're accessing a real disk from userland, we need to use * 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); return (errno);
if (fstat64(fd, &st) == -1) { if (fstat64(fd, &st) == -1) {
err = errno;
close(fd); close(fd);
return (errno); return (err);
} }
(void) fcntl(fd, F_SETFD, FD_CLOEXEC); (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, 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) 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) { if (uio == UIO_READ) {
iolen = pread64(vp->v_fd, addr, len, offset); rc = pread64(vp->v_fd, addr, len, offset);
} else { } else {
/* /*
* To simulate partial disk writes, we split writes into two * To simulate partial disk writes, we split writes into two
* system calls so that the process can be killed in between. * system calls so that the process can be killed in between.
*/ */
split = (len > 0 ? rand() % len : 0); split = (len > 0 ? rand() % len : 0);
iolen = pwrite64(vp->v_fd, addr, split, offset); rc = pwrite64(vp->v_fd, addr, split, offset);
iolen += pwrite64(vp->v_fd, (char *)addr + split, if (rc != -1) {
len - split, offset + split); done = rc;
rc = pwrite64(vp->v_fd, (char *)addr + split,
len - split, offset + split);
}
} }
if (iolen == -1) if (rc == -1)
return (errno); return (errno);
done += rc;
if (residp) if (residp)
*residp = len - iolen; *residp = len - done;
else if (iolen != len) else if (done != len)
return (EIO); return (EIO);
return (0); return (0);
} }