xref: /csrg-svn/sys/ufs/lfs/lfs_vnops.c (revision 53533)
123405Smckusick /*
251502Sbostic  * Copyright (c) 1986, 1989, 1991 Regents of the University of California.
337737Smckusick  * All rights reserved.
423405Smckusick  *
544539Sbostic  * %sccs.include.redist.c%
637737Smckusick  *
7*53533Sheideman  *	@(#)lfs_vnops.c	7.81 (Berkeley) 05/14/92
823405Smckusick  */
937Sbill 
1051482Sbostic #include <sys/param.h>
1151482Sbostic #include <sys/systm.h>
1251482Sbostic #include <sys/namei.h>
1351482Sbostic #include <sys/resourcevar.h>
1451482Sbostic #include <sys/kernel.h>
1551482Sbostic #include <sys/file.h>
1651482Sbostic #include <sys/stat.h>
1751482Sbostic #include <sys/buf.h>
1851482Sbostic #include <sys/proc.h>
1951482Sbostic #include <sys/conf.h>
2051482Sbostic #include <sys/mount.h>
2151482Sbostic #include <sys/vnode.h>
2251482Sbostic #include <sys/specdev.h>
2351482Sbostic #include <sys/fifo.h>
2451482Sbostic #include <sys/malloc.h>
2537Sbill 
2653321Smckusick #include <vm/vm.h>
2753321Smckusick 
2851502Sbostic #include <ufs/ufs/quota.h>
2951502Sbostic #include <ufs/ufs/inode.h>
3051502Sbostic #include <ufs/ufs/dir.h>
3151502Sbostic #include <ufs/ufs/ufs_extern.h>
3247571Skarels 
3351502Sbostic #include <ufs/lfs/lfs.h>
3451502Sbostic #include <ufs/lfs/lfs_extern.h>
3551134Sbostic 
3651482Sbostic /* Global vfs data structures for lfs. */
37*53533Sheideman int (**lfs_vnodeop_p)();
38*53533Sheideman struct vnodeopv_entry_desc lfs_vnodeop_entries[] = {
39*53533Sheideman 	{ &vop_default_desc, vn_default_error },
40*53533Sheideman 	{ &vop_lookup_desc, ufs_lookup },		/* lookup */
41*53533Sheideman 	{ &vop_create_desc, ufs_create },		/* create */
42*53533Sheideman 	{ &vop_mknod_desc, ufs_mknod },		/* mknod */
43*53533Sheideman 	{ &vop_open_desc, ufs_open },		/* open */
44*53533Sheideman 	{ &vop_close_desc, ufs_close },		/* close */
45*53533Sheideman 	{ &vop_access_desc, ufs_access },		/* access */
46*53533Sheideman 	{ &vop_getattr_desc, ufs_getattr },		/* getattr */
47*53533Sheideman 	{ &vop_setattr_desc, ufs_setattr },		/* setattr */
48*53533Sheideman 	{ &vop_read_desc, lfs_read },		/* read */
49*53533Sheideman 	{ &vop_write_desc, lfs_write },		/* write */
50*53533Sheideman 	{ &vop_ioctl_desc, ufs_ioctl },		/* ioctl */
51*53533Sheideman 	{ &vop_select_desc, ufs_select },		/* select */
52*53533Sheideman 	{ &vop_mmap_desc, ufs_mmap },		/* mmap */
53*53533Sheideman 	{ &vop_fsync_desc, lfs_fsync },		/* fsync */
54*53533Sheideman 	{ &vop_seek_desc, ufs_seek },		/* seek */
55*53533Sheideman 	{ &vop_remove_desc, ufs_remove },		/* remove */
56*53533Sheideman 	{ &vop_link_desc, ufs_link },		/* link */
57*53533Sheideman 	{ &vop_rename_desc, ufs_rename },		/* rename */
58*53533Sheideman 	{ &vop_mkdir_desc, ufs_mkdir },		/* mkdir */
59*53533Sheideman 	{ &vop_rmdir_desc, ufs_rmdir },		/* rmdir */
60*53533Sheideman 	{ &vop_symlink_desc, ufs_symlink },		/* symlink */
61*53533Sheideman 	{ &vop_readdir_desc, ufs_readdir },		/* readdir */
62*53533Sheideman 	{ &vop_readlink_desc, ufs_readlink },		/* readlink */
63*53533Sheideman 	{ &vop_abortop_desc, ufs_abortop },		/* abortop */
64*53533Sheideman 	{ &vop_inactive_desc, lfs_inactive },		/* inactive */
65*53533Sheideman 	{ &vop_reclaim_desc, ufs_reclaim },		/* reclaim */
66*53533Sheideman 	{ &vop_lock_desc, ufs_lock },		/* lock */
67*53533Sheideman 	{ &vop_unlock_desc, ufs_unlock },		/* unlock */
68*53533Sheideman 	{ &vop_bmap_desc, lfs_bmap },		/* bmap */
69*53533Sheideman 	{ &vop_strategy_desc, ufs_strategy },		/* strategy */
70*53533Sheideman 	{ &vop_print_desc, ufs_print },		/* print */
71*53533Sheideman 	{ &vop_islocked_desc, ufs_islocked },		/* islocked */
72*53533Sheideman 	{ &vop_advlock_desc, ufs_advlock },		/* advlock */
73*53533Sheideman 	{ &vop_blkatoff_desc, lfs_blkatoff },		/* blkatoff */
74*53533Sheideman 	{ &vop_vget_desc, lfs_vget },		/* vget */
75*53533Sheideman 	{ &vop_valloc_desc, lfs_valloc },		/* valloc */
76*53533Sheideman 	{ &vop_vfree_desc, lfs_vfree },		/* vfree */
77*53533Sheideman 	{ &vop_truncate_desc, lfs_truncate },		/* truncate */
78*53533Sheideman 	{ &vop_update_desc, lfs_update },		/* update */
79*53533Sheideman 	{ &vop_bwrite_desc, lfs_bwrite },		/* bwrite */
80*53533Sheideman 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
8151482Sbostic };
82*53533Sheideman struct vnodeopv_desc lfs_vnodeop_opv_desc =
83*53533Sheideman 	{ &lfs_vnodeop_p, lfs_vnodeop_entries };
846254Sroot 
85*53533Sheideman int (**lfs_specop_p)();
86*53533Sheideman struct vnodeopv_entry_desc lfs_specop_entries[] = {
87*53533Sheideman 	{ &vop_default_desc, vn_default_error },
88*53533Sheideman 	{ &vop_lookup_desc, spec_lookup },		/* lookup */
89*53533Sheideman 	{ &vop_create_desc, spec_create },		/* create */
90*53533Sheideman 	{ &vop_mknod_desc, spec_mknod },		/* mknod */
91*53533Sheideman 	{ &vop_open_desc, spec_open },		/* open */
92*53533Sheideman 	{ &vop_close_desc, ufsspec_close },		/* close */
93*53533Sheideman 	{ &vop_access_desc, ufs_access },		/* access */
94*53533Sheideman 	{ &vop_getattr_desc, ufs_getattr },		/* getattr */
95*53533Sheideman 	{ &vop_setattr_desc, ufs_setattr },		/* setattr */
96*53533Sheideman 	{ &vop_read_desc, ufsspec_read },		/* read */
97*53533Sheideman 	{ &vop_write_desc, ufsspec_write },		/* write */
98*53533Sheideman 	{ &vop_ioctl_desc, spec_ioctl },		/* ioctl */
99*53533Sheideman 	{ &vop_select_desc, spec_select },		/* select */
100*53533Sheideman 	{ &vop_mmap_desc, spec_mmap },		/* mmap */
101*53533Sheideman 	{ &vop_fsync_desc, spec_fsync },		/* fsync */
102*53533Sheideman 	{ &vop_seek_desc, spec_seek },		/* seek */
103*53533Sheideman 	{ &vop_remove_desc, spec_remove },		/* remove */
104*53533Sheideman 	{ &vop_link_desc, spec_link },		/* link */
105*53533Sheideman 	{ &vop_rename_desc, spec_rename },		/* rename */
106*53533Sheideman 	{ &vop_mkdir_desc, spec_mkdir },		/* mkdir */
107*53533Sheideman 	{ &vop_rmdir_desc, spec_rmdir },		/* rmdir */
108*53533Sheideman 	{ &vop_symlink_desc, spec_symlink },		/* symlink */
109*53533Sheideman 	{ &vop_readdir_desc, spec_readdir },		/* readdir */
110*53533Sheideman 	{ &vop_readlink_desc, spec_readlink },		/* readlink */
111*53533Sheideman 	{ &vop_abortop_desc, spec_abortop },		/* abortop */
112*53533Sheideman 	{ &vop_inactive_desc, lfs_inactive },		/* inactive */
113*53533Sheideman 	{ &vop_reclaim_desc, ufs_reclaim },		/* reclaim */
114*53533Sheideman 	{ &vop_lock_desc, ufs_lock },		/* lock */
115*53533Sheideman 	{ &vop_unlock_desc, ufs_unlock },		/* unlock */
116*53533Sheideman 	{ &vop_bmap_desc, spec_bmap },		/* bmap */
117*53533Sheideman 	{ &vop_strategy_desc, spec_strategy },		/* strategy */
118*53533Sheideman 	{ &vop_print_desc, ufs_print },		/* print */
119*53533Sheideman 	{ &vop_islocked_desc, ufs_islocked },		/* islocked */
120*53533Sheideman 	{ &vop_advlock_desc, spec_advlock },		/* advlock */
121*53533Sheideman 	{ &vop_blkatoff_desc, spec_blkatoff },		/* blkatoff */
122*53533Sheideman 	{ &vop_vget_desc, spec_vget },		/* vget */
123*53533Sheideman 	{ &vop_valloc_desc, spec_valloc },		/* valloc */
124*53533Sheideman 	{ &vop_vfree_desc, spec_vfree },		/* vfree */
125*53533Sheideman 	{ &vop_truncate_desc, spec_truncate },		/* truncate */
126*53533Sheideman 	{ &vop_update_desc, lfs_update },		/* update */
127*53533Sheideman 	{ &vop_bwrite_desc, lfs_bwrite },		/* bwrite */
128*53533Sheideman 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
12951558Smckusick };
130*53533Sheideman struct vnodeopv_desc lfs_specop_opv_desc =
131*53533Sheideman 	{ &lfs_specop_p, lfs_specop_entries };
13251558Smckusick 
13351558Smckusick #ifdef FIFO
134*53533Sheideman int (**lfs_fifoop_p)();
135*53533Sheideman struct vnodeopv_entry_desc lfs_fifoop_entries[] = {
136*53533Sheideman 	{ &vop_default_desc, vn_default_error },
137*53533Sheideman 	{ &vop_lookup_desc, fifo_lookup },		/* lookup */
138*53533Sheideman 	{ &vop_create_desc, fifo_create },		/* create */
139*53533Sheideman 	{ &vop_mknod_desc, fifo_mknod },		/* mknod */
140*53533Sheideman 	{ &vop_open_desc, fifo_open },		/* open */
141*53533Sheideman 	{ &vop_close_desc, ufsfifo_close },		/* close */
142*53533Sheideman 	{ &vop_access_desc, ufs_access },		/* access */
143*53533Sheideman 	{ &vop_getattr_desc, ufs_getattr },		/* getattr */
144*53533Sheideman 	{ &vop_setattr_desc, ufs_setattr },		/* setattr */
145*53533Sheideman 	{ &vop_read_desc, ufsfifo_read },		/* read */
146*53533Sheideman 	{ &vop_write_desc, ufsfifo_write },		/* write */
147*53533Sheideman 	{ &vop_ioctl_desc, fifo_ioctl },		/* ioctl */
148*53533Sheideman 	{ &vop_select_desc, fifo_select },		/* select */
149*53533Sheideman 	{ &vop_mmap_desc, fifo_mmap },		/* mmap */
150*53533Sheideman 	{ &vop_fsync_desc, fifo_fsync },		/* fsync */
151*53533Sheideman 	{ &vop_seek_desc, fifo_seek },		/* seek */
152*53533Sheideman 	{ &vop_remove_desc, fifo_remove },		/* remove */
153*53533Sheideman 	{ &vop_link_desc, fifo_link },		/* link */
154*53533Sheideman 	{ &vop_rename_desc, fifo_rename },		/* rename */
155*53533Sheideman 	{ &vop_mkdir_desc, fifo_mkdir },		/* mkdir */
156*53533Sheideman 	{ &vop_rmdir_desc, fifo_rmdir },		/* rmdir */
157*53533Sheideman 	{ &vop_symlink_desc, fifo_symlink },		/* symlink */
158*53533Sheideman 	{ &vop_readdir_desc, fifo_readdir },		/* readdir */
159*53533Sheideman 	{ &vop_readlink_desc, fifo_readlink },		/* readlink */
160*53533Sheideman 	{ &vop_abortop_desc, fifo_abortop },		/* abortop */
161*53533Sheideman 	{ &vop_inactive_desc, lfs_inactive },		/* inactive */
162*53533Sheideman 	{ &vop_reclaim_desc, ufs_reclaim },		/* reclaim */
163*53533Sheideman 	{ &vop_lock_desc, ufs_lock },		/* lock */
164*53533Sheideman 	{ &vop_unlock_desc, ufs_unlock },		/* unlock */
165*53533Sheideman 	{ &vop_bmap_desc, fifo_bmap },		/* bmap */
166*53533Sheideman 	{ &vop_strategy_desc, fifo_strategy },		/* strategy */
167*53533Sheideman 	{ &vop_print_desc, ufs_print },		/* print */
168*53533Sheideman 	{ &vop_islocked_desc, ufs_islocked },		/* islocked */
169*53533Sheideman 	{ &vop_advlock_desc, fifo_advlock },		/* advlock */
170*53533Sheideman 	{ &vop_blkatoff_desc, fifo_blkatoff },		/* blkatoff */
171*53533Sheideman 	{ &vop_vget_desc, fifo_vget },		/* vget */
172*53533Sheideman 	{ &vop_valloc_desc, fifo_valloc },		/* valloc */
173*53533Sheideman 	{ &vop_vfree_desc, fifo_vfree },		/* vfree */
174*53533Sheideman 	{ &vop_truncate_desc, fifo_truncate },		/* truncate */
175*53533Sheideman 	{ &vop_update_desc, lfs_update },		/* update */
176*53533Sheideman 	{ &vop_bwrite_desc, lfs_bwrite },		/* bwrite */
177*53533Sheideman 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
17851558Smckusick };
179*53533Sheideman struct vnodeopv_desc lfs_fifoop_opv_desc =
180*53533Sheideman 	{ &lfs_fifoop_p, lfs_fifoop_entries };
18151558Smckusick #endif /* FIFO */
18251558Smckusick 
18337Sbill /*
18439608Smckusick  * Vnode op for reading.
18539608Smckusick  */
18637737Smckusick /* ARGSUSED */
187*53533Sheideman lfs_read (ap)
188*53533Sheideman 	struct vop_read_args *ap;
189*53533Sheideman #define vp (ap->a_vp)
190*53533Sheideman #define uio (ap->a_uio)
191*53533Sheideman #define ioflag (ap->a_ioflag)
192*53533Sheideman #define cred (ap->a_cred)
19339608Smckusick {
19439608Smckusick 	register struct inode *ip = VTOI(vp);
19551502Sbostic 	register struct lfs *fs;				/* LFS */
19639608Smckusick 	struct buf *bp;
19739608Smckusick 	daddr_t lbn, bn, rablock;
19853233Smckusick 	int size, error = 0;
19939608Smckusick 	long n, on, type;
20053233Smckusick 	off_t diff;
20139608Smckusick 
20251852Sbostic #ifdef VERBOSE
20351852Sbostic 	printf("lfs_read: ino %d\n", ip->i_number);
20451852Sbostic #endif
20548039Smckusick #ifdef DIAGNOSTIC
20639608Smckusick 	if (uio->uio_rw != UIO_READ)
20739608Smckusick 		panic("ufs_read mode");
20839608Smckusick 	type = ip->i_mode & IFMT;
20939608Smckusick 	if (type != IFDIR && type != IFREG && type != IFLNK)
21039608Smckusick 		panic("ufs_read type");
21148039Smckusick #endif
21239608Smckusick 	if (uio->uio_resid == 0)
21339608Smckusick 		return (0);
21439608Smckusick 	if (uio->uio_offset < 0)
21539608Smckusick 		return (EINVAL);
21639608Smckusick 	ip->i_flag |= IACC;
21751155Sbostic 
21851155Sbostic 	fs = ip->i_lfs;						/* LFS */
21939608Smckusick 	do {
22039608Smckusick 		lbn = lblkno(fs, uio->uio_offset);
22139608Smckusick 		on = blkoff(fs, uio->uio_offset);
22251155Sbostic 		n = MIN((unsigned)(fs->lfs_bsize - on), uio->uio_resid);
22339608Smckusick 		diff = ip->i_size - uio->uio_offset;
22439608Smckusick 		if (diff <= 0)
22539608Smckusick 			return (0);
22639608Smckusick 		if (diff < n)
22739608Smckusick 			n = diff;
22851155Sbostic 		size = blksize(fs);				/* LFS */
22939674Smckusick 		rablock = lbn + 1;
23039896Smckusick 		if (vp->v_lastr + 1 == lbn &&
23139896Smckusick 		    lblktosize(fs, rablock) < ip->i_size)
23252195Smckusick 			error = breadn(ITOV(ip), lbn, size, &rablock,
23352195Smckusick 				&size, 1, NOCRED, &bp);
23439608Smckusick 		else
23539674Smckusick 			error = bread(ITOV(ip), lbn, size, NOCRED, &bp);
23639815Smckusick 		vp->v_lastr = lbn;
23739608Smckusick 		n = MIN(n, size - bp->b_resid);
23839608Smckusick 		if (error) {
23939608Smckusick 			brelse(bp);
24039608Smckusick 			return (error);
24139608Smckusick 		}
24239608Smckusick 		error = uiomove(bp->b_un.b_addr + on, (int)n, uio);
24351155Sbostic 		if (n + on == fs->lfs_bsize || uio->uio_offset == ip->i_size)
24439608Smckusick 			bp->b_flags |= B_AGE;
24539608Smckusick 		brelse(bp);
24639608Smckusick 	} while (error == 0 && uio->uio_resid > 0 && n != 0);
24739608Smckusick 	return (error);
24839608Smckusick }
249*53533Sheideman #undef vp
250*53533Sheideman #undef uio
251*53533Sheideman #undef ioflag
252*53533Sheideman #undef cred
25339608Smckusick 
25439608Smckusick /*
25539608Smckusick  * Vnode op for writing.
25639608Smckusick  */
257*53533Sheideman lfs_write (ap)
258*53533Sheideman 	struct vop_write_args *ap;
259*53533Sheideman #define vp (ap->a_vp)
260*53533Sheideman #define uio (ap->a_uio)
261*53533Sheideman #define ioflag (ap->a_ioflag)
262*53533Sheideman #define cred (ap->a_cred)
26339608Smckusick {
264*53533Sheideman 	USES_VOP_TRUNCATE;
265*53533Sheideman 	USES_VOP_UPDATE;
26648039Smckusick 	struct proc *p = uio->uio_procp;
26739608Smckusick 	register struct inode *ip = VTOI(vp);
26852091Sbostic 	register struct lfs *fs;
26939608Smckusick 	struct buf *bp;
27052091Sbostic 	daddr_t lbn;
27153233Smckusick 	off_t osize;
27252091Sbostic 	int n, on, flags, newblock;
27345722Smckusick 	int size, resid, error = 0;
27439608Smckusick 
27551852Sbostic #ifdef VERBOSE
27651852Sbostic 	printf("lfs_write ino %d\n", ip->i_number);
27751852Sbostic #endif
27848039Smckusick #ifdef DIAGNOSTIC
27939608Smckusick 	if (uio->uio_rw != UIO_WRITE)
28052091Sbostic 		panic("lfs_write mode");
28148039Smckusick #endif
28239608Smckusick 	switch (vp->v_type) {
28339608Smckusick 	case VREG:
28439608Smckusick 		if (ioflag & IO_APPEND)
28539608Smckusick 			uio->uio_offset = ip->i_size;
28639608Smckusick 		/* fall through */
28739608Smckusick 	case VLNK:
28839608Smckusick 		break;
28939608Smckusick 
29039608Smckusick 	case VDIR:
29152091Sbostic 		/* XXX This may not be correct for LFS. */
29239608Smckusick 		if ((ioflag & IO_SYNC) == 0)
29352091Sbostic 			panic("lfs_write nonsync dir write");
29439608Smckusick 		break;
29539608Smckusick 
29639608Smckusick 	default:
29752091Sbostic 		panic("lfs_write type");
29839608Smckusick 	}
29939608Smckusick 	if (uio->uio_offset < 0)
30039608Smckusick 		return (EINVAL);
30139608Smckusick 	if (uio->uio_resid == 0)
30239608Smckusick 		return (0);
30339608Smckusick 	/*
30439608Smckusick 	 * Maybe this should be above the vnode op call, but so long as
30539608Smckusick 	 * file servers have no limits, i don't think it matters
30639608Smckusick 	 */
30749679Smckusick 	if (vp->v_type == VREG && p &&
30839608Smckusick 	    uio->uio_offset + uio->uio_resid >
30947571Skarels 	      p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
31047571Skarels 		psignal(p, SIGXFSZ);
31139608Smckusick 		return (EFBIG);
31239608Smckusick 	}
31339608Smckusick 	resid = uio->uio_resid;
31439608Smckusick 	osize = ip->i_size;
31551183Sbostic 	fs = ip->i_lfs;						/* LFS */
31639674Smckusick 	flags = 0;
31751183Sbostic #ifdef NOTLFS
31839674Smckusick 	if (ioflag & IO_SYNC)
31939674Smckusick 		flags = B_SYNC;
32051183Sbostic #endif
32139608Smckusick 	do {
32239608Smckusick 		lbn = lblkno(fs, uio->uio_offset);
32351932Sbostic 		on = blkoff(fs, uio->uio_offset);
32451183Sbostic 		n = MIN((unsigned)(fs->lfs_bsize - on), uio->uio_resid);
32552091Sbostic 		if (error = lfs_balloc(vp, n, lbn, &bp))
32639608Smckusick 			break;
32745722Smckusick 		if (uio->uio_offset + n > ip->i_size) {
32839608Smckusick 			ip->i_size = uio->uio_offset + n;
32952019Smckusick 			vnode_pager_setsize(vp, (u_long)ip->i_size);
33045722Smckusick 		}
33151183Sbostic 		size = blksize(fs);
33245722Smckusick 		(void) vnode_pager_uncache(vp);
33339608Smckusick 		n = MIN(n, size - bp->b_resid);
33439608Smckusick 		error = uiomove(bp->b_un.b_addr + on, n, uio);
33551183Sbostic #ifdef NOTLFS							/* LFS */
33639608Smckusick 		if (ioflag & IO_SYNC)
33739608Smckusick 			(void) bwrite(bp);
33839608Smckusick 		else if (n + on == fs->fs_bsize) {
33939608Smckusick 			bp->b_flags |= B_AGE;
34039608Smckusick 			bawrite(bp);
34139608Smckusick 		} else
34239608Smckusick 			bdwrite(bp);
34352091Sbostic 		ip->i_flag |= IUPD|ICHG;
34451183Sbostic #else
34552091Sbostic 		/* XXX This doesn't handle IO_SYNC. */
34652091Sbostic 		LFS_UBWRITE(bp);
34751183Sbostic #endif
34839608Smckusick 		if (cred->cr_uid != 0)
34939608Smckusick 			ip->i_mode &= ~(ISUID|ISGID);
35039608Smckusick 	} while (error == 0 && uio->uio_resid > 0 && n != 0);
35139608Smckusick 	if (error && (ioflag & IO_UNIT)) {
352*53533Sheideman 		(void)VOP_TRUNCATE(vp, osize, ioflag & IO_SYNC, cred);
35339608Smckusick 		uio->uio_offset -= resid - uio->uio_resid;
35439608Smckusick 		uio->uio_resid = resid;
35539608Smckusick 	}
35642493Smckusick 	if (!error && (ioflag & IO_SYNC))
357*53533Sheideman 		error = VOP_UPDATE(vp, &time, &time, 1);
35839608Smckusick 	return (error);
35939608Smckusick }
360*53533Sheideman #undef vp
361*53533Sheideman #undef uio
362*53533Sheideman #undef ioflag
363*53533Sheideman #undef cred
36439608Smckusick 
3659167Ssam /*
36637737Smckusick  * Synch an open file.
3679167Ssam  */
36837737Smckusick /* ARGSUSED */
369*53533Sheideman lfs_fsync (ap)
370*53533Sheideman 	struct vop_fsync_args *ap;
371*53533Sheideman #define vp (ap->a_vp)
372*53533Sheideman #define fflags (ap->a_fflags)
373*53533Sheideman #define cred (ap->a_cred)
374*53533Sheideman #define waitfor (ap->a_waitfor)
375*53533Sheideman #define p (ap->a_p)
3767701Ssam {
377*53533Sheideman 	USES_VOP_UPDATE;
37851852Sbostic 	struct inode *ip;
3797701Ssam 
38051852Sbostic #ifdef VERBOSE
38151852Sbostic 	printf("lfs_fsync\n");
38251852Sbostic #endif
38351852Sbostic 	ip = VTOI(vp);
38448039Smckusick 	if (fflags & FWRITE)
38537737Smckusick 		ip->i_flag |= ICHG;
386*53533Sheideman 	return (VOP_UPDATE(vp, &time, &time, waitfor == MNT_WAIT));
38737737Smckusick }
388*53533Sheideman #undef vp
389*53533Sheideman #undef fflags
390*53533Sheideman #undef cred
391*53533Sheideman #undef waitfor
392*53533Sheideman #undef p
39351558Smckusick 
39451558Smckusick /*
39551558Smckusick  * Last reference to an inode, write the inode out and if necessary,
39651558Smckusick  * truncate and deallocate the file.
39751558Smckusick  */
39851558Smckusick int
399*53533Sheideman lfs_inactive (ap)
400*53533Sheideman 	struct vop_inactive_args *ap;
401*53533Sheideman #define vp (ap->a_vp)
402*53533Sheideman #define p (ap->a_p)
40351558Smckusick {
404*53533Sheideman 	USES_VOP_TRUNCATE;
405*53533Sheideman 	USES_VOP_UPDATE;
406*53533Sheideman 	USES_VOP_VFREE;
40751852Sbostic 	extern int prtactive;
40851558Smckusick 	register struct inode *ip;
40951558Smckusick 	int mode, error;
41051558Smckusick 
41151852Sbostic #ifdef VERBOSE
41251852Sbostic 	printf("lfs_inactive\n");
41351852Sbostic #endif
41451558Smckusick 	if (prtactive && vp->v_usecount != 0)
41551558Smckusick 		vprint("lfs_inactive: pushing active", vp);
41651558Smckusick 
41751558Smckusick 	/* Get rid of inodes related to stale file handles. */
41851558Smckusick 	ip = VTOI(vp);
41951558Smckusick 	if (ip->i_mode == 0) {
42051558Smckusick 		if ((vp->v_flag & VXLOCK) == 0)
42151558Smckusick 			vgone(vp);
42251558Smckusick 		return (0);
42351558Smckusick 	}
42451558Smckusick 
42551558Smckusick 	error = 0;
42651558Smckusick 	ILOCK(ip);
42751558Smckusick 	if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
42851558Smckusick #ifdef QUOTA
42951558Smckusick 		if (!getinoquota(ip))
43051558Smckusick 			(void)chkiq(ip, -1, NOCRED, 0);
43151558Smckusick #endif
432*53533Sheideman 		error = VOP_TRUNCATE(vp, (off_t)0, 0, NOCRED);
43351558Smckusick 		mode = ip->i_mode;
43451558Smckusick 		ip->i_mode = 0;
43551558Smckusick 		ip->i_rdev = 0;
43651558Smckusick 		ip->i_flag |= IUPD|ICHG;
437*53533Sheideman 		VOP_VFREE(vp, ip->i_number, mode);
43851558Smckusick 	}
43951558Smckusick 	if (ip->i_flag&(IUPD|IACC|ICHG|IMOD))
440*53533Sheideman 		VOP_UPDATE(vp, &time, &time, 0);
44151558Smckusick 	IUNLOCK(ip);
44251558Smckusick 	ip->i_flag = 0;
44351558Smckusick 	/*
44451558Smckusick 	 * If we are done with the inode, reclaim it
44551558Smckusick 	 * so that it can be reused immediately.
44651558Smckusick 	 */
44751558Smckusick 	if (vp->v_usecount == 0 && ip->i_mode == 0)
44851558Smckusick 		vgone(vp);
44951558Smckusick 	return (error);
45051558Smckusick }
451*53533Sheideman #undef vp
452*53533Sheideman #undef p
453