-/*
- * Vnode op for reading.
- */
-/* ARGSUSED */
-lfs_read(ap)
- struct vop_read_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
-{
- register struct vnode *vp = ap->a_vp;
- register struct inode *ip = VTOI(vp);
- register struct uio *uio = ap->a_uio;
- register struct lfs *fs;
- struct buf *bp;
- daddr_t lbn, bn, rablock;
- off_t diff;
- int type, error = 0, size;
- long n, on;
-
- type = ip->i_mode & IFMT;
-#ifdef DIAGNOSTIC
- if (uio->uio_rw != UIO_READ)
- panic("lfs_read mode");
- if (type != IFDIR && type != IFREG && type != IFLNK)
- panic("lfs_read type");
- if (type == IFLNK && (int)ip->i_size < vp->v_mount->mnt_maxsymlinklen)
- panic("read short symlink");
-#endif
- if (uio->uio_resid == 0)
- return (0);
- fs = ip->i_lfs;
- if (uio->uio_offset < 0 ||
- (u_quad_t)uio->uio_offset + uio->uio_resid > fs->lfs_maxfilesize)
- return (EFBIG);
- ip->i_flag |= IACC;
- do {
- lbn = lblkno(fs, uio->uio_offset);
- on = blkoff(fs, uio->uio_offset);
- n = min((unsigned)(fs->lfs_bsize - on), uio->uio_resid);
- diff = ip->i_size - uio->uio_offset;
- if (diff <= 0)
- break;
- if (diff < n)
- n = diff;
- size = blksize(fs);
- lfs_check(vp, lbn);
- error = cluster_read(vp, ip->i_size, lbn, size, NOCRED, &bp);
- vp->v_lastr = lbn;
- n = min(n, size - bp->b_resid);
- if (error)
- break;
- error = uiomove(bp->b_un.b_addr + on, (int)n, uio);
- if (type == IFREG &&
- n + on == fs->lfs_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);
-}
-
-/*
- * Vnode op for writing.
- */
-lfs_write(ap)
- struct vop_write_args /* {
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
- } */ *ap;
-{
- register struct vnode *vp = ap->a_vp;
- register struct uio *uio = ap->a_uio;
- struct proc *p = uio->uio_procp;
- register struct inode *ip = VTOI(vp);
- register struct lfs *fs;
- register ioflag = ap->a_ioflag;
- struct timeval tv;
- struct buf *bp;
- daddr_t lbn;
- off_t osize;
- int n, on, flags, newblock;
- int size, resid, error = 0;
-
-#ifdef DIAGNOSTIC
- if (uio->uio_rw != UIO_WRITE)
- panic("lfs_write mode");
-#endif
- switch (vp->v_type) {
- case VREG:
- if (ioflag & IO_APPEND)
- uio->uio_offset = ip->i_size;
- /* fall through */
- case VLNK:
- break;
-
- case VDIR:
- /* XXX This may not be correct for LFS. */
- if ((ioflag & IO_SYNC) == 0)
- panic("lfs_write nonsync dir write");
- break;
-
- default:
- panic("lfs_write type");
- }
- if (uio->uio_offset < 0)
- return (EINVAL);
- if (uio->uio_resid == 0)
- return (0);
- /*
- * Maybe this should be above the vnode op call, but so long as
- * file servers have no limits, i don't think it matters
- */
- if (vp->v_type == VREG && p &&
- uio->uio_offset + uio->uio_resid >
- p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
- psignal(p, SIGXFSZ);
- return (EFBIG);
- }
- resid = uio->uio_resid;
- osize = ip->i_size;
- fs = ip->i_lfs; /* LFS */
- if (uio->uio_offset < 0 ||
- (u_quad_t)uio->uio_offset + uio->uio_resid > fs->lfs_maxfilesize)
- return (EFBIG);
-
- do {
- lbn = lblkno(fs, uio->uio_offset);
- on = blkoff(fs, uio->uio_offset);
- n = min((unsigned)(fs->lfs_bsize - on), uio->uio_resid);
- lfs_check(vp, lbn);
- if (error = lfs_balloc(vp, n, lbn, &bp))
- break;
- if (uio->uio_offset + n > ip->i_size) {
- ip->i_size = uio->uio_offset + n;
- vnode_pager_setsize(vp, (u_long)ip->i_size);
- }
- size = blksize(fs);
- (void) vnode_pager_uncache(vp);
- n = min(n, size - bp->b_resid);
- error = uiomove(bp->b_un.b_addr + on, n, uio);
- error = VOP_BWRITE(bp);
- /* XXX Why is this in the loop? */
- if (ap->a_cred && ap->a_cred->cr_uid != 0)
- ip->i_mode &= ~(ISUID|ISGID);
- } while (error == 0 && uio->uio_resid > 0 && n != 0);
-
- if (error) {
- if (ioflag & IO_UNIT) {
- (void)VOP_TRUNCATE(vp, osize, ioflag & IO_SYNC,
- ap->a_cred, uio->uio_procp);
- uio->uio_offset -= resid - uio->uio_resid;
- uio->uio_resid = resid;
- }
- }
-
- /* TURN OFF SYNC FOR NOW
- if (!error && (ioflag & IO_SYNC)) {
- tv = time;
- if (!(error = VOP_UPDATE(vp, &tv, &tv, 1)))
- error = VOP_FSYNC(vp, ap->a_cred, MNT_WAIT,
- uio->uio_procp);
- }
- */
- return (error);
-}