|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution is only permitted until one year after the first shipment
6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
7: * binary forms are permitted provided that: (1) source distributions retain
8: * this entire copyright notice and comment, and (2) distributions including
9: * binaries display the following acknowledgement: This product includes
10: * software developed by the University of California, Berkeley and its
11: * contributors'' in the documentation or other materials provided with the
12: * distribution and in all advertising materials mentioning features or use
13: * of this software. Neither the name of the University nor the names of
14: * its contributors may be used to endorse or promote products derived from
15: * this software without specific prior written permission.
16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19: *
20: * @(#)ufs_disksubr.c 7.14 (Berkeley) 6/28/90
21: */
22:
23: #include "param.h"
24: #include "systm.h"
25: #include "buf.h"
26: #include "disklabel.h"
27: #include "syslog.h"
28: #include "user.h"
29:
30: /*
31: * Seek sort for disks. We depend on the driver
32: * which calls us using b_resid as the current cylinder number.
33: *
34: * The argument dp structure holds a b_actf activity chain pointer
35: * on which we keep two queues, sorted in ascending cylinder order.
36: * The first queue holds those requests which are positioned after
37: * the current cylinder (in the first request); the second holds
38: * requests which came in after their cylinder number was passed.
39: * Thus we implement a one way scan, retracting after reaching the
40: * end of the drive to the first request on the second queue,
41: * at which time it becomes the first queue.
42: *
43: * A one-way scan is natural because of the way UNIX read-ahead
44: * blocks are allocated.
45: */
46:
47: #define b_cylin b_resid
48:
49: disksort(dp, bp)
50: register struct buf *dp, *bp;
51: {
52: register struct buf *ap;
53:
54: /*
55: * If nothing on the activity queue, then
56: * we become the only thing.
57: */
58: ap = dp->b_actf;
59: if(ap == NULL) {
60: dp->b_actf = bp;
61: dp->b_actl = bp;
62: bp->av_forw = NULL;
63: return;
64: }
65: /*
66: * If we lie after the first (currently active)
67: * request, then we must locate the second request list
68: * and add ourselves to it.
69: */
70: if (bp->b_cylin < ap->b_cylin) {
71: while (ap->av_forw) {
72: /*
73: * Check for an ``inversion'' in the
74: * normally ascending cylinder numbers,
75: * indicating the start of the second request list.
76: */
77: if (ap->av_forw->b_cylin < ap->b_cylin) {
78: /*
79: * Search the second request list
80: * for the first request at a larger
81: * cylinder number. We go before that;
82: * if there is no such request, we go at end.
83: */
84: do {
85: if (bp->b_cylin < ap->av_forw->b_cylin)
86: goto insert;
87: if (bp->b_cylin == ap->av_forw->b_cylin &&
88: bp->b_blkno < ap->av_forw->b_blkno)
89: goto insert;
90: ap = ap->av_forw;
91: } while (ap->av_forw);
92: goto insert; /* after last */
93: }
94: ap = ap->av_forw;
95: }
96: /*
97: * No inversions... we will go after the last, and
98: * be the first request in the second request list.
99: */
100: goto insert;
101: }
102: /*
103: * Request is at/after the current request...
104: * sort in the first request list.
105: */
106: while (ap->av_forw) {
107: /*
108: * We want to go after the current request
109: * if there is an inversion after it (i.e. it is
110: * the end of the first request list), or if
111: * the next request is a larger cylinder than our request.
112: */
113: if (ap->av_forw->b_cylin < ap->b_cylin ||
114: bp->b_cylin < ap->av_forw->b_cylin ||
115: (bp->b_cylin == ap->av_forw->b_cylin &&
116: bp->b_blkno < ap->av_forw->b_blkno))
117: goto insert;
118: ap = ap->av_forw;
119: }
120: /*
121: * Neither a second list nor a larger
122: * request... we go at the end of the first list,
123: * which is the same as the end of the whole schebang.
124: */
125: insert:
126: bp->av_forw = ap->av_forw;
127: ap->av_forw = bp;
128: if (ap == dp->b_actl)
129: dp->b_actl = bp;
130: }
131:
132: /*
133: * Attempt to read a disk label from a device
134: * using the indicated stategy routine.
135: * The label must be partly set up before this:
136: * secpercyl and anything required in the strategy routine
137: * (e.g., sector size) must be filled in before calling us.
138: * Returns null on success and an error string on failure.
139: */
140: char *
141: readdisklabel(dev, strat, lp)
142: dev_t dev;
143: int (*strat)();
144: register struct disklabel *lp;
145: {
146: register struct buf *bp;
147: struct disklabel *dlp;
148: char *msg = NULL;
149:
150: if (lp->d_secperunit == 0)
151: lp->d_secperunit = 0x1fffffff;
152: lp->d_npartitions = 1;
153: if (lp->d_partitions[0].p_size == 0)
154: lp->d_partitions[0].p_size = 0x1fffffff;
155: lp->d_partitions[0].p_offset = 0;
156:
157: bp = geteblk((int)lp->d_secsize);
158: bp->b_dev = dev;
159: bp->b_blkno = LABELSECTOR;
160: bp->b_bcount = lp->d_secsize;
161: bp->b_flags = B_BUSY | B_READ;
162: bp->b_cylin = LABELSECTOR / lp->d_secpercyl;
163: (*strat)(bp);
164: if (biowait(bp)) {
165: msg = "I/O error";
166: } else for (dlp = (struct disklabel *)bp->b_un.b_addr;
167: dlp <= (struct disklabel *)(bp->b_un.b_addr+DEV_BSIZE-sizeof(*dlp));
168: dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
169: if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
170: if (msg == NULL)
171: msg = "no disk label";
172: } else if (dlp->d_npartitions > MAXPARTITIONS ||
173: dkcksum(dlp) != 0)
174: msg = "disk label corrupted";
175: else {
176: *lp = *dlp;
177: msg = NULL;
178: break;
179: }
180: }
181: bp->b_flags = B_INVAL | B_AGE;
182: brelse(bp);
183: return (msg);
184: }
185:
186: /*
187: * Check new disk label for sensibility
188: * before setting it.
189: */
190: setdisklabel(olp, nlp, openmask)
191: register struct disklabel *olp, *nlp;
192: u_long openmask;
193: {
194: register i;
195: register struct partition *opp, *npp;
196:
197: if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC ||
198: dkcksum(nlp) != 0)
199: return (EINVAL);
200: while ((i = ffs((long)openmask)) != 0) {
201: i--;
202: openmask &= ~(1 << i);
203: if (nlp->d_npartitions <= i)
204: return (EBUSY);
205: opp = &olp->d_partitions[i];
206: npp = &nlp->d_partitions[i];
207: if (npp->p_offset != opp->p_offset || npp->p_size < opp->p_size)
208: return (EBUSY);
209: /*
210: * Copy internally-set partition information
211: * if new label doesn't include it. XXX
212: */
213: if (npp->p_fstype == FS_UNUSED && opp->p_fstype != FS_UNUSED) {
214: npp->p_fstype = opp->p_fstype;
215: npp->p_fsize = opp->p_fsize;
216: npp->p_frag = opp->p_frag;
217: npp->p_cpg = opp->p_cpg;
218: }
219: }
220: nlp->d_checksum = 0;
221: nlp->d_checksum = dkcksum(nlp);
222: *olp = *nlp;
223: return (0);
224: }
225:
226: /* encoding of disk minor numbers, should be elsewhere... */
227: #define dkunit(dev) (minor(dev) >> 3)
228: #define dkpart(dev) (minor(dev) & 07)
229: #define dkminor(unit, part) (((unit) << 3) | (part))
230:
231: /*
232: * Write disk label back to device after modification.
233: */
234: writedisklabel(dev, strat, lp)
235: dev_t dev;
236: int (*strat)();
237: register struct disklabel *lp;
238: {
239: struct buf *bp;
240: struct disklabel *dlp;
241: int labelpart;
242: int error = 0;
243:
244: labelpart = dkpart(dev);
245: if (lp->d_partitions[labelpart].p_offset != 0) {
246: if (lp->d_partitions[0].p_offset != 0)
247: return (EXDEV); /* not quite right */
248: labelpart = 0;
249: }
250: bp = geteblk((int)lp->d_secsize);
251: bp->b_dev = makedev(major(dev), dkminor(dkunit(dev), labelpart));
252: bp->b_blkno = LABELSECTOR;
253: bp->b_bcount = lp->d_secsize;
254: bp->b_flags = B_READ;
255: (*strat)(bp);
256: if (error = biowait(bp))
257: goto done;
258: for (dlp = (struct disklabel *)bp->b_un.b_addr;
259: dlp <= (struct disklabel *)
260: (bp->b_un.b_addr + lp->d_secsize - sizeof(*dlp));
261: dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
262: if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
263: dkcksum(dlp) == 0) {
264: *dlp = *lp;
265: bp->b_flags = B_WRITE;
266: (*strat)(bp);
267: error = biowait(bp);
268: goto done;
269: }
270: }
271: error = ESRCH;
272: done:
273: brelse(bp);
274: return (error);
275: }
276:
277: /*
278: * Compute checksum for disk label.
279: */
280: dkcksum(lp)
281: register struct disklabel *lp;
282: {
283: register u_short *start, *end;
284: register u_short sum = 0;
285:
286: start = (u_short *)lp;
287: end = (u_short *)&lp->d_partitions[lp->d_npartitions];
288: while (start < end)
289: sum ^= *start++;
290: return (sum);
291: }
292:
293: /*
294: * Disk error is the preface to plaintive error messages
295: * about failing disk transfers. It prints messages of the form
296:
297: hp0g: hard error reading fsbn 12345 of 12344-12347 (hp0 bn %d cn %d tn %d sn %d)
298:
299: * if the offset of the error in the transfer and a disk label
300: * are both available. blkdone should be -1 if the position of the error
301: * is unknown; the disklabel pointer may be null from drivers that have not
302: * been converted to use them. The message is printed with printf
303: * if pri is LOG_PRINTF, otherwise it uses log at the specified priority.
304: * The message should be completed (with at least a newline) with printf
305: * or addlog, respectively. There is no trailing space.
306: */
307: diskerr(bp, dname, what, pri, blkdone, lp)
308: register struct buf *bp;
309: char *dname, *what;
310: int pri, blkdone;
311: register struct disklabel *lp;
312: {
313: int unit = dkunit(bp->b_dev), part = dkpart(bp->b_dev);
314: register int (*pr)(), sn;
315: char partname = 'a' + part;
316: extern printf(), addlog();
317:
318: if (pri != LOG_PRINTF) {
319: log(pri, "");
320: pr = addlog;
321: } else
322: pr = printf;
323: (*pr)("%s%d%c: %s %sing fsbn ", dname, unit, partname, what,
324: bp->b_flags & B_READ ? "read" : "writ");
325: sn = bp->b_blkno;
326: if (bp->b_bcount <= DEV_BSIZE)
327: (*pr)("%d", sn);
328: else {
329: if (blkdone >= 0) {
330: sn += blkdone;
331: (*pr)("%d of ", sn);
332: }
333: (*pr)("%d-%d", bp->b_blkno,
334: bp->b_blkno + (bp->b_bcount - 1) / DEV_BSIZE);
335: }
336: if (lp && (blkdone >= 0 || bp->b_bcount <= lp->d_secsize)) {
337: #ifdef tahoe
338: sn *= DEV_BSIZE / lp->d_secsize; /* XXX */
339: #endif
340: sn += lp->d_partitions[part].p_offset;
341: (*pr)(" (%s%d bn %d; cn %d", dname, unit, sn,
342: sn / lp->d_secpercyl);
343: sn %= lp->d_secpercyl;
344: (*pr)(" tn %d sn %d)", sn / lp->d_nsectors, sn % lp->d_nsectors);
345: }
346: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.