Add another argument to fp_read() to tell the kernel to read the entire
authorMatthew Dillon <dillon@dragonflybsd.org>
Wed, 6 Jul 2005 05:59:43 +0000 (05:59 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Wed, 6 Jul 2005 05:59:43 +0000 (05:59 +0000)
requested size, looping if necessary.

sys/kern/kern_checkpoint.c
sys/kern/kern_firmware.c
sys/kern/kern_fp.c
sys/sys/file.h

index ba18a1d..eee999f 100644 (file)
@@ -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 <sys/types.h>
@@ -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) {
index c760fd9..856c1f7 100644 (file)
@@ -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 <sys/param.h>
@@ -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;
        }
index 8eda3c7..d363983 100644 (file)
@@ -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);
 }
 
index 71086c5..53dbbe4 100644 (file)
@@ -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);