summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/io/blkdev/blkdev.c
diff options
context:
space:
mode:
authorHans Rosenfeld <hans.rosenfeld@nexenta.com>2014-09-09 20:51:46 +0200
committerDan McDonald <danmcd@omniti.com>2014-09-12 15:17:32 -0400
commit32ce6b819524e8719d4ce58db40a00e9f17843e2 (patch)
tree9a7b2407035beda3fafcafed57b75299ca7e16f3 /usr/src/uts/common/io/blkdev/blkdev.c
parenta0cb694bef8ce5b375d89d042945f0e24bbd4026 (diff)
downloadillumos-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.c85
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);