xref: /csrg-svn/sys/ufs/lfs/lfs_vnops.c (revision 51482)
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