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.46 2007/06/18 05:13:42 dillon Exp $
50 #include <sys/param.h>
51 #include <sys/systm.h>
54 #include <sys/disklabel.h>
55 #include <sys/disklabel32.h>
56 #include <sys/diskslice.h>
58 #include <sys/diskmbr.h>
59 #include <sys/fcntl.h>
60 #include <sys/malloc.h>
62 #include <sys/syslog.h>
64 #include <sys/vnode.h>
65 #include <sys/device.h>
66 #include <sys/thread2.h>
68 #include <vfs/ufs/dinode.h> /* XXX used only for fs.h */
69 #include <vfs/ufs/fs.h> /* XXX used only to get BBSIZE/SBSIZE */
71 static int dsreadandsetlabel(cdev_t dev, u_int flags,
72 struct diskslices *ssp, struct diskslice *sp,
73 struct disk_info *info);
74 static void free_ds_label (struct diskslices *ssp, int slice);
75 static void set_ds_label (struct diskslices *ssp, int slice, disklabel_t lp);
76 static void set_ds_wlabel (struct diskslices *ssp, int slice, int wlabel);
78 #define ops (&disklabel32_ops)
81 * Determine the size of the transfer, and make sure it is
82 * within the boundaries of the partition. Adjust transfer
83 * if needed, and signal errors or early completion.
86 * o Split buffers that are too big for the device.
87 * o Check for overflow.
88 * o Finish cleaning this up.
90 * This function returns 1 on success, 0 if transfer equates
91 * to EOF (end of disk) or -1 on failure. The appropriate
92 * 'errno' value is also set in bp->b_error and bp->b_flags
93 * is marked with B_ERROR.
96 dscheck(cdev_t dev, struct bio *bio, struct diskslices *ssp)
98 struct buf *bp = bio->bio_buf;
104 u_int64_t slicerel_secno;
105 struct diskslice *sp;
111 slice = dkslice(dev);
114 if (bio->bio_offset < 0) {
115 kprintf("dscheck(%s): negative bio_offset %lld\n",
116 devtoname(dev), bio->bio_offset);
119 if (slice >= ssp->dss_nslices) {
120 kprintf("dscheck(%s): slice too large %d/%d\n",
121 devtoname(dev), slice, ssp->dss_nslices);
124 sp = &ssp->dss_slices[slice];
127 * Calculate secno and nsec
129 if (ssp->dss_secmult == 1) {
132 } else if (ssp->dss_secshift != -1) {
133 shift = DEV_BSHIFT + ssp->dss_secshift;
135 mask = (1 << shift) - 1;
136 if ((int)bp->b_bcount & mask)
138 if ((int)bio->bio_offset & mask)
140 secno = bio->bio_offset >> shift;
141 nsec = bp->b_bcount >> shift;
143 if (bp->b_bcount % ssp->dss_secsize)
145 if (bio->bio_offset % ssp->dss_secsize)
147 secno = bio->bio_offset / ssp->dss_secsize;
148 nsec = bp->b_bcount / ssp->dss_secsize;
152 * Calculate slice-relative sector number end slice-relative
155 if (slice == WHOLE_DISK_SLICE) {
157 * Labels have not been allowed on whole-disks for a while.
158 * This really puts the nail in the coffin.
160 * Accesses to the WHOLE_DISK_SLICE do not use a disklabel
161 * and partition numbers are special-cased. Currently numbers
162 * less then 128 are not allowed. Partition numbers >= 128
163 * are encoded in the high 8 bits of the 64 bit buffer offset
164 * and are fed directly through to the device with no
165 * further interpretation. In particular, no sector
166 * translation interpretation should occur because the
167 * sector size for the special raw access may not be the
168 * same as the nominal sector size for the device.
172 kprintf("dscheck(%s): illegal partition number (%d) "
173 "for WHOLE_DISK_SLICE access\n",
174 devtoname(dev), part);
176 } else if (part != WHOLE_SLICE_PART) {
177 nbio = push_bio(bio);
178 nbio->bio_offset = bio->bio_offset |
179 (u_int64_t)part << 56;
184 * sp->ds_size is for the whole disk in the WHOLE_DISK_SLICE,
185 * there are no reserved areas.
187 endsecno = sp->ds_size;
188 slicerel_secno = secno;
189 } else if (part == WHOLE_SLICE_PART) {
191 * NOTE! opens on a whole-slice partition will not attempt
192 * to read a disklabel in, so there may not be an in-core
193 * disklabel even if there is one on the disk.
195 endsecno = sp->ds_size;
196 slicerel_secno = secno;
197 } else if ((lp = sp->ds_label).opaque != NULL) {
199 * A label is present, extract the partition. Snooping of
200 * the disklabel is not supported even if accessible. Of
201 * course, the reserved area is still write protected.
203 if (ops->op_getpartbounds(lp, part, &slicerel_secno, &endsecno)) {
204 kprintf("dscheck(%s): partition %d out of bounds\n",
205 devtoname(dev), part);
208 slicerel_secno += secno;
211 * Attempt to access partition when no disklabel present
213 kprintf("dscheck(%s): attempt to access non-existant partition\n",
219 * Disallow writes to reserved areas unless ds_wlabel allows it.
221 if (slicerel_secno < sp->ds_reserved && nsec &&
222 bp->b_cmd != BUF_CMD_READ && sp->ds_wlabel == 0) {
228 * If we get here, bio_offset must be on a block boundary and
229 * the sector size must be a power of 2.
231 if ((bio->bio_offset & (ssp->dss_secsize - 1)) ||
232 (ssp->dss_secsize ^ (ssp->dss_secsize - 1)) !=
233 ((ssp->dss_secsize << 1) - 1)) {
234 kprintf("%s: invalid BIO offset, not sector aligned or"
235 " invalid sector size (not power of 2) %08llx %d\n",
236 devtoname(dev), bio->bio_offset, ssp->dss_secsize);
243 if (secno + nsec > endsecno) {
245 * Return an error if beyond the end of the disk, or
246 * if B_BNOCLIP is set. Tell the system that we do not
247 * need to keep the buffer around.
249 if (secno > endsecno || (bp->b_flags & B_BNOCLIP))
253 * If exactly at end of disk, return an EOF. Throw away
254 * the buffer contents, if any, by setting B_INVAL.
256 if (secno == endsecno) {
257 bp->b_resid = bp->b_bcount;
258 bp->b_flags |= B_INVAL;
265 nsec = endsecno - secno;
266 bp->b_bcount = nsec * ssp->dss_secsize;
269 nbio = push_bio(bio);
270 nbio->bio_offset = (off_t)(sp->ds_offset + slicerel_secno) *
276 "dscheck(%s): b_bcount %d is not on a sector boundary (ssize %d)\n",
277 devtoname(dev), bp->b_bcount, ssp->dss_secsize);
282 "dscheck(%s): bio_offset %lld is not on a sector boundary (ssize %d)\n",
283 devtoname(dev), bio->bio_offset, ssp->dss_secsize);
285 bp->b_error = EINVAL;
289 * Terminate the I/O with a ranging error. Since the buffer is
290 * either illegal or beyond the file EOF, mark it B_INVAL as well.
292 bp->b_resid = bp->b_bcount;
293 bp->b_flags |= B_ERROR | B_INVAL;
296 * Caller must biodone() the originally passed bio if NULL is
303 dsclose(cdev_t dev, int mode, struct diskslices *ssp)
307 struct diskslice *sp;
309 slice = dkslice(dev);
311 if (slice < ssp->dss_nslices) {
312 sp = &ssp->dss_slices[slice];
318 dsgone(struct diskslices **sspp)
321 struct diskslice *sp;
322 struct diskslices *ssp;
324 for (slice = 0, ssp = *sspp; slice < ssp->dss_nslices; slice++) {
325 sp = &ssp->dss_slices[slice];
326 free_ds_label(ssp, slice);
328 kfree(ssp, M_DEVBUF);
333 * For the "write" commands (DIOCSDINFO and DIOCWDINFO), this
334 * is subject to the same restriction as dsopen().
337 dsioctl(cdev_t dev, u_long cmd, caddr_t data, int flags,
338 struct diskslices **sspp, struct disk_info *info)
344 u_int32_t openmask[DKMAXPARTITIONS/(sizeof(u_int32_t)*8)];
347 struct diskslice *sp;
348 struct diskslices *ssp;
350 slice = dkslice(dev);
353 if (slice >= ssp->dss_nslices)
355 sp = &ssp->dss_slices[slice];
361 * You can only retrieve a virgin disklabel on the whole
362 * disk slice or whole-slice partition.
364 if (slice != WHOLE_DISK_SLICE &&
365 part != WHOLE_SLICE_PART) {
370 ops->op_makevirginlabel(lp, ssp, sp, info);
375 * You can only retrieve a disklabel on the whole
378 * We do not support labels directly on whole-disks
379 * any more (that is, disks without slices), unless the
380 * device driver has asked for a compatible label (e.g.
381 * for a CD) to allow booting off of storage that is
382 * otherwise unlabeled.
385 if (part != WHOLE_SLICE_PART)
387 if (slice == WHOLE_DISK_SLICE &&
388 (info->d_dsflags & DSO_COMPATLABEL) == 0) {
391 if (sp->ds_label.opaque == NULL) {
392 error = dsreadandsetlabel(dev, info->d_dsflags,
396 bcopy(sp->ds_label.opaque, data, ops->labelsize);
401 struct partinfo *dpart = (void *)data;
404 * The disk management layer may not have read the
405 * disklabel yet because simply opening a slice no
406 * longer 'probes' the disk that way. Be sure we
409 * We ignore any error.
411 if (sp->ds_label.opaque == NULL &&
412 part == WHOLE_SLICE_PART &&
413 slice != WHOLE_DISK_SLICE) {
414 dsreadandsetlabel(dev, info->d_dsflags,
418 bzero(dpart, sizeof(*dpart));
419 dpart->media_offset = (u_int64_t)sp->ds_offset *
420 info->d_media_blksize;
421 dpart->media_size = (u_int64_t)sp->ds_size *
422 info->d_media_blksize;
423 dpart->media_blocks = sp->ds_size;
424 dpart->media_blksize = info->d_media_blksize;
425 dpart->reserved_blocks= sp->ds_reserved;
427 if (slice != WHOLE_DISK_SLICE &&
428 part != WHOLE_SLICE_PART) {
431 if (lp.opaque == NULL)
433 if (ops->op_getpartbounds(lp, part, &start, &blocks))
435 dpart->fstype = ops->op_getpartfstype(lp, part);
436 dpart->media_offset += start *
437 info->d_media_blksize;
438 dpart->media_size = blocks *
439 info->d_media_blksize;
440 dpart->media_blocks = blocks;
443 * partition starting sector (p_offset)
444 * requires slice's reserved areas to be
447 if (dpart->reserved_blocks > start)
448 dpart->reserved_blocks -= start;
450 dpart->reserved_blocks = 0;
454 * Load remaining fields from the info structure
456 dpart->d_nheads = info->d_nheads;
457 dpart->d_ncylinders = info->d_ncylinders;
458 dpart->d_secpertrack = info->d_secpertrack;
459 dpart->d_secpercyl = info->d_secpercyl;
464 bcopy(ssp, data, (char *)&ssp->dss_slices[ssp->dss_nslices] -
470 * You can write a disklabel on the whole disk slice or
471 * whole-slice partition.
473 if (slice != WHOLE_DISK_SLICE &&
474 part != WHOLE_SLICE_PART) {
479 * We no longer support writing disklabels directly to media
480 * without there being a slice. Keep this as a separate
483 if (slice == WHOLE_DISK_SLICE)
486 if (!(flags & FWRITE))
488 lp.opaque = kmalloc(ops->labelsize, M_DEVBUF, M_WAITOK);
489 if (sp->ds_label.opaque == NULL)
490 bzero(lp.opaque, ops->labelsize);
492 bcopy(sp->ds_label.opaque, lp.opaque, ops->labelsize);
493 if (sp->ds_label.opaque == NULL) {
494 bzero(openmask, sizeof(openmask));
496 bcopy(sp->ds_openmask, openmask, sizeof(openmask));
499 error = ops->op_setdisklabel(lp, lptmp, sp, openmask);
501 kfree(lp.opaque, M_DEVBUF);
504 free_ds_label(ssp, slice);
505 set_ds_label(ssp, slice, lp);
508 case DIOCSYNCSLICEINFO:
510 * This ioctl can only be done on the whole disk
512 if (slice != WHOLE_DISK_SLICE || part != WHOLE_SLICE_PART)
515 if (*(int *)data == 0) {
516 for (slice = 0; slice < ssp->dss_nslices; slice++) {
517 struct diskslice *ds = &ssp->dss_slices[slice];
519 switch(dscountmask(ds)) {
523 if (slice != WHOLE_DISK_SLICE)
525 if (!dschkmask(ds, RAW_PART))
535 * Temporarily forget the current slices struct and read
540 * XXX should wait for current accesses on this disk to
541 * complete, then lock out future accesses and opens.
544 error = dsopen(dev, S_IFCHR, ssp->dss_oflags, sspp, info);
551 * Reopen everything. This is a no-op except in the "force"
552 * case and when the raw bdev and cdev are both open. Abort
555 for (slice = 0; slice < ssp->dss_nslices; slice++) {
556 for (part = 0; part < DKMAXPARTITIONS; ++part) {
557 if (!dschkmask(&ssp->dss_slices[slice], part))
559 error = dsopen(dkmodslice(dkmodpart(dev, part),
561 S_IFCHR, ssp->dss_oflags, sspp,
574 error = dsioctl(dev, DIOCSDINFO32, data, flags, &ssp, info);
579 * Set the reserved area
581 old_wlabel = sp->ds_wlabel;
582 set_ds_wlabel(ssp, slice, TRUE);
583 error = ops->op_writedisklabel(dev, sp, sp->ds_label);
584 set_ds_wlabel(ssp, slice, old_wlabel);
585 /* XXX should invalidate in-core label if write failed. */
589 if (slice == WHOLE_DISK_SLICE)
591 if (!(flags & FWRITE))
593 set_ds_wlabel(ssp, slice, *(int *)data != 0);
602 dsisopen(struct diskslices *ssp)
608 for (slice = 0; slice < ssp->dss_nslices; slice++) {
609 if (dscountmask(&ssp->dss_slices[slice]))
616 * Allocate a slices "struct" and initialize it to contain only an empty
617 * compatibility slice (pointing to itself), a whole disk slice (covering
618 * the disk as described by the label), and (nslices - BASE_SLICES) empty
619 * slices beginning at BASE_SLICE.
621 * Note that the compatibility slice is no longer really a compatibility
622 * slice. It is slice 0 if a GPT label is present, and the dangerously
623 * dedicated slice if no slice table otherwise exists. Else it is 0-sized.
626 dsmakeslicestruct(int nslices, struct disk_info *info)
628 struct diskslice *sp;
629 struct diskslices *ssp;
631 ssp = kmalloc(offsetof(struct diskslices, dss_slices) +
632 nslices * sizeof *sp, M_DEVBUF, M_WAITOK);
633 ssp->dss_first_bsd_slice = COMPATIBILITY_SLICE;
634 ssp->dss_nslices = nslices;
638 * Figure out if we can use shifts or whether we have to
639 * use mod/multply to translate byte offsets into sector numbers.
641 if ((info->d_media_blksize ^ (info->d_media_blksize - 1)) ==
642 (info->d_media_blksize << 1) - 1) {
643 ssp->dss_secmult = info->d_media_blksize / DEV_BSIZE;
644 if (ssp->dss_secmult & (ssp->dss_secmult - 1))
645 ssp->dss_secshift = -1;
647 ssp->dss_secshift = ffs(ssp->dss_secmult) - 1;
649 ssp->dss_secmult = 0;
650 ssp->dss_secshift = -1;
652 ssp->dss_secsize = info->d_media_blksize;
653 sp = &ssp->dss_slices[0];
654 bzero(sp, nslices * sizeof *sp);
655 sp[WHOLE_DISK_SLICE].ds_size = info->d_media_blocks;
660 dsname(cdev_t dev, int unit, int slice, int part, char *partname)
662 static char name[32];
666 dname = dev_dname(dev);
667 if (strlen(dname) > 16)
668 dname = "nametoolong";
669 ksnprintf(name, sizeof(name), "%s%d", dname, unit);
673 if (slice != WHOLE_DISK_SLICE) {
675 * slice or slice + partition. BASE_SLICE is s1, but
676 * the compatibility slice (0) needs to be s0.
678 used += ksnprintf(name + used, sizeof(name) - used,
679 "s%d", (slice ? slice - BASE_SLICE + 1 : 0));
680 if (part != WHOLE_SLICE_PART) {
681 used += ksnprintf(name + used, sizeof(name) - used,
683 partname[0] = 'a' + part;
686 } else if (part == WHOLE_SLICE_PART) {
688 * whole-disk-device, raw access to disk
690 /* no string extension */
691 } else if (part > 128) {
693 * whole-disk-device, extended raw access partitions.
694 * (typically used to access CD audio tracks)
696 used += ksnprintf(name + used, sizeof(name) - used,
700 * whole-disk-device, illegal partition number
702 used += ksnprintf(name + used, sizeof(name) - used,
709 * This should only be called when the unit is inactive and the strategy
710 * routine should not allow it to become active unless we call it. Our
711 * strategy routine must be special to allow activity.
714 dsopen(cdev_t dev, int mode, u_int flags,
715 struct diskslices **sspp, struct disk_info *info)
720 struct diskslice *sp;
721 struct diskslices *ssp;
725 dev->si_bsize_phys = info->d_media_blksize;
728 * Do not attempt to read the slice table or disk label when
729 * accessing the whole-disk slice or a while-slice partition.
731 if (dkslice(dev) == WHOLE_DISK_SLICE)
732 flags |= DSO_ONESLICE | DSO_NOLABELS;
733 if (dkpart(dev) == WHOLE_SLICE_PART)
734 flags |= DSO_NOLABELS;
737 * Reinitialize the slice table unless there is an open device
740 * It would be nice if we didn't have to do this but when a
741 * user is slicing and partitioning up a disk it is a lot safer
742 * to not take any chances.
745 need_init = !dsisopen(ssp);
746 if (ssp != NULL && need_init)
750 * Allocate a minimal slices "struct". This will become
751 * the final slices "struct" if we don't want real slices
752 * or if we can't find any real slices.
756 *sspp = dsmakeslicestruct(BASE_SLICE, info);
758 if ((flags & DSO_ONESLICE) == 0) {
759 error = mbrinit(dev, info, sspp);
766 ssp->dss_oflags = flags;
769 * If there are no real slices, then make the compatiblity
770 * slice cover the whole disk.
772 if (ssp->dss_nslices == BASE_SLICE) {
773 sp = &ssp->dss_slices[COMPATIBILITY_SLICE];
775 sp->ds_size = info->d_media_blocks;
780 * Set dss_first_bsd_slice to point at the first BSD
783 for (slice = BASE_SLICE; slice < ssp->dss_nslices; slice++) {
784 sp = &ssp->dss_slices[slice];
785 if (sp->ds_type == DOSPTYP_386BSD /* XXX */) {
787 struct diskslice *csp;
790 ssp->dss_first_bsd_slice = slice;
793 * no longer supported, s0 is a real slice
796 csp = &ssp->dss_slices[COMPATIBILITY_SLICE];
797 csp->ds_offset = sp->ds_offset;
798 csp->ds_size = sp->ds_size;
799 csp->ds_type = sp->ds_type;
800 csp->ds_reserved = sp->ds_reserved;
807 * By definition accesses via the whole-disk device do not
808 * specify any reserved areas. The whole disk may be read
809 * or written by the whole-disk device.
811 * ds_label for a whole-disk device is only used as a
814 sp = &ssp->dss_slices[WHOLE_DISK_SLICE];
815 sp->ds_label = ops->op_clone_label(info, NULL);
816 sp->ds_wlabel = TRUE;
821 * Load the disklabel for the slice being accessed unless it is
822 * a whole-disk-slice or a whole-slice-partition (as determined
825 * We could scan all slices here and try to load up their
826 * disklabels, but that would cause us to access slices that
827 * the user may otherwise not intend us to access, or corrupted
830 * XXX if there are no opens on the slice we may want to re-read
831 * the disklabel anyway, even if we have one cached.
833 slice = dkslice(dev);
834 if (slice >= ssp->dss_nslices)
836 sp = &ssp->dss_slices[slice];
839 if ((flags & DSO_NOLABELS) == 0 && sp->ds_label.opaque == NULL) {
840 dev1 = dkmodslice(dkmodpart(dev, WHOLE_SLICE_PART), slice);
843 * If opening a raw disk we do not try to
844 * read the disklabel now. No interpretation of raw disks
845 * (e.g. like 'da0') ever occurs. We will try to read the
846 * disklabel for a raw slice if asked to via DIOC* ioctls.
848 * Access to the label area is disallowed by default. Note
849 * however that accesses via WHOLE_DISK_SLICE, and accesses
850 * via WHOLE_SLICE_PART for slices without valid disklabels,
851 * will allow writes and ignore the flag.
853 set_ds_wlabel(ssp, slice, FALSE);
854 dsreadandsetlabel(dev1, flags, ssp, sp, info);
858 * If opening a particular partition the disklabel must exist and
859 * the partition must be present in the label.
861 * If the partition is the special whole-disk-slice no partition
864 if (part != WHOLE_SLICE_PART && slice != WHOLE_DISK_SLICE) {
865 if (sp->ds_label.opaque == NULL ||
866 part >= ops->op_getnumparts(sp->ds_label)) {
873 * Do not allow special raw-extension partitions to be opened
874 * if the device doesn't support them. Raw-extension partitions
875 * are typically used to handle CD tracks.
877 if (slice == WHOLE_DISK_SLICE && part >= 128 &&
878 part != WHOLE_SLICE_PART) {
879 if ((info->d_dsflags & DSO_RAWEXTENSIONS) == 0)
886 * Attempt to read the disklabel. If successful, store it in sp->ds_label.
888 * If we cannot read the disklabel and DSO_COMPATLABEL is set, we construct
889 * a fake label covering the whole disk.
893 dsreadandsetlabel(cdev_t dev, u_int flags,
894 struct diskslices *ssp, struct diskslice *sp,
895 struct disk_info *info)
901 int slice = dkslice(dev);
905 sname = dsname(dev, dkunit(dev), slice, WHOLE_SLICE_PART, partname);
906 msg = ops->op_readdisklabel(dev, sp, &lp, info);
908 if (msg != NULL && (flags & DSO_COMPATLABEL)) {
910 lp = ops->op_clone_label(info, sp);
913 if (sp->ds_type == DOSPTYP_386BSD /* XXX */)
914 log(LOG_WARNING, "%s: cannot find label (%s)\n",
917 kfree(lp.opaque, M_DEVBUF);
919 set_ds_label(ssp, slice, lp);
920 set_ds_wlabel(ssp, slice, FALSE);
922 return (msg ? EINVAL : 0);
926 dssize(cdev_t dev, struct diskslices **sspp)
931 struct diskslices *ssp;
935 slice = dkslice(dev);
938 if (ssp == NULL || slice >= ssp->dss_nslices
939 || !dschkmask(&ssp->dss_slices[slice], part)) {
940 if (dev_dopen(dev, FREAD, S_IFCHR, proc0.p_ucred) != 0)
942 dev_dclose(dev, FREAD, S_IFCHR);
945 lp = ssp->dss_slices[slice].ds_label;
946 if (lp.opaque == NULL)
948 if (ops->op_getpartbounds(lp, part, &start, &blocks))
950 return ((int64_t)blocks);
954 free_ds_label(struct diskslices *ssp, int slice)
956 struct diskslice *sp;
959 sp = &ssp->dss_slices[slice];
961 if (lp.opaque != NULL) {
962 kfree(lp.opaque, M_DEVBUF);
964 set_ds_label(ssp, slice, lp);
969 set_ds_label(struct diskslices *ssp, int slice, disklabel_t lp)
971 struct diskslice *sp = &ssp->dss_slices[slice];
974 ops->op_adjust_label_reserved(ssp, slice, sp);
978 set_ds_wlabel(struct diskslices *ssp, int slice, int wlabel)
980 ssp->dss_slices[slice].ds_wlabel = wlabel;