summaryrefslogtreecommitdiff
path: root/usr/src/uts
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts')
-rw-r--r--usr/src/uts/common/io/cmlb.c552
-rw-r--r--usr/src/uts/common/io/scsi/targets/sd.c6
-rw-r--r--usr/src/uts/common/sys/cmlb_impl.h20
-rw-r--r--usr/src/uts/common/sys/dkio.h5
-rw-r--r--usr/src/uts/common/sys/dktp/fdisk.h31
-rw-r--r--usr/src/uts/common/sys/scsi/targets/sddef.h10
-rw-r--r--usr/src/uts/common/xen/io/xdf.c1
-rw-r--r--usr/src/uts/i86pc/i86hvm/io/xdf_shell.c9
-rw-r--r--usr/src/uts/intel/io/dktp/disk/cmdk.c1
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;