xref: /original-bsd/sys/ufs/ffs/ffs_vnops.c (revision f8846554)
13ad81ce0Smckusick /*
22b768bd7Sbostic  * Copyright (c) 1982, 1986, 1989, 1993
32b768bd7Sbostic  *	The Regents of the University of California.  All rights reserved.
43ad81ce0Smckusick  *
58eb14236Sbostic  * %sccs.include.redist.c%
6065083aeSmckusick  *
7*f8846554Smckusick  *	@(#)ffs_vnops.c	8.15 (Berkeley) 05/14/95
83ad81ce0Smckusick  */
9ff129ffdSmckusic 
105b516ec6Sbostic #include <sys/param.h>
115b516ec6Sbostic #include <sys/systm.h>
125b516ec6Sbostic #include <sys/resourcevar.h>
135b516ec6Sbostic #include <sys/kernel.h>
145b516ec6Sbostic #include <sys/file.h>
155b516ec6Sbostic #include <sys/stat.h>
165b516ec6Sbostic #include <sys/buf.h>
175b516ec6Sbostic #include <sys/proc.h>
185b516ec6Sbostic #include <sys/conf.h>
195b516ec6Sbostic #include <sys/mount.h>
205b516ec6Sbostic #include <sys/vnode.h>
215b516ec6Sbostic #include <sys/malloc.h>
2226a59bf8Skarels 
23a0fa47aeSmckusick #include <vm/vm.h>
24a0fa47aeSmckusick 
25b489f476Smckusick #include <miscfs/specfs/specdev.h>
26b489f476Smckusick #include <miscfs/fifofs/fifo.h>
27b489f476Smckusick 
285b516ec6Sbostic #include <ufs/ufs/lockf.h>
295b516ec6Sbostic #include <ufs/ufs/quota.h>
305b516ec6Sbostic #include <ufs/ufs/inode.h>
315b516ec6Sbostic #include <ufs/ufs/dir.h>
32e08bd631Smckusick #include <ufs/ufs/ufsmount.h>
335b516ec6Sbostic #include <ufs/ufs/ufs_extern.h>
344476fdfbSroot 
355b516ec6Sbostic #include <ufs/ffs/fs.h>
365b516ec6Sbostic #include <ufs/ffs/ffs_extern.h>
37065083aeSmckusick 
385b516ec6Sbostic /* Global vfs data structures for ufs. */
394c2ecc49Sheideman int (**ffs_vnodeop_p)();
404c2ecc49Sheideman struct vnodeopv_entry_desc ffs_vnodeop_entries[] = {
414c2ecc49Sheideman 	{ &vop_default_desc, vn_default_error },
424c2ecc49Sheideman 	{ &vop_lookup_desc, ufs_lookup },		/* lookup */
434c2ecc49Sheideman 	{ &vop_create_desc, ufs_create },		/* create */
444ba124f7Spendry 	{ &vop_whiteout_desc, ufs_whiteout },		/* whiteout */
454c2ecc49Sheideman 	{ &vop_mknod_desc, ufs_mknod },			/* mknod */
464c2ecc49Sheideman 	{ &vop_open_desc, ufs_open },			/* open */
474c2ecc49Sheideman 	{ &vop_close_desc, ufs_close },			/* close */
484c2ecc49Sheideman 	{ &vop_access_desc, ufs_access },		/* access */
494c2ecc49Sheideman 	{ &vop_getattr_desc, ufs_getattr },		/* getattr */
504c2ecc49Sheideman 	{ &vop_setattr_desc, ufs_setattr },		/* setattr */
514c2ecc49Sheideman 	{ &vop_read_desc, ffs_read },			/* read */
524c2ecc49Sheideman 	{ &vop_write_desc, ffs_write },			/* write */
53e2e07ecbSmckusick 	{ &vop_lease_desc, ufs_lease_check },		/* lease */
544c2ecc49Sheideman 	{ &vop_ioctl_desc, ufs_ioctl },			/* ioctl */
554c2ecc49Sheideman 	{ &vop_select_desc, ufs_select },		/* select */
5635e970ecSmckusick 	{ &vop_revoke_desc, ufs_revoke },		/* revoke */
574c2ecc49Sheideman 	{ &vop_mmap_desc, ufs_mmap },			/* mmap */
584c2ecc49Sheideman 	{ &vop_fsync_desc, ffs_fsync },			/* fsync */
594c2ecc49Sheideman 	{ &vop_seek_desc, ufs_seek },			/* seek */
604c2ecc49Sheideman 	{ &vop_remove_desc, ufs_remove },		/* remove */
614c2ecc49Sheideman 	{ &vop_link_desc, ufs_link },			/* link */
624c2ecc49Sheideman 	{ &vop_rename_desc, ufs_rename },		/* rename */
634c2ecc49Sheideman 	{ &vop_mkdir_desc, ufs_mkdir },			/* mkdir */
644c2ecc49Sheideman 	{ &vop_rmdir_desc, ufs_rmdir },			/* rmdir */
654c2ecc49Sheideman 	{ &vop_symlink_desc, ufs_symlink },		/* symlink */
664c2ecc49Sheideman 	{ &vop_readdir_desc, ufs_readdir },		/* readdir */
674c2ecc49Sheideman 	{ &vop_readlink_desc, ufs_readlink },		/* readlink */
684c2ecc49Sheideman 	{ &vop_abortop_desc, ufs_abortop },		/* abortop */
690b614b73Smckusick 	{ &vop_inactive_desc, ufs_inactive },		/* inactive */
70abf9880aSmckusick 	{ &vop_reclaim_desc, ffs_reclaim },		/* reclaim */
714c2ecc49Sheideman 	{ &vop_lock_desc, ufs_lock },			/* lock */
724c2ecc49Sheideman 	{ &vop_unlock_desc, ufs_unlock },		/* unlock */
73cd3cfc28Smargo 	{ &vop_bmap_desc, ufs_bmap },			/* bmap */
744c2ecc49Sheideman 	{ &vop_strategy_desc, ufs_strategy },		/* strategy */
754c2ecc49Sheideman 	{ &vop_print_desc, ufs_print },			/* print */
764c2ecc49Sheideman 	{ &vop_islocked_desc, ufs_islocked },		/* islocked */
77f38482b1Smckusick 	{ &vop_pathconf_desc, ufs_pathconf },		/* pathconf */
784c2ecc49Sheideman 	{ &vop_advlock_desc, ufs_advlock },		/* advlock */
794c2ecc49Sheideman 	{ &vop_blkatoff_desc, ffs_blkatoff },		/* blkatoff */
804c2ecc49Sheideman 	{ &vop_valloc_desc, ffs_valloc },		/* valloc */
819ba9fa2aSmckusick 	{ &vop_reallocblks_desc, ffs_reallocblks },	/* reallocblks */
824c2ecc49Sheideman 	{ &vop_vfree_desc, ffs_vfree },			/* vfree */
834c2ecc49Sheideman 	{ &vop_truncate_desc, ffs_truncate },		/* truncate */
844c2ecc49Sheideman 	{ &vop_update_desc, ffs_update },		/* update */
853abd5335Sheideman 	{ &vop_bwrite_desc, vn_bwrite },
864c2ecc49Sheideman 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
875b516ec6Sbostic };
884c2ecc49Sheideman struct vnodeopv_desc ffs_vnodeop_opv_desc =
894c2ecc49Sheideman 	{ &ffs_vnodeop_p, ffs_vnodeop_entries };
904476fdfbSroot 
914c2ecc49Sheideman int (**ffs_specop_p)();
924c2ecc49Sheideman struct vnodeopv_entry_desc ffs_specop_entries[] = {
934c2ecc49Sheideman 	{ &vop_default_desc, vn_default_error },
944c2ecc49Sheideman 	{ &vop_lookup_desc, spec_lookup },		/* lookup */
954c2ecc49Sheideman 	{ &vop_create_desc, spec_create },		/* create */
964c2ecc49Sheideman 	{ &vop_mknod_desc, spec_mknod },		/* mknod */
974c2ecc49Sheideman 	{ &vop_open_desc, spec_open },			/* open */
984c2ecc49Sheideman 	{ &vop_close_desc, ufsspec_close },		/* close */
994c2ecc49Sheideman 	{ &vop_access_desc, ufs_access },		/* access */
1004c2ecc49Sheideman 	{ &vop_getattr_desc, ufs_getattr },		/* getattr */
1014c2ecc49Sheideman 	{ &vop_setattr_desc, ufs_setattr },		/* setattr */
1024c2ecc49Sheideman 	{ &vop_read_desc, ufsspec_read },		/* read */
1034c2ecc49Sheideman 	{ &vop_write_desc, ufsspec_write },		/* write */
104e2e07ecbSmckusick 	{ &vop_lease_desc, spec_lease_check },		/* lease */
1054c2ecc49Sheideman 	{ &vop_ioctl_desc, spec_ioctl },		/* ioctl */
1064c2ecc49Sheideman 	{ &vop_select_desc, spec_select },		/* select */
10735e970ecSmckusick 	{ &vop_revoke_desc, spec_revoke },		/* revoke */
1084c2ecc49Sheideman 	{ &vop_mmap_desc, spec_mmap },			/* mmap */
1099899e5a2Smckusick 	{ &vop_fsync_desc, ffs_fsync },			/* fsync */
1104c2ecc49Sheideman 	{ &vop_seek_desc, spec_seek },			/* seek */
1114c2ecc49Sheideman 	{ &vop_remove_desc, spec_remove },		/* remove */
1124c2ecc49Sheideman 	{ &vop_link_desc, spec_link },			/* link */
1134c2ecc49Sheideman 	{ &vop_rename_desc, spec_rename },		/* rename */
1144c2ecc49Sheideman 	{ &vop_mkdir_desc, spec_mkdir },		/* mkdir */
1154c2ecc49Sheideman 	{ &vop_rmdir_desc, spec_rmdir },		/* rmdir */
1164c2ecc49Sheideman 	{ &vop_symlink_desc, spec_symlink },		/* symlink */
1174c2ecc49Sheideman 	{ &vop_readdir_desc, spec_readdir },		/* readdir */
1184c2ecc49Sheideman 	{ &vop_readlink_desc, spec_readlink },		/* readlink */
1194c2ecc49Sheideman 	{ &vop_abortop_desc, spec_abortop },		/* abortop */
1200b614b73Smckusick 	{ &vop_inactive_desc, ufs_inactive },		/* inactive */
121abf9880aSmckusick 	{ &vop_reclaim_desc, ffs_reclaim },		/* reclaim */
1224c2ecc49Sheideman 	{ &vop_lock_desc, ufs_lock },			/* lock */
1234c2ecc49Sheideman 	{ &vop_unlock_desc, ufs_unlock },		/* unlock */
1244c2ecc49Sheideman 	{ &vop_bmap_desc, spec_bmap },			/* bmap */
1254c2ecc49Sheideman 	{ &vop_strategy_desc, spec_strategy },		/* strategy */
1264c2ecc49Sheideman 	{ &vop_print_desc, ufs_print },			/* print */
1274c2ecc49Sheideman 	{ &vop_islocked_desc, ufs_islocked },		/* islocked */
128f38482b1Smckusick 	{ &vop_pathconf_desc, spec_pathconf },		/* pathconf */
1294c2ecc49Sheideman 	{ &vop_advlock_desc, spec_advlock },		/* advlock */
1304c2ecc49Sheideman 	{ &vop_blkatoff_desc, spec_blkatoff },		/* blkatoff */
1314c2ecc49Sheideman 	{ &vop_valloc_desc, spec_valloc },		/* valloc */
1329ba9fa2aSmckusick 	{ &vop_reallocblks_desc, spec_reallocblks },	/* reallocblks */
1334fc932a0Smckusick 	{ &vop_vfree_desc, ffs_vfree },			/* vfree */
1344c2ecc49Sheideman 	{ &vop_truncate_desc, spec_truncate },		/* truncate */
1354c2ecc49Sheideman 	{ &vop_update_desc, ffs_update },		/* update */
1363abd5335Sheideman 	{ &vop_bwrite_desc, vn_bwrite },
1374c2ecc49Sheideman 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
138103644d0Smckusick };
1394c2ecc49Sheideman struct vnodeopv_desc ffs_specop_opv_desc =
1404c2ecc49Sheideman 	{ &ffs_specop_p, ffs_specop_entries };
141103644d0Smckusick 
142103644d0Smckusick #ifdef FIFO
1434c2ecc49Sheideman int (**ffs_fifoop_p)();
1444c2ecc49Sheideman struct vnodeopv_entry_desc ffs_fifoop_entries[] = {
1454c2ecc49Sheideman 	{ &vop_default_desc, vn_default_error },
1464c2ecc49Sheideman 	{ &vop_lookup_desc, fifo_lookup },		/* lookup */
1474c2ecc49Sheideman 	{ &vop_create_desc, fifo_create },		/* create */
1484c2ecc49Sheideman 	{ &vop_mknod_desc, fifo_mknod },		/* mknod */
1494c2ecc49Sheideman 	{ &vop_open_desc, fifo_open },			/* open */
1504c2ecc49Sheideman 	{ &vop_close_desc, ufsfifo_close },		/* close */
1514c2ecc49Sheideman 	{ &vop_access_desc, ufs_access },		/* access */
1524c2ecc49Sheideman 	{ &vop_getattr_desc, ufs_getattr },		/* getattr */
1534c2ecc49Sheideman 	{ &vop_setattr_desc, ufs_setattr },		/* setattr */
1544c2ecc49Sheideman 	{ &vop_read_desc, ufsfifo_read },		/* read */
1554c2ecc49Sheideman 	{ &vop_write_desc, ufsfifo_write },		/* write */
156e2e07ecbSmckusick 	{ &vop_lease_desc, fifo_lease_check },		/* lease */
1574c2ecc49Sheideman 	{ &vop_ioctl_desc, fifo_ioctl },		/* ioctl */
1584c2ecc49Sheideman 	{ &vop_select_desc, fifo_select },		/* select */
15935e970ecSmckusick 	{ &vop_revoke_desc, fifo_revoke },		/* revoke */
1604c2ecc49Sheideman 	{ &vop_mmap_desc, fifo_mmap },			/* mmap */
1619899e5a2Smckusick 	{ &vop_fsync_desc, ffs_fsync },			/* fsync */
1624c2ecc49Sheideman 	{ &vop_seek_desc, fifo_seek },			/* seek */
1634c2ecc49Sheideman 	{ &vop_remove_desc, fifo_remove },		/* remove */
1644c2ecc49Sheideman 	{ &vop_link_desc, fifo_link },			/* link */
1654c2ecc49Sheideman 	{ &vop_rename_desc, fifo_rename },		/* rename */
1664c2ecc49Sheideman 	{ &vop_mkdir_desc, fifo_mkdir },		/* mkdir */
1674c2ecc49Sheideman 	{ &vop_rmdir_desc, fifo_rmdir },		/* rmdir */
1684c2ecc49Sheideman 	{ &vop_symlink_desc, fifo_symlink },		/* symlink */
1694c2ecc49Sheideman 	{ &vop_readdir_desc, fifo_readdir },		/* readdir */
1704c2ecc49Sheideman 	{ &vop_readlink_desc, fifo_readlink },		/* readlink */
1714c2ecc49Sheideman 	{ &vop_abortop_desc, fifo_abortop },		/* abortop */
1720b614b73Smckusick 	{ &vop_inactive_desc, ufs_inactive },		/* inactive */
173abf9880aSmckusick 	{ &vop_reclaim_desc, ffs_reclaim },		/* reclaim */
1744c2ecc49Sheideman 	{ &vop_lock_desc, ufs_lock },			/* lock */
1754c2ecc49Sheideman 	{ &vop_unlock_desc, ufs_unlock },		/* unlock */
1764c2ecc49Sheideman 	{ &vop_bmap_desc, fifo_bmap },			/* bmap */
1774c2ecc49Sheideman 	{ &vop_strategy_desc, fifo_strategy },		/* strategy */
1784c2ecc49Sheideman 	{ &vop_print_desc, ufs_print },			/* print */
1794c2ecc49Sheideman 	{ &vop_islocked_desc, ufs_islocked },		/* islocked */
180f38482b1Smckusick 	{ &vop_pathconf_desc, fifo_pathconf },		/* pathconf */
1814c2ecc49Sheideman 	{ &vop_advlock_desc, fifo_advlock },		/* advlock */
1824c2ecc49Sheideman 	{ &vop_blkatoff_desc, fifo_blkatoff },		/* blkatoff */
1834c2ecc49Sheideman 	{ &vop_valloc_desc, fifo_valloc },		/* valloc */
1849ba9fa2aSmckusick 	{ &vop_reallocblks_desc, fifo_reallocblks },	/* reallocblks */
1854fc932a0Smckusick 	{ &vop_vfree_desc, ffs_vfree },			/* vfree */
1864c2ecc49Sheideman 	{ &vop_truncate_desc, fifo_truncate },		/* truncate */
1874c2ecc49Sheideman 	{ &vop_update_desc, ffs_update },		/* update */
1883abd5335Sheideman 	{ &vop_bwrite_desc, vn_bwrite },
1894c2ecc49Sheideman 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
190103644d0Smckusick };
1914c2ecc49Sheideman struct vnodeopv_desc ffs_fifoop_opv_desc =
1924c2ecc49Sheideman 	{ &ffs_fifoop_p, ffs_fifoop_entries };
193103644d0Smckusick #endif /* FIFO */
194103644d0Smckusick 
1959a45e376Smckusick /*
1969a45e376Smckusick  * Enabling cluster read/write operations.
1979a45e376Smckusick  */
198ed20614cSmckusick int doclusterread = 1;
199ed20614cSmckusick int doclusterwrite = 1;
2004476fdfbSroot 
2010549e7feSmckusick #include <ufs/ufs/ufs_readwrite.c>
202d982b431Smckusick 
2030c465d6dSsam /*
2040c465d6dSsam  * Synch an open file.
2050c465d6dSsam  */
206065083aeSmckusick /* ARGSUSED */
2075b516ec6Sbostic int
ffs_fsync(ap)2084c2ecc49Sheideman ffs_fsync(ap)
2099899e5a2Smckusick 	struct vop_fsync_args /* {
2109899e5a2Smckusick 		struct vnode *a_vp;
2119899e5a2Smckusick 		struct ucred *a_cred;
2129899e5a2Smckusick 		int a_waitfor;
2139899e5a2Smckusick 		struct proc *a_p;
2149899e5a2Smckusick 	} */ *ap;
2150c465d6dSsam {
2169899e5a2Smckusick 	register struct vnode *vp = ap->a_vp;
2179899e5a2Smckusick 	register struct buf *bp;
218100a94d5Smckusick 	struct timeval tv;
2199899e5a2Smckusick 	struct buf *nbp;
2209899e5a2Smckusick 	int s;
2210c465d6dSsam 
2229899e5a2Smckusick 	/*
2239899e5a2Smckusick 	 * Flush all dirty buffers associated with a vnode.
2249899e5a2Smckusick 	 */
2259899e5a2Smckusick loop:
2269899e5a2Smckusick 	s = splbio();
2277d2dba8aSmckusick 	for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
2287d2dba8aSmckusick 		nbp = bp->b_vnbufs.le_next;
2299899e5a2Smckusick 		if ((bp->b_flags & B_BUSY))
2309899e5a2Smckusick 			continue;
2319899e5a2Smckusick 		if ((bp->b_flags & B_DELWRI) == 0)
2329899e5a2Smckusick 			panic("ffs_fsync: not dirty");
2339899e5a2Smckusick 		bremfree(bp);
2349899e5a2Smckusick 		bp->b_flags |= B_BUSY;
2359899e5a2Smckusick 		splx(s);
2369899e5a2Smckusick 		/*
2379899e5a2Smckusick 		 * Wait for I/O associated with indirect blocks to complete,
2389899e5a2Smckusick 		 * since there is no way to quickly wait for them below.
2399899e5a2Smckusick 		 */
2409899e5a2Smckusick 		if (bp->b_vp == vp || ap->a_waitfor == MNT_NOWAIT)
2419899e5a2Smckusick 			(void) bawrite(bp);
2429899e5a2Smckusick 		else
2439899e5a2Smckusick 			(void) bwrite(bp);
2449899e5a2Smckusick 		goto loop;
2459899e5a2Smckusick 	}
2469899e5a2Smckusick 	if (ap->a_waitfor == MNT_WAIT) {
2479899e5a2Smckusick 		while (vp->v_numoutput) {
2489899e5a2Smckusick 			vp->v_flag |= VBWAIT;
2499899e5a2Smckusick 			sleep((caddr_t)&vp->v_numoutput, PRIBIO + 1);
2509899e5a2Smckusick 		}
2519899e5a2Smckusick #ifdef DIAGNOSTIC
2527d2dba8aSmckusick 		if (vp->v_dirtyblkhd.lh_first) {
2539899e5a2Smckusick 			vprint("ffs_fsync: dirty", vp);
2549899e5a2Smckusick 			goto loop;
2559899e5a2Smckusick 		}
2569899e5a2Smckusick #endif
2579899e5a2Smckusick 	}
2589899e5a2Smckusick 	splx(s);
259100a94d5Smckusick 	tv = time;
26073bac521Sbostic 	return (VOP_UPDATE(ap->a_vp, &tv, &tv, ap->a_waitfor == MNT_WAIT));
26173bac521Sbostic }
262abf9880aSmckusick 
263abf9880aSmckusick /*
264abf9880aSmckusick  * Reclaim an inode so that it can be used for other purposes.
265abf9880aSmckusick  */
266abf9880aSmckusick int
ffs_reclaim(ap)267abf9880aSmckusick ffs_reclaim(ap)
268abf9880aSmckusick 	struct vop_reclaim_args /* {
269abf9880aSmckusick 		struct vnode *a_vp;
270*f8846554Smckusick 		struct proc *a_p;
271abf9880aSmckusick 	} */ *ap;
272abf9880aSmckusick {
273abf9880aSmckusick 	register struct vnode *vp = ap->a_vp;
274abf9880aSmckusick 	int error;
275abf9880aSmckusick 
276*f8846554Smckusick 	if (error = ufs_reclaim(vp, ap->a_p))
277abf9880aSmckusick 		return (error);
2787624df1cSmckusick 	FREE(vp->v_data, VFSTOUFS(vp->v_mount)->um_devvp->v_tag == VT_MFS ?
2797624df1cSmckusick 	    M_MFSNODE : M_FFSNODE);
280abf9880aSmckusick 	vp->v_data = NULL;
281abf9880aSmckusick 	return (0);
282abf9880aSmckusick }
283