- if (uio->uio_resid == 0)
- return (0);
- fs = ip->i_fs;
- if (uio->uio_offset + uio->uio_resid > fs->fs_maxfilesize)
- return (EFBIG);
- ip->i_flag |= IACC;
- do {
- lbn = lblkno(fs, uio->uio_offset);
- on = blkoff(fs, uio->uio_offset);
- n = MIN((unsigned)(fs->fs_bsize - on), uio->uio_resid);
- diff = ip->i_size - uio->uio_offset;
- if (diff <= 0)
- return (0);
- if (diff < n)
- n = diff;
- size = blksize(fs, ip, lbn);
- rablock = lbn + 1;
- if (vp->v_lastr + 1 == lbn &&
- lblktosize(fs, rablock) < ip->i_size) {
- rasize = blksize(fs, ip, rablock);
- error = breadn(vp, lbn, size, &rablock,
- &rasize, 1, NOCRED, &bp);
- } else
- error = bread(vp, lbn, size, NOCRED, &bp);
- vp->v_lastr = lbn;
- n = MIN(n, size - bp->b_resid);
- if (error) {
- brelse(bp);
- return (error);
- }
- error = uiomove(bp->b_un.b_addr + on, (int)n, uio);
- if (n + on == fs->fs_bsize || uio->uio_offset == ip->i_size)
- bp->b_flags |= B_AGE;
- brelse(bp);
- } while (error == 0 && uio->uio_resid > 0 && n != 0);
- return (error);
-}