Fix sector size and capacity calculation.

Remove the hard coded 512 byte SECTOR_SIZE and replace it with
bdev_hardsect_size() to get the correct hardware sector size.

Usage of get_capacity() was incorrect.  We the block_device
references a partition we need to return bdev->part->nr_sects.
If get_capacity() is used the entire device size will be returned
ignoring partition information.  This is however the correct thing
to do when the block device in question has not partition table.
This commit is contained in:
Brian Behlendorf 2009-10-14 16:02:51 -07:00
parent 772839efe9
commit 18eee5d03f
1 changed files with 18 additions and 9 deletions

View File

@ -76,6 +76,19 @@ vdev_bdev_mode(int smode)
}
#endif /* HAVE_OPEN_BDEV_EXCLUSIVE */
static uint64_t
bdev_capacity(struct block_device *bdev)
{
struct hd_struct *part = bdev->bd_part;
/* The partition capacity referenced by the block device */
if (part)
return part->nr_sects;
/* Otherwise assume the full device capacity */
return get_capacity(bdev->bd_disk);
}
static int
vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *ashift)
{
@ -122,15 +135,11 @@ vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *ashift)
/* Clear the nowritecache bit, causes vdev_reopen() to try again. */
v->vdev_nowritecache = B_FALSE;
/* Determine the actual size of the device (in bytes)
*
* XXX: SECTOR_SIZE is defined to 512b which may not be true for
* your device, we must use the actual hardware sector size.
*/
*psize = get_capacity(bdev->bd_disk) * SECTOR_SIZE;
/* Physical volume size in bytes */
*psize = bdev_capacity(bdev) * bdev_hardsect_size(bdev);
/* Based on the minimum sector size set the block size */
*ashift = highbit(MAX(SECTOR_SIZE, SPA_MINBLOCKSIZE)) - 1;
*ashift = highbit(MAX(bdev_hardsect_size(bdev), SPA_MINBLOCKSIZE)) - 1;
return 0;
}
@ -314,7 +323,7 @@ __vdev_disk_physio(struct block_device *bdev, zio_t *zio, caddr_t kbuf_ptr,
uint64_t bio_offset;
int i, error = 0, bio_count, bio_size;
ASSERT3S(kbuf_offset % SECTOR_SIZE, ==, 0);
ASSERT3S(kbuf_offset % bdev_hardsect_size(bdev), ==, 0);
q = bdev_get_queue(bdev);
if (!q)
return ENXIO;
@ -558,7 +567,7 @@ vdev_disk_read_rootlabel(char *devpath, char *devid, nvlist_t **config)
if (IS_ERR(bdev))
return -PTR_ERR(bdev);
s = get_capacity(bdev->bd_disk) * SECTOR_SIZE;
s = bdev_capacity(bdev) * bdev_hardsect_size(bdev);
if (s == 0) {
vdev_bdev_close(bdev, vdev_bdev_mode(FREAD));
return EIO;