xref: /original-bsd/sys/ufs/lfs/lfs_bio.c (revision e49f9654)
1 /*
2  * Copyright (c) 1991, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)lfs_bio.c	8.10 (Berkeley) 06/10/95
8  */
9 
10 #include <sys/param.h>
11 #include <sys/proc.h>
12 #include <sys/buf.h>
13 #include <sys/vnode.h>
14 #include <sys/resourcevar.h>
15 #include <sys/mount.h>
16 #include <sys/kernel.h>
17 
18 #include <ufs/ufs/quota.h>
19 #include <ufs/ufs/inode.h>
20 #include <ufs/ufs/ufsmount.h>
21 
22 #include <ufs/lfs/lfs.h>
23 #include <ufs/lfs/lfs_extern.h>
24 
25 /*
26  * LFS block write function.
27  *
28  * XXX
29  * No write cost accounting is done.
30  * This is almost certainly wrong for synchronous operations and NFS.
31  */
32 int	lfs_allclean_wakeup;		/* Cleaner wakeup address. */
33 int	locked_queue_count;		/* XXX Count of locked-down buffers. */
34 int	lfs_writing;			/* Set if already kicked off a writer
35 					   because of buffer space */
36 /*
37 #define WRITE_THRESHHOLD	((nbuf >> 2) - 10)
38 #define WAIT_THRESHHOLD		((nbuf >> 1) - 10)
39 */
40 #define WAIT_THRESHHOLD         (nbuf - (nbuf >> 2) - 10)
41 #define WRITE_THRESHHOLD        ((nbuf >> 1) - 10)
42 #define LFS_BUFWAIT	2
43 
44 int
45 lfs_bwrite(ap)
46 	struct vop_bwrite_args /* {
47 		struct buf *a_bp;
48 	} */ *ap;
49 {
50 	register struct buf *bp = ap->a_bp;
51 	struct lfs *fs;
52 	struct inode *ip;
53 	int db, error, s;
54 
55 	/*
56 	 * Set the delayed write flag and use reassignbuf to move the buffer
57 	 * from the clean list to the dirty one.
58 	 *
59 	 * Set the B_LOCKED flag and unlock the buffer, causing brelse to move
60 	 * the buffer onto the LOCKED free list.  This is necessary, otherwise
61 	 * getnewbuf() would try to reclaim the buffers using bawrite, which
62 	 * isn't going to work.
63 	 *
64 	 * XXX we don't let meta-data writes run out of space because they can
65 	 * come from the segment writer.  We need to make sure that there is
66 	 * enough space reserved so that there's room to write meta-data
67 	 * blocks.
68 	 */
69 	if (!(bp->b_flags & B_LOCKED)) {
70 		fs = VFSTOUFS(bp->b_vp->v_mount)->um_lfs;
71 		db = fragstodb(fs, numfrags(fs, bp->b_bcount));
72 		while (!LFS_FITS(fs, db) && !IS_IFILE(bp) &&
73 		    bp->b_lblkno > 0) {
74 			/* Out of space, need cleaner to run */
75 			wakeup(&lfs_allclean_wakeup);
76 			wakeup(&fs->lfs_nextseg);
77 			if (error = tsleep(&fs->lfs_avail, PCATCH | PUSER,
78 			    "cleaner", NULL)) {
79 				brelse(bp);
80 				return (error);
81 			}
82 		}
83 		ip = VTOI((bp)->b_vp);
84 		if (!(ip->i_flag & IN_MODIFIED))
85 			++fs->lfs_uinodes;
86 		ip->i_flag |= IN_CHANGE | IN_MODIFIED | IN_UPDATE;
87 		fs->lfs_avail -= db;
88 		++locked_queue_count;
89 		bp->b_flags |= B_DELWRI | B_LOCKED;
90 		bp->b_flags &= ~(B_READ | B_ERROR);
91 		s = splbio();
92 		reassignbuf(bp, bp->b_vp);
93 		splx(s);
94 	}
95 	brelse(bp);
96 	return (0);
97 }
98 
99 /*
100  * XXX
101  * This routine flushes buffers out of the B_LOCKED queue when LFS has too
102  * many locked down.  Eventually the pageout daemon will simply call LFS
103  * when pages need to be reclaimed.  Note, we have one static count of locked
104  * buffers, so we can't have more than a single file system.  To make this
105  * work for multiple file systems, put the count into the mount structure.
106  */
107 void
108 lfs_flush()
109 {
110 	register struct mount *mp, *nmp;
111 	struct proc *p = curproc;	/* XXX */
112 
113 #ifdef DOSTATS
114 	++lfs_stats.write_exceeded;
115 #endif
116 	if (lfs_writing)
117 		return;
118 	lfs_writing = 1;
119 	simple_lock(&mountlist_slock);
120 	for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
121 		if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
122 			nmp = mp->mnt_list.cqe_next;
123 			continue;
124 		}
125 		if (mp->mnt_stat.f_type == lfs_mount_type &&
126 		    (mp->mnt_flag & MNT_RDONLY) == 0 &&
127 		    !((((struct ufsmount *)mp->mnt_data))->ufsmount_u.lfs)->lfs_dirops ) {
128 			/*
129 			 * We set the queue to 0 here because we are about to
130 			 * write all the dirty buffers we have.  If more come
131 			 * in while we're writing the segment, they may not
132 			 * get written, so we want the count to reflect these
133 			 * new writes after the segwrite completes.
134 			 */
135 #ifdef DOSTATS
136 			++lfs_stats.flush_invoked;
137 #endif
138 			lfs_segwrite(mp, 0);
139 		}
140 		simple_lock(&mountlist_slock);
141 		nmp = mp->mnt_list.cqe_next;
142 		vfs_unbusy(mp, p);
143 	}
144 	simple_unlock(&mountlist_slock);
145 	lfs_writing = 0;
146 }
147 
148 int
149 lfs_check(vp, blkno)
150 	struct vnode *vp;
151 	ufs_daddr_t blkno;
152 {
153 	extern int lfs_allclean_wakeup;
154 	int error;
155 
156 	error = 0;
157 	if (incore(vp, blkno))
158 		return (0);
159 	if (locked_queue_count > WRITE_THRESHHOLD)
160 		lfs_flush();
161 
162 	/* If out of buffers, wait on writer */
163 	while (locked_queue_count > WAIT_THRESHHOLD) {
164 #ifdef DOSTATS
165 	    ++lfs_stats.wait_exceeded;
166 #endif
167 	    error = tsleep(&locked_queue_count, PCATCH | PUSER, "buffers",
168 	        hz * LFS_BUFWAIT);
169 	}
170 
171 	return (error);
172 }
173