diff --git a/hw/block-common.c b/hw/block-common.c
index f0196d7..a9c8a09 100644
--- a/hw/block-common.c
+++ b/hw/block-common.c
@@ -10,6 +10,9 @@
 #include "blockdev.h"
 #include "hw/block-common.h"
 #include "qemu-error.h"
+#ifdef __linux__
+#include <linux/fs.h>
+#endif
 
 void blkconf_serial(BlockConf *conf, char **serial)
 {
@@ -24,6 +27,32 @@ void blkconf_serial(BlockConf *conf, char **serial)
     }
 }
 
+/* Read the host block size in case the machine or the user asked for it */
+void blkconf_blocksizes(BlockConf *conf)
+{
+#ifdef __linux__
+    int block_size;
+
+    if (!conf->physical_block_size) {
+        if (bdrv_ioctl(conf->bs, BLKPBSZGET, &block_size) == 0) {
+           conf->physical_block_size = (uint16_t) block_size;
+        } else {
+            conf->physical_block_size = BLOCK_PROPERTY_STD_BLKSIZE;
+        }
+    }
+    if (!conf->logical_block_size) {
+        if (bdrv_ioctl(conf->bs, BLKSSZGET, &block_size) == 0) {
+            conf->logical_block_size = (uint16_t) block_size;
+        } else {
+            conf->logical_block_size = BLOCK_PROPERTY_STD_BLKSIZE;
+        }
+    }
+#else
+    conf->physical_block_size = BLOCK_PROPERTY_STD_BLKSIZE;
+    conf->logical_block_size  = BLOCK_PROPERTY_STD_BLKSIZE;
+#endif
+}
+
 int blkconf_geometry(BlockConf *conf, int *ptrans,
                      unsigned cyls_max, unsigned heads_max, unsigned secs_max)
 {
diff --git a/hw/block-common.h b/hw/block-common.h
index bb808f7..d593128 100644
--- a/hw/block-common.h
+++ b/hw/block-common.h
@@ -40,18 +40,23 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
     return exp;
 }
 
-#define DEFINE_BLOCK_PROPERTIES(_state, _conf)                          \
+#define BLOCK_PROPERTY_STD_BLKSIZE 512
+#define DEFINE_BLOCK_PROPERTIES_EXTENDED(_state, _conf, _blksize)       \
     DEFINE_PROP_DRIVE("drive", _state, _conf.bs),                       \
     DEFINE_PROP_BLOCKSIZE("logical_block_size", _state,                 \
-                          _conf.logical_block_size, 512),               \
+                          _conf.logical_block_size, _blksize),          \
     DEFINE_PROP_BLOCKSIZE("physical_block_size", _state,                \
-                          _conf.physical_block_size, 512),              \
+                          _conf.physical_block_size, _blksize),         \
     DEFINE_PROP_UINT16("min_io_size", _state, _conf.min_io_size, 0),  \
     DEFINE_PROP_UINT32("opt_io_size", _state, _conf.opt_io_size, 0),    \
     DEFINE_PROP_INT32("bootindex", _state, _conf.bootindex, -1),        \
     DEFINE_PROP_UINT32("discard_granularity", _state, \
                        _conf.discard_granularity, 0)
 
+#define DEFINE_BLOCK_PROPERTIES(_state, _conf)                          \
+    DEFINE_BLOCK_PROPERTIES_EXTENDED(_state, _conf,                     \
+                                     BLOCK_PROPERTY_STD_BLKSIZE)
+
 #define DEFINE_BLOCK_CHS_PROPERTIES(_state, _conf)      \
     DEFINE_PROP_UINT32("cyls", _state, _conf.cyls, 0),  \
     DEFINE_PROP_UINT32("heads", _state, _conf.heads, 0), \
@@ -60,6 +65,7 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf)
 /* Configuration helpers */
 
 void blkconf_serial(BlockConf *conf, char **serial);
+void blkconf_blocksizes(BlockConf *conf);
 int blkconf_geometry(BlockConf *conf, int *trans,
                      unsigned cyls_max, unsigned heads_max, unsigned secs_max);
 
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index f2e4ea4..e110caf 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -149,6 +149,7 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind)
     }
 
     blkconf_serial(&dev->conf, &dev->serial);
+    blkconf_blocksizes(&dev->conf);
     if (kind != IDE_CD
         && blkconf_geometry(&dev->conf, &dev->chs_trans, 65536, 16, 255) < 0) {
         return -1;
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 8aca0d4..e99dee4 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -904,7 +904,9 @@ static void set_blocksize(Object *obj, Visitor *v, void *opaque,
         error_propagate(errp, local_err);
         return;
     }
-    if (value < min || value > max) {
+
+    /* value == 0 indicates that block size should be sensed later on */
+    if ((value < min || value > max) && value > 0) {
         error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
                   dev->id?:"", name, (int64_t)value, min, max);
         return;
diff --git a/hw/s390-virtio-bus.c b/hw/s390-virtio-bus.c
index 5849a96..223ff2d 100644
--- a/hw/s390-virtio-bus.c
+++ b/hw/s390-virtio-bus.c
@@ -401,7 +401,7 @@ static TypeInfo s390_virtio_net = {
 };
 
 static Property s390_virtio_blk_properties[] = {
-    DEFINE_BLOCK_PROPERTIES(VirtIOS390Device, blk.conf),
+    DEFINE_BLOCK_PROPERTIES_EXTENDED(VirtIOS390Device, blk.conf, 0),
     DEFINE_BLOCK_CHS_PROPERTIES(VirtIOS390Device, blk.conf),
     DEFINE_PROP_STRING("serial", VirtIOS390Device, blk.serial),
 #ifdef __linux__
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 1b0afa6..29df433 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -2046,6 +2046,7 @@ static int scsi_initfn(SCSIDevice *dev)
     }
 
     blkconf_serial(&s->qdev.conf, &s->serial);
+    blkconf_blocksizes(&s->qdev.conf);
     if (dev->type == TYPE_DISK
         && blkconf_geometry(&dev->conf, NULL, 65535, 255, 255) < 0) {
         return -1;
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index e25cc96..f11ceb7 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -615,6 +615,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk)
     }
 
     blkconf_serial(&blk->conf, &blk->serial);
+    blkconf_blocksizes(&blk->conf);
     if (blkconf_geometry(&blk->conf, NULL, 65535, 255, 255) < 0) {
         return NULL;
     }
