]>
Commit | Line | Data |
---|---|---|
1c79356b A |
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 | /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ | |
23 | /* | |
24 | * Copyright (c) 1982, 1986, 1988, 1993 | |
25 | * The Regents of the University of California. All rights reserved. | |
26 | * (c) UNIX System Laboratories, Inc. | |
27 | * All or some portions of this file are derived from material licensed | |
28 | * to the University of California by American Telephone and Telegraph | |
29 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with | |
30 | * the permission of UNIX System Laboratories, Inc. | |
31 | * | |
32 | * Redistribution and use in source and binary forms, with or without | |
33 | * modification, are permitted provided that the following conditions | |
34 | * are met: | |
35 | * 1. Redistributions of source code must retain the above copyright | |
36 | * notice, this list of conditions and the following disclaimer. | |
37 | * 2. Redistributions in binary form must reproduce the above copyright | |
38 | * notice, this list of conditions and the following disclaimer in the | |
39 | * documentation and/or other materials provided with the distribution. | |
40 | * 3. All advertising materials mentioning features or use of this software | |
41 | * must display the following acknowledgement: | |
42 | * This product includes software developed by the University of | |
43 | * California, Berkeley and its contributors. | |
44 | * 4. Neither the name of the University nor the names of its contributors | |
45 | * may be used to endorse or promote products derived from this software | |
46 | * without specific prior written permission. | |
47 | * | |
48 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
49 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
50 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
51 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
52 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
53 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
54 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
55 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
56 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
57 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
58 | * SUCH DAMAGE. | |
59 | * | |
60 | * @(#)ufs_disksubr.c 8.5 (Berkeley) 1/21/94 | |
61 | */ | |
62 | ||
63 | #include <sys/param.h> | |
64 | #include <sys/systm.h> | |
65 | #include <sys/buf.h> | |
66 | #include <sys/disklabel.h> | |
67 | #include <sys/syslog.h> | |
68 | ||
69 | /* | |
70 | * Seek sort for disks. We depend on the driver which calls us using b_resid | |
71 | * as the current cylinder number. | |
72 | * | |
73 | * The argument ap structure holds a b_actf activity chain pointer on which we | |
74 | * keep two queues, sorted in ascending cylinder order. The first queue holds | |
75 | * those requests which are positioned after the current cylinder (in the first | |
76 | * request); the second holds requests which came in after their cylinder number | |
77 | * was passed. Thus we implement a one way scan, retracting after reaching the | |
78 | * end of the drive to the first request on the second queue, at which time it | |
79 | * becomes the first queue. | |
80 | * | |
81 | * A one-way scan is natural because of the way UNIX read-ahead blocks are | |
82 | * allocated. | |
83 | */ | |
84 | ||
85 | /* | |
86 | * For portability with historic industry practice, the | |
87 | * cylinder number has to be maintained in the `b_resid' | |
88 | * field. | |
89 | */ | |
90 | #define b_cylinder b_resid | |
91 | ||
92 | void | |
93 | disksort(ap, bp) | |
94 | register struct buf *ap, *bp; | |
95 | { | |
96 | register struct buf *bq; | |
97 | ||
98 | /* If the queue is empty, then it's easy. */ | |
99 | if (ap->b_actf == NULL) { | |
100 | bp->b_actf = NULL; | |
101 | ap->b_actf = bp; | |
102 | return; | |
103 | } | |
104 | ||
105 | /* | |
106 | * If we lie after the first (currently active) request, then we | |
107 | * must locate the second request list and add ourselves to it. | |
108 | */ | |
109 | bq = ap->b_actf; | |
110 | if (bp->b_cylinder < bq->b_cylinder) { | |
111 | while (bq->b_actf) { | |
112 | /* | |
113 | * Check for an ``inversion'' in the normally ascending | |
114 | * cylinder numbers, indicating the start of the second | |
115 | * request list. | |
116 | */ | |
117 | if (bq->b_actf->b_cylinder < bq->b_cylinder) { | |
118 | /* | |
119 | * Search the second request list for the first | |
120 | * request at a larger cylinder number. We go | |
121 | * before that; if there is no such request, we | |
122 | * go at end. | |
123 | */ | |
124 | do { | |
125 | if (bp->b_cylinder < | |
126 | bq->b_actf->b_cylinder) | |
127 | goto insert; | |
128 | if (bp->b_cylinder == | |
129 | bq->b_actf->b_cylinder && | |
130 | bp->b_blkno < bq->b_actf->b_blkno) | |
131 | goto insert; | |
132 | bq = bq->b_actf; | |
133 | } while (bq->b_actf); | |
134 | goto insert; /* after last */ | |
135 | } | |
136 | bq = bq->b_actf; | |
137 | } | |
138 | /* | |
139 | * No inversions... we will go after the last, and | |
140 | * be the first request in the second request list. | |
141 | */ | |
142 | goto insert; | |
143 | } | |
144 | /* | |
145 | * Request is at/after the current request... | |
146 | * sort in the first request list. | |
147 | */ | |
148 | while (bq->b_actf) { | |
149 | /* | |
150 | * We want to go after the current request if there is an | |
151 | * inversion after it (i.e. it is the end of the first | |
152 | * request list), or if the next request is a larger cylinder | |
153 | * than our request. | |
154 | */ | |
155 | if (bq->b_actf->b_cylinder < bq->b_cylinder || | |
156 | bp->b_cylinder < bq->b_actf->b_cylinder || | |
157 | (bp->b_cylinder == bq->b_actf->b_cylinder && | |
158 | bp->b_blkno < bq->b_actf->b_blkno)) | |
159 | goto insert; | |
160 | bq = bq->b_actf; | |
161 | } | |
162 | /* | |
163 | * Neither a second list nor a larger request... we go at the end of | |
164 | * the first list, which is the same as the end of the whole schebang. | |
165 | */ | |
166 | insert: bp->b_actf = bq->b_actf; | |
167 | bq->b_actf = bp; | |
168 | } | |
169 | ||
170 | /* encoding of disk minor numbers, should be elsewhere... */ | |
171 | #define dkunit(dev) (minor(dev) >> 3) | |
172 | #define dkpart(dev) (minor(dev) & 07) | |
173 | #define dkminor(unit, part) (((unit) << 3) | (part)) | |
174 | ||
175 | /* | |
176 | * Compute checksum for disk label. | |
177 | */ | |
178 | u_int | |
179 | dkcksum(lp) | |
180 | register struct disklabel *lp; | |
181 | { | |
182 | register u_short *start, *end; | |
183 | register u_short sum = 0; | |
184 | ||
185 | start = (u_short *)lp; | |
186 | end = (u_short *)&lp->d_partitions[lp->d_npartitions]; | |
187 | while (start < end) | |
188 | sum ^= *start++; | |
189 | return (sum); | |
190 | } | |
191 | ||
192 | /* | |
193 | * Disk error is the preface to plaintive error messages | |
194 | * about failing disk transfers. It prints messages of the form | |
195 | ||
196 | hp0g: hard error reading fsbn 12345 of 12344-12347 (hp0 bn %d cn %d tn %d sn %d) | |
197 | ||
198 | * if the offset of the error in the transfer and a disk label | |
199 | * are both available. blkdone should be -1 if the position of the error | |
200 | * is unknown; the disklabel pointer may be null from drivers that have not | |
201 | * been converted to use them. The message is printed with printf | |
202 | * if pri is LOG_PRINTF, otherwise it uses log at the specified priority. | |
203 | * The message should be completed (with at least a newline) with printf | |
204 | * or addlog, respectively. There is no trailing space. | |
205 | */ | |
206 | void | |
207 | diskerr(bp, dname, what, pri, blkdone, lp) | |
208 | register struct buf *bp; | |
209 | char *dname, *what; | |
210 | int pri, blkdone; | |
211 | register struct disklabel *lp; | |
212 | { | |
213 | int unit = dkunit(bp->b_dev), part = dkpart(bp->b_dev); | |
214 | register void (*pr) __P((const char *, ...)); | |
215 | char partname = 'a' + part; | |
216 | int sn; | |
217 | ||
218 | if (pri != LOG_PRINTF) { | |
219 | log(pri, ""); | |
220 | pr = addlog; | |
221 | } else | |
222 | pr = printf; | |
223 | (*pr)("%s%d%c: %s %sing fsbn ", dname, unit, partname, what, | |
224 | bp->b_flags & B_READ ? "read" : "writ"); | |
225 | sn = bp->b_blkno; | |
226 | if (bp->b_bcount <= DEV_BSIZE) | |
227 | (*pr)("%d", sn); | |
228 | else { | |
229 | if (blkdone >= 0) { | |
230 | sn += blkdone; | |
231 | (*pr)("%d of ", sn); | |
232 | } | |
233 | (*pr)("%d-%d", bp->b_blkno, | |
234 | bp->b_blkno + (bp->b_bcount - 1) / DEV_BSIZE); | |
235 | } | |
236 | if (lp && (blkdone >= 0 || bp->b_bcount <= lp->d_secsize)) { | |
237 | #ifdef tahoe | |
238 | sn *= DEV_BSIZE / lp->d_secsize; /* XXX */ | |
239 | #endif | |
240 | sn += lp->d_partitions[part].p_offset; | |
241 | (*pr)(" (%s%d bn %d; cn %d", dname, unit, sn, | |
242 | sn / lp->d_secpercyl); | |
243 | sn %= lp->d_secpercyl; | |
244 | (*pr)(" tn %d sn %d)", sn / lp->d_nsectors, sn % lp->d_nsectors); | |
245 | } | |
246 | } |