X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/6fd40ceab2e46e46437f21b3d54c0acc3d4bcc31..b32450f463002a07ee0e7581a231c6916a24a5d7:/usr/src/sys/kern/sys_generic.c diff --git a/usr/src/sys/kern/sys_generic.c b/usr/src/sys/kern/sys_generic.c index 1f99bcca32..987754cdd0 100644 --- a/usr/src/sys/kern/sys_generic.c +++ b/usr/src/sys/kern/sys_generic.c @@ -1,4 +1,4 @@ -/* sys_generic.c 5.7 82/08/11 */ +/* sys_generic.c 5.18 82/10/17 */ #include "../h/param.h" #include "../h/systm.h" @@ -9,12 +9,9 @@ #include "../h/inode.h" #include "../h/buf.h" #include "../h/proc.h" -#include "../h/inline.h" #include "../h/conf.h" #include "../h/socket.h" #include "../h/socketvar.h" -#include "../h/cmap.h" -#include "../h/vlimit.h" #include "../h/fs.h" #ifdef MUSH #include "../h/quota.h" @@ -30,44 +27,43 @@ */ read() { - register struct file *fp; - register struct inode *ip; register struct a { int fdes; char *cbuf; unsigned count; - } *uap; + } *uap = (struct a *)u.u_ap; + struct uio auio; + struct iovec aiov; - uap = (struct a *)u.u_ap; - if ((int)uap->count < 0) { + aiov.iov_base = (caddr_t)uap->cbuf; + aiov.iov_len = uap->count; + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + rwuio(&auio, UIO_READ); +} + +readv() +{ + register struct a { + int fdes; + struct iovec *iovp; + int iovcnt; + } *uap = (struct a *)u.u_ap; + struct uio auio; + struct iovec aiov[16]; /* XXX */ + + if (uap->iovcnt <= 0 || uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) { u.u_error = EINVAL; return; } - GETF(fp, uap->fdes); - if ((fp->f_flag&FREAD) == 0) { - u.u_error = EBADF; + auio.uio_iov = aiov; + auio.uio_iovcnt = uap->iovcnt; + if (copyin((caddr_t)uap->iovp, (caddr_t)aiov, + (unsigned)(uap->iovcnt * sizeof (struct iovec)))) { + u.u_error = EFAULT; return; } - u.u_base = (caddr_t)uap->cbuf; - u.u_count = uap->count; - u.u_segflg = 0; - if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { - if (u.u_count == uap->count) - u.u_eosys = RESTARTSYS; - } else if (fp->f_type == DTYPE_SOCKET) - u.u_error = soreceive(fp->f_socket, (struct sockaddr *)0); - else { - ip = fp->f_inode; - u.u_offset = fp->f_offset; - if ((ip->i_mode&IFMT) == IFREG) { - ilock(ip); - readi(ip); - iunlock(ip); - } else - readi(ip); - fp->f_offset += uap->count - u.u_count; - } - u.u_r.r_val1 = uap->count - u.u_count; + rwuio(&auio, UIO_READ); } /* @@ -75,56 +71,379 @@ read() */ write() { - register struct file *fp; - register struct inode *ip; register struct a { int fdes; char *cbuf; - unsigned count; - } *uap; + int count; + } *uap = (struct a *)u.u_ap; + struct uio auio; + struct iovec aiov; - uap = (struct a *)u.u_ap; - if ((int)uap->count < 0) { + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + aiov.iov_base = uap->cbuf; + aiov.iov_len = uap->count; + rwuio(&auio, UIO_WRITE); +} + +writev() +{ + register struct a { + int fdes; + struct iovec *iovp; + int iovcnt; + } *uap = (struct a *)u.u_ap; + struct uio auio; + struct iovec aiov[16]; /* XXX */ + + if (uap->iovcnt <= 0 || uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) { u.u_error = EINVAL; return; } - GETF(fp, uap->fdes); - if ((fp->f_flag&FWRITE) == 0) { + auio.uio_iov = aiov; + auio.uio_iovcnt = uap->iovcnt; + if (copyin((caddr_t)uap->iovp, (caddr_t)aiov, + (unsigned)(uap->iovcnt * sizeof (struct iovec)))) { + u.u_error = EFAULT; + return; + } + rwuio(&auio, UIO_WRITE); +} + +rwuio(uio, rw) + register struct uio *uio; + enum uio_rw rw; +{ + struct a { + int fdes; + }; + register struct file *fp; + register struct iovec *iov; + register struct inode *ip; + int i, count; + + GETF(fp, ((struct a *)u.u_ap)->fdes); + if ((fp->f_flag&(rw==UIO_READ ? FREAD : FWRITE)) == 0) { u.u_error = EBADF; return; } - u.u_base = (caddr_t)uap->cbuf; - u.u_count = uap->count; - u.u_segflg = 0; - if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { - if (u.u_count == uap->count) + uio->uio_resid = 0; + uio->uio_segflg = 0; + iov = uio->uio_iov; + for (i = 0; i < uio->uio_iovcnt; i++) { + if (iov->iov_len < 0) { + u.u_error = EINVAL; + return; + } + uio->uio_resid += iov->iov_len; + if (uio->uio_resid < 0) { + u.u_error = EINVAL; + return; + } + } + count = uio->uio_resid; + if ((u.u_procp->p_flag&SNUSIG) && setjmp(&u.u_qsave)) { + if (uio->uio_resid == count) u.u_eosys = RESTARTSYS; - } else if (fp->f_type == DTYPE_SOCKET) - u.u_error = sosend(fp->f_socket, (struct sockaddr *)0); - else { + } else if (fp->f_type == DTYPE_SOCKET) { + int sosend(), soreceive(); + u.u_error = + (*(rw==UIO_READ?soreceive:sosend)) + (fp->f_socket, (struct sockaddr *)0, uio, 0); + } else { ip = fp->f_inode; - if (fp->f_flag&FAPPEND) - fp->f_offset = ip->i_size; - u.u_offset = fp->f_offset; + uio->uio_offset = fp->f_offset; if ((ip->i_mode&IFMT) == IFREG) { - ilock(ip); - writei(ip); - iunlock(ip); + ILOCK(ip); + u.u_error = rwip(ip, uio, rw); + IUNLOCK(ip); } else - writei(ip); - fp->f_offset += uap->count - u.u_count; + u.u_error = rwip(ip, uio, rw); + fp->f_offset += count - uio->uio_resid; } - u.u_r.r_val1 = uap->count - u.u_count; + u.u_r.r_val1 = count - uio->uio_resid; } -readv() +rdwri(rw, ip, base, len, offset, segflg, aresid) + struct inode *ip; + caddr_t base; + int len, offset, segflg; + int *aresid; + enum uio_rw rw; { + struct uio auio; + struct iovec aiov; + int error; + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + aiov.iov_base = base; + aiov.iov_len = len; + auio.uio_resid = len; + auio.uio_offset = offset; + auio.uio_segflg = segflg; + error = rwip(ip, &auio, rw); + if (aresid) + *aresid = auio.uio_resid; + else + if (auio.uio_resid) + error = EIO; + return (error); } -writev() +rwip(ip, uio, rw) + register struct inode *ip; + register struct uio *uio; + enum uio_rw rw; +{ + dev_t dev = (dev_t)ip->i_rdev; + struct buf *bp; + struct fs *fs; + daddr_t lbn, bn; + register int on, type; + register unsigned n; + int size; + long bsize; + extern int mem_no; + int error = 0; + + if (rw != UIO_READ && rw != UIO_WRITE) + panic("rwip"); + if (uio->uio_offset < 0 && + ((ip->i_mode&IFMT) != IFCHR || mem_no != major(dev))) + return (EINVAL); if (rw == UIO_READ) + ip->i_flag |= IACC; + type = ip->i_mode&IFMT; + if (type == IFCHR) { +#ifdef QUOTA + register c = uio->uio_resid; +#endif + if (rw == UIO_READ) + u.u_error = (*cdevsw[major(dev)].d_read)(dev, uio); + else { + ip->i_flag |= IUPD|ICHG; + u.u_error = (*cdevsw[major(dev)].d_write)(dev, uio); + } + CHARGE(sc_tio * (c - uio->uio_resid)); + return (u.u_error); + } + if (rw == UIO_WRITE && type == IFREG && + uio->uio_offset + uio->uio_resid > + u.u_rlimit[RLIMIT_FSIZE].rlim_cur) { + psignal(u.u_procp, SIGXFSZ); + return (EMFILE); + } + if (type != IFBLK) { + dev = ip->i_dev; + fs = ip->i_fs; + bsize = fs->fs_bsize; + } else + bsize = BLKDEV_IOSIZE; + do { + lbn = uio->uio_offset / bsize; + on = uio->uio_offset % bsize; + n = MIN((unsigned)(bsize - on), uio->uio_resid); + if (type != IFBLK) { + if (rw == UIO_READ) { + int diff = ip->i_size - uio->uio_offset; + if (diff <= 0) + return (0); + if (diff < n) + n = diff; + } + bn = fsbtodb(fs, + bmap(ip, lbn, rw == UIO_WRITE ? B_WRITE: B_READ, (int)(on+n))); + if (u.u_error || rw == UIO_WRITE && (long)bn<0) + return (u.u_error); + if (rw == UIO_WRITE && uio->uio_offset + n > ip->i_size && + (type == IFDIR || type == IFREG || type == IFLNK)) + ip->i_size = uio->uio_offset + n; + size = blksize(fs, ip, lbn); + } else { + bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE); + rablock = bn + (BLKDEV_IOSIZE/DEV_BSIZE); + rasize = size = bsize; + } + if (rw == UIO_READ) { + if ((long)bn<0) { + bp = geteblk(size); + clrbuf(bp); + } else if (ip->i_lastr + 1 == lbn) + bp = breada(dev, bn, size, rablock, rasize); + else + bp = bread(dev, bn, size); + ip->i_lastr = lbn; + } else { + int i, count; + extern struct cmap *mfind(); + + count = howmany(size, DEV_BSIZE); + for (i = 0; i < count; i += CLSIZE) + if (mfind(dev, bn + i)) + munhash(dev, bn + i); + if (n == bsize) + bp = getblk(dev, bn, size); + else + bp = bread(dev, bn, size); + } + n = MIN(n, size - bp->b_resid); + if (bp->b_flags & B_ERROR) { + error = EIO; + brelse(bp); + goto bad; + } + u.u_error = + uiomove(bp->b_un.b_addr+on, n, rw, uio); + if (rw == UIO_READ) { + if (n + on == bsize || uio->uio_offset == ip->i_size) + bp->b_flags |= B_AGE; + brelse(bp); + } else { + if ((ip->i_mode&IFMT) == IFDIR) + bwrite(bp); + else if (n + on == bsize) { + bp->b_flags |= B_AGE; + bawrite(bp); + } else + bdwrite(bp); + ip->i_flag |= IUPD|ICHG; + if (u.u_ruid != 0) + ip->i_mode &= ~(ISUID|ISGID); + } + } while (u.u_error == 0 && uio->uio_resid > 0 && n != 0); +bad: + return (error); +} + +uiomove(cp, n, rw, uio) + register caddr_t cp; + register int n; + enum uio_rw rw; + register struct uio *uio; +{ + register struct iovec *iov; + int error; + u_int cnt; + + while (n > 0 && uio->uio_resid) { + iov = uio->uio_iov; + cnt = iov->iov_len; + if (cnt == 0) { + uio->uio_iov++; + uio->uio_iovcnt--; + continue; + } + if (cnt > n) + cnt = n; + switch (uio->uio_segflg) { + + case 0: + case 2: + if (rw == UIO_READ) + error = copyout(cp, iov->iov_base, cnt); + else + error = copyin(iov->iov_base, cp, cnt); + if (error) + return (error); + break; + + case 1: + if (rw == UIO_READ) + bcopy((caddr_t)cp, iov->iov_base, cnt); + else + bcopy(iov->iov_base, (caddr_t)cp, cnt); + break; + } + iov->iov_base += cnt; + iov->iov_len -= cnt; + uio->uio_resid -= cnt; + uio->uio_offset += cnt; + cp += cnt; + n -= cnt; + } + return (error); +} + +/* + * Give next character to user as result of read. + */ +ureadc(c, uio) + register int c; + register struct uio *uio; { + register struct iovec *iov; + +again: + if (uio->uio_iovcnt == 0) + panic("ureadc"); + iov = uio->uio_iov; + if (iov->iov_len <= 0 || uio->uio_resid <= 0) { + uio->uio_iovcnt--; + uio->uio_iov++; + goto again; + } + switch (uio->uio_segflg) { + + case 0: + if (subyte(iov->iov_base, c) < 0) + return (EFAULT); + break; + + case 1: + *iov->iov_base = c; + break; + case 2: + if (suibyte(iov->iov_base, c) < 0) + return (EFAULT); + break; + } + iov->iov_base++; + iov->iov_len--; + uio->uio_resid--; + uio->uio_offset++; + return (0); +} + +/* + * Get next character written in by user from uio. + */ +uwritec(uio) + struct uio *uio; +{ + register struct iovec *iov; + register int c; + +again: + if (uio->uio_iovcnt <= 0 || uio->uio_resid <= 0) + panic("uwritec"); + iov = uio->uio_iov; + if (iov->iov_len == 0) { + uio->uio_iovcnt--; + uio->uio_iov++; + goto again; + } + switch (uio->uio_segflg) { + + case 0: + c = fubyte(iov->iov_base); + break; + + case 1: + c = *iov->iov_base & 0377; + break; + + case 2: + c = fuibyte(iov->iov_base); + break; + } + if (c < 0) + return (-1); + iov->iov_base++; + iov->iov_len--; + uio->uio_resid--; + uio->uio_offset++; + return (c & 0377); } /* @@ -140,7 +459,8 @@ ioctl() int cmd; caddr_t cmarg; } *uap; - register int com, size; + register int com; + register u_int size; char data[IOCPARM_MASK+1]; uap = (struct a *)u.u_ap; @@ -178,7 +498,6 @@ ioctl() * Interpret high order word to find * amount of data to be copied to/from the * user's address space. - * (this'll have to change if we have in+out ioctls) */ size = (com &~ (IOC_INOUT|IOC_VOID)) >> 16; if (size > sizeof (data)) { @@ -186,7 +505,7 @@ ioctl() return; } if (com&IOC_IN && size) { - if (copyin(uap->cmarg, (caddr_t)data, size)) { + if (copyin(uap->cmarg, (caddr_t)data, (u_int)size)) { u.u_error = EFAULT; return; } @@ -200,7 +519,7 @@ ioctl() bzero((caddr_t)data, size); if (fp->f_type == DTYPE_SOCKET) - soioctl(fp->f_socket, com, data); + u.u_error = soioctl(fp->f_socket, com, data); else { register struct inode *ip = fp->f_inode; int fmt = ip->i_mode & IFMT; @@ -217,11 +536,11 @@ ioctl() } dev = ip->i_rdev; u.u_r.r_val1 = 0; - if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { + if ((u.u_procp->p_flag&SNUSIG) && setjmp(&u.u_qsave)) { u.u_eosys = RESTARTSYS; return; } - (*cdevsw[major(dev)].d_ioctl)(dev, com, data, 0); + u.u_error = (*cdevsw[major(dev)].d_ioctl)(dev, com, data, 0); } returndata: @@ -229,8 +548,8 @@ returndata: * Copy any data to user, size was * already set and checked above. */ - if (u.u_error == 0 && com&IOC_OUT) - if (size && copyout(data, uap->cmarg, size)) + if (u.u_error == 0 && (com&IOC_OUT)) + if (size && copyout(data, uap->cmarg, (u_int)size)) u.u_error = EFAULT; } @@ -248,350 +567,15 @@ nullioctl(tp, cmd, data, flags) #ifdef lint tp = tp; data = data; flags = flags; #endif - return (cmd); + return (-1); } -/* - * Read the file corresponding to - * the inode pointed at by the argument. - * The actual read arguments are found - * in the variables: - * u_base core address for destination - * u_offset byte offset in file - * u_count number of bytes to read - * u_segflg read to kernel/user/user I - */ -readi(ip) - register struct inode *ip; +ostty() { - struct buf *bp; - struct fs *fs; - dev_t dev; - daddr_t lbn, bn; - off_t diff; - register int on, type; - register unsigned n; - int size; - long bsize; - extern int mem_no; - if (u.u_count == 0) - return; - dev = (dev_t)ip->i_rdev; - if (u.u_offset < 0 && ((ip->i_mode&IFMT) != IFCHR || - mem_no != major(dev))) { - u.u_error = EINVAL; - return; - } - ip->i_flag |= IACC; - type = ip->i_mode&IFMT; - if (type == IFCHR) { - register c = u.u_count; - (*cdevsw[major(dev)].d_read)(dev); - CHARGE(sc_tio * (c - u.u_count)); - return; - } - if (type != IFBLK) { - dev = ip->i_dev; - fs = ip->i_fs; - bsize = fs->fs_bsize; - } else - bsize = BLKDEV_IOSIZE; - do { - lbn = u.u_offset / bsize; - on = u.u_offset % bsize; - n = MIN((unsigned)(bsize - on), u.u_count); - if (type != IFBLK) { - diff = ip->i_size - u.u_offset; - if (diff <= 0) - return; - if (diff < n) - n = diff; - bn = fsbtodb(fs, bmap(ip, lbn, B_READ)); - if (u.u_error) - return; - size = blksize(fs, ip, lbn); - } else { - size = bsize; - bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE); - rablock = bn + (BLKDEV_IOSIZE/DEV_BSIZE); - rasize = bsize; - } - if ((long)bn<0) { - bp = geteblk(size); - clrbuf(bp); - } else if (ip->i_lastr + 1 == lbn) - bp = breada(dev, bn, size, rablock, rasize); - else - bp = bread(dev, bn, size); - ip->i_lastr = lbn; - n = MIN(n, size - bp->b_resid); - if (n != 0) { - if (u.u_segflg != 1) { - if (copyout(bp->b_un.b_addr+on, u.u_base, n)) { - u.u_error = EFAULT; - goto bad; - } - } else - bcopy(bp->b_un.b_addr + on, u.u_base, n); - u.u_base += n; - u.u_offset += n; - u.u_count -= n; -bad: - ; - } - if (n + on == bsize || u.u_offset == ip->i_size) - bp->b_flags |= B_AGE; - brelse(bp); - } while (u.u_error == 0 && u.u_count != 0 && n != 0); } -/* - * Write the file corresponding to - * the inode pointed at by the argument. - * The actual write arguments are found - * in the variables: - * u_base core address for source - * u_offset byte offset in file - * u_count number of bytes to write - * u_segflg write to kernel/user/user I - */ -writei(ip) - register struct inode *ip; +ogtty() { - struct buf *bp; - register struct fs *fs; - dev_t dev; - daddr_t lbn, bn; - register int on, type; - register unsigned n; - long bsize; - int size, i, count; - extern int mem_no; - dev = (dev_t)ip->i_rdev; - if (u.u_offset < 0 && ((ip->i_mode&IFMT) != IFCHR || - mem_no != major(dev)) ) { - u.u_error = EINVAL; - return; - } - type = ip->i_mode & IFMT; - if (type == IFCHR) { - ip->i_flag |= IUPD|ICHG; - CHARGE(sc_tio * u.u_count); - (*cdevsw[major(dev)].d_write)(dev); - return; - } - if (u.u_count == 0) - return; - if ((ip->i_mode & IFMT) == IFREG && - u.u_offset + u.u_count > u.u_limit[LIM_FSIZE]) { - psignal(u.u_procp, SIGXFSZ); - u.u_error = EMFILE; - return; - } - if (type!=IFBLK) { - dev = ip->i_dev; - fs = ip->i_fs; - bsize = fs->fs_bsize; - } else - bsize = BLKDEV_IOSIZE; - do { - lbn = u.u_offset / bsize; - on = u.u_offset % bsize; - n = MIN((unsigned)(bsize - on), u.u_count); - if (type != IFBLK) { - bn = fsbtodb(fs, bmap(ip, lbn, B_WRITE, (int)(on + n))); - if (u.u_error || (long)bn<0) - return; - if(u.u_offset + n > ip->i_size && - (type == IFDIR || type == IFREG || type == IFLNK)) - ip->i_size = u.u_offset + n; - size = blksize(fs, ip, lbn); - } else { - size = bsize; - bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE); - } - count = howmany(size, DEV_BSIZE); - for (i = 0; i < count; i += CLSIZE) - if (mfind(dev, bn + i)) - munhash(dev, bn + i); - if (n == bsize) - bp = getblk(dev, bn, size); - else - bp = bread(dev, bn, size); - if (u.u_segflg != 1) { - if (copyin(u.u_base, bp->b_un.b_addr + on, n)) { - u.u_error = EFAULT; - goto bad; - } - } else - bcopy(u.u_base, bp->b_un.b_addr + on, n); - u.u_base += n; - u.u_offset += n; - u.u_count -= n; -bad: - ; - if (u.u_error != 0) - brelse(bp); - else { - if ((ip->i_mode&IFMT) == IFDIR) - /* - * Writing to clear a directory entry. - * Must insure the write occurs before - * the inode is freed, or may end up - * pointing at a new (different) file - * if inode is quickly allocated again - * and system crashes. - */ - bwrite(bp); - else if (n + on == bsize) { - bp->b_flags |= B_AGE; - bawrite(bp); - } else - bdwrite(bp); - } - ip->i_flag |= IUPD|ICHG; - if (u.u_ruid != 0) - ip->i_mode &= ~(ISUID|ISGID); - } while (u.u_error == 0 && u.u_count != 0); -} - -/* - * Move n bytes at byte location - * &bp->b_un.b_addr[o] to/from (flag) the - * user/kernel (u.segflg) area starting at u.base. - * Update all the arguments by the number - * of bytes moved. - */ -iomove(cp, n, flag) - register caddr_t cp; - register unsigned n; -{ - register int t; - - if (n==0) - return; - if (u.u_segflg != 1) { - if (flag==B_WRITE) - t = copyin(u.u_base, (caddr_t)cp, n); - else - t = copyout((caddr_t)cp, u.u_base, n); - if (t) { - u.u_error = EFAULT; - return; - } - } else - if (flag == B_WRITE) - bcopy(u.u_base, (caddr_t)cp, n); - else - bcopy((caddr_t)cp, u.u_base, n); - u.u_base += n; - u.u_offset += n; - u.u_count -= n; -} - -readip(ip, uio) - register struct inode *ip; - register struct uio *uio; -{ - register struct iovec *iov = uio->uio_iov; - struct buf *bp; - struct fs *fs; - dev_t dev; - daddr_t lbn, bn; - off_t diff; - register int on, type; - register unsigned n; - int size; - long bsize; - extern int mem_no; - int error = 0; - - uio->uio_resid = 0; - if (uio->uio_iovcnt == 0) - return (0); - dev = (dev_t)ip->i_rdev; - if (uio->uio_offset < 0 && - ((ip->i_mode&IFMT) != IFCHR || mem_no != major(dev))) { - error = EINVAL; - goto bad; - } - ip->i_flag |= IACC; - type = ip->i_mode&IFMT; - if (type == IFCHR) { - register c = u.u_count; - error = (*cdevsw[major(dev)].d_read)(dev, uio); - CHARGE(sc_tio * (c - u.u_count)); - return (error); - } - if (type != IFBLK) { - dev = ip->i_dev; - fs = ip->i_fs; - bsize = fs->fs_bsize; - } else - bsize = BLKDEV_IOSIZE; -nextiov: - if (uio->uio_iovcnt == 0) - goto getresid; - if (iov->iov_len > 0) - do { - lbn = uio->uio_offset / bsize; - on = uio->uio_offset % bsize; - n = MIN((unsigned)(bsize - on), iov->iov_len); - if (type != IFBLK) { - diff = ip->i_size - uio->uio_offset; - if (diff <= 0) - return; - if (diff < n) - n = diff; - bn = fsbtodb(fs, bmap(ip, lbn, B_READ)); - if (u.u_error) - goto getresid; - size = blksize(fs, ip, lbn); - } else { - size = bsize; - bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE); - rablock = bn + (BLKDEV_IOSIZE/DEV_BSIZE); - rasize = bsize; - } - if ((long)bn<0) { - bp = geteblk(size); - clrbuf(bp); - } else if (ip->i_lastr + 1 == lbn) - bp = breada(dev, bn, size, rablock, rasize); - else - bp = bread(dev, bn, size); - ip->i_lastr = lbn; - n = MIN(n, size - bp->b_resid); - if (n != 0) { - if (uio->uio_segflg != 1) { - if (copyout(bp->b_un.b_addr+on, iov->iov_base, n)) { - error = EFAULT; - goto getresid; - } - } else - bcopy(bp->b_un.b_addr + on, iov->iov_base, n); - iov->iov_base += n; - uio->uio_offset += n; - iov->iov_len -= n; -bad: - ; - } - if (n + on == bsize || uio->uio_offset == ip->i_size) - bp->b_flags |= B_AGE; - brelse(bp); - } while (u.u_error == 0 && iov->iov_len != 0 && n != 0); - if (u.u_error == 0 && n > 0) { - iov++; - uio->uio_iovcnt--; - goto nextiov; - } -getresid: - while (uio->uio_iovcnt > 0) { - uio->uio_resid += iov->iov_len; - iov++; - uio->uio_iovcnt--; - } - return (error); }