2 * Copyright (c) 1994 Bruce D. Evans.
5 * Copyright (c) 1990 The Regents of the University of California.
8 * This code is derived from software contributed to Berkeley by
11 * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
12 * All rights reserved.
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgement:
24 * This product includes software developed by the University of
25 * California, Berkeley and its contributors.
26 * 4. Neither the name of the University nor the names of its contributors
27 * may be used to endorse or promote products derived from this software
28 * without specific prior written permission.
30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 * from: @(#)wd.c 7.2 (Berkeley) 5/9/91
43 * from: wd.c,v 1.55 1994/10/22 01:57:12 phk Exp $
44 * from: @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91
45 * from: ufs_disksubr.c,v 1.8 1994/06/07 01:21:39 phk Exp $
46 * $FreeBSD: src/sys/kern/subr_diskslice.c,v 1.82.2.6 2001/07/24 09:49:41 dd Exp $
47 * $DragonFly: src/sys/kern/subr_diskslice.c,v 1.9 2005/04/30 23:04:21 swildner Exp $
50 #include <sys/param.h>
51 #include <sys/systm.h>
54 #include <sys/disklabel.h>
55 #include <sys/diskslice.h>
56 #include <sys/diskmbr.h>
57 #include <sys/fcntl.h>
58 #include <sys/malloc.h>
60 #include <sys/syslog.h>
61 #include <sys/vnode.h>
62 #include <sys/device.h>
64 #include <vfs/ufs/fs.h>
66 #define TRACE(str) do { if (ds_debug) printf str; } while (0)
68 typedef u_char bool_t
;
70 static volatile bool_t ds_debug
;
72 static struct disklabel
*clone_label (struct disklabel
*lp
);
73 static void dsiodone (struct buf
*bp
);
74 static char *fixlabel (char *sname
, struct diskslice
*sp
,
75 struct disklabel
*lp
, int writeflag
);
76 static void free_ds_label (struct diskslices
*ssp
, int slice
);
77 static void partition_info (char *sname
, int part
, struct partition
*pp
);
78 static void slice_info (char *sname
, struct diskslice
*sp
);
79 static void set_ds_label (struct diskslices
*ssp
, int slice
,
80 struct disklabel
*lp
);
81 static void set_ds_wlabel (struct diskslices
*ssp
, int slice
, int wlabel
);
84 * Duplicate a label for the whole disk, and initialize defaults in the
85 * copy for fields that are not already initialized. The caller only
86 * needs to initialize d_secsize and d_secperunit, and zero the fields
87 * that are to be defaulted.
89 static struct disklabel
*
90 clone_label(struct disklabel
*lp
)
92 struct disklabel
*lp1
;
94 lp1
= malloc(sizeof *lp1
, M_DEVBUF
, M_WAITOK
);
97 if (lp1
->d_typename
[0] == '\0')
98 strncpy(lp1
->d_typename
, "amnesiac", sizeof(lp1
->d_typename
));
99 if (lp1
->d_packname
[0] == '\0')
100 strncpy(lp1
->d_packname
, "fictitious", sizeof(lp1
->d_packname
));
101 if (lp1
->d_nsectors
== 0)
102 lp1
->d_nsectors
= 32;
103 if (lp1
->d_ntracks
== 0)
105 lp1
->d_secpercyl
= lp1
->d_nsectors
* lp1
->d_ntracks
;
106 lp1
->d_ncylinders
= lp1
->d_secperunit
/ lp1
->d_secpercyl
;
109 if (lp1
->d_interleave
== 0)
110 lp1
->d_interleave
= 1;
111 if (lp1
->d_npartitions
< RAW_PART
+ 1)
112 lp1
->d_npartitions
= MAXPARTITIONS
;
113 if (lp1
->d_bbsize
== 0)
114 lp1
->d_bbsize
= BBSIZE
;
115 if (lp1
->d_sbsize
== 0)
116 lp1
->d_sbsize
= SBSIZE
;
117 lp1
->d_partitions
[RAW_PART
].p_size
= lp1
->d_secperunit
;
118 lp1
->d_magic
= DISKMAGIC
;
119 lp1
->d_magic2
= DISKMAGIC
;
120 lp1
->d_checksum
= dkcksum(lp1
);
125 * Determine the size of the transfer, and make sure it is
126 * within the boundaries of the partition. Adjust transfer
127 * if needed, and signal errors or early completion.
130 * o Split buffers that are too big for the device.
131 * o Check for overflow.
132 * o Finish cleaning this up.
135 dscheck(struct buf
*bp
, struct diskslices
*ssp
)
140 struct disklabel
*lp
;
143 struct partition
*pp
;
145 daddr_t slicerel_secno
;
146 struct diskslice
*sp
;
151 printf("dscheck(%s): negative b_blkno %ld\n",
152 devtoname(bp
->b_dev
), (long)blkno
);
153 bp
->b_error
= EINVAL
;
156 sp
= &ssp
->dss_slices
[dkslice(bp
->b_dev
)];
158 if (ssp
->dss_secmult
== 1) {
159 if (bp
->b_bcount
% (u_long
)DEV_BSIZE
)
162 nsec
= bp
->b_bcount
>> DEV_BSHIFT
;
163 } else if (ssp
->dss_secshift
!= -1) {
164 if (bp
->b_bcount
& (ssp
->dss_secsize
- 1))
166 if (blkno
& (ssp
->dss_secmult
- 1))
168 secno
= blkno
>> ssp
->dss_secshift
;
169 nsec
= bp
->b_bcount
>> (DEV_BSHIFT
+ ssp
->dss_secshift
);
171 if (bp
->b_bcount
% ssp
->dss_secsize
)
173 if (blkno
% ssp
->dss_secmult
)
175 secno
= blkno
/ ssp
->dss_secmult
;
176 nsec
= bp
->b_bcount
/ ssp
->dss_secsize
;
179 labelsect
= -LABELSECTOR
- 1;
180 endsecno
= sp
->ds_size
;
181 slicerel_secno
= secno
;
183 labelsect
= lp
->d_partitions
[LABEL_PART
].p_offset
;
185 Debugger("labelsect != 0 in dscheck()");
186 pp
= &lp
->d_partitions
[dkpart(bp
->b_dev
)];
187 endsecno
= pp
->p_size
;
188 slicerel_secno
= pp
->p_offset
+ secno
;
191 /* overwriting disk label ? */
192 /* XXX should also protect bootstrap in first 8K */
193 if (slicerel_secno
<= LABELSECTOR
+ labelsect
&&
195 slicerel_secno
+ nsec
> LABELSECTOR
+ labelsect
&&
197 (bp
->b_flags
& B_READ
) == 0 && sp
->ds_wlabel
== 0) {
202 #if defined(DOSBBSECTOR) && defined(notyet)
203 /* overwriting master boot record? */
204 if (slicerel_secno
<= DOSBBSECTOR
&& (bp
->b_flags
& B_READ
) == 0 &&
205 sp
->ds_wlabel
== 0) {
211 /* beyond partition? */
212 if (secno
+ nsec
> endsecno
) {
213 /* if exactly at end of disk, return an EOF */
214 if (secno
== endsecno
) {
215 bp
->b_resid
= bp
->b_bcount
;
218 /* or truncate if part of it fits */
219 nsec
= endsecno
- secno
;
221 bp
->b_error
= EINVAL
;
224 bp
->b_bcount
= nsec
* ssp
->dss_secsize
;
227 bp
->b_pblkno
= sp
->ds_offset
+ slicerel_secno
;
230 * Snoop on label accesses if the slice offset is nonzero. Fudge
231 * offsets in the label to keep the in-core label coherent with
234 if (slicerel_secno
<= LABELSECTOR
+ labelsect
236 && slicerel_secno
+ nsec
> LABELSECTOR
+ labelsect
238 && sp
->ds_offset
!= 0) {
239 struct iodone_chain
*ic
;
241 ic
= malloc(sizeof *ic
, M_DEVBUF
, M_WAITOK
);
242 ic
->ic_prev_flags
= bp
->b_flags
;
243 ic
->ic_prev_iodone
= bp
->b_iodone
;
244 ic
->ic_prev_iodone_chain
= bp
->b_iodone_chain
;
245 ic
->ic_args
[0].ia_long
= (LABELSECTOR
+ labelsect
-
246 slicerel_secno
) * ssp
->dss_secsize
;
247 ic
->ic_args
[1].ia_ptr
= sp
;
248 bp
->b_flags
|= B_CALL
;
249 bp
->b_iodone
= dsiodone
;
250 bp
->b_iodone_chain
= ic
;
251 if (!(bp
->b_flags
& B_READ
)) {
253 * XXX even disklabel(8) writes directly so we need
254 * to adjust writes. Perhaps we should drop support
255 * for DIOCWLABEL (always write protect labels) and
256 * require the use of DIOCWDINFO.
258 * XXX probably need to copy the data to avoid even
259 * temporarily corrupting the in-core copy.
261 if (bp
->b_vp
!= NULL
) {
263 bp
->b_vp
->v_numoutput
++;
266 /* XXX need name here. */
267 msg
= fixlabel((char *)NULL
, sp
,
269 (bp
->b_data
+ ic
->ic_args
[0].ia_long
),
272 printf("dscheck(%s): %s\n",
273 devtoname(bp
->b_dev
), msg
);
283 "dscheck(%s): b_bcount %ld is not on a sector boundary (ssize %d)\n",
284 devtoname(bp
->b_dev
), bp
->b_bcount
, ssp
->dss_secsize
);
285 bp
->b_error
= EINVAL
;
290 "dscheck(%s): b_blkno %ld is not on a sector boundary (ssize %d)\n",
291 devtoname(bp
->b_dev
), (long)blkno
, ssp
->dss_secsize
);
292 bp
->b_error
= EINVAL
;
296 bp
->b_resid
= bp
->b_bcount
;
297 bp
->b_flags
|= B_ERROR
;
302 dsclose(dev_t dev
, int mode
, struct diskslices
*ssp
)
305 struct diskslice
*sp
;
307 sp
= &ssp
->dss_slices
[dkslice(dev
)];
308 mask
= 1 << dkpart(dev
);
309 sp
->ds_openmask
&= ~mask
;
313 dsgone(struct diskslices
**sspp
)
316 struct diskslice
*sp
;
317 struct diskslices
*ssp
;
319 for (slice
= 0, ssp
= *sspp
; slice
< ssp
->dss_nslices
; slice
++) {
320 sp
= &ssp
->dss_slices
[slice
];
321 free_ds_label(ssp
, slice
);
328 * For the "write" commands (DIOCSDINFO and DIOCWDINFO), this
329 * is subject to the same restriction as dsopen().
332 dsioctl(dev_t dev
, u_long cmd
, caddr_t data
,
333 int flags
, struct diskslices
**sspp
)
336 struct disklabel
*lp
;
341 struct diskslice
*sp
;
342 struct diskslices
*ssp
;
343 struct partition
*pp
;
345 slice
= dkslice(dev
);
347 sp
= &ssp
->dss_slices
[slice
];
352 lp
= (struct disklabel
*)data
;
353 if (ssp
->dss_slices
[WHOLE_DISK_SLICE
].ds_label
) {
354 *lp
= *ssp
->dss_slices
[WHOLE_DISK_SLICE
].ds_label
;
356 bzero(lp
, sizeof(struct disklabel
));
359 lp
->d_magic
= DISKMAGIC
;
360 lp
->d_magic2
= DISKMAGIC
;
361 pp
= &lp
->d_partitions
[RAW_PART
];
363 pp
->p_size
= sp
->ds_size
;
365 lp
->d_npartitions
= MAXPARTITIONS
;
366 if (lp
->d_interleave
== 0)
367 lp
->d_interleave
= 1;
370 if (lp
->d_nsectors
== 0)
372 if (lp
->d_ntracks
== 0)
375 lp
->d_bbsize
= BBSIZE
;
376 lp
->d_sbsize
= SBSIZE
;
377 lp
->d_secpercyl
= lp
->d_nsectors
* lp
->d_ntracks
;
378 lp
->d_ncylinders
= sp
->ds_size
/ lp
->d_secpercyl
;
379 lp
->d_secperunit
= sp
->ds_size
;
381 lp
->d_checksum
= dkcksum(lp
);
387 *(struct disklabel
*)data
= *lp
;
394 *(struct disklabel
**)data
= lp
;
401 ((struct partinfo
*)data
)->disklab
= lp
;
402 ((struct partinfo
*)data
)->part
403 = &lp
->d_partitions
[dkpart(dev
)];
407 bcopy(ssp
, data
, (char *)&ssp
->dss_slices
[ssp
->dss_nslices
] -
412 if (slice
== WHOLE_DISK_SLICE
)
414 if (!(flags
& FWRITE
))
416 lp
= malloc(sizeof *lp
, M_DEVBUF
, M_WAITOK
);
417 if (sp
->ds_label
== NULL
)
418 bzero(lp
, sizeof *lp
);
420 bcopy(sp
->ds_label
, lp
, sizeof *lp
);
421 if (sp
->ds_label
== NULL
)
424 openmask
= sp
->ds_openmask
;
425 if (slice
== COMPATIBILITY_SLICE
)
426 openmask
|= ssp
->dss_slices
[
427 ssp
->dss_first_bsd_slice
].ds_openmask
;
428 else if (slice
== ssp
->dss_first_bsd_slice
)
429 openmask
|= ssp
->dss_slices
[
430 COMPATIBILITY_SLICE
].ds_openmask
;
432 error
= setdisklabel(lp
, (struct disklabel
*)data
,
434 /* XXX why doesn't setdisklabel() check this? */
435 if (error
== 0 && lp
->d_partitions
[RAW_PART
].p_offset
!= 0)
438 if (lp
->d_secperunit
> sp
->ds_size
)
440 for (part
= 0; part
< lp
->d_npartitions
; part
++)
441 if (lp
->d_partitions
[part
].p_size
> sp
->ds_size
)
448 free_ds_label(ssp
, slice
);
449 set_ds_label(ssp
, slice
, lp
);
452 case DIOCSYNCSLICEINFO
:
453 if (slice
!= WHOLE_DISK_SLICE
|| dkpart(dev
) != RAW_PART
)
456 for (slice
= 0; slice
< ssp
->dss_nslices
; slice
++) {
457 openmask
= ssp
->dss_slices
[slice
].ds_openmask
;
459 && (slice
!= WHOLE_DISK_SLICE
460 || openmask
& ~(1 << RAW_PART
)))
465 * Temporarily forget the current slices struct and read
467 * XXX should wait for current accesses on this disk to
468 * complete, then lock out future accesses and opens.
471 lp
= malloc(sizeof *lp
, M_DEVBUF
, M_WAITOK
);
472 *lp
= *ssp
->dss_slices
[WHOLE_DISK_SLICE
].ds_label
;
473 error
= dsopen(dev
, S_IFCHR
, ssp
->dss_oflags
, sspp
, lp
);
481 * Reopen everything. This is a no-op except in the "force"
482 * case and when the raw bdev and cdev are both open. Abort
485 for (slice
= 0; slice
< ssp
->dss_nslices
; slice
++) {
486 for (openmask
= ssp
->dss_slices
[slice
].ds_openmask
,
487 part
= 0; openmask
; openmask
>>= 1, part
++) {
490 error
= dsopen(dkmodslice(dkmodpart(dev
, part
),
492 S_IFCHR
, ssp
->dss_oflags
, sspp
,
507 error
= dsioctl(dev
, DIOCSDINFO
, data
, flags
, &ssp
);
511 * XXX this used to hack on dk_openpart to fake opening
512 * partition 0 in case that is used instead of dkpart(dev).
514 old_wlabel
= sp
->ds_wlabel
;
515 set_ds_wlabel(ssp
, slice
, TRUE
);
516 error
= writedisklabel(dev
, sp
->ds_label
);
517 /* XXX should invalidate in-core label if write failed. */
518 set_ds_wlabel(ssp
, slice
, old_wlabel
);
522 if (slice
== WHOLE_DISK_SLICE
)
524 if (!(flags
& FWRITE
))
526 set_ds_wlabel(ssp
, slice
, *(int *)data
!= 0);
535 dsiodone(struct buf
*bp
)
537 struct iodone_chain
*ic
;
540 ic
= bp
->b_iodone_chain
;
541 bp
->b_flags
= (ic
->ic_prev_flags
& B_CALL
)
542 | (bp
->b_flags
& ~(B_CALL
| B_DONE
));
543 bp
->b_iodone
= ic
->ic_prev_iodone
;
544 bp
->b_iodone_chain
= ic
->ic_prev_iodone_chain
;
545 if (!(bp
->b_flags
& B_READ
)
546 || (!(bp
->b_flags
& B_ERROR
) && bp
->b_error
== 0)) {
547 msg
= fixlabel((char *)NULL
, ic
->ic_args
[1].ia_ptr
,
549 (bp
->b_data
+ ic
->ic_args
[0].ia_long
),
559 dsisopen(struct diskslices
*ssp
)
565 for (slice
= 0; slice
< ssp
->dss_nslices
; slice
++) {
566 if (ssp
->dss_slices
[slice
].ds_openmask
)
573 * Allocate a slices "struct" and initialize it to contain only an empty
574 * compatibility slice (pointing to itself), a whole disk slice (covering
575 * the disk as described by the label), and (nslices - BASE_SLICES) empty
576 * slices beginning at BASE_SLICE.
579 dsmakeslicestruct(int nslices
, struct disklabel
*lp
)
581 struct diskslice
*sp
;
582 struct diskslices
*ssp
;
584 ssp
= malloc(offsetof(struct diskslices
, dss_slices
) +
585 nslices
* sizeof *sp
, M_DEVBUF
, M_WAITOK
);
586 ssp
->dss_first_bsd_slice
= COMPATIBILITY_SLICE
;
587 ssp
->dss_nslices
= nslices
;
589 ssp
->dss_secmult
= lp
->d_secsize
/ DEV_BSIZE
;
590 if (ssp
->dss_secmult
& (ssp
->dss_secmult
- 1))
591 ssp
->dss_secshift
= -1;
593 ssp
->dss_secshift
= ffs(ssp
->dss_secmult
) - 1;
594 ssp
->dss_secsize
= lp
->d_secsize
;
595 sp
= &ssp
->dss_slices
[0];
596 bzero(sp
, nslices
* sizeof *sp
);
597 sp
[WHOLE_DISK_SLICE
].ds_size
= lp
->d_secperunit
;
602 dsname(dev_t dev
, int unit
, int slice
, int part
, char *partname
)
604 static char name
[32];
607 dname
= dev_dname(dev
);
608 if (strlen(dname
) > 16)
609 dname
= "nametoolong";
610 snprintf(name
, sizeof(name
), "%s%d", dname
, unit
);
612 if (slice
!= WHOLE_DISK_SLICE
|| part
!= RAW_PART
) {
613 partname
[0] = 'a' + part
;
615 if (slice
!= COMPATIBILITY_SLICE
) {
616 snprintf(name
+ strlen(name
),
617 sizeof(name
) - strlen(name
), "s%d", slice
- 1);
624 * This should only be called when the unit is inactive and the strategy
625 * routine should not allow it to become active unless we call it. Our
626 * strategy routine must be special to allow activity.
629 dsopen(dev_t dev
, int mode
, u_int flags
,
630 struct diskslices
**sspp
, struct disklabel
*lp
)
634 struct disklabel
*lp1
;
642 struct diskslice
*sp
;
643 struct diskslices
*ssp
;
646 dev
->si_bsize_phys
= lp
->d_secsize
;
649 if (lp
->d_secsize
% DEV_BSIZE
) {
650 printf("%s: invalid sector size %lu\n", devtoname(dev
),
651 (u_long
)lp
->d_secsize
);
656 * XXX reinitialize the slice table unless there is an open device
657 * on the unit. This should only be done if the media has changed.
660 need_init
= !dsisopen(ssp
);
661 if (ssp
!= NULL
&& need_init
)
665 * Allocate a minimal slices "struct". This will become
666 * the final slices "struct" if we don't want real slices
667 * or if we can't find any real slices.
669 *sspp
= dsmakeslicestruct(BASE_SLICE
, lp
);
671 if (!(flags
& DSO_ONESLICE
)) {
673 error
= dsinit(dev
, lp
, sspp
);
680 ssp
->dss_oflags
= flags
;
683 * If there are no real slices, then make the compatiblity
684 * slice cover the whole disk.
686 if (ssp
->dss_nslices
== BASE_SLICE
)
687 ssp
->dss_slices
[COMPATIBILITY_SLICE
].ds_size
690 /* Point the compatibility slice at the BSD slice, if any. */
691 for (slice
= BASE_SLICE
; slice
< ssp
->dss_nslices
; slice
++) {
692 sp
= &ssp
->dss_slices
[slice
];
693 if (sp
->ds_type
== DOSPTYP_386BSD
/* XXX */) {
694 ssp
->dss_first_bsd_slice
= slice
;
695 ssp
->dss_slices
[COMPATIBILITY_SLICE
].ds_offset
697 ssp
->dss_slices
[COMPATIBILITY_SLICE
].ds_size
699 ssp
->dss_slices
[COMPATIBILITY_SLICE
].ds_type
705 ssp
->dss_slices
[WHOLE_DISK_SLICE
].ds_label
= clone_label(lp
);
706 ssp
->dss_slices
[WHOLE_DISK_SLICE
].ds_wlabel
= TRUE
;
710 * Initialize secondary info for all slices. It is needed for more
711 * than the current slice in the DEVFS case. XXX DEVFS is no more.
713 for (slice
= 0; slice
< ssp
->dss_nslices
; slice
++) {
714 sp
= &ssp
->dss_slices
[slice
];
715 if (sp
->ds_label
!= NULL
)
717 dev1
= dkmodslice(dkmodpart(dev
, RAW_PART
), slice
);
718 sname
= dsname(dev
, unit
, slice
, RAW_PART
, partname
);
720 * XXX this should probably only be done for the need_init
721 * case, but there may be a problem with DIOCSYNCSLICEINFO.
723 set_ds_wlabel(ssp
, slice
, TRUE
); /* XXX invert */
724 lp1
= clone_label(lp
);
725 TRACE(("readdisklabel\n"));
726 if (flags
& DSO_NOLABELS
)
729 msg
= readdisklabel(dev1
, lp1
);
732 * readdisklabel() returns NULL for success, and an
733 * error string for failure.
735 * If there isn't a label on the disk, and if the
736 * DSO_COMPATLABEL is set, we want to use the
737 * faked-up label provided by the caller.
739 * So we set msg to NULL to indicate that there is
740 * no failure (since we have a faked-up label),
741 * free lp1, and then clone it again from lp.
742 * (In case readdisklabel() modified lp1.)
744 if (msg
!= NULL
&& (flags
& DSO_COMPATLABEL
)) {
747 lp1
= clone_label(lp
);
751 msg
= fixlabel(sname
, sp
, lp1
, FALSE
);
752 if (msg
== NULL
&& lp1
->d_secsize
!= ssp
->dss_secsize
)
753 msg
= "inconsistent sector size";
755 if (sp
->ds_type
== DOSPTYP_386BSD
/* XXX */)
756 log(LOG_WARNING
, "%s: cannot find label (%s)\n",
761 if (lp1
->d_flags
& D_BADSECT
) {
762 log(LOG_ERR
, "%s: bad sector table not supported\n",
767 set_ds_label(ssp
, slice
, lp1
);
768 set_ds_wlabel(ssp
, slice
, FALSE
);
771 slice
= dkslice(dev
);
772 if (slice
>= ssp
->dss_nslices
)
774 sp
= &ssp
->dss_slices
[slice
];
777 && (sp
->ds_label
== NULL
|| part
>= sp
->ds_label
->d_npartitions
))
778 return (EINVAL
); /* XXX needs translation */
780 sp
->ds_openmask
|= mask
;
785 dssize(dev_t dev
, struct diskslices
**sspp
)
787 struct disklabel
*lp
;
790 struct diskslices
*ssp
;
792 slice
= dkslice(dev
);
795 if (ssp
== NULL
|| slice
>= ssp
->dss_nslices
796 || !(ssp
->dss_slices
[slice
].ds_openmask
& (1 << part
))) {
797 if (dev_dopen(dev
, FREAD
, S_IFCHR
, NULL
) != 0)
799 dev_dclose(dev
, FREAD
, S_IFCHR
, NULL
);
802 lp
= ssp
->dss_slices
[slice
].ds_label
;
805 return ((int)lp
->d_partitions
[part
].p_size
);
809 free_ds_label(struct diskslices
*ssp
, int slice
)
811 struct disklabel
*lp
;
812 struct diskslice
*sp
;
814 sp
= &ssp
->dss_slices
[slice
];
819 set_ds_label(ssp
, slice
, (struct disklabel
*)NULL
);
823 fixlabel(char *sname
, struct diskslice
*sp
, struct disklabel
*lp
, int writeflag
)
828 struct partition
*pp
;
832 /* These errors "can't happen" so don't bother reporting details. */
833 if (lp
->d_magic
!= DISKMAGIC
|| lp
->d_magic2
!= DISKMAGIC
)
834 return ("fixlabel: invalid magic");
835 if (dkcksum(lp
) != 0)
836 return ("fixlabel: invalid checksum");
838 pp
= &lp
->d_partitions
[RAW_PART
];
841 offset
= sp
->ds_offset
;
843 start
= sp
->ds_offset
;
844 offset
= -sp
->ds_offset
;
846 if (pp
->p_offset
!= start
) {
849 "%s: rejecting BSD label: raw partition offset != slice offset\n",
851 slice_info(sname
, sp
);
852 partition_info(sname
, RAW_PART
, pp
);
854 return ("fixlabel: raw partition offset != slice offset");
856 if (pp
->p_size
!= sp
->ds_size
) {
858 printf("%s: raw partition size != slice size\n", sname
);
859 slice_info(sname
, sp
);
860 partition_info(sname
, RAW_PART
, pp
);
862 if (pp
->p_size
> sp
->ds_size
) {
864 return ("fixlabel: raw partition size > slice size");
865 printf("%s: truncating raw partition\n", sname
);
866 pp
->p_size
= sp
->ds_size
;
869 end
= start
+ sp
->ds_size
;
871 return ("fixlabel: slice wraps");
872 if (lp
->d_secpercyl
<= 0)
873 return ("fixlabel: d_secpercyl <= 0");
876 for (part
= 0; part
< lp
->d_npartitions
; part
++, pp
++) {
877 if (pp
->p_offset
!= 0 || pp
->p_size
!= 0) {
878 if (pp
->p_offset
< start
879 || pp
->p_offset
+ pp
->p_size
> end
880 || pp
->p_offset
+ pp
->p_size
< pp
->p_offset
) {
883 "%s: rejecting partition in BSD label: it isn't entirely within the slice\n",
886 slice_info(sname
, sp
);
889 partition_info(sname
, part
, pp
);
891 /* XXX else silently discard junk. */
892 bzero(pp
, sizeof *pp
);
894 pp
->p_offset
+= offset
;
897 lp
->d_ncylinders
= sp
->ds_size
/ lp
->d_secpercyl
;
898 lp
->d_secperunit
= sp
->ds_size
;
900 lp
->d_checksum
= dkcksum(lp
);
905 partition_info(char *sname
, int part
, struct partition
*pp
)
907 printf("%s%c: start %lu, end %lu, size %lu\n", sname
, 'a' + part
,
908 (u_long
)pp
->p_offset
, (u_long
)(pp
->p_offset
+ pp
->p_size
- 1),
913 slice_info(char *sname
, struct diskslice
*sp
)
915 printf("%s: start %lu, end %lu, size %lu\n", sname
,
916 sp
->ds_offset
, sp
->ds_offset
+ sp
->ds_size
- 1, sp
->ds_size
);
920 set_ds_label(struct diskslices
*ssp
, int slice
, struct disklabel
*lp
)
922 ssp
->dss_slices
[slice
].ds_label
= lp
;
923 if (slice
== COMPATIBILITY_SLICE
)
924 ssp
->dss_slices
[ssp
->dss_first_bsd_slice
].ds_label
= lp
;
925 else if (slice
== ssp
->dss_first_bsd_slice
)
926 ssp
->dss_slices
[COMPATIBILITY_SLICE
].ds_label
= lp
;
930 set_ds_wlabel(struct diskslices
*ssp
, int slice
, int wlabel
)
932 ssp
->dss_slices
[slice
].ds_wlabel
= wlabel
;
933 if (slice
== COMPATIBILITY_SLICE
)
934 ssp
->dss_slices
[ssp
->dss_first_bsd_slice
].ds_wlabel
= wlabel
;
935 else if (slice
== ssp
->dss_first_bsd_slice
)
936 ssp
->dss_slices
[COMPATIBILITY_SLICE
].ds_wlabel
= wlabel
;