123405Smckusick /* 251155Sbostic * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California. 337737Smckusick * All rights reserved. 423405Smckusick * 544539Sbostic * %sccs.include.redist.c% 637737Smckusick * 7*51482Sbostic * @(#)lfs_vnops.c 7.69 (Berkeley) 11/01/91 823405Smckusick */ 937Sbill 10*51482Sbostic #include <sys/param.h> 11*51482Sbostic #include <sys/systm.h> 12*51482Sbostic #include <sys/namei.h> 13*51482Sbostic #include <sys/resourcevar.h> 14*51482Sbostic #include <sys/kernel.h> 15*51482Sbostic #include <sys/file.h> 16*51482Sbostic #include <sys/stat.h> 17*51482Sbostic #include <sys/buf.h> 18*51482Sbostic #include <sys/proc.h> 19*51482Sbostic #include <sys/conf.h> 20*51482Sbostic #include <sys/mount.h> 21*51482Sbostic #include <sys/vnode.h> 22*51482Sbostic #include <sys/specdev.h> 23*51482Sbostic #include <sys/fifo.h> 24*51482Sbostic #include <sys/malloc.h> 2537Sbill 26*51482Sbostic #include <ufs/quota.h> 27*51482Sbostic #include <ufs/inode.h> 28*51482Sbostic #include <ufs/dir.h> 29*51482Sbostic #include <ufs/ufs_extern.h> 3047571Skarels 31*51482Sbostic #include <lfs/lfs.h> 32*51482Sbostic #include <lfs/lfs_extern.h> 3351134Sbostic 34*51482Sbostic /* Global vfs data structures for lfs. */ 35*51482Sbostic struct vnodeops lfs_vnodeops = { 36*51482Sbostic ufs_lookup, /* lookup */ 37*51482Sbostic ufs_create, /* create */ 38*51482Sbostic ufs_mknod, /* mknod */ 39*51482Sbostic ufs_open, /* open */ 40*51482Sbostic ufs_close, /* close */ 41*51482Sbostic ufs_access, /* access */ 42*51482Sbostic ufs_getattr, /* getattr */ 43*51482Sbostic ufs_setattr, /* setattr */ 44*51482Sbostic lfs_read, /* read */ 45*51482Sbostic lfs_write, /* write */ 46*51482Sbostic ufs_ioctl, /* ioctl */ 47*51482Sbostic ufs_select, /* select */ 48*51482Sbostic ufs_mmap, /* mmap */ 49*51482Sbostic lfs_fsync, /* fsync */ 50*51482Sbostic ufs_seek, /* seek */ 51*51482Sbostic ufs_remove, /* remove */ 52*51482Sbostic ufs_link, /* link */ 53*51482Sbostic ufs_rename, /* rename */ 54*51482Sbostic ufs_mkdir, /* mkdir */ 55*51482Sbostic ufs_rmdir, /* rmdir */ 56*51482Sbostic ufs_symlink, /* symlink */ 57*51482Sbostic ufs_readdir, /* readdir */ 58*51482Sbostic ufs_readlink, /* readlink */ 59*51482Sbostic ufs_abortop, /* abortop */ 60*51482Sbostic ufs_inactive, /* inactive */ 61*51482Sbostic ufs_reclaim, /* reclaim */ 62*51482Sbostic ufs_lock, /* lock */ 63*51482Sbostic ufs_unlock, /* unlock */ 64*51482Sbostic ufs_bmap, /* bmap */ 65*51482Sbostic ufs_strategy, /* strategy */ 66*51482Sbostic ufs_print, /* print */ 67*51482Sbostic ufs_islocked, /* islocked */ 68*51482Sbostic ufs_advlock, /* advlock */ 69*51482Sbostic }; 706254Sroot 7137Sbill /* 7239608Smckusick * Vnode op for reading. 7339608Smckusick */ 7437737Smckusick /* ARGSUSED */ 7551134Sbostic lfs_read(vp, uio, ioflag, cred) 7639608Smckusick struct vnode *vp; 7739608Smckusick register struct uio *uio; 7839608Smckusick int ioflag; 7939608Smckusick struct ucred *cred; 8039608Smckusick { 8139608Smckusick register struct inode *ip = VTOI(vp); 8251155Sbostic register LFS *fs; /* LFS */ 8339608Smckusick struct buf *bp; 8439608Smckusick daddr_t lbn, bn, rablock; 8539896Smckusick int size, diff, error = 0; 8639608Smckusick long n, on, type; 8739608Smckusick 8851155Sbostic printf("lfs_read: ino %d\n", ip->i_number); 8948039Smckusick #ifdef DIAGNOSTIC 9039608Smckusick if (uio->uio_rw != UIO_READ) 9139608Smckusick panic("ufs_read mode"); 9239608Smckusick type = ip->i_mode & IFMT; 9339608Smckusick if (type != IFDIR && type != IFREG && type != IFLNK) 9439608Smckusick panic("ufs_read type"); 9548039Smckusick #endif 9639608Smckusick if (uio->uio_resid == 0) 9739608Smckusick return (0); 9839608Smckusick if (uio->uio_offset < 0) 9939608Smckusick return (EINVAL); 10039608Smckusick ip->i_flag |= IACC; 10151155Sbostic 10251155Sbostic fs = ip->i_lfs; /* LFS */ 10339608Smckusick do { 10439608Smckusick lbn = lblkno(fs, uio->uio_offset); 10539608Smckusick on = blkoff(fs, uio->uio_offset); 10651155Sbostic n = MIN((unsigned)(fs->lfs_bsize - on), uio->uio_resid); 10739608Smckusick diff = ip->i_size - uio->uio_offset; 10839608Smckusick if (diff <= 0) 10939608Smckusick return (0); 11039608Smckusick if (diff < n) 11139608Smckusick n = diff; 11251155Sbostic size = blksize(fs); /* LFS */ 11339674Smckusick rablock = lbn + 1; 11439896Smckusick if (vp->v_lastr + 1 == lbn && 11539896Smckusick lblktosize(fs, rablock) < ip->i_size) 11639896Smckusick error = breada(ITOV(ip), lbn, size, rablock, 11751155Sbostic blksize(fs), NOCRED, &bp); 11839608Smckusick else 11939674Smckusick error = bread(ITOV(ip), lbn, size, NOCRED, &bp); 12039815Smckusick vp->v_lastr = lbn; 12139608Smckusick n = MIN(n, size - bp->b_resid); 12239608Smckusick if (error) { 12339608Smckusick brelse(bp); 12439608Smckusick return (error); 12539608Smckusick } 12639608Smckusick error = uiomove(bp->b_un.b_addr + on, (int)n, uio); 12751155Sbostic if (n + on == fs->lfs_bsize || uio->uio_offset == ip->i_size) 12839608Smckusick bp->b_flags |= B_AGE; 12939608Smckusick brelse(bp); 13039608Smckusick } while (error == 0 && uio->uio_resid > 0 && n != 0); 13139608Smckusick return (error); 13239608Smckusick } 13339608Smckusick 13439608Smckusick /* 13539608Smckusick * Vnode op for writing. 13639608Smckusick */ 13751134Sbostic lfs_write(vp, uio, ioflag, cred) 13839608Smckusick register struct vnode *vp; 13939608Smckusick struct uio *uio; 14039608Smckusick int ioflag; 14139608Smckusick struct ucred *cred; 14239608Smckusick { 14348039Smckusick struct proc *p = uio->uio_procp; 14439608Smckusick register struct inode *ip = VTOI(vp); 14551183Sbostic register LFS *fs; /* LFS */ 14639608Smckusick struct buf *bp; 14739608Smckusick daddr_t lbn, bn; 14839608Smckusick u_long osize; 14945722Smckusick int n, on, flags; 15045722Smckusick int size, resid, error = 0; 15139608Smckusick 15251155Sbostic printf("lfs_write ino %d\n", ip->i_number); 15348039Smckusick #ifdef DIAGNOSTIC 15439608Smckusick if (uio->uio_rw != UIO_WRITE) 15539608Smckusick panic("ufs_write mode"); 15648039Smckusick #endif 15739608Smckusick switch (vp->v_type) { 15839608Smckusick case VREG: 15939608Smckusick if (ioflag & IO_APPEND) 16039608Smckusick uio->uio_offset = ip->i_size; 16139608Smckusick /* fall through */ 16239608Smckusick case VLNK: 16339608Smckusick break; 16439608Smckusick 16539608Smckusick case VDIR: 16639608Smckusick if ((ioflag & IO_SYNC) == 0) 16739608Smckusick panic("ufs_write nonsync dir write"); 16839608Smckusick break; 16939608Smckusick 17039608Smckusick default: 17139608Smckusick panic("ufs_write type"); 17239608Smckusick } 17339608Smckusick if (uio->uio_offset < 0) 17439608Smckusick return (EINVAL); 17539608Smckusick if (uio->uio_resid == 0) 17639608Smckusick return (0); 17739608Smckusick /* 17839608Smckusick * Maybe this should be above the vnode op call, but so long as 17939608Smckusick * file servers have no limits, i don't think it matters 18039608Smckusick */ 18149679Smckusick if (vp->v_type == VREG && p && 18239608Smckusick uio->uio_offset + uio->uio_resid > 18347571Skarels p->p_rlimit[RLIMIT_FSIZE].rlim_cur) { 18447571Skarels psignal(p, SIGXFSZ); 18539608Smckusick return (EFBIG); 18639608Smckusick } 18739608Smckusick resid = uio->uio_resid; 18839608Smckusick osize = ip->i_size; 18951183Sbostic fs = ip->i_lfs; /* LFS */ 19039674Smckusick flags = 0; 19151183Sbostic #ifdef NOTLFS 19239674Smckusick if (ioflag & IO_SYNC) 19339674Smckusick flags = B_SYNC; 19451183Sbostic #endif 19539608Smckusick do { 19639608Smckusick lbn = lblkno(fs, uio->uio_offset); 19751183Sbostic on = blkoff(fs, uio->uio_offset); /* LFS */ 19851183Sbostic n = MIN((unsigned)(fs->lfs_bsize - on), uio->uio_resid); 19951183Sbostic if (n < fs->lfs_bsize) /* LFS */ 20039674Smckusick flags |= B_CLRBUF; 20139608Smckusick else 20251183Sbostic flags &= ~B_CLRBUF; /* LFS */ 20351183Sbostic if (error = bread(vp, lbn, fs->lfs_bsize, NOCRED, &bp)) 20439608Smckusick break; 20539674Smckusick bn = bp->b_blkno; 20645722Smckusick if (uio->uio_offset + n > ip->i_size) { 20739608Smckusick ip->i_size = uio->uio_offset + n; 20845722Smckusick vnode_pager_setsize(vp, ip->i_size); 20945722Smckusick } 21051183Sbostic size = blksize(fs); 21145722Smckusick (void) vnode_pager_uncache(vp); 21239608Smckusick n = MIN(n, size - bp->b_resid); 21339608Smckusick error = uiomove(bp->b_un.b_addr + on, n, uio); 21451183Sbostic #ifdef NOTLFS /* LFS */ 21539608Smckusick if (ioflag & IO_SYNC) 21639608Smckusick (void) bwrite(bp); 21739608Smckusick else if (n + on == fs->fs_bsize) { 21839608Smckusick bp->b_flags |= B_AGE; 21939608Smckusick bawrite(bp); 22039608Smckusick } else 22139608Smckusick bdwrite(bp); 22251183Sbostic #else 22351183Sbostic /* 22451183Sbostic * Update segment usage information; call segment 22551183Sbostic * writer if necessary. 22651183Sbostic */ 22751183Sbostic lfs_bwrite(bp); 22851183Sbostic #endif 22939608Smckusick ip->i_flag |= IUPD|ICHG; 23039608Smckusick if (cred->cr_uid != 0) 23139608Smckusick ip->i_mode &= ~(ISUID|ISGID); 23239608Smckusick } while (error == 0 && uio->uio_resid > 0 && n != 0); 23339608Smckusick if (error && (ioflag & IO_UNIT)) { 23451183Sbostic #ifdef NOTLFS 23551183Sbostic /* This just doesn't work... */ 23651155Sbostic (void) lfs_itrunc(ip, osize, ioflag & IO_SYNC); 23751183Sbostic #endif 23839608Smckusick uio->uio_offset -= resid - uio->uio_resid; 23939608Smckusick uio->uio_resid = resid; 24039608Smckusick } 24142493Smckusick if (!error && (ioflag & IO_SYNC)) 24251183Sbostic ITIMES(ip, &time, &time); /* LFS */ 24339608Smckusick return (error); 24439608Smckusick } 24539608Smckusick 2469167Ssam /* 24737737Smckusick * Synch an open file. 2489167Ssam */ 24937737Smckusick /* ARGSUSED */ 25051134Sbostic lfs_fsync(vp, fflags, cred, waitfor, p) 25137737Smckusick struct vnode *vp; 25237737Smckusick int fflags; 25337737Smckusick struct ucred *cred; 25439597Smckusick int waitfor; 25548039Smckusick struct proc *p; 2567701Ssam { 25739597Smckusick struct inode *ip = VTOI(vp); 2587701Ssam 25948039Smckusick if (fflags & FWRITE) 26037737Smckusick ip->i_flag |= ICHG; 26149737Smckusick /* 262*51482Sbostic * XXX 263*51482Sbostic * Sync the mounted file system associated with the file 264*51482Sbostic * descriptor. 26549737Smckusick */ 26651183Sbostic ITIMES(ip, &time, &time); /* LFS */ 26737737Smckusick return (0); 26837737Smckusick } 269