xref: /csrg-svn/sys/ufs/lfs/lfs_bio.c (revision 68550)
151184Sbostic /*
263375Sbostic  * Copyright (c) 1991, 1993
363375Sbostic  *	The Regents of the University of California.  All rights reserved.
451184Sbostic  *
551184Sbostic  * %sccs.include.redist.c%
651184Sbostic  *
7*68550Smckusick  *	@(#)lfs_bio.c	8.5 (Berkeley) 03/21/95
851184Sbostic  */
951184Sbostic 
1051480Sbostic #include <sys/param.h>
1151480Sbostic #include <sys/proc.h>
1251480Sbostic #include <sys/buf.h>
1352081Sbostic #include <sys/vnode.h>
1451480Sbostic #include <sys/resourcevar.h>
1552081Sbostic #include <sys/mount.h>
1656865Smargo #include <sys/kernel.h>
1751184Sbostic 
1852081Sbostic #include <ufs/ufs/quota.h>
1952081Sbostic #include <ufs/ufs/inode.h>
2052081Sbostic #include <ufs/ufs/ufsmount.h>
2152081Sbostic 
2251493Sbostic #include <ufs/lfs/lfs.h>
2351493Sbostic #include <ufs/lfs/lfs_extern.h>
2451480Sbostic 
2552081Sbostic /*
2652081Sbostic  * LFS block write function.
2752081Sbostic  *
2852081Sbostic  * XXX
2952081Sbostic  * No write cost accounting is done.
3052081Sbostic  * This is almost certainly wrong for synchronous operations and NFS.
3152081Sbostic  */
3256052Sbostic int	lfs_allclean_wakeup;		/* Cleaner wakeup address. */
3352081Sbostic int	locked_queue_count;		/* XXX Count of locked-down buffers. */
3455935Sbostic int	lfs_writing;			/* Set if already kicked off a writer
3555935Sbostic 					   because of buffer space */
3657066Smargo /*
3755935Sbostic #define WRITE_THRESHHOLD	((nbuf >> 2) - 10)
3855935Sbostic #define WAIT_THRESHHOLD		((nbuf >> 1) - 10)
3957066Smargo */
4057066Smargo #define WAIT_THRESHHOLD         (nbuf - (nbuf >> 2) - 10)
4157066Smargo #define WRITE_THRESHHOLD        ((nbuf >> 1) - 10)
4256865Smargo #define LFS_BUFWAIT	2
4352081Sbostic 
4451480Sbostic int
4554621Smckusick lfs_bwrite(ap)
4654621Smckusick 	struct vop_bwrite_args /* {
4754621Smckusick 		struct buf *a_bp;
4854621Smckusick 	} */ *ap;
4951184Sbostic {
5053867Sheideman 	register struct buf *bp = ap->a_bp;
5155935Sbostic 	struct lfs *fs;
5255935Sbostic 	struct inode *ip;
5356865Smargo 	int error, s;
5455807Sbostic 
5551851Sbostic 	/*
5652081Sbostic 	 * Set the delayed write flag and use reassignbuf to move the buffer
5752081Sbostic 	 * from the clean list to the dirty one.
5851851Sbostic 	 *
5952081Sbostic 	 * Set the B_LOCKED flag and unlock the buffer, causing brelse to move
6052081Sbostic 	 * the buffer onto the LOCKED free list.  This is necessary, otherwise
6152081Sbostic 	 * getnewbuf() would try to reclaim the buffers using bawrite, which
6252081Sbostic 	 * isn't going to work.
6356155Smargo 	 *
6456155Smargo 	 * XXX we don't let meta-data writes run out of space because they can
6556155Smargo 	 * come from the segment writer.  We need to make sure that there is
6656155Smargo 	 * enough space reserved so that there's room to write meta-data
6756155Smargo 	 * blocks.
6851851Sbostic 	 */
6953867Sheideman 	if (!(bp->b_flags & B_LOCKED)) {
7055935Sbostic 		fs = VFSTOUFS(bp->b_vp->v_mount)->um_lfs;
7156865Smargo 		while (!LFS_FITS(fs, fsbtodb(fs, 1)) && !IS_IFILE(bp) &&
7256155Smargo 		    bp->b_lblkno > 0) {
7356865Smargo 			/* Out of space, need cleaner to run */
7456052Sbostic 			wakeup(&lfs_allclean_wakeup);
7556865Smargo 			if (error = tsleep(&fs->lfs_avail, PCATCH | PUSER,
7656865Smargo 			    "cleaner", NULL)) {
7756865Smargo 				brelse(bp);
7856865Smargo 				return (error);
7956865Smargo 			}
8055935Sbostic 		}
8155935Sbostic 		ip = VTOI((bp)->b_vp);
8264608Sbostic 		if (!(ip->i_flag & IN_MODIFIED))
8355935Sbostic 			++fs->lfs_uinodes;
8464608Sbostic 		ip->i_flag |= IN_CHANGE | IN_MODIFIED | IN_UPDATE;
8555935Sbostic 		fs->lfs_avail -= fsbtodb(fs, 1);
8652081Sbostic 		++locked_queue_count;
8753867Sheideman 		bp->b_flags |= B_DELWRI | B_LOCKED;
8855935Sbostic 		bp->b_flags &= ~(B_READ | B_ERROR);
8953143Sstaelin 		s = splbio();
9053867Sheideman 		reassignbuf(bp, bp->b_vp);
9153143Sstaelin 		splx(s);
9253143Sstaelin 	}
9353867Sheideman 	brelse(bp);
9451480Sbostic 	return (0);
9551184Sbostic }
9652081Sbostic 
9752081Sbostic /*
9852081Sbostic  * XXX
9952081Sbostic  * This routine flushes buffers out of the B_LOCKED queue when LFS has too
10052081Sbostic  * many locked down.  Eventually the pageout daemon will simply call LFS
10152325Sbostic  * when pages need to be reclaimed.  Note, we have one static count of locked
10252325Sbostic  * buffers, so we can't have more than a single file system.  To make this
10352325Sbostic  * work for multiple file systems, put the count into the mount structure.
10452081Sbostic  */
10552081Sbostic void
10652081Sbostic lfs_flush()
10752081Sbostic {
10852081Sbostic 	register struct mount *mp;
10952081Sbostic 
11057066Smargo #ifdef DOSTATS
11157066Smargo 	++lfs_stats.write_exceeded;
11257066Smargo #endif
11355935Sbostic 	if (lfs_writing)
11452081Sbostic 		return;
11555935Sbostic 	lfs_writing = 1;
11665238Smckusick 	for (mp = mountlist.tqh_first; mp != NULL; mp = mp->mnt_list.tqe_next) {
11755935Sbostic 		/* The lock check below is to avoid races with unmount. */
11852081Sbostic 		if (mp->mnt_stat.f_type == MOUNT_LFS &&
11955935Sbostic 		    (mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_UNMOUNT)) == 0 &&
12055935Sbostic 		    !((((struct ufsmount *)mp->mnt_data))->ufsmount_u.lfs)->lfs_dirops ) {
12152347Sbostic 			/*
12252347Sbostic 			 * We set the queue to 0 here because we are about to
12352347Sbostic 			 * write all the dirty buffers we have.  If more come
12452347Sbostic 			 * in while we're writing the segment, they may not
12552347Sbostic 			 * get written, so we want the count to reflect these
12652347Sbostic 			 * new writes after the segwrite completes.
12752347Sbostic 			 */
12857066Smargo #ifdef DOSTATS
12957066Smargo 			++lfs_stats.flush_invoked;
13057066Smargo #endif
13152081Sbostic 			lfs_segwrite(mp, 0);
13255935Sbostic 		}
13365238Smckusick 	}
13455935Sbostic 	lfs_writing = 0;
13552081Sbostic }
13655935Sbostic 
13755935Sbostic int
13855935Sbostic lfs_check(vp, blkno)
13955935Sbostic 	struct vnode *vp;
140*68550Smckusick 	ufs_daddr_t blkno;
14155935Sbostic {
14255935Sbostic 	extern int lfs_allclean_wakeup;
14355935Sbostic 	int error;
14455935Sbostic 
14556865Smargo 	error = 0;
14655935Sbostic 	if (incore(vp, blkno))
14755935Sbostic 		return (0);
14855935Sbostic 	if (locked_queue_count > WRITE_THRESHHOLD)
14955935Sbostic 		lfs_flush();
15056865Smargo 
15156865Smargo 	/* If out of buffers, wait on writer */
15257066Smargo 	while (locked_queue_count > WAIT_THRESHHOLD) {
15357066Smargo #ifdef DOSTATS
15457066Smargo 	    ++lfs_stats.wait_exceeded;
15557066Smargo #endif
15656865Smargo 	    error = tsleep(&locked_queue_count, PCATCH | PUSER, "buffers",
15756865Smargo 	        hz * LFS_BUFWAIT);
15857066Smargo 	}
15956865Smargo 
16055935Sbostic 	return (error);
16155935Sbostic }
162