diff options
author | Hans Rosenfeld <hans.rosenfeld@nexenta.com> | 2014-09-09 20:51:46 +0200 |
---|---|---|
committer | Dan McDonald <danmcd@omniti.com> | 2014-09-12 15:17:32 -0400 |
commit | 32ce6b819524e8719d4ce58db40a00e9f17843e2 (patch) | |
tree | 9a7b2407035beda3fafcafed57b75299ca7e16f3 /usr/src/uts/common/io/blkdev/blkdev.c | |
parent | a0cb694bef8ce5b375d89d042945f0e24bbd4026 (diff) | |
download | illumos-joyent-32ce6b819524e8719d4ce58db40a00e9f17843e2.tar.gz |
5151 blkdev should support reporting of physical block size
Reviewed by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
Reviewed by: Garrett D'Amore <garrett@damore.org>
Approved by: Dan McDonald <danmcd@omniti.com>
Diffstat (limited to 'usr/src/uts/common/io/blkdev/blkdev.c')
-rw-r--r-- | usr/src/uts/common/io/blkdev/blkdev.c | 85 |
1 files changed, 44 insertions, 41 deletions
diff --git a/usr/src/uts/common/io/blkdev/blkdev.c b/usr/src/uts/common/io/blkdev/blkdev.c index 0af66ed457..a34aec9fdd 100644 --- a/usr/src/uts/common/io/blkdev/blkdev.c +++ b/usr/src/uts/common/io/blkdev/blkdev.c @@ -75,6 +75,7 @@ struct bd { uint32_t d_qactive; uint32_t d_maxxfer; uint32_t d_blkshift; + uint32_t d_pblkshift; uint64_t d_numblks; ddi_devid_t d_devid; @@ -1070,7 +1071,7 @@ bd_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *credp, int *rvalp) bzero(&miext, sizeof (miext)); miext.dki_media_type = DK_FIXED_DISK; miext.dki_lbsize = (1U << bd->d_blkshift); - miext.dki_pbsize = miext.dki_lbsize; + miext.dki_pbsize = (1U << bd->d_pblkshift); miext.dki_capacity = bd->d_numblks; if (ddi_copyout(&miext, ptr, sizeof (miext), flag)) { return (EFAULT); @@ -1364,54 +1365,56 @@ bd_runq_exit(bd_xfer_impl_t *xi, int err) static void bd_update_state(bd_t *bd) { - enum dkio_state state; - bd_media_t media; + enum dkio_state state = DKIO_INSERTED; boolean_t docmlb = B_FALSE; + bd_media_t media; bzero(&media, sizeof (media)); mutex_enter(&bd->d_statemutex); - if (bd->d_ops.o_media_info(bd->d_private, &media) == 0) { - if ((1U << bd->d_blkshift) != media.m_blksize) { - if ((media.m_blksize < 512) || - (!ISP2(media.m_blksize)) || - (P2PHASE(bd->d_maxxfer, media.m_blksize))) { - cmn_err(CE_WARN, - "%s%d: Invalid media block size (%d)", - ddi_driver_name(bd->d_dip), - ddi_get_instance(bd->d_dip), - media.m_blksize); - /* - * We can't use the media, treat it as - * not present. - */ - state = DKIO_EJECTED; - bd->d_numblks = 0; - } else { - bd->d_blkshift = ddi_ffs(media.m_blksize) - 1; - bd->d_numblks = media.m_nblks; - bd->d_rdonly = media.m_readonly; - bd->d_ssd = media.m_solidstate; - state = DKIO_INSERTED; - } - - /* Device size changed */ - docmlb = B_TRUE; - - } else { - if (bd->d_numblks != media.m_nblks) { - /* Device size changed */ - docmlb = B_TRUE; - } - bd->d_numblks = media.m_nblks; - bd->d_rdonly = media.m_readonly; - state = DKIO_INSERTED; - } - - } else { + if (bd->d_ops.o_media_info(bd->d_private, &media) != 0) { bd->d_numblks = 0; state = DKIO_EJECTED; + goto done; + } + + if ((media.m_blksize < 512) || + (!ISP2(media.m_blksize)) || + (P2PHASE(bd->d_maxxfer, media.m_blksize))) { + cmn_err(CE_WARN, "%s%d: Invalid media block size (%d)", + ddi_driver_name(bd->d_dip), ddi_get_instance(bd->d_dip), + media.m_blksize); + /* + * We can't use the media, treat it as not present. + */ + state = DKIO_EJECTED; + bd->d_numblks = 0; + goto done; + } + + if (((1U << bd->d_blkshift) != media.m_blksize) || + (bd->d_numblks != media.m_nblks)) { + /* Device size changed */ + docmlb = B_TRUE; } + + bd->d_blkshift = ddi_ffs(media.m_blksize) - 1; + bd->d_pblkshift = bd->d_blkshift; + bd->d_numblks = media.m_nblks; + bd->d_rdonly = media.m_readonly; + bd->d_ssd = media.m_solidstate; + + /* + * Only use the supplied physical block size if it is non-zero, + * greater or equal to the block size, and a power of 2. Ignore it + * if not, it's just informational and we can still use the media. + */ + if ((media.m_pblksize != 0) && + (media.m_pblksize >= media.m_blksize) && + (ISP2(media.m_pblksize))) + bd->d_pblkshift = ddi_ffs(media.m_pblksize) - 1; + +done: if (state != bd->d_state) { bd->d_state = state; cv_broadcast(&bd->d_statecv); |