| 1 | /* |
| 2 | * Copyright (c) 2007 The DragonFly Project. All rights reserved. |
| 3 | * |
| 4 | * This code is derived from software contributed to The DragonFly Project |
| 5 | * by Matthew Dillon <dillon@backplane.com> |
| 6 | * |
| 7 | * Redistribution and use in source and binary forms, with or without |
| 8 | * modification, are permitted provided that the following conditions |
| 9 | * are met: |
| 10 | * |
| 11 | * 1. Redistributions of source code must retain the above copyright |
| 12 | * notice, this list of conditions and the following disclaimer. |
| 13 | * 2. Redistributions in binary form must reproduce the above copyright |
| 14 | * notice, this list of conditions and the following disclaimer in |
| 15 | * the documentation and/or other materials provided with the |
| 16 | * distribution. |
| 17 | * 3. Neither the name of The DragonFly Project nor the names of its |
| 18 | * contributors may be used to endorse or promote products derived |
| 19 | * from this software without specific, prior written permission. |
| 20 | * |
| 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| 24 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
| 25 | * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
| 26 | * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, |
| 27 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 28 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
| 29 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| 30 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| 31 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 32 | * SUCH DAMAGE. |
| 33 | */ |
| 34 | /*- |
| 35 | * Copyright (c) 1994 Bruce D. Evans. |
| 36 | * All rights reserved. |
| 37 | * |
| 38 | * Redistribution and use in source and binary forms, with or without |
| 39 | * modification, are permitted provided that the following conditions |
| 40 | * are met: |
| 41 | * 1. Redistributions of source code must retain the above copyright |
| 42 | * notice, this list of conditions and the following disclaimer. |
| 43 | * 2. Redistributions in binary form must reproduce the above copyright |
| 44 | * notice, this list of conditions and the following disclaimer in the |
| 45 | * documentation and/or other materials provided with the distribution. |
| 46 | * |
| 47 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
| 48 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 49 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 50 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
| 51 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 52 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 53 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 54 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 55 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 56 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 57 | * SUCH DAMAGE. |
| 58 | * |
| 59 | * $FreeBSD: src/sys/sys/diskslice.h,v 1.36.2.1 2001/01/29 01:50:50 ken Exp $ |
| 60 | * $DragonFly: src/sys/sys/diskslice.h,v 1.22 2007/06/19 06:07:51 dillon Exp $ |
| 61 | */ |
| 62 | |
| 63 | #ifndef _SYS_DISKSLICE_H_ |
| 64 | #define _SYS_DISKSLICE_H_ |
| 65 | |
| 66 | #ifndef _SYS_TYPES_H_ |
| 67 | #include <sys/types.h> |
| 68 | #endif |
| 69 | #ifndef _SYS_DISKLABEL_H_ |
| 70 | #include <sys/disklabel.h> |
| 71 | #endif |
| 72 | #ifndef _SYS_UUID_H_ |
| 73 | #include <sys/uuid.h> |
| 74 | #endif |
| 75 | #ifndef _SYS_IOCCOM_H_ |
| 76 | #include <sys/ioccom.h> |
| 77 | #endif |
| 78 | #if defined(_KERNEL) |
| 79 | #ifndef _SYS_CONF_H_ |
| 80 | #include <sys/conf.h> /* for make_sub_dev() */ |
| 81 | #endif |
| 82 | #ifndef _SYS_SYSTM_H_ |
| 83 | #include <sys/systm.h> /* for minor() */ |
| 84 | #endif |
| 85 | #endif |
| 86 | |
| 87 | #define BASE_SLICE 2 /* e.g. ad0s1 */ |
| 88 | #define COMPATIBILITY_SLICE 0 /* e.g. ad0a-j */ |
| 89 | /* 101 - compat disklabel DIOCGDINFO */ |
| 90 | /* 102 - compat disklabel DIOCSDINFO */ |
| 91 | /* 103 - compat disklabel DIOCWDINFO */ |
| 92 | /* 104 - DIOCGPART (see below) */ |
| 93 | /* 105 - compat disklabel DIOCGDVIRGIN */ |
| 94 | #define DIOCWLABEL _IOW('d', 109, int) |
| 95 | #define DIOCGSLICEINFO _IOR('d', 111, struct diskslices) |
| 96 | #define DIOCSYNCSLICEINFO _IOW('d', 112, int) |
| 97 | #define DIOCGKERNELDUMP _IOW('d', 133, u_int) /* Set/Clear dumps */ |
| 98 | #define DIOCRECLUSTER _IOWR('d', 134, struct disk_ioc_recluster) |
| 99 | #define DIOCGMEDIASIZE _IOR('d', 135, off_t) |
| 100 | #define DIOCGSECTORSIZE _IOR('d', 136, u_int) |
| 101 | #define MAX_SLICES 16 |
| 102 | |
| 103 | /* |
| 104 | * Support limits |
| 105 | */ |
| 106 | #define DKMAXUNITS 512 /* maximum supported disk units */ |
| 107 | #define DKMAXSLICES 128 /* maximum supported slices (0 & 1 special) */ |
| 108 | #define DKRESPARTITIONS 128 /* 128+ have special meanings */ |
| 109 | #define DKMAXPARTITIONS 256 /* maximum supported in-kernel partitions */ |
| 110 | |
| 111 | /* |
| 112 | * The whole-disk-slice does not try to interpret the MBR. The whole slice |
| 113 | * partition does not try to interpret the disklabel within the slice. |
| 114 | */ |
| 115 | #define WHOLE_DISK_SLICE 1 |
| 116 | #define WHOLE_SLICE_PART (DKMAXPARTITIONS - 1) |
| 117 | |
| 118 | #ifdef MAXPARTITIONS /* XXX don't depend on disklabel.h */ |
| 119 | #if MAXPARTITIONS != 16 /* but check consistency if possible */ |
| 120 | #error "inconsistent MAXPARTITIONS" |
| 121 | #endif |
| 122 | #else |
| 123 | #define MAXPARTITIONS 16 |
| 124 | #endif |
| 125 | |
| 126 | /* |
| 127 | * diskslice structure - slices up the disk and indicates where the |
| 128 | * BSD labels are, if any. |
| 129 | * |
| 130 | * ds_reserved - indicates read-only sectors due to an overlap with |
| 131 | * a parent partition or an in-band label. BSD labels |
| 132 | * are in-band labels. This field is also set if |
| 133 | * label snooping has been requested, even if there is |
| 134 | * no label present. |
| 135 | */ |
| 136 | struct diskslice { |
| 137 | #if defined(_KERNEL) || defined(_KERNEL_STRUCTURES) |
| 138 | cdev_t ds_dev; |
| 139 | #else |
| 140 | void *ds_dev; |
| 141 | #endif |
| 142 | u_int64_t ds_offset; /* starting sector */ |
| 143 | u_int64_t ds_size; /* number of sectors */ |
| 144 | u_int32_t ds_reserved; /* sectors reserved parent overlap */ |
| 145 | struct uuid ds_type_uuid; /* slice type uuid */ |
| 146 | struct uuid ds_stor_uuid; /* slice storage unique uuid */ |
| 147 | int ds_type; /* (foreign) slice type */ |
| 148 | int ds_flags; /* DSF_ flags */ |
| 149 | disklabel_t ds_label; /* label, if any */ |
| 150 | struct disklabel_ops *ds_ops; /* label ops (probe default) */ |
| 151 | //void *ds_dev; /* devfs token for raw whole slice */ |
| 152 | void *ds_devs[MAXPARTITIONS]; /* XXX s.b. in label */ |
| 153 | u_int32_t ds_openmask[DKMAXPARTITIONS/(sizeof(u_int32_t)*8)]; |
| 154 | /* devs open */ |
| 155 | u_char ds_wlabel; /* nonzero if label is writable */ |
| 156 | int ds_ttlopens; /* total opens, incl slice & raw */ |
| 157 | }; |
| 158 | |
| 159 | #define DSF_REPROBE 0x0001 /* sniffer wants us to reprobe */ |
| 160 | |
| 161 | struct diskslices { |
| 162 | struct cdevsw *dss_cdevsw; /* for containing device */ |
| 163 | int dss_first_bsd_slice; /* COMPATIBILITY_SLICE is mapped here */ |
| 164 | u_int dss_nslices; /* actual dimension of dss_slices[] */ |
| 165 | u_int dss_oflags; /* copy of flags for "first" open */ |
| 166 | int dss_secmult; /* block to sector multiplier */ |
| 167 | int dss_secshift; /* block to sector shift (or -1) */ |
| 168 | int dss_secsize; /* sector size */ |
| 169 | struct diskslice |
| 170 | dss_slices[MAX_SLICES]; /* actually usually less */ |
| 171 | }; |
| 172 | |
| 173 | struct disk_ioc_recluster { |
| 174 | int fd; |
| 175 | }; |
| 176 | |
| 177 | /* |
| 178 | * DIOCGPART ioctl - returns information about a disk, slice, or partition. |
| 179 | * This ioctl is primarily used to get the block size and media size. |
| 180 | * |
| 181 | * NOTE: media_offset currently represents the byte offset on the raw device, |
| 182 | * it is not a partition relative offset. disklabel(32) uses this field |
| 183 | * to figure out the slice offset so it fixup raw labels. |
| 184 | * |
| 185 | * NOTE: reserved_blocks indicates how many blocks at the beginning of the |
| 186 | * partition are read-only due to in-band sharing with the parent. For |
| 187 | * example, if partition 'a' starts at block 0, it actually overlaps the |
| 188 | * disklabel itself so numerous sectors at the beginning of 'a' will be |
| 189 | * reserved. |
| 190 | */ |
| 191 | struct partinfo { |
| 192 | u_int64_t media_offset; /* byte offset in parent layer */ |
| 193 | u_int64_t media_size; /* media size in bytes */ |
| 194 | u_int64_t media_blocks; /* media size in blocks */ |
| 195 | int media_blksize; /* block size in bytes (sector size) */ |
| 196 | |
| 197 | u_int64_t reserved_blocks;/* read-only, in sectors */ |
| 198 | int fstype; /* legacy filesystem type or FS_OTHER */ |
| 199 | char fsreserved[16]; /* reserved for future use */ |
| 200 | |
| 201 | /* |
| 202 | * These fields are loaded from the diskinfo structure |
| 203 | */ |
| 204 | u_int d_nheads; |
| 205 | u_int d_ncylinders; |
| 206 | u_int d_secpertrack; |
| 207 | u_int d_secpercyl; |
| 208 | u_int d_reserved[8]; /* reserved for future use */ |
| 209 | |
| 210 | /* |
| 211 | * UUIDs can be extracted from GPT slices and disklabel64 |
| 212 | * partitions. If not known, they will be set to a nil uuid. |
| 213 | * |
| 214 | * fstype_uuid represents the slice or partition type, e.g. |
| 215 | * like GPT_ENT_TYPE_DRAGONFLY_DISKLABEL32. If not nil, |
| 216 | * storage_uuid uniquely identifies the physical storage. |
| 217 | */ |
| 218 | struct uuid fstype_uuid; |
| 219 | struct uuid storage_uuid; |
| 220 | }; |
| 221 | |
| 222 | #define DIOCGPART _IOR('d', 104, struct partinfo) /* get partition */ |
| 223 | |
| 224 | /* |
| 225 | * disk unit and slice helper functions |
| 226 | * |
| 227 | * 3 2 1 0 |
| 228 | * 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 |
| 229 | * _________________________________________________________________ |
| 230 | * | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
| 231 | * ----------------------------------------------------------------- |
| 232 | * | SL2 | PART3 |UNIT_2 |P| SLICE | MAJOR? | UNIT |PART | |
| 233 | * ----------------------------------------------------------------- |
| 234 | */ |
| 235 | |
| 236 | #if defined(_KERNEL) || defined(_KERNEL_STRUCTURES) |
| 237 | |
| 238 | /* |
| 239 | * Build a minor device number. |
| 240 | */ |
| 241 | static __inline u_int32_t |
| 242 | dkmakeminor(u_int32_t unit, u_int32_t slice, u_int32_t part) |
| 243 | { |
| 244 | u_int32_t val; |
| 245 | |
| 246 | val = ((unit & 0x001f) << 3) | ((unit & 0x01e0) << 16) | |
| 247 | ((slice & 0x000f) << 16) | ((slice & 0x0070) << 25) | |
| 248 | (part & 0x0007) | ((part & 0x0008) << 17) | |
| 249 | ((part & 0x00F0) << 21); |
| 250 | return(val); |
| 251 | } |
| 252 | |
| 253 | /* |
| 254 | * Generate the minor number representing the entire disk, with no |
| 255 | * mbr or label interpretation. |
| 256 | */ |
| 257 | static __inline u_int32_t |
| 258 | dkmakewholedisk(u_int32_t unit) |
| 259 | { |
| 260 | return(dkmakeminor(unit, WHOLE_DISK_SLICE, WHOLE_SLICE_PART)); |
| 261 | } |
| 262 | |
| 263 | /* |
| 264 | * Generate the minor number representing an entire slice, with no |
| 265 | * recursive mbr, boot sector, or label interpretation. |
| 266 | */ |
| 267 | static __inline u_int32_t |
| 268 | dkmakewholeslice(u_int32_t unit, u_int32_t slice) |
| 269 | { |
| 270 | return(dkmakeminor(unit, slice, WHOLE_SLICE_PART)); |
| 271 | } |
| 272 | |
| 273 | /* |
| 274 | * Return the unit mask, used in calls to make_dev() |
| 275 | */ |
| 276 | static __inline u_int32_t |
| 277 | dkunitmask(void) |
| 278 | { |
| 279 | return (0x01e000f8); |
| 280 | } |
| 281 | |
| 282 | /* |
| 283 | * build minor number elements - encode unit number, slice, and partition |
| 284 | * (OR the results together). |
| 285 | */ |
| 286 | static __inline u_int32_t |
| 287 | dkmakeunit(int unit) |
| 288 | { |
| 289 | return(dkmakeminor((u_int32_t)unit, 0, 0)); |
| 290 | } |
| 291 | |
| 292 | static __inline u_int32_t |
| 293 | dkmakeslice(int slice) |
| 294 | { |
| 295 | return(dkmakeminor(0, (u_int32_t)slice, 0)); |
| 296 | } |
| 297 | |
| 298 | static __inline u_int32_t |
| 299 | dkmakepart(int part) |
| 300 | { |
| 301 | return(dkmakeminor(0, 0, (u_int32_t)part)); |
| 302 | } |
| 303 | |
| 304 | #endif |
| 305 | |
| 306 | /* |
| 307 | * dk*() support functions operating on cdev_t's |
| 308 | */ |
| 309 | #ifdef _KERNEL |
| 310 | |
| 311 | static __inline int |
| 312 | dkunit(cdev_t dev) |
| 313 | { |
| 314 | u_int32_t val = minor(dev); |
| 315 | |
| 316 | val = ((val >> 3) & 0x001f) | ((val >> 16) & 0x01e0); |
| 317 | return((int)val); |
| 318 | } |
| 319 | |
| 320 | static __inline u_int32_t |
| 321 | dkslice(cdev_t dev) |
| 322 | { |
| 323 | u_int32_t val = minor(dev); |
| 324 | |
| 325 | val = ((val >> 16) & 0x000f) | ((val >> 25) & 0x0070); |
| 326 | return(val); |
| 327 | } |
| 328 | |
| 329 | static __inline u_int32_t |
| 330 | dkpart(cdev_t dev) |
| 331 | { |
| 332 | u_int32_t val = minor(dev); |
| 333 | |
| 334 | val = (val & 0x0007) | ((val >> 17) & 0x0008) | ((val >> 21) & 0x00f0); |
| 335 | return(val); |
| 336 | } |
| 337 | |
| 338 | #endif |
| 339 | |
| 340 | /* |
| 341 | * Bitmask ops, keeping track of which partitions are open. |
| 342 | */ |
| 343 | static __inline |
| 344 | void |
| 345 | dsclrmask(struct diskslice *ds, int part) |
| 346 | { |
| 347 | part &= (DKMAXPARTITIONS - 1); |
| 348 | ds->ds_openmask[part >> 5] &= ~(1 << (part & 31)); |
| 349 | } |
| 350 | |
| 351 | static __inline |
| 352 | void |
| 353 | dssetmask(struct diskslice *ds, int part) |
| 354 | { |
| 355 | part &= (DKMAXPARTITIONS - 1); |
| 356 | ds->ds_openmask[part >> 5] |= (1 << (part & 31)); |
| 357 | } |
| 358 | |
| 359 | static __inline |
| 360 | int |
| 361 | dschkmask(struct diskslice *ds, int part) |
| 362 | { |
| 363 | part &= (DKMAXPARTITIONS - 1); |
| 364 | return (ds->ds_openmask[part >> 5] & (1 << (part & 31))); |
| 365 | } |
| 366 | |
| 367 | static __inline |
| 368 | int |
| 369 | dscountmask(struct diskslice *ds) |
| 370 | { |
| 371 | int count = 0; |
| 372 | int i; |
| 373 | int j; |
| 374 | |
| 375 | for (i = 0; i < DKMAXPARTITIONS / 32; ++i) { |
| 376 | if (ds->ds_openmask[i]) { |
| 377 | for (j = 0; j < 32; ++j) { |
| 378 | if (ds->ds_openmask[i] & (1 << j)) |
| 379 | ++count; |
| 380 | } |
| 381 | } |
| 382 | } |
| 383 | return(count); |
| 384 | } |
| 385 | |
| 386 | static __inline |
| 387 | void |
| 388 | dssetmaskfrommask(struct diskslice *ds, u_int32_t *tmask) |
| 389 | { |
| 390 | int i; |
| 391 | |
| 392 | for (i = 0; i < DKMAXPARTITIONS / 32; ++i) |
| 393 | tmask[i] |= ds->ds_openmask[i]; |
| 394 | } |
| 395 | |
| 396 | /* |
| 397 | * disk management functions |
| 398 | */ |
| 399 | |
| 400 | #ifdef _KERNEL |
| 401 | |
| 402 | struct buf; |
| 403 | struct bio; |
| 404 | struct disk_info; |
| 405 | struct bio_queue_head; |
| 406 | |
| 407 | int mbrinit (cdev_t dev, struct disk_info *info, |
| 408 | struct diskslices **sspp); |
| 409 | int gptinit (cdev_t dev, struct disk_info *info, |
| 410 | struct diskslices **sspp); |
| 411 | struct bio * |
| 412 | dscheck (cdev_t dev, struct bio *bio, struct diskslices *ssp); |
| 413 | void dsclose (cdev_t dev, int mode, struct diskslices *ssp); |
| 414 | void dsgone (struct diskslices **sspp); |
| 415 | int dsioctl (cdev_t dev, u_long cmd, caddr_t data, int flags, |
| 416 | struct diskslices **sspp, struct disk_info *info); |
| 417 | int dsisopen (struct diskslices *ssp); |
| 418 | struct diskslices * |
| 419 | dsmakeslicestruct (int nslices, struct disk_info *info); |
| 420 | char *dsname (cdev_t dev, int unit, int slice, int part, |
| 421 | char *partname); |
| 422 | int dsopen (cdev_t dev, int mode, u_int flags, |
| 423 | struct diskslices **sspp, struct disk_info *info); |
| 424 | int64_t dssize (cdev_t dev, struct diskslices **sspp); |
| 425 | |
| 426 | /* |
| 427 | * Ancillary functions |
| 428 | */ |
| 429 | |
| 430 | void diskerr (struct bio *bio, cdev_t dev, const char *what, int pri, |
| 431 | int donecnt); |
| 432 | void bioqdisksort (struct bio_queue_head *ap, struct bio *bio); |
| 433 | |
| 434 | #endif /* _KERNEL */ |
| 435 | |
| 436 | #endif /* !_SYS_DISKSLICE_H_ */ |