diff options
Diffstat (limited to 'usr/src/uts')
-rw-r--r-- | usr/src/uts/common/io/cmlb.c | 552 | ||||
-rw-r--r-- | usr/src/uts/common/io/scsi/targets/sd.c | 6 | ||||
-rw-r--r-- | usr/src/uts/common/sys/cmlb_impl.h | 20 | ||||
-rw-r--r-- | usr/src/uts/common/sys/dkio.h | 5 | ||||
-rw-r--r-- | usr/src/uts/common/sys/dktp/fdisk.h | 31 | ||||
-rw-r--r-- | usr/src/uts/common/sys/scsi/targets/sddef.h | 10 | ||||
-rw-r--r-- | usr/src/uts/common/xen/io/xdf.c | 1 | ||||
-rw-r--r-- | usr/src/uts/i86pc/i86hvm/io/xdf_shell.c | 9 | ||||
-rw-r--r-- | usr/src/uts/intel/io/dktp/disk/cmdk.c | 1 |
9 files changed, 619 insertions, 16 deletions
diff --git a/usr/src/uts/common/io/cmlb.c b/usr/src/uts/common/io/cmlb.c index 343b1b965c..040b8c56f9 100644 --- a/usr/src/uts/common/io/cmlb.c +++ b/usr/src/uts/common/io/cmlb.c @@ -39,6 +39,9 @@ #include <sys/efi_partition.h> #include <sys/cmlb.h> #include <sys/cmlb_impl.h> +#if defined(__i386) || defined(__amd64) +#include <sys/fs/dv_node.h> +#endif #include <sys/ddi_impldefs.h> /* @@ -104,6 +107,78 @@ static struct driver_minor_data dk_minor_data[] = { {0} }; +#if defined(__i386) || defined(__amd64) +#if defined(_FIRMWARE_NEEDS_FDISK) +static struct driver_minor_data dk_ext_minor_data[] = { + {"p5", 21, S_IFBLK}, + {"p6", 22, S_IFBLK}, + {"p7", 23, S_IFBLK}, + {"p8", 24, S_IFBLK}, + {"p9", 25, S_IFBLK}, + {"p10", 26, S_IFBLK}, + {"p11", 27, S_IFBLK}, + {"p12", 28, S_IFBLK}, + {"p13", 29, S_IFBLK}, + {"p14", 30, S_IFBLK}, + {"p15", 31, S_IFBLK}, + {"p16", 32, S_IFBLK}, + {"p17", 33, S_IFBLK}, + {"p18", 34, S_IFBLK}, + {"p19", 35, S_IFBLK}, + {"p20", 36, S_IFBLK}, + {"p21", 37, S_IFBLK}, + {"p22", 38, S_IFBLK}, + {"p23", 39, S_IFBLK}, + {"p24", 40, S_IFBLK}, + {"p25", 41, S_IFBLK}, + {"p26", 42, S_IFBLK}, + {"p27", 43, S_IFBLK}, + {"p28", 44, S_IFBLK}, + {"p29", 45, S_IFBLK}, + {"p30", 46, S_IFBLK}, + {"p31", 47, S_IFBLK}, + {"p32", 48, S_IFBLK}, + {"p33", 49, S_IFBLK}, + {"p34", 50, S_IFBLK}, + {"p35", 51, S_IFBLK}, + {"p36", 52, S_IFBLK}, + {"p5,raw", 21, S_IFCHR}, + {"p6,raw", 22, S_IFCHR}, + {"p7,raw", 23, S_IFCHR}, + {"p8,raw", 24, S_IFCHR}, + {"p9,raw", 25, S_IFCHR}, + {"p10,raw", 26, S_IFCHR}, + {"p11,raw", 27, S_IFCHR}, + {"p12,raw", 28, S_IFCHR}, + {"p13,raw", 29, S_IFCHR}, + {"p14,raw", 30, S_IFCHR}, + {"p15,raw", 31, S_IFCHR}, + {"p16,raw", 32, S_IFCHR}, + {"p17,raw", 33, S_IFCHR}, + {"p18,raw", 34, S_IFCHR}, + {"p19,raw", 35, S_IFCHR}, + {"p20,raw", 36, S_IFCHR}, + {"p21,raw", 37, S_IFCHR}, + {"p22,raw", 38, S_IFCHR}, + {"p23,raw", 39, S_IFCHR}, + {"p24,raw", 40, S_IFCHR}, + {"p25,raw", 41, S_IFCHR}, + {"p26,raw", 42, S_IFCHR}, + {"p27,raw", 43, S_IFCHR}, + {"p28,raw", 44, S_IFCHR}, + {"p29,raw", 45, S_IFCHR}, + {"p30,raw", 46, S_IFCHR}, + {"p31,raw", 47, S_IFCHR}, + {"p32,raw", 48, S_IFCHR}, + {"p33,raw", 49, S_IFCHR}, + {"p34,raw", 50, S_IFCHR}, + {"p35,raw", 51, S_IFCHR}, + {"p36,raw", 52, S_IFCHR}, + {0} +}; +#endif /* defined(_FIRMWARE_NEEDS_FDISK) */ +#endif /* if defined(__i386) || defined(__amd64) */ + static struct driver_minor_data dk_minor_data_efi[] = { {"a", 0, S_IFBLK}, {"b", 1, S_IFBLK}, @@ -267,6 +342,12 @@ static int cmlb_dkio_partition(struct cmlb_lun *cl, caddr_t arg, int flag, void *tg_cookie); #if defined(__i386) || defined(__amd64) +static int cmlb_dkio_set_ext_part(struct cmlb_lun *cl, caddr_t arg, int flag, + void *tg_cookie); +static int cmlb_validate_ext_part(struct cmlb_lun *cl, int part, int epart, + uint32_t start, uint32_t size); +static int cmlb_is_linux_swap(struct cmlb_lun *cl, uint32_t part_start, + void *tg_cookie); static int cmlb_dkio_get_virtgeom(struct cmlb_lun *cl, caddr_t arg, int flag); static int cmlb_dkio_get_phygeom(struct cmlb_lun *cl, caddr_t arg, int flag); static int cmlb_dkio_partinfo(struct cmlb_lun *cl, dev_t dev, caddr_t arg, @@ -614,6 +695,9 @@ cmlb_attach(dev_info_t *devi, cmlb_tg_ops_t *tgopsp, int device_type, cl->cl_alter_behavior = alter_behavior; cl->cl_reserved = -1; cl->cl_msglog_flag |= CMLB_ALLOW_2TB_WARN; +#if defined(__i386) || defined(__amd64) + cl->cl_logical_drive_count = 0; +#endif if (!is_removable) { mutex_exit(CMLB_MUTEX(cl)); @@ -945,6 +1029,9 @@ cmlb_partinfo(cmlb_handle_t cmlbhandle, int part, diskaddr_t *nblocksp, struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; int rval; +#if defined(__i386) || defined(__amd64) + int ext_part; +#endif ASSERT(cl != NULL); mutex_enter(CMLB_MUTEX(cl)); @@ -986,8 +1073,17 @@ cmlb_partinfo(cmlb_handle_t cmlbhandle, int part, diskaddr_t *nblocksp, } /* consistent with behavior of sd for getting minor name */ - if (partnamep != NULL) + if (partnamep != NULL) { +#if defined(__i386) || defined(__amd64) +#if defined(_FIRMWARE_NEEDS_FDISK) + if (part > FDISK_P4) { + ext_part = part-FDISK_P4-1; + *partnamep = dk_ext_minor_data[ext_part].name; + } else +#endif +#endif *partnamep = dk_minor_data[part].name; + } } @@ -1072,6 +1168,9 @@ cmlb_ioctl(cmlb_handle_t cmlbhandle, dev_t dev, int cmd, intptr_t arg, case DKIOCSGEOM: case DKIOCSETEFI: case DKIOCSMBOOT: +#if defined(__i386) || defined(__amd64) + case DKIOCSETEXTPART: +#endif break; case DKIOCSVTOC: #if defined(__i386) || defined(__amd64) @@ -1216,7 +1315,12 @@ cmlb_ioctl(cmlb_handle_t cmlbhandle, dev_t dev, int cmd, intptr_t arg, err = ENOTTY; #endif break; - +#if defined(__i386) || defined(__amd64) + case DKIOCSETEXTPART: + cmlb_dbg(CMLB_TRACE, cl, "DKIOCSETEXTPART"); + err = cmlb_dkio_set_ext_part(cl, (caddr_t)arg, flag, tg_cookie); + break; +#endif default: err = ENOTTY; @@ -1661,7 +1765,7 @@ no_solaris_partition: * Note that dkl_cylno is not used for the fdisk map entries, so * we set it to an entirely bogus value. */ - for (count = 0; count < FD_NUMPART; count++) { + for (count = 0; count < FDISK_PARTS; count++) { cl->cl_map[FDISK_P1 + count].dkl_cylno = UINT16_MAX; cl->cl_map[FDISK_P1 + count].dkl_nblk = cl->cl_fmap[count].fmap_nblk; @@ -1869,6 +1973,281 @@ cmlb_resync_geom_caches(struct cmlb_lun *cl, diskaddr_t capacity, } +#if defined(__i386) || defined(__amd64) +/* + * Function: cmlb_update_ext_minor_nodes + * + * Description: Routine to add/remove extended partition device nodes + * + * Arguments: + * cl driver soft state (unit) structure + * num_parts Number of logical drives found on the LUN + * + * Should be called with the mutex held + * + * Return Code: 0 for success + * + * Context: User and Kernel thread + * + */ +static int +cmlb_update_ext_minor_nodes(struct cmlb_lun *cl, int num_parts) +{ + int i, count; + char name[48]; + int instance; + struct driver_minor_data *demdp, *demdpr; + char *devnm; + dev_info_t *pdip; + boolean_t internal; + + ASSERT(mutex_owned(CMLB_MUTEX(cl))); + ASSERT(cl->cl_update_ext_minor_nodes == 1); + + internal = VOID2BOOLEAN( + (cl->cl_alter_behavior & (CMLB_INTERNAL_MINOR_NODES)) != 0); + instance = ddi_get_instance(CMLB_DEVINFO(cl)); + demdp = dk_ext_minor_data; + demdpr = &dk_ext_minor_data[MAX_EXT_PARTS]; + + + if (cl->cl_logical_drive_count) { + for (i = 0; i < cl->cl_logical_drive_count; i++) { + (void) sprintf(name, "%s", demdp->name); + ddi_remove_minor_node(CMLB_DEVINFO(cl), name); + (void) sprintf(name, "%s", demdpr->name); + ddi_remove_minor_node(CMLB_DEVINFO(cl), name); + demdp++; + demdpr++; + } + /* There are existing device nodes. Remove them */ + devnm = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP); + (void) ddi_deviname(cl->cl_devi, devnm); + pdip = ddi_get_parent(cl->cl_devi); + (void) devfs_clean(pdip, devnm + 1, DV_CLEAN_FORCE); + kmem_free(devnm, MAXNAMELEN + 1); + } + + demdp = dk_ext_minor_data; + demdpr = &dk_ext_minor_data[MAX_EXT_PARTS]; + + for (i = 0; i < num_parts; i++) { + (void) sprintf(name, "%s", demdp->name); + if (cmlb_create_minor(CMLB_DEVINFO(cl), name, + demdp->type, + (instance << CMLBUNIT_SHIFT) | demdp->minor, + cl->cl_node_type, NULL, internal) == DDI_FAILURE) { + /* + * Clean up any nodes that may have been + * created, in case this fails in the middle + * of the loop. + */ + ddi_remove_minor_node(CMLB_DEVINFO(cl), NULL); + cl->cl_logical_drive_count = 0; + return (ENXIO); + } + (void) sprintf(name, "%s", demdpr->name); + if (ddi_create_minor_node(CMLB_DEVINFO(cl), name, + demdpr->type, + (instance << CMLBUNIT_SHIFT) | demdpr->minor, + cl->cl_node_type, NULL) == DDI_FAILURE) { + /* + * Clean up any nodes that may have been + * created, in case this fails in the middle + * of the loop. + */ + ddi_remove_minor_node(CMLB_DEVINFO(cl), NULL); + cl->cl_logical_drive_count = 0; + return (ENXIO); + } + demdp++; + demdpr++; + } + + /* Update the cl_map array for logical drives */ + for (count = 0; count < MAX_EXT_PARTS; count++) { + cl->cl_map[FDISK_P4 + 1 + count].dkl_cylno = UINT32_MAX; + cl->cl_map[FDISK_P4 + 1 + count].dkl_nblk = + cl->cl_fmap[FD_NUMPART + count].fmap_nblk; + cl->cl_offset[FDISK_P4 + 1 + count] = + cl->cl_fmap[FD_NUMPART + count].fmap_start; + } + + cl->cl_logical_drive_count = i; + cl->cl_update_ext_minor_nodes = 0; + return (0); +} +/* + * Function: cmlb_validate_ext_part + * + * Description: utility routine to validate an extended partition's + * metadata as found on disk + * + * Arguments: + * cl driver soft state (unit) structure + * part partition number of the extended partition + * epart partition number of the logical drive + * start absolute sector number of the start of the logical + * drive being validated + * size size of logical drive being validated + * + * Return Code: 0 for success + * + * Context: User and Kernel thread + * + * Algorithm : + * Error cases are : + * 1. If start block is lesser than or equal to the end block + * 2. If either start block or end block is beyond the bounadry + * of the extended partition. + * 3. start or end block overlap with existing partitions. + * To check this, first make sure that the start block doesnt + * overlap with existing partitions. Then, calculate the + * possible end block for the given start block that doesnt + * overlap with existing partitions. This can be calculated by + * first setting the possible end block to the end of the + * extended partition (optimistic) and then, checking if there + * is any other partition that lies after the start of the + * partition being validated. If so, set the possible end to + * one block less than the beginning of the next nearest partition + * If the actual end block is greater than the calculated end + * block, we have an overlap. + * + */ +static int +cmlb_validate_ext_part(struct cmlb_lun *cl, int part, int epart, uint32_t start, + uint32_t size) +{ + int i; + uint32_t end = start + size - 1; + uint32_t ext_start = cl->cl_fmap[part].fmap_start; + uint32_t ext_end = ext_start + cl->cl_fmap[part].fmap_nblk - 1; + uint32_t ts, te; + uint32_t poss_end = ext_end; + + if (end <= start) { + return (1); + } + + /* + * Check if the logical drive boundaries are within that of the + * extended partition. + */ + if (start <= ext_start || start > ext_end || end <= ext_start || + end > ext_end) { + return (1); + } + + /* + * epart will be equal to FD_NUMPART if it is the first logical drive. + * There is no need to check for overlaps with other logical drives, + * since it is the only logical drive that we have come across so far. + */ + if (epart == FD_NUMPART) { + return (0); + } + + /* Check for overlaps with existing logical drives */ + i = FD_NUMPART; + ts = cl->cl_fmap[FD_NUMPART].fmap_start; + te = ts + cl->cl_fmap[FD_NUMPART].fmap_nblk - 1; + + while ((i < epart) && ts && te) { + if (start >= ts && start <= te) { + return (1); + } + + if ((ts < poss_end) && (ts > start)) { + poss_end = ts - 1; + } + + i++; + ts = cl->cl_fmap[i].fmap_start; + te = ts + cl->cl_fmap[i].fmap_nblk - 1; + } + + if (end > poss_end) { + return (1); + } + + return (0); +} + + +/* + * Function: cmlb_is_linux_swap + * + * Description: utility routine to verify if a partition is a linux swap + * partition or not. + * + * Arguments: + * cl driver soft state (unit) structure + * part_start absolute sector number of the start of the partition + * being verified + * tg_cookie cookie from target driver to be passed back to target + * driver when we call back to it through tg_ops. + * + * Return Code: 0 for success + * + * Context: User and Kernel thread + * + * Notes: + * The linux swap magic "SWAP-SPACE" or "SWAPSPACE2" is found as the + * last 10 bytes of a disk block whose size is that of the linux page + * size. This disk block is found at the beginning of the swap partition. + */ +static int +cmlb_is_linux_swap(struct cmlb_lun *cl, uint32_t part_start, void *tg_cookie) +{ + int i; + int rval = -1; + uint32_t seek_offset; + uint32_t linux_pg_size; + char *buf, *linux_swap_magic; + int sec_sz = cl->cl_sys_blocksize; + /* Known linux kernel page sizes */ + uint32_t linux_pg_size_arr[] = {4096, }; + + ASSERT(cl != NULL); + ASSERT(mutex_owned(CMLB_MUTEX(cl))); + + if ((buf = kmem_zalloc(sec_sz, KM_NOSLEEP)) == NULL) { + return (ENOMEM); + } + + linux_swap_magic = buf + sec_sz - 10; + + for (i = 0; i < sizeof (linux_pg_size_arr)/sizeof (uint32_t); i++) { + linux_pg_size = linux_pg_size_arr[i]; + seek_offset = linux_pg_size/sec_sz - 1; + seek_offset += part_start; + + mutex_exit(CMLB_MUTEX(cl)); + rval = DK_TG_READ(cl, buf, seek_offset, sec_sz, tg_cookie); + mutex_enter(CMLB_MUTEX(cl)); + + if (rval != 0) { + cmlb_dbg(CMLB_ERROR, cl, + "cmlb_is_linux_swap: disk read err\n"); + rval = EIO; + break; + } + + rval = -1; + + if ((strncmp(linux_swap_magic, "SWAP-SPACE", 10) == 0) || + (strncmp(linux_swap_magic, "SWAPSPACE2", 10) == 0)) { + /* Found a linux swap */ + rval = 0; + break; + } + } + + kmem_free(buf, sec_sz); + return (rval); +} +#endif + /* * Function: cmlb_read_fdisk * @@ -1901,7 +2280,7 @@ cmlb_read_fdisk(struct cmlb_lun *cl, diskaddr_t capacity, void *tg_cookie) struct ipart *fdp; struct mboot *mbp; struct ipart fdisk[FD_NUMPART]; - int i; + int i, k; char sigbuf[2]; caddr_t bufp; int uidx; @@ -1910,6 +2289,13 @@ cmlb_read_fdisk(struct cmlb_lun *cl, diskaddr_t capacity, void *tg_cookie) uint_t solaris_offset; /* offset to solaris part. */ daddr_t solaris_size; /* size of solaris partition */ uint32_t blocksize; +#if defined(__i386) || defined(__amd64) + struct ipart eparts[2]; + struct ipart *efdp1 = &eparts[0]; + struct ipart *efdp2 = &eparts[1]; + int ext_part_exists = 0; + int ld_count = 0; +#endif ASSERT(cl != NULL); ASSERT(mutex_owned(CMLB_MUTEX(cl))); @@ -2024,6 +2410,14 @@ cmlb_read_fdisk(struct cmlb_lun *cl, diskaddr_t capacity, void *tg_cookie) for (fdp = fdisk, i = 0; i < FD_NUMPART; i++, fdp++) { uint32_t relsect; uint32_t numsect; + uchar_t systid; +#if defined(__i386) || defined(__amd64) + /* + * Stores relative block offset from the beginning of the + * Extended Partition. + */ + int ext_relsect = 0; +#endif if (fdp->numsect == 0) { cl->cl_fmap[i].fmap_start = 0; @@ -2039,6 +2433,96 @@ cmlb_read_fdisk(struct cmlb_lun *cl, diskaddr_t capacity, void *tg_cookie) cl->cl_fmap[i].fmap_start = relsect; cl->cl_fmap[i].fmap_nblk = numsect; + cl->cl_fmap[i].fmap_systid = LE_8(fdp->systid); + +#if defined(__i386) || defined(__amd64) + /* Support only one extended partition per LUN */ + if ((fdp->systid == EXTDOS || fdp->systid == FDISK_EXTLBA) && + (ext_part_exists == 0)) { + int j; + uint32_t logdrive_offset; + uint32_t ext_numsect; + uint32_t abs_secnum; + int is_linux_swap; + + ext_part_exists = 1; + + for (j = FD_NUMPART; j < FDISK_PARTS; j++) { + mutex_exit(CMLB_MUTEX(cl)); + rval = DK_TG_READ(cl, bufp, + (relsect + ext_relsect), blocksize, + tg_cookie); + mutex_enter(CMLB_MUTEX(cl)); + + if (rval != 0) { + cmlb_dbg(CMLB_ERROR, cl, + "cmlb_read_fdisk: Extended " + "partition read err\n"); + goto done; + } + /* + * The first ipart entry provides the offset + * at which the logical drive starts off from + * the beginning of the container partition + * and the size of the logical drive. + * The second ipart entry provides the offset + * of the next container partition from the + * beginning of the extended partition. + */ + bcopy(&bufp[FDISK_PART_TABLE_START], eparts, + sizeof (eparts)); + logdrive_offset = LE_32(efdp1->relsect); + ext_numsect = LE_32(efdp1->numsect); + systid = LE_8(efdp1->systid); + if (logdrive_offset <= 0 || ext_numsect <= 0) + break; + abs_secnum = relsect + ext_relsect + + logdrive_offset; + + /* Boundary condition and overlap checking */ + if (cmlb_validate_ext_part(cl, i, j, abs_secnum, + ext_numsect)) { + break; + } + + if ((cl->cl_fmap[j].fmap_start != abs_secnum) || + (cl->cl_fmap[j].fmap_nblk != ext_numsect) || + (cl->cl_fmap[j].fmap_systid != systid)) { + /* + * Indicates change from previous + * partinfo. Need to recreate + * logical device nodes. + */ + cl->cl_update_ext_minor_nodes = 1; + } + cl->cl_fmap[j].fmap_start = abs_secnum; + cl->cl_fmap[j].fmap_nblk = ext_numsect; + cl->cl_fmap[j].fmap_systid = systid; + ld_count++; + + is_linux_swap = 0; + if (efdp1->systid == SUNIXOS) { + if (cmlb_is_linux_swap(cl, abs_secnum, + tg_cookie) == 0) { + is_linux_swap = 1; + } + } + + if ((efdp1->systid == SUNIXOS) || + (efdp1->systid == SUNIXOS2)) { + if ((uidx == -1) && (!is_linux_swap)) { + uidx = 0; + solaris_offset = abs_secnum; + solaris_size = ext_numsect; + } + } + + if ((ext_relsect = LE_32(efdp2->relsect)) == 0) + break; + } + } + +#endif if (fdp->systid != SUNIXOS && fdp->systid != SUNIXOS2 && @@ -2054,12 +2538,38 @@ cmlb_read_fdisk(struct cmlb_lun *cl, diskaddr_t capacity, void *tg_cookie) * then use the first inactive solaris partition id */ if ((uidx == -1) || (fdp->bootid == ACTIVE)) { - uidx = i; - solaris_offset = relsect; - solaris_size = numsect; +#if defined(__i386) || defined(__amd64) + if (cmlb_is_linux_swap(cl, relsect, tg_cookie) != 0) { +#endif + uidx = i; + solaris_offset = relsect; + solaris_size = numsect; +#if defined(__i386) || defined(__amd64) + } +#endif } } - +#if defined(__i386) || defined(__amd64) + if (ld_count < cl->cl_logical_drive_count) { + /* + * Some/all logical drives were deleted. Clear out + * the fmap entries correspoding to those deleted drives. + */ + for (k = ld_count + FD_NUMPART; + k < cl->cl_logical_drive_count + FD_NUMPART; k++) { + cl->cl_fmap[k].fmap_start = 0; + cl->cl_fmap[k].fmap_nblk = 0; + cl->cl_fmap[k].fmap_systid = 0; + } + cl->cl_update_ext_minor_nodes = 1; + } + if (cl->cl_update_ext_minor_nodes) { + rval = cmlb_update_ext_minor_nodes(cl, ld_count); + if (rval != 0) { + goto done; + } + } +#endif cmlb_dbg(CMLB_INFO, cl, "fdisk 0x%x 0x%lx", cl->cl_solaris_offset, cl->cl_solaris_size); done: @@ -4532,6 +5042,30 @@ cmlb_dkio_set_mboot(struct cmlb_lun *cl, caddr_t arg, int flag, void *tg_cookie) } +#if defined(__i386) || defined(__amd64) +/*ARGSUSED*/ +static int +cmlb_dkio_set_ext_part(struct cmlb_lun *cl, caddr_t arg, int flag, + void *tg_cookie) +{ + int fdisk_rval; + diskaddr_t capacity; + + ASSERT(!mutex_owned(CMLB_MUTEX(cl))); + + mutex_enter(CMLB_MUTEX(cl)); + capacity = cl->cl_blockcount; + fdisk_rval = cmlb_read_fdisk(cl, capacity, tg_cookie); + if (fdisk_rval != 0) { + mutex_exit(CMLB_MUTEX(cl)); + return (fdisk_rval); + } + + mutex_exit(CMLB_MUTEX(cl)); + return (fdisk_rval); +} +#endif + /* * Function: cmlb_setup_default_geometry * @@ -4770,7 +5304,7 @@ no_solaris_partition: * Note that dkl_cylno is not used for the fdisk map entries, so * we set it to an entirely bogus value. */ - for (count = 0; count < FD_NUMPART; count++) { + for (count = 0; count < FDISK_PARTS; count++) { cl->cl_map[FDISK_P1 + count].dkl_cylno = UINT32_MAX; cl->cl_map[FDISK_P1 + count].dkl_nblk = cl->cl_fmap[count].fmap_nblk; diff --git a/usr/src/uts/common/io/scsi/targets/sd.c b/usr/src/uts/common/io/scsi/targets/sd.c index 8cbc1310a3..eaba50c764 100644 --- a/usr/src/uts/common/io/scsi/targets/sd.c +++ b/usr/src/uts/common/io/scsi/targets/sd.c @@ -21762,6 +21762,9 @@ sdioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cred_p, int *rval_p) case DKIOCSMBOOT: case DKIOCG_PHYGEOM: case DKIOCG_VIRTGEOM: +#if defined(__i386) || defined(__amd64) + case DKIOCSETEXTPART: +#endif /* let cmlb handle it */ goto skip_ready_valid; @@ -21910,6 +21913,9 @@ skip_ready_valid: case DKIOCSMBOOT: case DKIOCG_PHYGEOM: case DKIOCG_VIRTGEOM: +#if defined(__i386) || defined(__amd64) + case DKIOCSETEXTPART: +#endif SD_TRACE(SD_LOG_IOCTL, un, "DKIOC %d\n", cmd); /* TUR should spin up */ diff --git a/usr/src/uts/common/sys/cmlb_impl.h b/usr/src/uts/common/sys/cmlb_impl.h index b77f6c0239..1927123457 100644 --- a/usr/src/uts/common/sys/cmlb_impl.h +++ b/usr/src/uts/common/sys/cmlb_impl.h @@ -35,10 +35,16 @@ extern "C" { #include <sys/ddi.h> #include <sys/sunddi.h> +/* + * FDISK partitions - 4 primary and MAX_EXT_PARTS number of Extended + * Partitions. + */ +#define FDISK_PARTS (FD_NUMPART + MAX_EXT_PARTS) + #if defined(_SUNOS_VTOC_8) #define NSDMAP NDKMAP #elif defined(_SUNOS_VTOC_16) -#define NSDMAP (NDKMAP + FD_NUMPART + 1) +#define NSDMAP (NDKMAP + FDISK_PARTS + 1) #else #error "No VTOC format defined." #endif @@ -111,6 +117,7 @@ extern "C" { struct fmap { ulong_t fmap_start; /* starting block number */ ulong_t fmap_nblk; /* number of blocks */ + uchar_t fmap_systid; /* systid of the partition */ }; /* for cm_state */ @@ -146,7 +153,7 @@ typedef struct cmlb_lun { diskaddr_t cl_offset[MAXPART]; /* partition start blocks */ - struct fmap cl_fmap[FD_NUMPART]; /* fdisk partitions */ + struct fmap cl_fmap[FDISK_PARTS]; /* fdisk partitions */ uchar_t cl_asciilabel[LEN_DKL_ASCII]; /* Disk ASCII label */ @@ -190,6 +197,15 @@ typedef struct cmlb_lun { int cl_device_type; /* DTYPE_DIRECT,.. */ int cl_reserved; /* reserved efi partition # */ cmlb_tg_ops_t *cmlb_tg_ops; +#if defined(__i386) || defined(__amd64) + /* + * Flag indicating whether extended partition nodes should be created + * or not. Is set in cmlb_attach. After creating nodes in + * cmlb_read_fdisk, it will be unset. + */ + int cl_update_ext_minor_nodes; + int cl_logical_drive_count; +#endif /* __i386 || __amd64 */ uint8_t cl_msglog_flag; /* used to enable/suppress */ /* certain log messages */ } cmlb_lun_t; diff --git a/usr/src/uts/common/sys/dkio.h b/usr/src/uts/common/sys/dkio.h index caf7d7976d..8d913d8974 100644 --- a/usr/src/uts/common/sys/dkio.h +++ b/usr/src/uts/common/sys/dkio.h @@ -230,6 +230,11 @@ struct dk_callback { */ #define DKIOCHOTPLUGGABLE (DKIOC|35) /* is hotpluggable */ +#if defined(__i386) || defined(__amd64) +/* ioctl to write extended partition structure into the disk */ +#define DKIOCSETEXTPART (DKIOC|46) +#endif + /* * Ioctl to force driver to re-read the alternate partition and rebuild * the internal defect map. diff --git a/usr/src/uts/common/sys/dktp/fdisk.h b/usr/src/uts/common/sys/dktp/fdisk.h index ea0c1ef3ce..e90135f362 100644 --- a/usr/src/uts/common/sys/dktp/fdisk.h +++ b/usr/src/uts/common/sys/dktp/fdisk.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988 AT&T */ @@ -44,6 +44,18 @@ extern "C" { */ /* + * the MAX values are the maximum usable values for BIOS chs values + * The MAX_CYL value of 1022 is the maximum usable value + * the value of 1023 is a fence value, + * indicating no CHS geometry exists for the corresponding LBA value. + * HEAD range [ 0 .. MAX_HEAD ], so number of heads is (MAX_HEAD + 1) + * SECT range [ 1 .. MAX_SECT ], so number of sectors is (MAX_SECT) + */ +#define MAX_SECT (63) +#define MAX_CYL (1022) +#define MAX_HEAD (254) + +/* * BOOTSZ was reduced from 446 to 440 bytes to NOT overwrite the Windows * Vista DISKID. Otherwise Vista won't boot from Solaris GRUB in a dual-boot * setup. @@ -80,6 +92,7 @@ struct ipart { /* * Values for systid. */ +#define UNUSED 0 /* Empty Partition */ #define DOSOS12 1 /* DOS partition, 12-bit FAT */ #define PCIXOS 2 /* PC/IX partition */ #define DOSOS16 4 /* DOS partition, 16-bit FAT */ @@ -103,7 +116,7 @@ struct ipart { /* raw partition. ID was 0 but conflicted */ /* with DOS 3.3 fdisk */ #define UNIXOS 99 /* UNIX V.x partition */ -#define UNUSED 100 /* unassigned partition */ +#define FDISK_NOVELL2 100 /* Novell Netware 286 */ #define FDISK_NOVELL3 101 /* Novell Netware 3.x and later */ #define FDISK_QNX4 119 /* QNX 4.x */ #define FDISK_QNX42 120 /* QNX 4.x 2nd part */ @@ -139,6 +152,20 @@ struct mboot { /* master boot block */ ushort_t signature; }; +#if defined(__i386) || defined(__amd64) + +/* Byte offset of the start of the partition table within the sector */ +#define FDISK_PART_TABLE_START 446 + +/* Maximum number of valid partitions assumed as 32 */ +#define MAX_EXT_PARTS 32 + +#else + +#define MAX_EXT_PARTS 0 + +#endif /* if defined(__i386) || defined(__amd64) */ + #ifdef __cplusplus } #endif diff --git a/usr/src/uts/common/sys/scsi/targets/sddef.h b/usr/src/uts/common/sys/scsi/targets/sddef.h index 90129e40c3..93705cc42b 100644 --- a/usr/src/uts/common/sys/scsi/targets/sddef.h +++ b/usr/src/uts/common/sys/scsi/targets/sddef.h @@ -93,9 +93,17 @@ extern "C" { #elif defined(_SUNOS_VTOC_16) +/* + * XXX - NSDMAP has multiple definitions, one more in cmlb_impl.h + * If they are coalesced into one, this definition will follow suit. + * FDISK partitions - 4 primary and MAX_EXT_PARTS number of Extended + * Partitions. + */ +#define FDISK_PARTS (FD_NUMPART + MAX_EXT_PARTS) + #define SDUNIT_SHIFT 6 #define SDPART_MASK 63 -#define NSDMAP (NDKMAP + FD_NUMPART + 1) +#define NSDMAP (NDKMAP + FDISK_PARTS + 1) #else #error "No VTOC format defined." diff --git a/usr/src/uts/common/xen/io/xdf.c b/usr/src/uts/common/xen/io/xdf.c index 3e9ccd0b4a..77419266c8 100644 --- a/usr/src/uts/common/xen/io/xdf.c +++ b/usr/src/uts/common/xen/io/xdf.c @@ -2578,6 +2578,7 @@ xdf_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, case DKIOCSMBOOT: case DKIOCGETEFI: case DKIOCSETEFI: + case DKIOCSETEXTPART: case DKIOCPARTITION: return (cmlb_ioctl(vdp->xdf_vd_lbl, dev, cmd, arg, mode, credp, rvalp, NULL)); diff --git a/usr/src/uts/i86pc/i86hvm/io/xdf_shell.c b/usr/src/uts/i86pc/i86hvm/io/xdf_shell.c index d9557a07cb..6255c5ddaf 100644 --- a/usr/src/uts/i86pc/i86hvm/io/xdf_shell.c +++ b/usr/src/uts/i86pc/i86hvm/io/xdf_shell.c @@ -794,8 +794,13 @@ xdfs_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *credp, rv = xdfs_c_ioctl(xsp, dev, part, cmd, arg, flag, credp, rvalp, &done); if (done) return (rv); - return (ldi_ioctl(xsp->xdfss_tgt_lh[part], - cmd, arg, flag, credp, rvalp)); + rv = ldi_ioctl(xsp->xdfss_tgt_lh[part], cmd, arg, flag, credp, rvalp); + if (rv == 0) { + /* Force Geometry Validation */ + (void) cmlb_invalidate(xsp->xdfss_cmlbhandle, 0); + (void) cmlb_validate(xsp->xdfss_cmlbhandle, 0, 0); + } + return (rv); } static int diff --git a/usr/src/uts/intel/io/dktp/disk/cmdk.c b/usr/src/uts/intel/io/dktp/disk/cmdk.c index 36dddd4a7b..8e144b05a9 100644 --- a/usr/src/uts/intel/io/dktp/disk/cmdk.c +++ b/usr/src/uts/intel/io/dktp/disk/cmdk.c @@ -1002,6 +1002,7 @@ cmdkioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *credp, int *rvalp) case DKIOCGETEFI: case DKIOCSETEFI: case DKIOCPARTITION: + case DKIOCSETEXTPART: { int rc; |