From: Matthew Dillon Date: Wed, 6 Jul 2005 05:59:43 +0000 (+0000) Subject: Add another argument to fp_read() to tell the kernel to read the entire X-Git-Tag: v2.0.1~6690 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/ba9c8ec16f062c93a3a11e59bf06c94c8fd68c09 Add another argument to fp_read() to tell the kernel to read the entire requested size, looping if necessary. --- diff --git a/sys/kern/kern_checkpoint.c b/sys/kern/kern_checkpoint.c index ba18a1de10..eee999fc40 100644 --- a/sys/kern/kern_checkpoint.c +++ b/sys/kern/kern_checkpoint.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/kern/kern_checkpoint.c,v 1.3 2005/06/22 01:33:21 dillon Exp $ + * $DragonFly: src/sys/kern/kern_checkpoint.c,v 1.4 2005/07/06 05:59:39 dillon Exp $ */ #include @@ -99,7 +99,7 @@ read_check(struct file *fp, void *buf, size_t nbyte) int error; PRINTF(("reading %d bytes\n", nbyte)); - error = fp_read(fp, buf, nbyte, &nread); + error = fp_read(fp, buf, nbyte, &nread, 1); if (error) { PRINTF(("read failed - %d", error)); } else if (nread != nbyte) { diff --git a/sys/kern/kern_firmware.c b/sys/kern/kern_firmware.c index c760fd90d6..856c1f7211 100644 --- a/sys/kern/kern_firmware.c +++ b/sys/kern/kern_firmware.c @@ -30,7 +30,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/kern/kern_firmware.c,v 1.2 2005/03/24 17:24:04 joerg Exp $ + * $DragonFly: src/sys/kern/kern_firmware.c,v 1.3 2005/07/06 05:59:39 dillon Exp $ */ #include @@ -177,8 +177,8 @@ firmware_image_load_file(const char *image_name) if (img == NULL) goto fail_stat; - if ((error = fp_read(fp, img->fw_image, img->fw_imglen, &nread)) != 0 || - nread != img->fw_imglen) { + error = fp_read(fp, img->fw_image, img->fw_imglen, &nread, 1); + if (error != 0 || nread != img->fw_imglen) { printf("firmware image could not be read: %d\n", error); goto fail_read; } diff --git a/sys/kern/kern_fp.c b/sys/kern/kern_fp.c index 8eda3c748b..d363983d25 100644 --- a/sys/kern/kern_fp.c +++ b/sys/kern/kern_fp.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/kern/kern_fp.c,v 1.9 2004/11/12 00:09:23 dillon Exp $ + * $DragonFly: src/sys/kern/kern_fp.c,v 1.10 2005/07/06 05:59:39 dillon Exp $ */ /* @@ -264,12 +264,12 @@ fp_pread(file_t fp, void *buf, size_t nbytes, off_t offset, ssize_t *res) } int -fp_read(file_t fp, void *buf, size_t nbytes, ssize_t *res) +fp_read(file_t fp, void *buf, size_t nbytes, ssize_t *res, int all) { struct uio auio; struct iovec aiov; - size_t count; int error; + int lastresid; if (res) *res = 0; @@ -289,18 +289,37 @@ fp_read(file_t fp, void *buf, size_t nbytes, ssize_t *res) auio.uio_segflg = UIO_SYSSPACE; auio.uio_td = curthread; - count = nbytes; - error = fo_read(fp, &auio, fp->f_cred, 0, auio.uio_td); + /* + * If all is false call fo_read() once. + * If all is true we attempt to read the entire request. We have to + * break out of the loop if an unrecoverable error or EOF occurs. + */ + do { + lastresid = auio.uio_resid; + error = fo_read(fp, &auio, fp->f_cred, 0, auio.uio_td); + } while (all && auio.uio_resid && + ((error == 0 && auio.uio_resid != lastresid) || + error == ERESTART || error == EINTR)); + if (all && error == 0 && auio.uio_resid) + error = ESPIPE; + + /* + * If an error occured but some data was read, silently forget the + * error. However, if this is a non-blocking descriptor and 'all' + * was specified, return an error even if some data was read (this + * is considered a bug in the caller for using an illegal combination + * of 'all' and a non-blocking descriptor). + */ if (error) { - if (auio.uio_resid != nbytes && (error == ERESTART || error == EINTR || - error == EWOULDBLOCK) - ) { - error = 0; + if (auio.uio_resid != nbytes) { + if (error == ERESTART || error == EINTR) + error = 0; + if (error == EWOULDBLOCK && all == 0) + error = 0; } } - count -= auio.uio_resid; if (res) - *res = count; + *res = nbytes - auio.uio_resid; return(error); } diff --git a/sys/sys/file.h b/sys/sys/file.h index 71086c56c0..53dbbe43ce 100644 --- a/sys/sys/file.h +++ b/sys/sys/file.h @@ -32,7 +32,7 @@ * * @(#)file.h 8.3 (Berkeley) 1/9/95 * $FreeBSD: src/sys/sys/file.h,v 1.22.2.7 2002/11/21 23:39:24 sam Exp $ - * $DragonFly: src/sys/sys/file.h,v 1.12 2004/11/12 00:09:27 dillon Exp $ + * $DragonFly: src/sys/sys/file.h,v 1.13 2005/07/06 05:59:43 dillon Exp $ */ #ifndef _SYS_FILE_H_ @@ -128,7 +128,7 @@ extern int fp_open(const char *path, int flags, int mode, struct file **fpp); extern int fp_vpopen(struct vnode *vp, int flags, struct file **fpp); extern int fp_pread(struct file *fp, void *buf, size_t nbytes, off_t offset, ssize_t *res); extern int fp_pwrite(struct file *fp, void *buf, size_t nbytes, off_t offset, ssize_t *res); -extern int fp_read(struct file *fp, void *buf, size_t nbytes, ssize_t *res); +extern int fp_read(struct file *fp, void *buf, size_t nbytes, ssize_t *res, int all); extern int fp_write(struct file *fp, void *buf, size_t nbytes, ssize_t *res); extern int fp_stat(struct file *fp, struct stat *ub); extern int fp_mmap(void *addr, size_t size, int prot, int flags, struct file *fp, off_t pos, void **resp);