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