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.51 2008/08/29 20:08:36 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/disklabel64.h>
57 #include <sys/diskslice.h>
59 #include <sys/diskmbr.h>
60 #include <sys/fcntl.h>
61 #include <sys/malloc.h>
63 #include <sys/syslog.h>
65 #include <sys/vnode.h>
66 #include <sys/device.h>
67 #include <sys/thread2.h>
69 #include <vfs/ufs/dinode.h> /* XXX used only for fs.h */
70 #include <vfs/ufs/fs.h> /* XXX used only to get BBSIZE/SBSIZE */
71 #include <sys/devfs.h>
73 static int dsreadandsetlabel(cdev_t dev
, u_int flags
,
74 struct diskslices
*ssp
, struct diskslice
*sp
,
75 struct disk_info
*info
);
76 static void free_ds_label (struct diskslices
*ssp
, int slice
);
77 static void set_ds_label (struct diskslices
*ssp
, int slice
, disklabel_t lp
,
79 static void set_ds_wlabel (struct diskslices
*ssp
, int slice
, int wlabel
);
82 * Determine the size of the transfer, and make sure it is
83 * within the boundaries of the partition. Adjust transfer
84 * if needed, and signal errors or early completion.
87 * o Split buffers that are too big for the device.
88 * o Check for overflow.
89 * o Finish cleaning this up.
91 * This function returns 1 on success, 0 if transfer equates
92 * to EOF (end of disk) or -1 on failure. The appropriate
93 * 'errno' value is also set in bp->b_error and bp->b_flags
94 * is marked with B_ERROR.
97 dscheck(cdev_t dev
, struct bio
*bio
, struct diskslices
*ssp
)
99 struct buf
*bp
= bio
->bio_buf
;
106 u_int64_t slicerel_secno
;
107 struct diskslice
*sp
;
113 slice
= dkslice(dev
);
116 if (bio
->bio_offset
< 0) {
117 kprintf("dscheck(%s): negative bio_offset %lld\n",
118 devtoname(dev
), (long long)bio
->bio_offset
);
121 if (slice
>= ssp
->dss_nslices
) {
122 kprintf("dscheck(%s): slice too large %d/%d\n",
123 devtoname(dev
), slice
, ssp
->dss_nslices
);
126 sp
= &ssp
->dss_slices
[slice
];
128 * Calculate secno and nsec
130 if (ssp
->dss_secmult
== 1) {
133 } else if (ssp
->dss_secshift
!= -1) {
134 shift
= DEV_BSHIFT
+ ssp
->dss_secshift
;
136 mask
= (1 << shift
) - 1;
137 if ((int)bp
->b_bcount
& mask
)
139 if ((int)bio
->bio_offset
& mask
)
141 secno
= bio
->bio_offset
>> shift
;
142 nsec
= bp
->b_bcount
>> shift
;
144 if (bp
->b_bcount
% ssp
->dss_secsize
)
146 if (bio
->bio_offset
% ssp
->dss_secsize
)
148 secno
= bio
->bio_offset
/ ssp
->dss_secsize
;
149 nsec
= bp
->b_bcount
/ ssp
->dss_secsize
;
153 * Calculate slice-relative sector number end slice-relative
156 if (slice
== WHOLE_DISK_SLICE
) {
158 * Labels have not been allowed on whole-disks for a while.
159 * This really puts the nail in the coffin.
161 * Accesses to the WHOLE_DISK_SLICE do not use a disklabel
162 * and partition numbers are special-cased. Currently numbers
163 * less then 128 are not allowed. Partition numbers >= 128
164 * are encoded in the high 8 bits of the 64 bit buffer offset
165 * and are fed directly through to the device with no
166 * further interpretation. In particular, no sector
167 * translation interpretation should occur because the
168 * sector size for the special raw access may not be the
169 * same as the nominal sector size for the device.
173 kprintf("dscheck(%s): illegal partition number (%d) "
174 "for WHOLE_DISK_SLICE access\n",
175 devtoname(dev
), part
);
177 } else if (part
!= WHOLE_SLICE_PART
) {
178 nbio
= push_bio(bio
);
179 nbio
->bio_offset
= bio
->bio_offset
|
180 (u_int64_t
)part
<< 56;
184 * If writing to the raw disk request a
185 * reprobe on the last close.
187 if (bp
->b_cmd
== BUF_CMD_WRITE
)
188 sp
->ds_flags
|= DSF_REPROBE
;
192 * sp->ds_size is for the whole disk in the WHOLE_DISK_SLICE,
193 * there are no reserved areas.
195 endsecno
= sp
->ds_size
;
196 slicerel_secno
= secno
;
197 } else if (part
== WHOLE_SLICE_PART
) {
199 * NOTE! opens on a whole-slice partition will not attempt
200 * to read a disklabel in, so there may not be an in-core
201 * disklabel even if there is one on the disk.
203 endsecno
= sp
->ds_size
;
204 slicerel_secno
= secno
;
205 } else if ((lp
= sp
->ds_label
).opaque
!= NULL
) {
207 * A label is present, extract the partition. Snooping of
208 * the disklabel is not supported even if accessible. Of
209 * course, the reserved area is still write protected.
212 if (ops
->op_getpartbounds(ssp
, lp
, part
,
213 &slicerel_secno
, &endsecno
)) {
214 kprintf("dscheck(%s): partition %d out of bounds\n",
215 devtoname(dev
), part
);
218 slicerel_secno
+= secno
;
221 * Attempt to access partition when no disklabel present
223 kprintf("dscheck(%s): attempt to access non-existent partition\n",
229 * Disallow writes to reserved areas unless ds_wlabel allows it.
230 * If the reserved area is written to request a reprobe of the
231 * disklabel when the slice is closed.
233 if (slicerel_secno
< sp
->ds_reserved
&& nsec
&&
234 bp
->b_cmd
== BUF_CMD_WRITE
) {
235 if (sp
->ds_wlabel
== 0) {
239 sp
->ds_flags
|= DSF_REPROBE
;
243 * If we get here, bio_offset must be on a block boundary and
244 * the sector size must be a power of 2.
246 if ((bio
->bio_offset
& (ssp
->dss_secsize
- 1)) ||
247 (ssp
->dss_secsize
^ (ssp
->dss_secsize
- 1)) !=
248 ((ssp
->dss_secsize
<< 1) - 1)) {
249 kprintf("%s: invalid BIO offset, not sector aligned or"
250 " invalid sector size (not power of 2) %08llx %d\n",
251 devtoname(dev
), (long long)bio
->bio_offset
,
259 if (secno
+ nsec
> endsecno
) {
261 * Return an error if beyond the end of the disk, or
262 * if B_BNOCLIP is set. Tell the system that we do not
263 * need to keep the buffer around.
265 if (secno
> endsecno
|| (bp
->b_flags
& B_BNOCLIP
))
269 * If exactly at end of disk, return an EOF. Throw away
270 * the buffer contents, if any, by setting B_INVAL.
272 if (secno
== endsecno
) {
273 bp
->b_resid
= bp
->b_bcount
;
274 bp
->b_flags
|= B_INVAL
;
281 nsec
= endsecno
- secno
;
282 bp
->b_bcount
= nsec
* ssp
->dss_secsize
;
285 nbio
= push_bio(bio
);
286 nbio
->bio_offset
= (off_t
)(sp
->ds_offset
+ slicerel_secno
) *
292 "dscheck(%s): b_bcount %d is not on a sector boundary (ssize %d)\n",
293 devtoname(dev
), bp
->b_bcount
, ssp
->dss_secsize
);
298 "dscheck(%s): bio_offset %lld is not on a sector boundary (ssize %d)\n",
299 devtoname(dev
), (long long)bio
->bio_offset
, ssp
->dss_secsize
);
301 bp
->b_error
= EINVAL
;
305 * Terminate the I/O with a ranging error. Since the buffer is
306 * either illegal or beyond the file EOF, mark it B_INVAL as well.
308 bp
->b_resid
= bp
->b_bcount
;
309 bp
->b_flags
|= B_ERROR
| B_INVAL
;
312 * Caller must biodone() the originally passed bio if NULL is
319 * dsclose() - close a cooked disk slice.
321 * WARNING! The passed diskslices and related diskslice structures may
322 * be invalidated or replaced by this function, callers must
323 * reload from the disk structure for continued access.
326 dsclose(cdev_t dev
, int mode
, struct diskslices
*ssp
)
330 struct diskslice
*sp
;
332 slice
= dkslice(dev
);
334 if (slice
< ssp
->dss_nslices
) {
335 sp
= &ssp
->dss_slices
[slice
];
337 if (sp
->ds_flags
& DSF_REPROBE
) {
338 sp
->ds_flags
&= ~DSF_REPROBE
;
339 if (slice
== WHOLE_DISK_SLICE
) {
340 disk_msg_send_sync(DISK_DISK_REPROBE
,
344 disk_msg_send_sync(DISK_SLICE_REPROBE
,
348 /* ssp and sp may both be invalid after reprobe */
354 dsgone(struct diskslices
**sspp
)
357 struct diskslice
*sp
;
358 struct diskslices
*ssp
;
360 kprintf("dsgone is called... fear!\n");
362 for (slice
= 0, ssp
= *sspp
; slice
< ssp
->dss_nslices
; slice
++) {
363 sp
= &ssp
->dss_slices
[slice
];
364 free_ds_label(ssp
, slice
);
366 kfree(ssp
, M_DEVBUF
);
371 * For the "write" commands (DIOCSDINFO and DIOCWDINFO), this
372 * is subject to the same restriction as dsopen().
375 dsioctl(cdev_t dev
, u_long cmd
, caddr_t data
, int flags
,
376 struct diskslices
**sspp
, struct disk_info
*info
)
383 u_int32_t openmask
[DKMAXPARTITIONS
/(sizeof(u_int32_t
)*8)];
386 struct diskslice
*sp
;
387 struct diskslices
*ssp
;
389 slice
= dkslice(dev
);
392 if (slice
>= ssp
->dss_nslices
)
394 sp
= &ssp
->dss_slices
[slice
];
396 ops
= sp
->ds_ops
; /* may be NULL if no label */
400 ops
= &disklabel32_ops
;
403 if (cmd
!= DIOCGDVIRGIN32
)
404 ops
= &disklabel64_ops
;
406 * You can only retrieve a virgin disklabel on the whole
407 * disk slice or whole-slice partition.
409 if (slice
!= WHOLE_DISK_SLICE
&&
410 part
!= WHOLE_SLICE_PART
) {
415 ops
->op_makevirginlabel(lp
, ssp
, sp
, info
);
421 * You can only retrieve a disklabel on the whole
424 * We do not support labels directly on whole-disks
425 * any more (that is, disks without slices), unless the
426 * device driver has asked for a compatible label (e.g.
427 * for a CD) to allow booting off of storage that is
428 * otherwise unlabeled.
431 if (part
!= WHOLE_SLICE_PART
)
433 if (slice
== WHOLE_DISK_SLICE
&&
434 (info
->d_dsflags
& DSO_COMPATLABEL
) == 0) {
437 if (sp
->ds_label
.opaque
== NULL
) {
438 error
= dsreadandsetlabel(dev
, info
->d_dsflags
,
440 ops
= sp
->ds_ops
; /* may be NULL */
444 * The type of label we found must match the type of
447 if (error
== 0 && IOCPARM_LEN(cmd
) != ops
->labelsize
)
450 bcopy(sp
->ds_label
.opaque
, data
, ops
->labelsize
);
455 struct partinfo
*dpart
= (void *)data
;
458 * The disk management layer may not have read the
459 * disklabel yet because simply opening a slice no
460 * longer 'probes' the disk that way. Be sure we
463 * We ignore any error.
465 if (sp
->ds_label
.opaque
== NULL
&&
466 part
== WHOLE_SLICE_PART
&&
467 slice
!= WHOLE_DISK_SLICE
) {
468 dsreadandsetlabel(dev
, info
->d_dsflags
,
470 ops
= sp
->ds_ops
; /* may be NULL */
473 bzero(dpart
, sizeof(*dpart
));
474 dpart
->media_offset
= (u_int64_t
)sp
->ds_offset
*
475 info
->d_media_blksize
;
476 dpart
->media_size
= (u_int64_t
)sp
->ds_size
*
477 info
->d_media_blksize
;
478 dpart
->media_blocks
= sp
->ds_size
;
479 dpart
->media_blksize
= info
->d_media_blksize
;
480 dpart
->reserved_blocks
= sp
->ds_reserved
;
481 dpart
->fstype_uuid
= sp
->ds_type_uuid
;
482 dpart
->storage_uuid
= sp
->ds_stor_uuid
;
484 if (slice
!= WHOLE_DISK_SLICE
&&
485 part
!= WHOLE_SLICE_PART
) {
488 if (lp
.opaque
== NULL
)
490 if (ops
->op_getpartbounds(ssp
, lp
, part
,
494 ops
->op_loadpartinfo(lp
, part
, dpart
);
495 dpart
->media_offset
+= start
*
496 info
->d_media_blksize
;
497 dpart
->media_size
= blocks
*
498 info
->d_media_blksize
;
499 dpart
->media_blocks
= blocks
;
502 * partition starting sector (p_offset)
503 * requires slice's reserved areas to be
506 if (dpart
->reserved_blocks
> start
)
507 dpart
->reserved_blocks
-= start
;
509 dpart
->reserved_blocks
= 0;
513 * Load remaining fields from the info structure
515 dpart
->d_nheads
= info
->d_nheads
;
516 dpart
->d_ncylinders
= info
->d_ncylinders
;
517 dpart
->d_secpertrack
= info
->d_secpertrack
;
518 dpart
->d_secpercyl
= info
->d_secpercyl
;
523 bcopy(ssp
, data
, (char *)&ssp
->dss_slices
[ssp
->dss_nslices
] -
528 ops
= &disklabel32_ops
;
531 if (cmd
!= DIOCSDINFO32
)
532 ops
= &disklabel64_ops
;
534 * You can write a disklabel on the whole disk slice or
535 * whole-slice partition.
537 if (slice
!= WHOLE_DISK_SLICE
&&
538 part
!= WHOLE_SLICE_PART
) {
543 * We no longer support writing disklabels directly to media
544 * without there being a slice. Keep this as a separate
547 if (slice
== WHOLE_DISK_SLICE
)
549 if (!(flags
& FWRITE
))
553 * If an existing label is present it must be the same
554 * type as the label being passed by the ioctl.
556 if (sp
->ds_label
.opaque
&& sp
->ds_ops
!= ops
)
560 * Create a temporary copy of the existing label
561 * (if present) so setdisklabel can compare it against
564 lp
.opaque
= kmalloc(ops
->labelsize
, M_DEVBUF
, M_WAITOK
);
565 if (sp
->ds_label
.opaque
== NULL
)
566 bzero(lp
.opaque
, ops
->labelsize
);
568 bcopy(sp
->ds_label
.opaque
, lp
.opaque
, ops
->labelsize
);
569 if (sp
->ds_label
.opaque
== NULL
) {
570 bzero(openmask
, sizeof(openmask
));
572 bcopy(sp
->ds_openmask
, openmask
, sizeof(openmask
));
575 error
= ops
->op_setdisklabel(lp
, lptmp
, ssp
, sp
, openmask
);
576 disk_msg_send_sync(DISK_SLICE_REPROBE
, dev
->si_disk
, sp
);
579 kfree(lp
.opaque
, M_DEVBUF
);
582 free_ds_label(ssp
, slice
);
583 set_ds_label(ssp
, slice
, lp
, ops
);
586 case DIOCSYNCSLICEINFO
:
588 * This ioctl can only be done on the whole disk
590 if (slice
!= WHOLE_DISK_SLICE
|| part
!= WHOLE_SLICE_PART
)
593 if (*(int *)data
== 0) {
594 for (slice
= 0; slice
< ssp
->dss_nslices
; slice
++) {
595 struct diskslice
*ds
= &ssp
->dss_slices
[slice
];
597 switch(dscountmask(ds
)) {
601 if (slice
!= WHOLE_DISK_SLICE
)
603 if (!dschkmask(ds
, RAW_PART
))
612 disk_msg_send_sync(DISK_DISK_REPROBE
, dev
->si_disk
, NULL
);
618 error
= dsioctl(dev
, ((cmd
== DIOCWDINFO32
) ?
619 DIOCSDINFO32
: DIOCSDINFO64
),
620 data
, flags
, &ssp
, info
);
621 if (error
== 0 && sp
->ds_label
.opaque
== NULL
)
623 if (part
!= WHOLE_SLICE_PART
)
629 * Allow the reserved area to be written, reload ops
630 * because the DIOCSDINFO op above may have installed
634 old_wlabel
= sp
->ds_wlabel
;
635 set_ds_wlabel(ssp
, slice
, TRUE
);
636 error
= ops
->op_writedisklabel(dev
, ssp
, sp
, sp
->ds_label
);
637 disk_msg_send_sync(DISK_SLICE_REPROBE
, dev
->si_disk
, sp
);
639 set_ds_wlabel(ssp
, slice
, old_wlabel
);
640 /* XXX should invalidate in-core label if write failed. */
644 if (slice
== WHOLE_DISK_SLICE
)
646 if (!(flags
& FWRITE
))
648 set_ds_wlabel(ssp
, slice
, *(int *)data
!= 0);
657 dsisopen(struct diskslices
*ssp
)
663 for (slice
= 0; slice
< ssp
->dss_nslices
; slice
++) {
664 if (dscountmask(&ssp
->dss_slices
[slice
]))
671 * Allocate a slices "struct" and initialize it to contain only an empty
672 * compatibility slice (pointing to itself), a whole disk slice (covering
673 * the disk as described by the label), and (nslices - BASE_SLICES) empty
674 * slices beginning at BASE_SLICE.
676 * Note that the compatibility slice is no longer really a compatibility
677 * slice. It is slice 0 if a GPT label is present, and the dangerously
678 * dedicated slice if no slice table otherwise exists. Else it is 0-sized.
681 dsmakeslicestruct(int nslices
, struct disk_info
*info
)
683 struct diskslice
*sp
;
684 struct diskslices
*ssp
;
686 ssp
= kmalloc(offsetof(struct diskslices
, dss_slices
) +
687 nslices
* sizeof *sp
, M_DEVBUF
, M_WAITOK
);
688 ssp
->dss_first_bsd_slice
= COMPATIBILITY_SLICE
;
689 ssp
->dss_nslices
= nslices
;
693 * Figure out if we can use shifts or whether we have to
694 * use mod/multply to translate byte offsets into sector numbers.
696 if ((info
->d_media_blksize
^ (info
->d_media_blksize
- 1)) ==
697 (info
->d_media_blksize
<< 1) - 1) {
698 ssp
->dss_secmult
= info
->d_media_blksize
/ DEV_BSIZE
;
699 if (ssp
->dss_secmult
& (ssp
->dss_secmult
- 1))
700 ssp
->dss_secshift
= -1;
702 ssp
->dss_secshift
= ffs(ssp
->dss_secmult
) - 1;
704 ssp
->dss_secmult
= 0;
705 ssp
->dss_secshift
= -1;
707 ssp
->dss_secsize
= info
->d_media_blksize
;
708 sp
= &ssp
->dss_slices
[0];
709 bzero(sp
, nslices
* sizeof *sp
);
710 sp
[WHOLE_DISK_SLICE
].ds_size
= info
->d_media_blocks
;
715 dsname(cdev_t dev
, int unit
, int slice
, int part
, char *partname
)
721 * This should only be called when the unit is inactive and the strategy
722 * routine should not allow it to become active unless we call it. Our
723 * strategy routine must be special to allow activity.
726 dsopen(cdev_t dev
, int mode
, u_int flags
,
727 struct diskslices
**sspp
, struct disk_info
*info
)
729 struct diskslice
*sp
;
730 struct diskslices
*ssp
;
735 dev
->si_bsize_phys
= info
->d_media_blksize
;
736 slice
= dkslice(dev
);
738 sp
= &ssp
->dss_slices
[slice
];
745 * Attempt to read the disklabel. If successful, store it in sp->ds_label.
747 * If we cannot read the disklabel and DSO_COMPATLABEL is set, we construct
748 * a fake label covering the whole disk.
752 dsreadandsetlabel(cdev_t dev
, u_int flags
,
753 struct diskslices
*ssp
, struct diskslice
*sp
,
754 struct disk_info
*info
)
761 int slice
= dkslice(dev
);
764 * Probe the disklabel
767 sname
= dsname(dev
, dkunit(dev
), slice
, WHOLE_SLICE_PART
, partname
);
768 ops
= &disklabel32_ops
;
769 msg
= ops
->op_readdisklabel(dev
, sp
, &lp
, info
);
770 if (msg
&& strcmp(msg
, "no disk label") == 0) {
771 ops
= &disklabel64_ops
;
772 msg
= disklabel64_ops
.op_readdisklabel(dev
, sp
, &lp
, info
);
776 * If we failed and COMPATLABEL is set, create a dummy disklabel.
778 if (msg
!= NULL
&& (flags
& DSO_COMPATLABEL
)) {
780 if (sp
->ds_size
>= 0x100000000ULL
)
781 ops
= &disklabel64_ops
;
783 ops
= &disklabel32_ops
;
784 lp
= ops
->op_clone_label(info
, sp
);
787 if (sp
->ds_type
== DOSPTYP_386BSD
/* XXX */)
788 log(LOG_WARNING
, "%s: cannot find label (%s)\n",
791 kfree(lp
.opaque
, M_DEVBUF
);
793 set_ds_label(ssp
, slice
, lp
, ops
);
794 set_ds_wlabel(ssp
, slice
, FALSE
);
796 return (msg
? EINVAL
: 0);
800 dssize(cdev_t dev
, struct diskslices
**sspp
)
806 struct diskslices
*ssp
;
810 slice
= dkslice(dev
);
813 if (ssp
== NULL
|| slice
>= ssp
->dss_nslices
814 || !dschkmask(&ssp
->dss_slices
[slice
], part
)) {
815 if (dev_dopen(dev
, FREAD
, S_IFCHR
, proc0
.p_ucred
) != 0)
817 dev_dclose(dev
, FREAD
, S_IFCHR
);
820 lp
= ssp
->dss_slices
[slice
].ds_label
;
821 if (lp
.opaque
== NULL
)
823 ops
= ssp
->dss_slices
[slice
].ds_ops
;
824 if (ops
->op_getpartbounds(ssp
, lp
, part
, &start
, &blocks
))
826 return ((int64_t)blocks
);
830 free_ds_label(struct diskslices
*ssp
, int slice
)
832 struct diskslice
*sp
;
835 sp
= &ssp
->dss_slices
[slice
];
837 if (lp
.opaque
!= NULL
) {
838 kfree(lp
.opaque
, M_DEVBUF
);
840 set_ds_label(ssp
, slice
, lp
, NULL
);
845 set_ds_label(struct diskslices
*ssp
, int slice
,
846 disklabel_t lp
, disklabel_ops_t ops
)
848 struct diskslice
*sp
= &ssp
->dss_slices
[slice
];
852 if (lp
.opaque
&& slice
!= WHOLE_DISK_SLICE
)
853 ops
->op_adjust_label_reserved(ssp
, slice
, sp
);
859 set_ds_wlabel(struct diskslices
*ssp
, int slice
, int wlabel
)
861 ssp
->dss_slices
[slice
].ds_wlabel
= wlabel
;