xref: /csrg-svn/sys/ufs/ffs/ffs_vnops.c (revision 69416)
123405Smckusick /*
263371Sbostic  * Copyright (c) 1982, 1986, 1989, 1993
363371Sbostic  *	The Regents of the University of California.  All rights reserved.
423405Smckusick  *
544539Sbostic  * %sccs.include.redist.c%
637737Smckusick  *
7*69416Smckusick  *	@(#)ffs_vnops.c	8.15 (Berkeley) 05/14/95
823405Smckusick  */
937Sbill 
1051474Sbostic #include <sys/param.h>
1151474Sbostic #include <sys/systm.h>
1251474Sbostic #include <sys/resourcevar.h>
1351474Sbostic #include <sys/kernel.h>
1451474Sbostic #include <sys/file.h>
1551474Sbostic #include <sys/stat.h>
1651474Sbostic #include <sys/buf.h>
1751474Sbostic #include <sys/proc.h>
1851474Sbostic #include <sys/conf.h>
1951474Sbostic #include <sys/mount.h>
2051474Sbostic #include <sys/vnode.h>
2151474Sbostic #include <sys/malloc.h>
2237Sbill 
2353319Smckusick #include <vm/vm.h>
2453319Smckusick 
2555032Smckusick #include <miscfs/specfs/specdev.h>
2655032Smckusick #include <miscfs/fifofs/fifo.h>
2755032Smckusick 
2851474Sbostic #include <ufs/ufs/lockf.h>
2951474Sbostic #include <ufs/ufs/quota.h>
3051474Sbostic #include <ufs/ufs/inode.h>
3151474Sbostic #include <ufs/ufs/dir.h>
3268131Smckusick #include <ufs/ufs/ufsmount.h>
3351474Sbostic #include <ufs/ufs/ufs_extern.h>
3447571Skarels 
3551474Sbostic #include <ufs/ffs/fs.h>
3651474Sbostic #include <ufs/ffs/ffs_extern.h>
376254Sroot 
3851474Sbostic /* Global vfs data structures for ufs. */
3953523Sheideman int (**ffs_vnodeop_p)();
4053523Sheideman struct vnodeopv_entry_desc ffs_vnodeop_entries[] = {
4153523Sheideman 	{ &vop_default_desc, vn_default_error },
4253523Sheideman 	{ &vop_lookup_desc, ufs_lookup },		/* lookup */
4353523Sheideman 	{ &vop_create_desc, ufs_create },		/* create */
4467575Spendry 	{ &vop_whiteout_desc, ufs_whiteout },		/* whiteout */
4554014Sheideman 	{ &vop_mknod_desc, ufs_mknod },			/* mknod */
4654014Sheideman 	{ &vop_open_desc, ufs_open },			/* open */
4754014Sheideman 	{ &vop_close_desc, ufs_close },			/* close */
4853523Sheideman 	{ &vop_access_desc, ufs_access },		/* access */
4953523Sheideman 	{ &vop_getattr_desc, ufs_getattr },		/* getattr */
5053523Sheideman 	{ &vop_setattr_desc, ufs_setattr },		/* setattr */
5154014Sheideman 	{ &vop_read_desc, ffs_read },			/* read */
5254014Sheideman 	{ &vop_write_desc, ffs_write },			/* write */
5367642Smckusick 	{ &vop_lease_desc, ufs_lease_check },		/* lease */
5454014Sheideman 	{ &vop_ioctl_desc, ufs_ioctl },			/* ioctl */
5553523Sheideman 	{ &vop_select_desc, ufs_select },		/* select */
5668419Smckusick 	{ &vop_revoke_desc, ufs_revoke },		/* revoke */
5754014Sheideman 	{ &vop_mmap_desc, ufs_mmap },			/* mmap */
5854014Sheideman 	{ &vop_fsync_desc, ffs_fsync },			/* fsync */
5954014Sheideman 	{ &vop_seek_desc, ufs_seek },			/* seek */
6053523Sheideman 	{ &vop_remove_desc, ufs_remove },		/* remove */
6154014Sheideman 	{ &vop_link_desc, ufs_link },			/* link */
6253523Sheideman 	{ &vop_rename_desc, ufs_rename },		/* rename */
6354014Sheideman 	{ &vop_mkdir_desc, ufs_mkdir },			/* mkdir */
6454014Sheideman 	{ &vop_rmdir_desc, ufs_rmdir },			/* rmdir */
6553523Sheideman 	{ &vop_symlink_desc, ufs_symlink },		/* symlink */
6653523Sheideman 	{ &vop_readdir_desc, ufs_readdir },		/* readdir */
6753523Sheideman 	{ &vop_readlink_desc, ufs_readlink },		/* readlink */
6853523Sheideman 	{ &vop_abortop_desc, ufs_abortop },		/* abortop */
6956745Smckusick 	{ &vop_inactive_desc, ufs_inactive },		/* inactive */
7067409Smckusick 	{ &vop_reclaim_desc, ffs_reclaim },		/* reclaim */
7154014Sheideman 	{ &vop_lock_desc, ufs_lock },			/* lock */
7253523Sheideman 	{ &vop_unlock_desc, ufs_unlock },		/* unlock */
7356447Smargo 	{ &vop_bmap_desc, ufs_bmap },			/* bmap */
7453523Sheideman 	{ &vop_strategy_desc, ufs_strategy },		/* strategy */
7554014Sheideman 	{ &vop_print_desc, ufs_print },			/* print */
7653523Sheideman 	{ &vop_islocked_desc, ufs_islocked },		/* islocked */
7760396Smckusick 	{ &vop_pathconf_desc, ufs_pathconf },		/* pathconf */
7853523Sheideman 	{ &vop_advlock_desc, ufs_advlock },		/* advlock */
7953523Sheideman 	{ &vop_blkatoff_desc, ffs_blkatoff },		/* blkatoff */
8053523Sheideman 	{ &vop_valloc_desc, ffs_valloc },		/* valloc */
8165977Smckusick 	{ &vop_reallocblks_desc, ffs_reallocblks },	/* reallocblks */
8254014Sheideman 	{ &vop_vfree_desc, ffs_vfree },			/* vfree */
8353523Sheideman 	{ &vop_truncate_desc, ffs_truncate },		/* truncate */
8453523Sheideman 	{ &vop_update_desc, ffs_update },		/* update */
8553575Sheideman 	{ &vop_bwrite_desc, vn_bwrite },
8653523Sheideman 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
8751474Sbostic };
8853523Sheideman struct vnodeopv_desc ffs_vnodeop_opv_desc =
8953523Sheideman 	{ &ffs_vnodeop_p, ffs_vnodeop_entries };
906254Sroot 
9153523Sheideman int (**ffs_specop_p)();
9253523Sheideman struct vnodeopv_entry_desc ffs_specop_entries[] = {
9353523Sheideman 	{ &vop_default_desc, vn_default_error },
9453523Sheideman 	{ &vop_lookup_desc, spec_lookup },		/* lookup */
9553523Sheideman 	{ &vop_create_desc, spec_create },		/* create */
9653523Sheideman 	{ &vop_mknod_desc, spec_mknod },		/* mknod */
9754014Sheideman 	{ &vop_open_desc, spec_open },			/* open */
9853523Sheideman 	{ &vop_close_desc, ufsspec_close },		/* close */
9953523Sheideman 	{ &vop_access_desc, ufs_access },		/* access */
10053523Sheideman 	{ &vop_getattr_desc, ufs_getattr },		/* getattr */
10153523Sheideman 	{ &vop_setattr_desc, ufs_setattr },		/* setattr */
10253523Sheideman 	{ &vop_read_desc, ufsspec_read },		/* read */
10353523Sheideman 	{ &vop_write_desc, ufsspec_write },		/* write */
10467642Smckusick 	{ &vop_lease_desc, spec_lease_check },		/* lease */
10553523Sheideman 	{ &vop_ioctl_desc, spec_ioctl },		/* ioctl */
10653523Sheideman 	{ &vop_select_desc, spec_select },		/* select */
10768419Smckusick 	{ &vop_revoke_desc, spec_revoke },		/* revoke */
10854014Sheideman 	{ &vop_mmap_desc, spec_mmap },			/* mmap */
10954462Smckusick 	{ &vop_fsync_desc, ffs_fsync },			/* fsync */
11054014Sheideman 	{ &vop_seek_desc, spec_seek },			/* seek */
11153523Sheideman 	{ &vop_remove_desc, spec_remove },		/* remove */
11254014Sheideman 	{ &vop_link_desc, spec_link },			/* link */
11353523Sheideman 	{ &vop_rename_desc, spec_rename },		/* rename */
11453523Sheideman 	{ &vop_mkdir_desc, spec_mkdir },		/* mkdir */
11553523Sheideman 	{ &vop_rmdir_desc, spec_rmdir },		/* rmdir */
11653523Sheideman 	{ &vop_symlink_desc, spec_symlink },		/* symlink */
11753523Sheideman 	{ &vop_readdir_desc, spec_readdir },		/* readdir */
11853523Sheideman 	{ &vop_readlink_desc, spec_readlink },		/* readlink */
11953523Sheideman 	{ &vop_abortop_desc, spec_abortop },		/* abortop */
12056745Smckusick 	{ &vop_inactive_desc, ufs_inactive },		/* inactive */
12167409Smckusick 	{ &vop_reclaim_desc, ffs_reclaim },		/* reclaim */
12254014Sheideman 	{ &vop_lock_desc, ufs_lock },			/* lock */
12353523Sheideman 	{ &vop_unlock_desc, ufs_unlock },		/* unlock */
12454014Sheideman 	{ &vop_bmap_desc, spec_bmap },			/* bmap */
12553523Sheideman 	{ &vop_strategy_desc, spec_strategy },		/* strategy */
12654014Sheideman 	{ &vop_print_desc, ufs_print },			/* print */
12753523Sheideman 	{ &vop_islocked_desc, ufs_islocked },		/* islocked */
12860396Smckusick 	{ &vop_pathconf_desc, spec_pathconf },		/* pathconf */
12953523Sheideman 	{ &vop_advlock_desc, spec_advlock },		/* advlock */
13053523Sheideman 	{ &vop_blkatoff_desc, spec_blkatoff },		/* blkatoff */
13153523Sheideman 	{ &vop_valloc_desc, spec_valloc },		/* valloc */
13265977Smckusick 	{ &vop_reallocblks_desc, spec_reallocblks },	/* reallocblks */
13354031Smckusick 	{ &vop_vfree_desc, ffs_vfree },			/* vfree */
13453523Sheideman 	{ &vop_truncate_desc, spec_truncate },		/* truncate */
13553523Sheideman 	{ &vop_update_desc, ffs_update },		/* update */
13653575Sheideman 	{ &vop_bwrite_desc, vn_bwrite },
13753523Sheideman 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
13851546Smckusick };
13953523Sheideman struct vnodeopv_desc ffs_specop_opv_desc =
14053523Sheideman 	{ &ffs_specop_p, ffs_specop_entries };
14151546Smckusick 
14251546Smckusick #ifdef FIFO
14353523Sheideman int (**ffs_fifoop_p)();
14453523Sheideman struct vnodeopv_entry_desc ffs_fifoop_entries[] = {
14553523Sheideman 	{ &vop_default_desc, vn_default_error },
14653523Sheideman 	{ &vop_lookup_desc, fifo_lookup },		/* lookup */
14753523Sheideman 	{ &vop_create_desc, fifo_create },		/* create */
14853523Sheideman 	{ &vop_mknod_desc, fifo_mknod },		/* mknod */
14954014Sheideman 	{ &vop_open_desc, fifo_open },			/* open */
15053523Sheideman 	{ &vop_close_desc, ufsfifo_close },		/* close */
15153523Sheideman 	{ &vop_access_desc, ufs_access },		/* access */
15253523Sheideman 	{ &vop_getattr_desc, ufs_getattr },		/* getattr */
15353523Sheideman 	{ &vop_setattr_desc, ufs_setattr },		/* setattr */
15453523Sheideman 	{ &vop_read_desc, ufsfifo_read },		/* read */
15553523Sheideman 	{ &vop_write_desc, ufsfifo_write },		/* write */
15667642Smckusick 	{ &vop_lease_desc, fifo_lease_check },		/* lease */
15753523Sheideman 	{ &vop_ioctl_desc, fifo_ioctl },		/* ioctl */
15853523Sheideman 	{ &vop_select_desc, fifo_select },		/* select */
15968419Smckusick 	{ &vop_revoke_desc, fifo_revoke },		/* revoke */
16054014Sheideman 	{ &vop_mmap_desc, fifo_mmap },			/* mmap */
16154462Smckusick 	{ &vop_fsync_desc, ffs_fsync },			/* fsync */
16254014Sheideman 	{ &vop_seek_desc, fifo_seek },			/* seek */
16353523Sheideman 	{ &vop_remove_desc, fifo_remove },		/* remove */
16454014Sheideman 	{ &vop_link_desc, fifo_link },			/* link */
16553523Sheideman 	{ &vop_rename_desc, fifo_rename },		/* rename */
16653523Sheideman 	{ &vop_mkdir_desc, fifo_mkdir },		/* mkdir */
16753523Sheideman 	{ &vop_rmdir_desc, fifo_rmdir },		/* rmdir */
16853523Sheideman 	{ &vop_symlink_desc, fifo_symlink },		/* symlink */
16953523Sheideman 	{ &vop_readdir_desc, fifo_readdir },		/* readdir */
17053523Sheideman 	{ &vop_readlink_desc, fifo_readlink },		/* readlink */
17153523Sheideman 	{ &vop_abortop_desc, fifo_abortop },		/* abortop */
17256745Smckusick 	{ &vop_inactive_desc, ufs_inactive },		/* inactive */
17367409Smckusick 	{ &vop_reclaim_desc, ffs_reclaim },		/* reclaim */
17454014Sheideman 	{ &vop_lock_desc, ufs_lock },			/* lock */
17553523Sheideman 	{ &vop_unlock_desc, ufs_unlock },		/* unlock */
17654014Sheideman 	{ &vop_bmap_desc, fifo_bmap },			/* bmap */
17753523Sheideman 	{ &vop_strategy_desc, fifo_strategy },		/* strategy */
17854014Sheideman 	{ &vop_print_desc, ufs_print },			/* print */
17953523Sheideman 	{ &vop_islocked_desc, ufs_islocked },		/* islocked */
18060396Smckusick 	{ &vop_pathconf_desc, fifo_pathconf },		/* pathconf */
18153523Sheideman 	{ &vop_advlock_desc, fifo_advlock },		/* advlock */
18253523Sheideman 	{ &vop_blkatoff_desc, fifo_blkatoff },		/* blkatoff */
18353523Sheideman 	{ &vop_valloc_desc, fifo_valloc },		/* valloc */
18465977Smckusick 	{ &vop_reallocblks_desc, fifo_reallocblks },	/* reallocblks */
18554031Smckusick 	{ &vop_vfree_desc, ffs_vfree },			/* vfree */
18653523Sheideman 	{ &vop_truncate_desc, fifo_truncate },		/* truncate */
18753523Sheideman 	{ &vop_update_desc, ffs_update },		/* update */
18853575Sheideman 	{ &vop_bwrite_desc, vn_bwrite },
18953523Sheideman 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
19051546Smckusick };
19153523Sheideman struct vnodeopv_desc ffs_fifoop_opv_desc =
19253523Sheideman 	{ &ffs_fifoop_p, ffs_fifoop_entries };
19351546Smckusick #endif /* FIFO */
19451546Smckusick 
19557416Smckusick /*
19657416Smckusick  * Enabling cluster read/write operations.
19757416Smckusick  */
19859158Smckusick int doclusterread = 1;
19959158Smckusick int doclusterwrite = 1;
2006254Sroot 
20164408Smckusick #include <ufs/ufs/ufs_readwrite.c>
20239608Smckusick 
20339608Smckusick /*
20437737Smckusick  * Synch an open file.
2059167Ssam  */
20637737Smckusick /* ARGSUSED */
20751474Sbostic int
ffs_fsync(ap)20853869Smckusick ffs_fsync(ap)
20954462Smckusick 	struct vop_fsync_args /* {
21054462Smckusick 		struct vnode *a_vp;
21154462Smckusick 		struct ucred *a_cred;
21254462Smckusick 		int a_waitfor;
21354462Smckusick 		struct proc *a_p;
21454462Smckusick 	} */ *ap;
2157701Ssam {
21654462Smckusick 	register struct vnode *vp = ap->a_vp;
21754462Smckusick 	register struct buf *bp;
21854763Smckusick 	struct timeval tv;
21954462Smckusick 	struct buf *nbp;
22054462Smckusick 	int s;
2217701Ssam 
22254462Smckusick 	/*
22354462Smckusick 	 * Flush all dirty buffers associated with a vnode.
22454462Smckusick 	 */
22554462Smckusick loop:
22654462Smckusick 	s = splbio();
22765237Smckusick 	for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
22865237Smckusick 		nbp = bp->b_vnbufs.le_next;
22954462Smckusick 		if ((bp->b_flags & B_BUSY))
23054462Smckusick 			continue;
23154462Smckusick 		if ((bp->b_flags & B_DELWRI) == 0)
23254462Smckusick 			panic("ffs_fsync: not dirty");
23354462Smckusick 		bremfree(bp);
23454462Smckusick 		bp->b_flags |= B_BUSY;
23554462Smckusick 		splx(s);
23654462Smckusick 		/*
23754462Smckusick 		 * Wait for I/O associated with indirect blocks to complete,
23854462Smckusick 		 * since there is no way to quickly wait for them below.
23954462Smckusick 		 */
24054462Smckusick 		if (bp->b_vp == vp || ap->a_waitfor == MNT_NOWAIT)
24154462Smckusick 			(void) bawrite(bp);
24254462Smckusick 		else
24354462Smckusick 			(void) bwrite(bp);
24454462Smckusick 		goto loop;
24554462Smckusick 	}
24654462Smckusick 	if (ap->a_waitfor == MNT_WAIT) {
24754462Smckusick 		while (vp->v_numoutput) {
24854462Smckusick 			vp->v_flag |= VBWAIT;
24954462Smckusick 			sleep((caddr_t)&vp->v_numoutput, PRIBIO + 1);
25054462Smckusick 		}
25154462Smckusick #ifdef DIAGNOSTIC
25265237Smckusick 		if (vp->v_dirtyblkhd.lh_first) {
25354462Smckusick 			vprint("ffs_fsync: dirty", vp);
25454462Smckusick 			goto loop;
25554462Smckusick 		}
25654462Smckusick #endif
25754462Smckusick 	}
25854462Smckusick 	splx(s);
25954763Smckusick 	tv = time;
26064438Sbostic 	return (VOP_UPDATE(ap->a_vp, &tv, &tv, ap->a_waitfor == MNT_WAIT));
26164438Sbostic }
26267409Smckusick 
26367409Smckusick /*
26467409Smckusick  * Reclaim an inode so that it can be used for other purposes.
26567409Smckusick  */
26667409Smckusick int
ffs_reclaim(ap)26767409Smckusick ffs_reclaim(ap)
26867409Smckusick 	struct vop_reclaim_args /* {
26967409Smckusick 		struct vnode *a_vp;
270*69416Smckusick 		struct proc *a_p;
27167409Smckusick 	} */ *ap;
27267409Smckusick {
27367409Smckusick 	register struct vnode *vp = ap->a_vp;
27467409Smckusick 	int error;
27567409Smckusick 
276*69416Smckusick 	if (error = ufs_reclaim(vp, ap->a_p))
27767409Smckusick 		return (error);
27868117Smckusick 	FREE(vp->v_data, VFSTOUFS(vp->v_mount)->um_devvp->v_tag == VT_MFS ?
27968117Smckusick 	    M_MFSNODE : M_FFSNODE);
28067409Smckusick 	vp->v_data = NULL;
28167409Smckusick 	return (0);
28267409Smckusick }
283