|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /* $NetBSD: lfs_bio.c,v 1.3 1995/01/18 06:19:52 mycroft Exp $ */
23:
24: /*
25: * Copyright (c) 1991, 1993
26: * The Regents of the University of California. All rights reserved.
27: *
28: * Redistribution and use in source and binary forms, with or without
29: * modification, are permitted provided that the following conditions
30: * are met:
31: * 1. Redistributions of source code must retain the above copyright
32: * notice, this list of conditions and the following disclaimer.
33: * 2. Redistributions in binary form must reproduce the above copyright
34: * notice, this list of conditions and the following disclaimer in the
35: * documentation and/or other materials provided with the distribution.
36: * 3. All advertising materials mentioning features or use of this software
37: * must display the following acknowledgement:
38: * This product includes software developed by the University of
39: * California, Berkeley and its contributors.
40: * 4. Neither the name of the University nor the names of its contributors
41: * may be used to endorse or promote products derived from this software
42: * without specific prior written permission.
43: *
44: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54: * SUCH DAMAGE.
55: *
56: * @(#)lfs_bio.c 8.4 (Berkeley) 12/30/93
57: */
58:
59: #include <sys/param.h>
60: #include <sys/proc.h>
61: #include <sys/buf.h>
62: #include <sys/vnode.h>
63: #include <sys/resourcevar.h>
64: #include <sys/mount.h>
65: #include <sys/kernel.h>
66:
67: #include <ufs/ufs/quota.h>
68: #include <ufs/ufs/inode.h>
69: #include <ufs/ufs/ufsmount.h>
70:
71: #include <ufs/lfs/lfs.h>
72: #include <ufs/lfs/lfs_extern.h>
73:
74: /*
75: * LFS block write function.
76: *
77: * XXX
78: * No write cost accounting is done.
79: * This is almost certainly wrong for synchronous operations and NFS.
80: */
81: int lfs_allclean_wakeup; /* Cleaner wakeup address. */
82: int locked_queue_count; /* XXX Count of locked-down buffers. */
83: int lfs_writing; /* Set if already kicked off a writer
84: because of buffer space */
85: /*
86: #define WRITE_THRESHHOLD ((nbuf >> 2) - 10)
87: #define WAIT_THRESHHOLD ((nbuf >> 1) - 10)
88: */
89: #define WAIT_THRESHHOLD (nbuf - (nbuf >> 2) - 10)
90: #define WRITE_THRESHHOLD ((nbuf >> 1) - 10)
91: #define LFS_BUFWAIT 2
92:
93: int
94: lfs_bwrite(ap)
95: struct vop_bwrite_args /* {
96: struct buf *a_bp;
97: } */ *ap;
98: {
99: register struct buf *bp = ap->a_bp;
100: struct lfs *fs;
101: struct inode *ip;
102: int error, s;
103:
104: /*
105: * Set the delayed write flag and use reassignbuf to move the buffer
106: * from the clean list to the dirty one.
107: *
108: * Set the B_LOCKED flag and unlock the buffer, causing brelse to move
109: * the buffer onto the LOCKED free list. This is necessary, otherwise
110: * getnewbuf() would try to reclaim the buffers using bawrite, which
111: * isn't going to work.
112: *
113: * XXX we don't let meta-data writes run out of space because they can
114: * come from the segment writer. We need to make sure that there is
115: * enough space reserved so that there's room to write meta-data
116: * blocks.
117: */
118: if (!(bp->b_flags & B_LOCKED)) {
119: fs = VFSTOUFS(bp->b_vp->v_mount)->um_lfs;
120: while (!LFS_FITS(fs, fsbtodb(fs, 1)) && !IS_IFILE(bp) &&
121: bp->b_lblkno > 0) {
122: /* Out of space, need cleaner to run */
123: wakeup(&lfs_allclean_wakeup);
124: if (error = tsleep(&fs->lfs_avail, PCATCH | PUSER,
125: "cleaner", NULL)) {
126: brelse(bp);
127: return (error);
128: }
129: }
130: ip = VTOI((bp)->b_vp);
131: if (!(ip->i_flag & IN_MODIFIED))
132: ++fs->lfs_uinodes;
133: ip->i_flag |= IN_CHANGE | IN_MODIFIED | IN_UPDATE;
134: fs->lfs_avail -= fsbtodb(fs, 1);
135: ++locked_queue_count;
136: bp->b_flags |= B_DELWRI | B_LOCKED;
137: bp->b_flags &= ~(B_READ | B_ERROR);
138: s = splbio();
139: reassignbuf(bp, bp->b_vp);
140: splx(s);
141: }
142: brelse(bp);
143: return (0);
144: }
145:
146: /*
147: * XXX
148: * This routine flushes buffers out of the B_LOCKED queue when LFS has too
149: * many locked down. Eventually the pageout daemon will simply call LFS
150: * when pages need to be reclaimed. Note, we have one static count of locked
151: * buffers, so we can't have more than a single file system. To make this
152: * work for multiple file systems, put the count into the mount structure.
153: */
154: void
155: lfs_flush()
156: {
157: register struct mount *mp;
158:
159: #ifdef DOSTATS
160: ++lfs_stats.write_exceeded;
161: #endif
162: if (lfs_writing)
163: return;
164: lfs_writing = 1;
165: for (mp = mountlist.cqh_first; mp != (void *)&mountlist;
166: mp = mp->mnt_list.cqe_next) {
167: /* The lock check below is to avoid races with unmount. */
168: if (!strcmp(&mp->mnt_stat.f_fstypename[0], MOUNT_LFS) &&
169: (mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_UNMOUNT)) == 0 &&
170: !((((struct ufsmount *)mp->mnt_data))->ufsmount_u.lfs)->lfs_dirops ) {
171: /*
172: * We set the queue to 0 here because we are about to
173: * write all the dirty buffers we have. If more come
174: * in while we're writing the segment, they may not
175: * get written, so we want the count to reflect these
176: * new writes after the segwrite completes.
177: */
178: #ifdef DOSTATS
179: ++lfs_stats.flush_invoked;
180: #endif
181: lfs_segwrite(mp, 0);
182: }
183: }
184: lfs_writing = 0;
185: }
186:
187: int
188: lfs_check(vp, blkno)
189: struct vnode *vp;
190: daddr_t blkno;
191: {
192: extern int lfs_allclean_wakeup;
193: int error;
194:
195: error = 0;
196: if (incore(vp, blkno))
197: return (0);
198: if (locked_queue_count > WRITE_THRESHHOLD)
199: lfs_flush();
200:
201: /* If out of buffers, wait on writer */
202: while (locked_queue_count > WAIT_THRESHHOLD) {
203: #ifdef DOSTATS
204: ++lfs_stats.wait_exceeded;
205: #endif
206: error = tsleep(&locked_queue_count, PCATCH | PUSER, "buffers",
207: hz * LFS_BUFWAIT);
208: }
209:
210: return (error);
211: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.