From 5350e1e9f12d796a3946a255ff1cc18649b6a26e Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Sat, 19 May 2007 00:52:02 +0000 Subject: [PATCH] Continue untangling the disklabel. * Move dk*() inline functions and other related stuff not directly related to the BSD disklabel out of sys/disklabel.h and into sys/diskslice.h. Add additional functions to sys/diskslice.h * Extend the slice and partition fields in the device minor number. We now support up to 128 slices and up to 256 partitions. * Implement new minor device numbers for 'raw slices', such as ad0s1. Previously raw slices used the same minor number as partition c within the slice. e.g. ad0s1 and ad0s1c had the same device number. This made it impossible to distinguish between the two. The 'whole disk' device's minor number has also changed. Our new whole-slice and whole-disk devices specify a partition number of (DKMAXPARTITIONS - 1) (aka 255). * Completely disable disklabel related operations on the raw disk, e.g. da0, and on partitions, e.g. da0s1a. Only allow disklabel operations on whole slices, e.g. da0s1. NOTE!! For compatibility while booting drivers which set DSO_COMPATLABEL, the compat disklabel may be read, but not written, via the whole-disk device. e.g. acd0. NOTE!! For compatibility we have no choice but to continue to snoop read/write operations on raw slices (e.g. da0s1) because the disklabel program and the kernel still depend on the snooping to modify the in-core version of the disklabel to the on-disk version. No snooping will occur on the whole-disk device (e.g. da0). No snooping will occur on raw slices (e.g. da0s1) if the disk is unlabeled and no in-core label was set. Note that disklabel -r -w DOES set an in-core label before writing to a raw-slice, so it is still ok. * dsopen() no longer attempts to scan the MBR or slice table when the whole-disk device (e.g. da0) is opened, and no longer attempts to read the disklabel when the whole-slice device is opened (e.g. da0s1). The disklabel is only read when a partition is explicitly opened or the label is explicitly read via an ioctl. * The virgin disklabel is stored in the struct diskslice for WHOLE_DISK_SLICE (slice 1). --- etc/MAKEDEV | 134 ++++++++------ lib/libc/gen/disklabel.c | 7 +- sbin/disklabel/disklabel.c | 7 +- sys/dev/disk/ata/atapi-tape.c | 4 +- sys/dev/disk/fd/fd.c | 3 +- sys/kern/subr_disk.c | 11 +- sys/kern/subr_diskslice.c | 336 ++++++++++++++++++++++++---------- sys/kern/vfs_conf.c | 4 +- sys/sys/disk.h | 6 +- sys/sys/disklabel.h | 117 +----------- sys/sys/disklabel32.h | 117 +----------- sys/sys/diskslice.h | 212 ++++++++++++++++++++- 12 files changed, 546 insertions(+), 412 deletions(-) diff --git a/etc/MAKEDEV b/etc/MAKEDEV index 5de708f05f..df1bb059bc 100644 --- a/etc/MAKEDEV +++ b/etc/MAKEDEV @@ -21,7 +21,7 @@ # # @(#)MAKEDEV 5.2 (Berkeley) 6/22/90 # $FreeBSD: src/etc/MAKEDEV,v 1.243.2.57 2003/02/10 11:35:53 simokawa Exp $ -# $DragonFly: src/etc/MAKEDEV,v 1.27 2007/05/17 19:26:05 swildner Exp $ +# $DragonFly: src/etc/MAKEDEV,v 1.28 2007/05/19 00:51:54 dillon Exp $ # # Device "make" file. Valid arguments: # all makes all known devices, standard number of units (or close) @@ -267,14 +267,16 @@ dkitos() } #----------------------------------------------------------------------------- -# Convert disk|type|unit|slice|partition to minor number. +# Convert unit, slice, partition to minor number. #----------------------------------------------------------------------------- +# +# ndkminor(unit, slice, partition) -dkminor() +ndkminor() { - echo $(($1 << 25 | ($2 / 32) << 21 | \ - ($2 % 32) << 3 | $3 << 16 | \ - ($4 & 7) | ($4 & 8) << 17)) + echo $(( (($1 & 31) << 3) | (($1 & 480) << 16) | \ + (($2 & 15) << 16) | (($2 & 112) << 25) | \ + ($3 & 7) | (($3 & 8) << 17) | (($3 & 240) << 21) )) } @@ -653,9 +655,10 @@ wt*) #----------------------------------------------------------------------------- -aacd*s*|ad*s*|ar*s*|afd*s*|amrd*s*|ccd*s*|da*s*|fla*s*|idad*s*|ipsd*s*|md*s*|mlxd*s*|pst*s*|twed*s*|vn*s*|vkd*s*) +aacd*s*|acd*s*|ad*s*|ar*s*|afd*s*|amrd*s*|ccd*s*|da*s*|fla*s*|idad*s*|ipsd*s*|md*s*|mlxd*s*|pst*s*|twed*s*|vn*s*|vkd*s*) case $i in aacd*s*) name=aacd; chr=151;; + acd*s*) name=acd; chr=117;; ad*s*) name=ad; chr=116;; ar*s*) name=ar; chr=157;; afd*s*) name=afd; chr=118;; @@ -680,7 +683,7 @@ aacd*s*|ad*s*|ar*s*|afd*s*|amrd*s*|ccd*s*|da*s*|fla*s*|idad*s*|ipsd*s*|md*s*|mlx part=`expr $i : '....[0-9]*s[0-9]*\(.*\)'` ;; - afd*s*|ccd*s*|fla*s*|pst*s*|wfd*s*|vkd*s*) + acd*s*|afd*s*|ccd*s*|fla*s*|pst*s*|wfd*s*|vkd*s*) unit=`expr $i : '...\([0-9]*\)s'` slice=`expr $i : '...[0-9]*s\([0-9]*\)'` part=`expr $i : '...[0-9]*s[0-9]*\(.*\)'` @@ -699,8 +702,11 @@ aacd*s*|ad*s*|ar*s*|afd*s*|amrd*s*|ccd*s*|da*s*|fla*s*|idad*s*|ipsd*s*|md*s*|mlx oldslice=$slice slice=$(($slice+1)) slicename=`dkitos $slice` - minor=`dkminor 0 $unit $slice 2` - mknod $name $unit$slicename c $chr $minor \ + minor=`ndkminor $unit $slice 2` + mknod $name $unit${slicename}.compat c $chr $minor \ + root:operator 640 + minor=`ndkminor $unit $slice 255` + mknod ${name} $unit$slicename c $chr $minor \ root:operator 640 rm -f r$name$unit$slicename @@ -709,7 +715,7 @@ aacd*s*|ad*s*|ar*s*|afd*s*|amrd*s*|ccd*s*|da*s*|fla*s*|idad*s*|ipsd*s*|md*s*|mlx for part in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 do - minor=`dkminor 0 $unit $slice $part` + minor=`ndkminor $unit $slice $part` partname=`dkitop $part` mknod $name $unit$slicename$partname \ c $chr $minor root:operator 640 @@ -841,9 +847,49 @@ fd*) #----------------------------------------------------------------------------- -aacd*|ad*|ar*|afd*|amrd*|ccd*|da*|fla*|idad*|ipsd*|md*|mlxd*|pst*|twed*|vn*|vkd*) +acd*t*) + units=`expr $i : '...\(.*\)t'`; + tracks=`expr $i : '.*t\(.*\)'`; + name=acd; + chr=117; + + [ "$units" ] || units=0 + [ "$tracks" ] || tracks=100 + + if [ "$units" -le 31 -a "$tracks" -le 169 ] + then + i=0 + while [ $i -le $units ] + do + dname=$name$i + rm -rf ${dname}t* + + j=1 + while [ $j -le $tracks ] + do + # cd unit tracks use the compatibility slice + # and partition numbers 129+ for tracks 1+. + # + minor=`ndkminor $i 0 $(($j + 128))` + mknod ${dname}t $j c $chr $minor \ + root:operator 640 + j=$(($j + 1)) + done + + i=$(($i + 1)) + done + else + echo "$i is invalid -- can't have more than 32 cd devices or 169 tracks" + fi + ;; + +#----------------------------------------------------------------------------- + +aacd*|acd*|ad*|ar*|afd*|amrd*|ccd*|da*|fla*|idad*|ipsd*|md*|mlxd*|pst*|twed*|vn*|vkd*) + doslices=1 case $i in aacd*) name=aacd; chr=151;; + acd*) name=acd; chr=117; doslices=0;; ad*) name=ad; chr=116;; ar*) name=ar; chr=157;; afd*) name=afd; chr=118;; @@ -865,7 +911,7 @@ aacd*|ad*|ar*|afd*|amrd*|ccd*|da*|fla*|idad*|ipsd*|md*|mlxd*|pst*|twed*|vn*|vkd* aacd*|amrd*|idad*|ipsd*|mlxd*|twed*) unit=`expr $i : '....\(.*\)'` ;; - afd*|ccd*|fla*|pst*|wfd*|vkd*) + acd*|afd*|ccd*|fla*|pst*|wfd*|vkd*) unit=`expr $i : '...\(.*\)'` ;; *) @@ -875,10 +921,25 @@ aacd*|ad*|ar*|afd*|amrd*|ccd*|da*|fla*|idad*|ipsd*|md*|mlxd*|pst*|twed*|vn*|vkd* case $unit in [0-9]|[0-9][0-9]|[0-4][0-9][0-9]|50[0-9]|51[0-1]) - for slicepartname in s0h s1h s2 s3 s4 - do - sh MAKEDEV $name$unit$slicepartname - done + if [ "$doslices" -gt 0 ]; then + for slicepartname in s0h s1h s2 s3 s4 + do + sh MAKEDEV $name$unit$slicepartname + done + else + minor=`ndkminor $unit 0 0` + mknod ${name} $unit.compat c $chr $minor \ + root:operator 640 + minor=`ndkminor $unit 1 255` + mknod ${name} ${unit} c $chr $minor \ + root:operator 640 + minor=`ndkminor $unit 1 0` + mknod ${name} ${unit}a c $chr $minor \ + root:operator 640 + minor=`ndkminor $unit 1 2` + mknod ${name} ${unit}c c $chr $minor \ + root:operator 640 + fi ;; *) echo bad unit for disk in: $i @@ -1090,45 +1151,8 @@ ast*) #----------------------------------------------------------------------------- -acd*t*) - units=`expr $i : '...\(.*\)t'`; - tracks=`expr $i : '.*t\(.*\)'`; - name=acd; - chr=117; - - [ "$units" ] || units=0 - [ "$tracks" ] || tracks=100 - - if [ "$units" -le 31 -a "$tracks" -le 169 ] - then - i=0 - while [ $i -le $units ] - do - dname=$name$i - rm -rf ${dname}t* - - j=1 - while [ $j -le $tracks ] - do - mknod ${dname}t $j c $chr \ - $((($i * 8) + (65536 * $j))) \ - root:operator 640 - - j=$(($j + 1)) - done - - i=$(($i + 1)) - done - else - echo "$i is invalid -- can't have more than 32 cd devices or 169 tracks" - fi - ;; - -#----------------------------------------------------------------------------- - -acd*|cd*) +cd*) case $i in - acd*) units=`expr $i : '...\(.*\)'`; name=acd; chr=117;; cd*) units=`expr $i : '..\(.*\)'` ; name=cd; chr=15;; esac diff --git a/lib/libc/gen/disklabel.c b/lib/libc/gen/disklabel.c index df8a07f02d..077732c41e 100644 --- a/lib/libc/gen/disklabel.c +++ b/lib/libc/gen/disklabel.c @@ -32,7 +32,7 @@ * * @(#)disklabel.c 8.2 (Berkeley) 5/3/95 * $FreeBSD: src/lib/libc/gen/disklabel.c,v 1.9.2.1 2001/03/05 08:40:47 obrien Exp $ - * $DragonFly: src/lib/libc/gen/disklabel.c,v 1.10 2007/05/17 23:50:00 dillon Exp $ + * $DragonFly: src/lib/libc/gen/disklabel.c,v 1.11 2007/05/19 00:51:56 dillon Exp $ */ #include @@ -77,11 +77,6 @@ getdiskbyname(const char *name) (*cq = *cp) && *cq != '|' && *cq != ':') cq++, cp++; *cq = '\0'; - /* - * boot name (optional) xxboot, bootxx - */ - cgetstr(buf, "b0", &dp->d_boot0); - cgetstr(buf, "b1", &dp->d_boot1); #define getnumdflt(field, dname, dflt) \ { long f; (field) = (cgetnum(buf, dname, &f) == -1) ? (dflt) : f; } diff --git a/sbin/disklabel/disklabel.c b/sbin/disklabel/disklabel.c index 923ffd416b..ce85985d05 100644 --- a/sbin/disklabel/disklabel.c +++ b/sbin/disklabel/disklabel.c @@ -37,7 +37,7 @@ * @(#)disklabel.c 1.2 (Symmetric) 11/28/85 * @(#)disklabel.c 8.2 (Berkeley) 1/7/94 * $FreeBSD: src/sbin/disklabel/disklabel.c,v 1.28.2.15 2003/01/24 16:18:16 des Exp $ - * $DragonFly: src/sbin/disklabel/disklabel.c,v 1.15 2007/05/18 17:05:12 dillon Exp $ + * $DragonFly: src/sbin/disklabel/disklabel.c,v 1.16 2007/05/19 00:51:59 dillon Exp $ */ #include @@ -233,11 +233,12 @@ main(int argc, char *argv[]) dkname = argv[0]; if (dkname[0] != '/') { - sprintf(np, "%s%s%c", _PATH_DEV, dkname, 'a' + RAW_PART); + sprintf(np, "%s%s", _PATH_DEV, dkname); specname = np; np += strlen(specname) + 1; - } else + } else { specname = dkname; + } f = open(specname, op == READ ? O_RDONLY : O_RDWR); if (f < 0 && errno == ENOENT && dkname[0] != '/') { sprintf(specname, "%s%s", _PATH_DEV, dkname); diff --git a/sys/dev/disk/ata/atapi-tape.c b/sys/dev/disk/ata/atapi-tape.c index a78cc82b73..1b96918a2e 100644 --- a/sys/dev/disk/ata/atapi-tape.c +++ b/sys/dev/disk/ata/atapi-tape.c @@ -26,7 +26,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/ata/atapi-tape.c,v 1.36.2.12 2002/07/31 11:19:26 sos Exp $ - * $DragonFly: src/sys/dev/disk/ata/atapi-tape.c,v 1.20 2006/12/22 23:26:15 swildner Exp $ + * $DragonFly: src/sys/dev/disk/ata/atapi-tape.c,v 1.21 2007/05/19 00:52:00 dillon Exp $ */ #include "opt_ata.h" @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/sys/dev/disk/fd/fd.c b/sys/dev/disk/fd/fd.c index 5da3fa8153..deb605dfd9 100644 --- a/sys/dev/disk/fd/fd.c +++ b/sys/dev/disk/fd/fd.c @@ -51,7 +51,7 @@ * * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 * $FreeBSD: src/sys/isa/fd.c,v 1.176.2.8 2002/05/15 21:56:14 joerg Exp $ - * $DragonFly: src/sys/dev/disk/fd/fd.c,v 1.37 2007/05/15 00:01:03 dillon Exp $ + * $DragonFly: src/sys/dev/disk/fd/fd.c,v 1.38 2007/05/19 00:52:00 dillon Exp $ * */ @@ -65,6 +65,7 @@ #include #include #include +#include #include #include #include diff --git a/sys/kern/subr_disk.c b/sys/kern/subr_disk.c index 727fc8b7be..1c7a5e7faa 100644 --- a/sys/kern/subr_disk.c +++ b/sys/kern/subr_disk.c @@ -77,7 +77,7 @@ * @(#)ufs_disksubr.c 8.5 (Berkeley) 1/21/94 * $FreeBSD: src/sys/kern/subr_disk.c,v 1.20.2.6 2001/10/05 07:14:57 peter Exp $ * $FreeBSD: src/sys/ufs/ufs/ufs_disksubr.c,v 1.44.2.3 2001/03/05 05:42:19 obrien Exp $ - * $DragonFly: src/sys/kern/subr_disk.c,v 1.31 2007/05/15 22:44:14 dillon Exp $ + * $DragonFly: src/sys/kern/subr_disk.c,v 1.32 2007/05/19 00:52:01 dillon Exp $ */ #include @@ -145,8 +145,7 @@ disk_create(int unit, struct disk *dp, struct dev_ops *raw_ops) * Create the raw backing device */ compile_dev_ops(raw_ops); - rawdev = make_dev(raw_ops, - dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART), + rawdev = make_dev(raw_ops, dkmakewholedisk(unit), UID_ROOT, GID_OPERATOR, 0640, "%s%d", raw_ops->head.name, unit); @@ -165,7 +164,7 @@ disk_create(int unit, struct disk *dp, struct dev_ops *raw_ops) dp->d_raw_ops = raw_ops; dp->d_dev_ops = dev_ops; dp->d_cdev = make_dev(dev_ops, - dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART), + dkmakewholedisk(unit), UID_ROOT, GID_OPERATOR, 0640, "%s%d", dev_ops->head.name, unit); @@ -729,7 +728,7 @@ writedisklabel(cdev_t dev, struct disklabel *lp) */ bp->b_flags &= ~B_INVAL; bp->b_cmd = BUF_CMD_READ; - dev_dstrategy(dkmodpart(dev, RAW_PART), &bp->b_bio1); + dev_dstrategy(dkmodpart(dev, WHOLE_SLICE_PART), &bp->b_bio1); error = biowait(bp); if (error) goto done; @@ -741,7 +740,7 @@ writedisklabel(cdev_t dev, struct disklabel *lp) dkcksum(dlp) == 0) { *dlp = *lp; bp->b_cmd = BUF_CMD_WRITE; - dev_dstrategy(dkmodpart(dev, RAW_PART), &bp->b_bio1); + dev_dstrategy(dkmodpart(dev, WHOLE_SLICE_PART), &bp->b_bio1); error = biowait(bp); goto done; } diff --git a/sys/kern/subr_diskslice.c b/sys/kern/subr_diskslice.c index 39e9dce932..7a178171e9 100644 --- a/sys/kern/subr_diskslice.c +++ b/sys/kern/subr_diskslice.c @@ -44,7 +44,7 @@ * from: @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91 * from: ufs_disksubr.c,v 1.8 1994/06/07 01:21:39 phk Exp $ * $FreeBSD: src/sys/kern/subr_diskslice.c,v 1.82.2.6 2001/07/24 09:49:41 dd Exp $ - * $DragonFly: src/sys/kern/subr_diskslice.c,v 1.34 2007/05/17 21:08:49 dillon Exp $ + * $DragonFly: src/sys/kern/subr_diskslice.c,v 1.35 2007/05/19 00:52:01 dillon Exp $ */ #include @@ -76,11 +76,14 @@ static volatile bool_t ds_debug; static struct disklabel *clone_label (struct disk_info *info, struct diskslice *sp); static void dsiodone (struct bio *bio); -static char *fixlabel (char *sname, struct diskslice *sp, +static char *fixlabel (const char *sname, struct diskslice *sp, struct disklabel *lp, int writeflag); +static int dsreadandsetlabel(cdev_t dev, u_int flags, + struct diskslices *ssp, struct diskslice *sp, + struct disk_info *info); static void free_ds_label (struct diskslices *ssp, int slice); -static void partition_info (char *sname, int part, struct partition *pp); -static void slice_info (char *sname, struct diskslice *sp); +static void partition_info (const char *sname, int part, struct partition *pp); +static void slice_info (const char *sname, struct diskslice *sp); static void set_ds_label (struct diskslices *ssp, int slice, struct disklabel *lp); static void set_ds_wlabel (struct diskslices *ssp, int slice, int wlabel); @@ -170,23 +173,34 @@ dscheck(cdev_t dev, struct bio *bio, struct diskslices *ssp) struct disklabel *lp; char *msg; long nsec; - struct partition *pp; u_int64_t secno; u_int64_t endsecno; u_int64_t labelsect; u_int64_t slicerel_secno; struct diskslice *sp; + u_int32_t part; + u_int32_t slice; int shift; int mask; + slice = dkslice(dev); + part = dkpart(dev); + if (bio->bio_offset < 0) { kprintf("dscheck(%s): negative bio_offset %lld\n", - devtoname(dev), bio->bio_offset); + devtoname(dev), bio->bio_offset); goto bad; } - sp = &ssp->dss_slices[dkslice(dev)]; - lp = sp->ds_label; + if (slice >= ssp->dss_nslices) { + kprintf("dscheck(%s): slice too large %d/%d\n", + devtoname(dev), slice, ssp->dss_nslices); + goto bad; + } + sp = &ssp->dss_slices[slice]; + /* + * Calculate secno and nsec + */ if (ssp->dss_secmult == 1) { shift = DEV_BSHIFT; goto doshift; @@ -208,14 +222,45 @@ doshift: secno = bio->bio_offset / ssp->dss_secsize; nsec = bp->b_bcount / ssp->dss_secsize; } - if (lp == NULL) { + + /* + * Calculate slice-relative sector number end slice-relative + * limit. + */ + lp = sp->ds_label; + if (slice == WHOLE_DISK_SLICE || lp == NULL) { + /* + * Labels have not been allowed on whole-disks for a while. + * This really puts the nail in the coffin... no disk + * snooping will occur even if you tried to write a label + * without a slice structure. + */ + lp = NULL; labelsect = -LABELSECTOR - 1; endsecno = sp->ds_size; slicerel_secno = secno; + } else if (part == WHOLE_SLICE_PART) { + /* + * XXX messy snoop case. Both disklabel -r -w and + * DIOCWDINFO depend on write snooping to properly + * correct the partition offsets for the label being + * written to disk. In both cases ds_label will be + * non-NULL. This is a mess because it violates the + * idea of being able to write to the raw slice. + */ + lp = NULL; + labelsect = 0; + endsecno = sp->ds_size; + slicerel_secno = secno; + } else if (part >= lp->d_npartitions) { + kprintf("dscheck(%s): partition out of bounds %d/%d\n", + devtoname(dev), + part, lp->d_npartitions); + goto bad; } else { - labelsect = lp->d_partitions[LABEL_PART].p_offset; - if (labelsect != 0) - Debugger("labelsect != 0 in dscheck()"); + struct partition *pp; + + labelsect = 0; pp = &lp->d_partitions[dkpart(dev)]; endsecno = pp->p_size; slicerel_secno = pp->p_offset + secno; @@ -300,6 +345,7 @@ doshift: * temporarily corrupting the in-core copy. */ /* XXX need name here. */ + kprintf("SNOOP LABEL WRITE\n"); msg = fixlabel( NULL, sp, (struct disklabel *) @@ -347,12 +393,17 @@ done: void dsclose(cdev_t dev, int mode, struct diskslices *ssp) { - u_char mask; + u_int32_t part; + u_int32_t slice; struct diskslice *sp; - sp = &ssp->dss_slices[dkslice(dev)]; - mask = 1 << dkpart(dev); - sp->ds_openmask &= ~mask; + slice = dkslice(dev); + part = dkpart(dev); + if (slice < ssp->dss_nslices) { + sp = &ssp->dss_slices[slice]; + if (part < sizeof(sp->ds_openmask) * 8) + sp->ds_openmask &= ~(1 << part); + } } void @@ -389,12 +440,24 @@ dsioctl(cdev_t dev, u_long cmd, caddr_t data, int flags, struct partition *pp; slice = dkslice(dev); + part = dkpart(dev); ssp = *sspp; + if (slice >= ssp->dss_nslices) + return (EINVAL); sp = &ssp->dss_slices[slice]; lp = sp->ds_label; switch (cmd) { case DIOCGDVIRGIN: + /* + * You can only retrieve a virgin disklabel on the whole + * disk slice or whole-slice partition. + */ + if (slice != WHOLE_DISK_SLICE && + part != WHOLE_SLICE_PART) { + return(EINVAL); + } + lp = (struct disklabel *)data; if (ssp->dss_slices[WHOLE_DISK_SLICE].ds_label) { *lp = *ssp->dss_slices[WHOLE_DISK_SLICE].ds_label; @@ -428,18 +491,30 @@ dsioctl(cdev_t dev, u_long cmd, caddr_t data, int flags, return (0); case DIOCGDINFO: - if (lp == NULL) - return (EINVAL); - *(struct disklabel *)data = *lp; - return (0); - -#ifdef notyet - case DIOCGDINFOP: - if (lp == NULL) - return (EINVAL); - *(struct disklabel **)data = lp; - return (0); -#endif + /* + * You can only retrieve a disklabel on the whole + * slice partition. + * + * We do not support labels directly on whole-disks + * any more (that is, disks without slices), unless the + * device driver has asked for a compatible label (e.g. + * for a CD) to allow booting off of storage that is + * otherwise unlabeled. + */ + error = 0; + if (part != WHOLE_SLICE_PART) + return(EINVAL); + if (slice == WHOLE_DISK_SLICE && + (info->d_dsflags & DSO_COMPATLABEL) == 0) { + return (ENODEV); + } + if (sp->ds_label == NULL) { + error = dsreadandsetlabel(dev, info->d_dsflags, + ssp, sp, info); + } + if (error == 0) + *(struct disklabel *)data = *sp->ds_label; + return (error); case DIOCGPART: { @@ -454,10 +529,15 @@ dsioctl(cdev_t dev, u_long cmd, caddr_t data, int flags, dpart->media_blksize = info->d_media_blksize; dpart->skip_platform = sp->ds_skip_platform; dpart->skip_bsdlabel = sp->ds_skip_bsdlabel; - if (lp && slice != WHOLE_DISK_SLICE) { + + if (slice != WHOLE_DISK_SLICE && + part != WHOLE_SLICE_PART) { struct partition *p; - p = &lp->d_partitions[dkpart(dev)]; + if (lp == NULL || part >= lp->d_npartitions) + return(EINVAL); + + p = &lp->d_partitions[part]; dpart->fstype = p->p_fstype; dpart->media_offset += (u_int64_t)p->p_offset * info->d_media_blksize; @@ -488,8 +568,23 @@ dsioctl(cdev_t dev, u_long cmd, caddr_t data, int flags, return (0); case DIOCSDINFO: + /* + * You can write a disklabel on the whole disk slice or + * whole-slice partition. + */ + if (slice != WHOLE_DISK_SLICE && + part != WHOLE_SLICE_PART) { + return(EINVAL); + } + + /* + * We no longer support writing disklabels directly to media + * without there being a slice. Keep this as a separate + * conditional. + */ if (slice == WHOLE_DISK_SLICE) return (ENODEV); + if (!(flags & FWRITE)) return (EBADF); lp = kmalloc(sizeof *lp, M_DEVBUF, M_WAITOK); @@ -530,8 +625,12 @@ dsioctl(cdev_t dev, u_long cmd, caddr_t data, int flags, return (0); case DIOCSYNCSLICEINFO: - if (slice != WHOLE_DISK_SLICE || dkpart(dev) != RAW_PART) + /* + * This ioctl can only be done on the whole disk + */ + if (slice != WHOLE_DISK_SLICE || part != WHOLE_SLICE_PART) return (EINVAL); + if (*(int *)data == 0) { for (slice = 0; slice < ssp->dss_nslices; slice++) { openmask = ssp->dss_slices[slice].ds_openmask; @@ -685,18 +784,25 @@ dsname(cdev_t dev, int unit, int slice, int part, char *partname) { static char name[32]; const char *dname; + int used; dname = dev_dname(dev); if (strlen(dname) > 16) dname = "nametoolong"; ksnprintf(name, sizeof(name), "%s%d", dname, unit); partname[0] = '\0'; - if (slice != WHOLE_DISK_SLICE || part != RAW_PART) { - partname[0] = 'a' + part; - partname[1] = '\0'; + used = strlen(name); + + if (slice != WHOLE_DISK_SLICE) { if (slice != COMPATIBILITY_SLICE) { - ksnprintf(name + strlen(name), - sizeof(name) - strlen(name), "s%d", slice - 1); + used += ksnprintf(name + used, sizeof(name) - used, + "s%d", slice - BASE_SLICE + 1); + } + if (part != WHOLE_SLICE_PART) { + used += ksnprintf(name + used, sizeof(name) - used, + "%c", 'a' + part); + partname[0] = 'a' + part; + partname[1] = 0; } } return (name); @@ -713,21 +819,15 @@ dsopen(cdev_t dev, int mode, u_int flags, { cdev_t dev1; int error; - struct disklabel *lp1; - char *msg; u_char mask; bool_t need_init; - int part; - char partname[2]; - int slice; - char *sname; struct diskslice *sp; struct diskslices *ssp; - int unit; + int slice; + int part; dev->si_bsize_phys = info->d_media_blksize; - unit = dkunit(dev); if (info->d_media_blksize % DEV_BSIZE) { kprintf("%s: invalid sector size %lu\n", devtoname(dev), (u_long)info->d_media_blksize); @@ -738,9 +838,10 @@ dsopen(cdev_t dev, int mode, u_int flags, * Do not attempt to read the slice table or disk label when * accessing the raw disk. */ - if (dkslice(dev) == WHOLE_DISK_SLICE && dkpart(dev) == RAW_PART) { + if (dkslice(dev) == WHOLE_DISK_SLICE) flags |= DSO_ONESLICE | DSO_NOLABELS; - } + if (dkpart(dev) == WHOLE_SLICE_PART) + flags |= DSO_NOLABELS; /* * XXX reinitialize the slice table unless there is an open device @@ -760,7 +861,7 @@ dsopen(cdev_t dev, int mode, u_int flags, */ *sspp = dsmakeslicestruct(BASE_SLICE, info); - if (!(flags & DSO_ONESLICE)) { + if ((flags & DSO_ONESLICE) == 0) { TRACE(("mbrinit\n")); error = mbrinit(dev, info, sspp); if (error != 0) { @@ -833,52 +934,17 @@ dsopen(cdev_t dev, int mode, u_int flags, sp = &ssp->dss_slices[slice]; if (sp->ds_label != NULL) continue; - dev1 = dkmodslice(dkmodpart(dev, RAW_PART), slice); - sname = dsname(dev, unit, slice, RAW_PART, partname); + + dev1 = dkmodslice(dkmodpart(dev, WHOLE_SLICE_PART), slice); + /* - * XXX this should probably only be done for the need_init - * case, but there may be a problem with DIOCSYNCSLICEINFO. + * If opening a raw disk or raw slice we do not try to + * read the disklabel, and we allow access to the whole + * gambino. */ - set_ds_wlabel(ssp, slice, TRUE); /* XXX invert */ - lp1 = clone_label(info, sp); - TRACE(("readdisklabel\n")); - if (flags & DSO_NOLABELS) { - msg = NULL; - } else { - msg = readdisklabel(dev1, lp1); - - /* - * readdisklabel() returns NULL for success, and an - * error string for failure. - * - * If there isn't a label on the disk, and if the - * DSO_COMPATLABEL is set, we want to use the - * faked-up label provided by the caller. - * - * So we set msg to NULL to indicate that there is - * no failure (since we have a faked-up label), - * free lp1, and then clone it again from lp. - * (In case readdisklabel() modified lp1.) - */ - if (msg != NULL && (flags & DSO_COMPATLABEL)) { - msg = NULL; - kfree(lp1, M_DEVBUF); - lp1 = clone_label(info, sp); - } - } - if (msg == NULL) - msg = fixlabel(sname, sp, lp1, FALSE); - if (msg == NULL && lp1->d_secsize != ssp->dss_secsize) - msg = "inconsistent sector size"; - if (msg != NULL) { - if (sp->ds_type == DOSPTYP_386BSD /* XXX */) - log(LOG_WARNING, "%s: cannot find label (%s)\n", - sname, msg); - kfree(lp1, M_DEVBUF); - continue; - } - set_ds_label(ssp, slice, lp1); - set_ds_wlabel(ssp, slice, FALSE); + set_ds_wlabel(ssp, slice, TRUE); + if ((flags & DSO_NOLABELS) == 0) + dsreadandsetlabel(dev1, flags, ssp, sp, info); } slice = dkslice(dev); @@ -886,14 +952,75 @@ dsopen(cdev_t dev, int mode, u_int flags, return (ENXIO); sp = &ssp->dss_slices[slice]; part = dkpart(dev); - if (part != RAW_PART - && (sp->ds_label == NULL || part >= sp->ds_label->d_npartitions)) - return (EINVAL); /* XXX needs translation */ - mask = 1 << part; - sp->ds_openmask |= mask; + + /* + * If opening a particular partition the disklabel must exist and + * the partition must be present in the label. + * + * If the partition is the special whole-disk-slice no partition + * table need exist. + */ + if (part != WHOLE_SLICE_PART && slice != WHOLE_DISK_SLICE) { + if (sp->ds_label == NULL || part >= sp->ds_label->d_npartitions) + return (EINVAL); + if (part < sizeof(sp->ds_openmask) * 8) { + mask = 1 << part; + sp->ds_openmask |= mask; + } + } + + /* + * If the slice is the whole-disk slice, the partition must be set + * to the whole slice partition. + */ + if (slice == WHOLE_DISK_SLICE && part != WHOLE_SLICE_PART) + return (EINVAL); return (0); } +/* + * Attempt to read the disklabel. If successful, store it in sp->ds_label. + * + * If we cannot read the disklabel and DSO_COMPATLABEL is set, we construct + * a fake label covering the whole disk. + */ +static +int +dsreadandsetlabel(cdev_t dev, u_int flags, + struct diskslices *ssp, struct diskslice *sp, + struct disk_info *info) +{ + struct disklabel *lp1; + const char *msg; + const char *sname; + char partname[2]; + int slice = dkslice(dev); + + sname = dsname(dev, dkunit(dev), slice, WHOLE_SLICE_PART, partname); + lp1 = clone_label(info, sp); + msg = readdisklabel(dev, lp1); + + if (msg != NULL && (flags & DSO_COMPATLABEL)) { + msg = NULL; + kfree(lp1, M_DEVBUF); + lp1 = clone_label(info, sp); + } + if (msg == NULL) + msg = fixlabel(sname, sp, lp1, FALSE); + if (msg == NULL && lp1->d_secsize != info->d_media_blksize) + msg = "inconsistent sector size"; + if (msg != NULL) { + if (sp->ds_type == DOSPTYP_386BSD /* XXX */) + log(LOG_WARNING, "%s: cannot find label (%s)\n", + sname, msg); + kfree(lp1, M_DEVBUF); + } else { + set_ds_label(ssp, slice, lp1); + set_ds_wlabel(ssp, slice, FALSE); + } + return (msg ? EINVAL : 0); +} + int64_t dssize(cdev_t dev, struct diskslices **sspp) { @@ -933,7 +1060,7 @@ free_ds_label(struct diskslices *ssp, int slice) } static char * -fixlabel(char *sname, struct diskslice *sp, struct disklabel *lp, int writeflag) +fixlabel(const char *sname, struct diskslice *sp, struct disklabel *lp, int writeflag) { u_int64_t start; u_int64_t end; @@ -949,6 +1076,14 @@ fixlabel(char *sname, struct diskslice *sp, struct disklabel *lp, int writeflag) return ("fixlabel: invalid checksum"); pp = &lp->d_partitions[RAW_PART]; + + /* + * What a mess. For ages old backwards compatibility the disklabel + * on-disk stores absolute offsets instead of slice-relative offsets. + * So fix it up when reading, writing, or snooping. + * + * The in-core label is always slice-relative. + */ if (writeflag) { start = 0; offset = sp->ds_offset; @@ -1003,8 +1138,9 @@ fixlabel(char *sname, struct diskslice *sp, struct disklabel *lp, int writeflag) } /* XXX else silently discard junk. */ bzero(pp, sizeof *pp); - } else + } else { pp->p_offset += offset; + } } } lp->d_ncylinders = sp->ds_size / lp->d_secpercyl; @@ -1015,7 +1151,7 @@ fixlabel(char *sname, struct diskslice *sp, struct disklabel *lp, int writeflag) } static void -partition_info(char *sname, int part, struct partition *pp) +partition_info(const char *sname, int part, struct partition *pp) { kprintf("%s%c: start %lu, end %lu, size %lu\n", sname, 'a' + part, (u_long)pp->p_offset, (u_long)(pp->p_offset + pp->p_size - 1), @@ -1023,7 +1159,7 @@ partition_info(char *sname, int part, struct partition *pp) } static void -slice_info(char *sname, struct diskslice *sp) +slice_info(const char *sname, struct diskslice *sp) { kprintf("%s: start %llu, end %llu, size %llu\n", sname, sp->ds_offset, sp->ds_offset + sp->ds_size - 1, sp->ds_size); diff --git a/sys/kern/vfs_conf.c b/sys/kern/vfs_conf.c index 1f68d86da0..54f6b12ba9 100644 --- a/sys/kern/vfs_conf.c +++ b/sys/kern/vfs_conf.c @@ -26,7 +26,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/kern/vfs_conf.c,v 1.49.2.5 2003/01/07 11:56:53 joerg Exp $ - * $DragonFly: src/sys/kern/vfs_conf.c,v 1.29 2007/05/09 00:53:34 dillon Exp $ + * $DragonFly: src/sys/kern/vfs_conf.c,v 1.30 2007/05/19 00:52:01 dillon Exp $ */ /* @@ -409,7 +409,7 @@ kgetdiskbyname(const char *name) * Get the unit. */ unit = strtol(cp, &cp, 10); - if (name + nlen == (const char *)cp || unit < 0 || unit > DKMAXUNIT) { + if (name + nlen == (const char *)cp || unit < 0 || unit >= DKMAXUNITS) { kprintf("bad unit: %d\n", unit); return (NULL); } diff --git a/sys/sys/disk.h b/sys/sys/disk.h index e527193c0f..209aa9e584 100644 --- a/sys/sys/disk.h +++ b/sys/sys/disk.h @@ -39,7 +39,7 @@ * ---------------------------------------------------------------------------- * * $FreeBSD: src/sys/sys/disk.h,v 1.16.2.3 2001/06/20 16:11:01 scottl Exp $ - * $DragonFly: src/sys/sys/disk.h,v 1.14 2007/05/17 03:20:11 dillon Exp $ + * $DragonFly: src/sys/sys/disk.h,v 1.15 2007/05/19 00:52:02 dillon Exp $ */ #ifndef _SYS_DISK_H_ @@ -52,10 +52,12 @@ #ifndef _SYS_DISKSLICE_H_ #include #endif - #ifndef _SYS_DISKLABEL_H_ #include #endif +#ifndef _SYS_QUEUE_H_ +#include +#endif /* * Media information structure - filled in by the media driver. diff --git a/sys/sys/disklabel.h b/sys/sys/disklabel.h index 3b1e8d07ec..e2be9edb70 100644 --- a/sys/sys/disklabel.h +++ b/sys/sys/disklabel.h @@ -32,7 +32,7 @@ * * @(#)disklabel.h 8.2 (Berkeley) 7/10/94 * $FreeBSD: src/sys/sys/disklabel.h,v 1.49.2.7 2001/05/27 05:58:26 jkh Exp $ - * $DragonFly: src/sys/sys/disklabel.h,v 1.22 2007/05/17 23:49:56 dillon Exp $ + * $DragonFly: src/sys/sys/disklabel.h,v 1.23 2007/05/19 00:52:02 dillon Exp $ */ #ifndef _SYS_DISKLABEL_H_ @@ -47,9 +47,6 @@ #ifndef _SYS_IOCCOM_H_ #include #endif -#if defined(_KERNEL) && !defined(_SYS_CONF_H_) -#include /* for make_sub_dev() */ -#endif /* * Each disk has a label which includes information about the hardware @@ -64,14 +61,6 @@ #define LABELOFFSET 0 /* offset of label in sector */ #endif -#ifndef LABELSECTOR -#define LABELSECTOR 0 /* sector containing label */ -#endif - -#ifndef LABELOFFSET -#define LABELOFFSET 64 /* offset of label in sector */ -#endif - #define DISKMAGIC ((u_int32_t)0x82564557) /* The disk magic number */ #ifndef MAXPARTITIONS #define MAXPARTITIONS 16 @@ -88,26 +77,9 @@ struct disklabel { u_int16_t d_subtype; /* controller/d_type specific */ char d_typename[16]; /* type name, e.g. "eagle" */ - /* - * d_packname contains the pack identifier and is returned when - * the disklabel is read off the disk or in-core copy. - * d_boot0 and d_boot1 are the (optional) names of the - * primary (block 0) and secondary (block 1-15) bootstraps - * as found in /boot. These are returned when using - * getdiskbyname(3) to retrieve the values from /etc/disktab. - */ - union { - char un_d_packname[16]; /* pack identifier */ - struct { - char *un_d_boot0; /* primary bootstrap name */ - char *un_d_boot1; /* secondary bootstrap name */ - } un_b; - } d_un; -#define d_packname d_un.un_d_packname -#define d_boot0 d_un.un_b.un_d_boot0 -#define d_boot1 d_un.un_b.un_d_boot1 + char d_packname[16]; /* pack identifier */ - /* disk geometry: */ + /* disk geometry: */ u_int32_t d_secsize; /* # of bytes per sector */ u_int32_t d_nsectors; /* # of data sectors per track */ u_int32_t d_ntracks; /* # of tracks per cylinder */ @@ -313,90 +285,7 @@ static const char *fstypenames[] = { #ifdef _KERNEL -/* - * XXX encoding of disk minor numbers, should be elsewhere. - * - * See for a possibly better encoding. - * - * "cpio -H newc" can be used to back up device files with large minor - * numbers (but not ones >= 2^31). Old cpio formats and all tar formats - * don't have enough bits, and cpio and tar don't notice the lossage. - * There are also some sign extension bugs. - */ - -/* - 3 2 1 0 - 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - _________________________________________________________________ - | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | - ----------------------------------------------------------------- - | TYPE |UNIT_2 |P| SLICE | MAJOR? | UNIT |PART | - ----------------------------------------------------------------- -*/ - -#define DKMAXUNIT 0x1ff /* Highest disk unit number */ - -#define dkmakeminor(unit, slice, part) \ - (((slice) << 16) | (((unit) & 0x1e0) << 16) | \ - (((unit) & 0x1f) << 3) | (part & 7) | \ - ((part & 0x08) << 17)) - -static __inline u_int -dkunitmask(void) -{ - return (0x01e000f8); -} - -static __inline u_int -dkmakeunit(int unit) -{ - return(dkmakeminor(unit, 0, 0)); -} - -static __inline cdev_t -dkmodpart(cdev_t dev, int part) -{ - int val; - - if (part < 8) - val = (part & 7); - else - val = (part & 7) | 0x100000; - return (make_sub_dev(dev, (minor(dev) & ~0x100007) | val)); -} - -static __inline cdev_t -dkmodslice(cdev_t dev, int slice) -{ - return (make_sub_dev(dev, (minor(dev) & ~0x0f0000) | (slice << 16))); -} - -static __inline int -dkpart(cdev_t dev) -{ - return (((minor(dev) >> 17) & 0x08) | (minor(dev) & 7)); -} - -#define dkslice(dev) ((minor(dev) >> 16) & 0x0f) -#define dktype(dev) ((minor(dev) >> 25) & 0x7f) - -static __inline u_int -dkunit(cdev_t dev) -{ - return (((minor(dev) >> 16) & 0x1e0) | ((minor(dev) >> 3) & 0x1f)); -} - -struct buf; -struct bio; -struct bio_queue_head; - -struct bio *bounds_check_with_label (cdev_t dev, struct bio *bio, - struct disklabel *lp, int wlabel); -void diskerr (struct bio *bio, cdev_t dev, const char *what, int pri, - int donecnt); -void disksort (struct buf *ap, struct buf *bp); char *readdisklabel (cdev_t dev, struct disklabel *lp); -void bioqdisksort (struct bio_queue_head *ap, struct bio *bio); int setdisklabel (struct disklabel *olp, struct disklabel *nlp, u_long openmask); int writedisklabel (cdev_t dev, struct disklabel *lp); diff --git a/sys/sys/disklabel32.h b/sys/sys/disklabel32.h index f3861c9d61..156eb69c88 100644 --- a/sys/sys/disklabel32.h +++ b/sys/sys/disklabel32.h @@ -32,7 +32,7 @@ * * @(#)disklabel.h 8.2 (Berkeley) 7/10/94 * $FreeBSD: src/sys/sys/disklabel.h,v 1.49.2.7 2001/05/27 05:58:26 jkh Exp $ - * $DragonFly: src/sys/sys/disklabel32.h,v 1.22 2007/05/17 23:49:56 dillon Exp $ + * $DragonFly: src/sys/sys/disklabel32.h,v 1.23 2007/05/19 00:52:02 dillon Exp $ */ #ifndef _SYS_DISKLABEL_H_ @@ -47,9 +47,6 @@ #ifndef _SYS_IOCCOM_H_ #include #endif -#if defined(_KERNEL) && !defined(_SYS_CONF_H_) -#include /* for make_sub_dev() */ -#endif /* * Each disk has a label which includes information about the hardware @@ -64,14 +61,6 @@ #define LABELOFFSET 0 /* offset of label in sector */ #endif -#ifndef LABELSECTOR -#define LABELSECTOR 0 /* sector containing label */ -#endif - -#ifndef LABELOFFSET -#define LABELOFFSET 64 /* offset of label in sector */ -#endif - #define DISKMAGIC ((u_int32_t)0x82564557) /* The disk magic number */ #ifndef MAXPARTITIONS #define MAXPARTITIONS 16 @@ -88,26 +77,9 @@ struct disklabel { u_int16_t d_subtype; /* controller/d_type specific */ char d_typename[16]; /* type name, e.g. "eagle" */ - /* - * d_packname contains the pack identifier and is returned when - * the disklabel is read off the disk or in-core copy. - * d_boot0 and d_boot1 are the (optional) names of the - * primary (block 0) and secondary (block 1-15) bootstraps - * as found in /boot. These are returned when using - * getdiskbyname(3) to retrieve the values from /etc/disktab. - */ - union { - char un_d_packname[16]; /* pack identifier */ - struct { - char *un_d_boot0; /* primary bootstrap name */ - char *un_d_boot1; /* secondary bootstrap name */ - } un_b; - } d_un; -#define d_packname d_un.un_d_packname -#define d_boot0 d_un.un_b.un_d_boot0 -#define d_boot1 d_un.un_b.un_d_boot1 + char d_packname[16]; /* pack identifier */ - /* disk geometry: */ + /* disk geometry: */ u_int32_t d_secsize; /* # of bytes per sector */ u_int32_t d_nsectors; /* # of data sectors per track */ u_int32_t d_ntracks; /* # of tracks per cylinder */ @@ -313,90 +285,7 @@ static const char *fstypenames[] = { #ifdef _KERNEL -/* - * XXX encoding of disk minor numbers, should be elsewhere. - * - * See for a possibly better encoding. - * - * "cpio -H newc" can be used to back up device files with large minor - * numbers (but not ones >= 2^31). Old cpio formats and all tar formats - * don't have enough bits, and cpio and tar don't notice the lossage. - * There are also some sign extension bugs. - */ - -/* - 3 2 1 0 - 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - _________________________________________________________________ - | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | - ----------------------------------------------------------------- - | TYPE |UNIT_2 |P| SLICE | MAJOR? | UNIT |PART | - ----------------------------------------------------------------- -*/ - -#define DKMAXUNIT 0x1ff /* Highest disk unit number */ - -#define dkmakeminor(unit, slice, part) \ - (((slice) << 16) | (((unit) & 0x1e0) << 16) | \ - (((unit) & 0x1f) << 3) | (part & 7) | \ - ((part & 0x08) << 17)) - -static __inline u_int -dkunitmask(void) -{ - return (0x01e000f8); -} - -static __inline u_int -dkmakeunit(int unit) -{ - return(dkmakeminor(unit, 0, 0)); -} - -static __inline cdev_t -dkmodpart(cdev_t dev, int part) -{ - int val; - - if (part < 8) - val = (part & 7); - else - val = (part & 7) | 0x100000; - return (make_sub_dev(dev, (minor(dev) & ~0x100007) | val)); -} - -static __inline cdev_t -dkmodslice(cdev_t dev, int slice) -{ - return (make_sub_dev(dev, (minor(dev) & ~0x0f0000) | (slice << 16))); -} - -static __inline int -dkpart(cdev_t dev) -{ - return (((minor(dev) >> 17) & 0x08) | (minor(dev) & 7)); -} - -#define dkslice(dev) ((minor(dev) >> 16) & 0x0f) -#define dktype(dev) ((minor(dev) >> 25) & 0x7f) - -static __inline u_int -dkunit(cdev_t dev) -{ - return (((minor(dev) >> 16) & 0x1e0) | ((minor(dev) >> 3) & 0x1f)); -} - -struct buf; -struct bio; -struct bio_queue_head; - -struct bio *bounds_check_with_label (cdev_t dev, struct bio *bio, - struct disklabel *lp, int wlabel); -void diskerr (struct bio *bio, cdev_t dev, const char *what, int pri, - int donecnt); -void disksort (struct buf *ap, struct buf *bp); char *readdisklabel (cdev_t dev, struct disklabel *lp); -void bioqdisksort (struct bio_queue_head *ap, struct bio *bio); int setdisklabel (struct disklabel *olp, struct disklabel *nlp, u_long openmask); int writedisklabel (cdev_t dev, struct disklabel *lp); diff --git a/sys/sys/diskslice.h b/sys/sys/diskslice.h index e44da8bfb2..12e7663071 100644 --- a/sys/sys/diskslice.h +++ b/sys/sys/diskslice.h @@ -1,3 +1,36 @@ +/* + * Copyright (c) 2007 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Matthew Dillon + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ /*- * Copyright (c) 1994 Bruce D. Evans. * All rights reserved. @@ -24,7 +57,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/sys/diskslice.h,v 1.36.2.1 2001/01/29 01:50:50 ken Exp $ - * $DragonFly: src/sys/sys/diskslice.h,v 1.12 2007/05/16 05:20:25 dillon Exp $ + * $DragonFly: src/sys/sys/diskslice.h,v 1.13 2007/05/19 00:52:02 dillon Exp $ */ #ifndef _SYS_DISKSLICE_H_ @@ -36,13 +69,22 @@ #ifndef _SYS_IOCCOM_H_ #include #endif +#if defined(_KERNEL) && !defined(_SYS_CONF_H_) +#include /* for make_sub_dev() */ +#endif #define BASE_SLICE 2 /* e.g. ad0s1 */ #define COMPATIBILITY_SLICE 0 /* e.g. ad0a-j */ #define DIOCGSLICEINFO _IOR('d', 111, struct diskslices) #define DIOCSYNCSLICEINFO _IOW('d', 112, int) #define MAX_SLICES 16 -#define WHOLE_DISK_SLICE 1 /* e.g. ad0 */ + +/* + * The whole-disk-slice does not try to interpret the MBR. The whole slice + * partition does not try to interpret the disklabel within the slice. + */ +#define WHOLE_DISK_SLICE 1 +#define WHOLE_SLICE_PART (DKMAXPARTITIONS - 1) #ifdef MAXPARTITIONS /* XXX don't depend on disklabel.h */ #if MAXPARTITIONS != 16 /* but check consistency if possible */ @@ -128,6 +170,150 @@ struct partinfo { #define DIOCGPART _IOR('d', 104, struct partinfo) /* get partition */ +/* + * disk unit and slice helper functions + * + * 3 2 1 0 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * _________________________________________________________________ + * | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | + * ----------------------------------------------------------------- + * | SL2 | PART3 |UNIT_2 |P| SLICE | MAJOR? | UNIT |PART | + * ----------------------------------------------------------------- + */ + +#if defined(_KERNEL) || defined(_KERNEL_STRUCTURES) + +#define DKMAXUNITS 512 +#define DKMAXSLICES 128 +#define DKMAXPARTITIONS 256 + +/* + * Build a minor device number. + */ +static __inline u_int32_t +dkmakeminor(u_int32_t unit, u_int32_t slice, u_int32_t part) +{ + u_int32_t val; + + val = ((unit & 0x001f) << 3) | ((unit & 0x01e0) << 16) | + ((slice & 0x000f) << 16) | ((slice & 0x0070) << 25) | + (part & 0x0007) | ((part & 0x0008) << 17) | + ((part & 0x00F0) << 21); + return(val); +} + +/* + * Generate the minor number representing the entire disk, with no + * mbr or label interpretation. + */ +static __inline u_int32_t +dkmakewholedisk(u_int32_t unit) +{ + return(dkmakeminor(unit, WHOLE_DISK_SLICE, WHOLE_SLICE_PART)); +} + +/* + * Generate the minor number representing an entire slice, with no + * recursive mbr, boot sector, or label interpretation. + */ +static __inline u_int32_t +dkmakewholeslice(u_int32_t unit, u_int32_t slice) +{ + return(dkmakeminor(unit, slice, WHOLE_SLICE_PART)); +} + +/* + * Return the unit mask, used in calls to make_dev() + */ +static __inline u_int32_t +dkunitmask(void) +{ + return (0x01e000f8); +} + +/* + * build minor number elements - encode unit number, slice, and partition + * (OR the results together). + */ +static __inline u_int32_t +dkmakeunit(int unit) +{ + return(dkmakeminor((u_int32_t)unit, 0, 0)); +} + +static __inline u_int32_t +dkmakeslice(int slice) +{ + return(dkmakeminor(0, (u_int32_t)slice, 0)); +} + +static __inline u_int32_t +dkmakepart(int part) +{ + return(dkmakeminor(0, 0, (u_int32_t)part)); +} + +#endif + +/* + * dk*() support functions operating on cdev_t's + */ +#ifdef _KERNEL + +static __inline int +dkunit(cdev_t dev) +{ + u_int32_t val = minor(dev); + + val = ((val >> 3) & 0x001f) | ((val >> 16) & 0x01e0); + return((int)val); +} + +static __inline u_int32_t +dkslice(cdev_t dev) +{ + u_int32_t val = minor(dev); + + val = ((val >> 16) & 0x000f) | ((val >> 25) & 0x0070); + return(val); +} + +static __inline u_int32_t +dkpart(cdev_t dev) +{ + u_int32_t val = minor(dev); + + val = (val & 0x0007) | ((val >> 17) & 0x0008) | ((val >> 21) & 0x00f0); + return(val); +} + +/* + * dkmodpart() - create sub-device + */ +static __inline cdev_t +dkmodpart(cdev_t dev, int part) +{ + u_int32_t val; + + val = (minor(dev) & ~dkmakepart(-1)) | dkmakepart(part); + return (make_sub_dev(dev, val)); +} + +static __inline cdev_t +dkmodslice(cdev_t dev, int slice) +{ + u_int32_t val; + + val = (minor(dev) & ~dkmakeslice(-1)) | dkmakeslice(slice); + return (make_sub_dev(dev, val)); +} + +#endif + +/* + * disk management functions + */ #ifdef _KERNEL @@ -137,22 +323,34 @@ struct buf; struct bio; struct disklabel; struct disk_info; +struct bio_queue_head; int mbrinit (cdev_t dev, struct disk_info *info, - struct diskslices **sspp); -struct bio *dscheck (cdev_t dev, struct bio *bio, struct diskslices *ssp); + struct diskslices **sspp); +struct bio * + dscheck (cdev_t dev, struct bio *bio, struct diskslices *ssp); void dsclose (cdev_t dev, int mode, struct diskslices *ssp); void dsgone (struct diskslices **sspp); int dsioctl (cdev_t dev, u_long cmd, caddr_t data, int flags, - struct diskslices **sspp, struct disk_info *info); + struct diskslices **sspp, struct disk_info *info); int dsisopen (struct diskslices *ssp); -struct diskslices *dsmakeslicestruct (int nslices, struct disk_info *info); +struct diskslices * + dsmakeslicestruct (int nslices, struct disk_info *info); char *dsname (cdev_t dev, int unit, int slice, int part, - char *partname); + char *partname); int dsopen (cdev_t dev, int mode, u_int flags, struct diskslices **sspp, struct disk_info *info); int64_t dssize (cdev_t dev, struct diskslices **sspp); +/* + * Ancillary functions + */ + +void diskerr (struct bio *bio, cdev_t dev, const char *what, int pri, + int donecnt); +void disksort (struct buf *ap, struct buf *bp); +void bioqdisksort (struct bio_queue_head *ap, struct bio *bio); + #endif /* _KERNEL */ #endif /* !_SYS_DISKSLICE_H_ */ -- 2.41.0