Mercurial > illumos > illumos-gate
changeset 10320:35786983c32a
6808004 fdisk fake cylinder size should be a multiple of 4k
author | yu, larry liu - Sun Microsystems - Beijing China <Larry.Liu@Sun.COM> |
---|---|
date | Mon, 17 Aug 2009 10:56:59 +0800 |
parents | 0355b7a83c0d |
children | 44087508eb73 |
files | usr/src/uts/common/io/cmlb.c usr/src/uts/common/io/scsi/targets/sd.c usr/src/uts/common/sys/cmlb.h usr/src/uts/common/sys/scsi/targets/sddef.h |
diffstat | 4 files changed, 139 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/io/cmlb.c Sun Aug 16 19:52:03 2009 +0800 +++ b/usr/src/uts/common/io/cmlb.c Mon Aug 17 10:56:59 2009 +0800 @@ -313,7 +313,8 @@ #endif #if defined(_SUNOS_VTOC_16) -static void cmlb_convert_geometry(diskaddr_t capacity, struct dk_geom *cl_g); +static void cmlb_convert_geometry(struct cmlb_lun *cl, diskaddr_t capacity, + struct dk_geom *cl_g, void *tg_cookie); #endif static int cmlb_dkio_get_geometry(struct cmlb_lun *cl, caddr_t arg, int flag, @@ -349,7 +350,8 @@ 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_get_phygeom(struct cmlb_lun *cl, caddr_t arg, int flag, + void *tg_cookie); static int cmlb_dkio_partinfo(struct cmlb_lun *cl, dev_t dev, caddr_t arg, int flag); static int cmlb_dkio_extpartinfo(struct cmlb_lun *cl, dev_t dev, caddr_t arg, @@ -1286,7 +1288,7 @@ case DKIOCG_PHYGEOM: cmlb_dbg(CMLB_TRACE, cl, "DKIOCG_PHYGEOM\n"); #if defined(__i386) || defined(__amd64) - err = cmlb_dkio_get_phygeom(cl, (caddr_t)arg, flag); + err = cmlb_dkio_get_phygeom(cl, (caddr_t)arg, flag, tg_cookie); #else err = ENOTTY; #endif @@ -1803,9 +1805,13 @@ * Context: Kernel thread only */ static void -cmlb_convert_geometry(diskaddr_t capacity, struct dk_geom *cl_g) +cmlb_convert_geometry(struct cmlb_lun *cl, diskaddr_t capacity, + struct dk_geom *cl_g, void *tg_cookie) { + ASSERT(cl != NULL); + ASSERT(mutex_owned(CMLB_MUTEX(cl))); + /* Unlabeled SCSI floppy device */ if (capacity <= 0x1000) { cl_g->dkg_nhead = 2; @@ -1839,6 +1845,15 @@ * 4211279100 (1.96TB) 255 252 * 5264098875 (2.45TB) 255 315 * ... + * + * For Solid State Drive(SSD), it uses 4K page size inside and may be + * double with every new generation. If the I/O is not aligned with + * page size on SSDs, SSDs perform a lot slower. + * By default, Solaris partition starts from cylinder 1. It will be + * misaligned even with 4K if using heads(255) and SPT(63). To + * workaround the problem, if the device is SSD, we use heads(224) and + * SPT multiple of 56. Thus the default Solaris partition starts from + * a position that aligns with 128K on a 512 bytes sector size SSD. */ if (capacity <= 0x200000) { @@ -1848,15 +1863,36 @@ cl_g->dkg_nhead = 128; cl_g->dkg_nsect = 32; } else { - cl_g->dkg_nhead = 255; - - /* make nsect be smallest multiple of 63 */ + tg_attribute_t tgattribute; + int is_solid_state; + unsigned short nhead; + unsigned short nsect; + + bzero(&tgattribute, sizeof (tg_attribute_t)); + + mutex_exit(CMLB_MUTEX(cl)); + is_solid_state = + (DK_TG_GETATTRIBUTE(cl, &tgattribute, tg_cookie) == 0) ? + tgattribute.media_is_solid_state : FALSE; + mutex_enter(CMLB_MUTEX(cl)); + + if (is_solid_state) { + nhead = 224; + nsect = 56; + } else { + nhead = 255; + nsect = 63; + } + + cl_g->dkg_nhead = nhead; + + /* make nsect be smallest multiple of nhead */ cl_g->dkg_nsect = ((capacity + - (UINT16_MAX * 255 * 63) - 1) / - (UINT16_MAX * 255 * 63)) * 63; + (UINT16_MAX * nhead * nsect) - 1) / + (UINT16_MAX * nhead * nsect)) * nsect; if (cl_g->dkg_nsect == 0) - cl_g->dkg_nsect = (UINT16_MAX / 63) * 63; + cl_g->dkg_nsect = (UINT16_MAX / nsect) * nsect; } } @@ -3327,7 +3363,7 @@ capacity = cl->cl_blockcount; - cmlb_convert_geometry(capacity, &cl_g); + cmlb_convert_geometry(cl, capacity, &cl_g, tg_cookie); bcopy(&cl_g, &cl->cl_g, sizeof (cl->cl_g)); phys_spc = cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect; } @@ -5381,7 +5417,8 @@ #if defined(__i386) || defined(__amd64) static int -cmlb_dkio_get_phygeom(struct cmlb_lun *cl, caddr_t arg, int flag) +cmlb_dkio_get_phygeom(struct cmlb_lun *cl, caddr_t arg, int flag, + void *tg_cookie) { int err = 0; diskaddr_t capacity; @@ -5443,7 +5480,7 @@ else capacity = cl->cl_blockcount; - cmlb_convert_geometry(capacity, dkgp); + cmlb_convert_geometry(cl, capacity, dkgp, tg_cookie); dkgp->dkg_acyl = 0; dkgp->dkg_ncyl = capacity / (dkgp->dkg_nhead * dkgp->dkg_nsect);
--- a/usr/src/uts/common/io/scsi/targets/sd.c Sun Aug 16 19:52:03 2009 +0800 +++ b/usr/src/uts/common/io/scsi/targets/sd.c Mon Aug 17 10:56:59 2009 +0800 @@ -879,6 +879,7 @@ #define sd_blank_cmp ssd_blank_cmp #define sd_chk_vers1_data ssd_chk_vers1_data #define sd_set_vers1_properties ssd_set_vers1_properties +#define sd_check_solid_state ssd_check_solid_state #define sd_get_physical_geometry ssd_get_physical_geometry #define sd_get_virtual_geometry ssd_get_virtual_geometry @@ -1271,6 +1272,7 @@ static int sd_get_write_cache_enabled(sd_ssc_t *ssc, int *is_enabled); static void sd_get_nv_sup(sd_ssc_t *ssc); static dev_t sd_make_device(dev_info_t *devi); +static void sd_check_solid_state(sd_ssc_t *ssc); static void sd_update_block_info(struct sd_lun *un, uint32_t lbasize, uint64_t capacity); @@ -5667,8 +5669,8 @@ * Description: This routine sends an inquiry command with the EVPD bit set and * a page code of 0x00 to the device. It is used to determine which * vital product pages are available to find the devid. We are - * looking for pages 0x83 or 0x80. If we return a negative 1, the - * device does not support that command. + * looking for pages 0x83 0x80 or 0xB1. If we return a negative 1, + * the device does not support that command. * * Arguments: un - driver soft state (unit) structure * @@ -5724,7 +5726,7 @@ * Pages are returned in ascending order, and 0x83 is what we * are hoping for. */ - while ((page_list[counter] <= 0x86) && + while ((page_list[counter] <= 0xB1) && (counter <= (page_list[VPD_PAGE_LENGTH] + VPD_HEAD_OFFSET))) { /* @@ -5751,6 +5753,9 @@ case 0x86: un->un_vpd_page_mask |= SD_VPD_EXTENDED_DATA_PG; break; + case 0xB1: + un->un_vpd_page_mask |= SD_VPD_DEV_CHARACTER_PG; + break; } counter++; } @@ -8092,6 +8097,11 @@ un->un_mediastate = DKIO_NONE; + /* + * Check if this is a SSD(Solid State Drive). + */ + sd_check_solid_state(ssc); + cmlb_alloc_handle(&un->un_cmlbhandle); #if defined(__i386) || defined(__amd64) @@ -30828,6 +30838,8 @@ mutex_enter(SD_MUTEX(un)); ((tg_attribute_t *)arg)->media_is_writable = un->un_f_mmc_writable_media; + ((tg_attribute_t *)arg)->media_is_solid_state = + un->un_f_is_solid_state; mutex_exit(SD_MUTEX(un)); return (0); default: @@ -31289,3 +31301,73 @@ xp->xb_ena = fm_ena_generate(0, FM_ENA_FMT1); ssc->ssc_uscsi_info->ui_ena = xp->xb_ena; } + + +/* + * Function: sd_check_solid_state + * + * Description: Query the optional INQUIRY VPD page 0xb1. If the device + * supports VPD page 0xb1, sd examines the MEDIUM ROTATION + * RATE. If the MEDIUM ROTATION RATE is 1, sd assumes the + * device is a solid state drive. + * + * Context: Kernel thread or interrupt context. + */ + +static void +sd_check_solid_state(sd_ssc_t *ssc) +{ + int rval = 0; + uchar_t *inqb1 = NULL; + size_t inqb1_len = MAX_INQUIRY_SIZE; + size_t inqb1_resid = 0; + struct sd_lun *un; + + ASSERT(ssc != NULL); + un = ssc->ssc_un; + ASSERT(un != NULL); + ASSERT(!mutex_owned(SD_MUTEX(un))); + + mutex_enter(SD_MUTEX(un)); + un->un_f_is_solid_state = FALSE; + + if (ISCD(un)) { + mutex_exit(SD_MUTEX(un)); + return; + } + + if (sd_check_vpd_page_support(ssc) == 0 && + un->un_vpd_page_mask & SD_VPD_DEV_CHARACTER_PG) { + mutex_exit(SD_MUTEX(un)); + /* collect page b1 data */ + inqb1 = kmem_zalloc(inqb1_len, KM_SLEEP); + + rval = sd_send_scsi_INQUIRY(ssc, inqb1, inqb1_len, + 0x01, 0xB1, &inqb1_resid); + + if (rval == 0 && (inqb1_len - inqb1_resid > 5)) { + SD_TRACE(SD_LOG_COMMON, un, + "sd_check_solid_state: \ + successfully get VPD page: %x \ + PAGE LENGTH: %x BYTE 4: %x \ + BYTE 5: %x", inqb1[1], inqb1[3], inqb1[4], + inqb1[5]); + + mutex_enter(SD_MUTEX(un)); + /* + * Check the MEDIUM ROTATION RATE. If it is set + * to 1, the device is a solid state drive. + */ + if (inqb1[4] == 0 && inqb1[5] == 1) { + un->un_f_is_solid_state = TRUE; + } + mutex_exit(SD_MUTEX(un)); + } else if (rval != 0) { + sd_ssc_assessment(ssc, SD_FMT_IGNORE); + } + + kmem_free(inqb1, inqb1_len); + } else { + mutex_exit(SD_MUTEX(un)); + } +}
--- a/usr/src/uts/common/sys/cmlb.h Sun Aug 16 19:52:03 2009 +0800 +++ b/usr/src/uts/common/sys/cmlb.h Mon Aug 17 10:56:59 2009 +0800 @@ -49,6 +49,7 @@ typedef struct tg_attribute { int media_is_writable; + int media_is_solid_state; } tg_attribute_t;
--- a/usr/src/uts/common/sys/scsi/targets/sddef.h Sun Aug 16 19:52:03 2009 +0800 +++ b/usr/src/uts/common/sys/scsi/targets/sddef.h Mon Aug 17 10:56:59 2009 +0800 @@ -453,7 +453,8 @@ /* field by hardware */ un_f_pm_log_sense_smart :1, /* log sense support SMART */ /* feature attribute */ - un_f_reserved :7; + un_f_is_solid_state :1, /* has solid state media */ + un_f_reserved :6; /* Ptr to table of strings for ASC/ASCQ error message printing */ struct scsi_asq_key_strings *un_additional_codes; @@ -2357,6 +2358,7 @@ #define SD_VPD_ASCII_OP_PG 0x08 /* 0x82 - ASCII Op Defs */ #define SD_VPD_DEVID_WWN_PG 0x10 /* 0x83 - Device Identification */ #define SD_VPD_EXTENDED_DATA_PG 0x80 /* 0x86 - Extended data about the lun */ +#define SD_VPD_DEV_CHARACTER_PG 0x400 /* 0xB1 - Device Characteristics */ /* * Non-volatile cache support