Commit f08bb1e0 authored by Martin K. Petersen's avatar Martin K. Petersen

sd: Fix excessive capacity printing on devices with blocks bigger than 512 bytes

During revalidate we check whether device capacity has changed before we
decide whether to output disk information or not.

The check for old capacity failed to take into account that we scaled
sdkp->capacity based on the reported logical block size. And therefore
the capacity test would always fail for devices with sectors bigger than
512 bytes and we would print several copies of the same discovery
information.

Avoid scaling sdkp->capacity and instead adjust the value on the fly
when setting the block device capacity and generating fake C/H/S
geometry.
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Cc: <stable@vger.kernel.org>
Reported-by: default avatarHannes Reinecke <hare@suse.de>
Reviewed-by: default avatarHannes Reinicke <hare@suse.de>
Reviewed-by: default avatarEwan Milne <emilne@redhat.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 38c31599
...@@ -1275,18 +1275,19 @@ static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo) ...@@ -1275,18 +1275,19 @@ static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk); struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk);
struct scsi_device *sdp = sdkp->device; struct scsi_device *sdp = sdkp->device;
struct Scsi_Host *host = sdp->host; struct Scsi_Host *host = sdp->host;
sector_t capacity = logical_to_sectors(sdp, sdkp->capacity);
int diskinfo[4]; int diskinfo[4];
/* default to most commonly used values */ /* default to most commonly used values */
diskinfo[0] = 0x40; /* 1 << 6 */ diskinfo[0] = 0x40; /* 1 << 6 */
diskinfo[1] = 0x20; /* 1 << 5 */ diskinfo[1] = 0x20; /* 1 << 5 */
diskinfo[2] = sdkp->capacity >> 11; diskinfo[2] = capacity >> 11;
/* override with calculated, extended default, or driver values */ /* override with calculated, extended default, or driver values */
if (host->hostt->bios_param) if (host->hostt->bios_param)
host->hostt->bios_param(sdp, bdev, sdkp->capacity, diskinfo); host->hostt->bios_param(sdp, bdev, capacity, diskinfo);
else else
scsicam_bios_param(bdev, sdkp->capacity, diskinfo); scsicam_bios_param(bdev, capacity, diskinfo);
geo->heads = diskinfo[0]; geo->heads = diskinfo[0];
geo->sectors = diskinfo[1]; geo->sectors = diskinfo[1];
...@@ -2337,14 +2338,6 @@ sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer) ...@@ -2337,14 +2338,6 @@ sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer)
if (sdkp->capacity > 0xffffffff) if (sdkp->capacity > 0xffffffff)
sdp->use_16_for_rw = 1; sdp->use_16_for_rw = 1;
/* Rescale capacity to 512-byte units */
if (sector_size == 4096)
sdkp->capacity <<= 3;
else if (sector_size == 2048)
sdkp->capacity <<= 2;
else if (sector_size == 1024)
sdkp->capacity <<= 1;
blk_queue_physical_block_size(sdp->request_queue, blk_queue_physical_block_size(sdp->request_queue,
sdkp->physical_block_size); sdkp->physical_block_size);
sdkp->device->sector_size = sector_size; sdkp->device->sector_size = sector_size;
...@@ -2812,11 +2805,6 @@ static int sd_try_extended_inquiry(struct scsi_device *sdp) ...@@ -2812,11 +2805,6 @@ static int sd_try_extended_inquiry(struct scsi_device *sdp)
return 0; return 0;
} }
static inline u32 logical_to_sectors(struct scsi_device *sdev, u32 blocks)
{
return blocks << (ilog2(sdev->sector_size) - 9);
}
/** /**
* sd_revalidate_disk - called the first time a new disk is seen, * sd_revalidate_disk - called the first time a new disk is seen,
* performs disk spin up, read_capacity, etc. * performs disk spin up, read_capacity, etc.
...@@ -2900,7 +2888,7 @@ static int sd_revalidate_disk(struct gendisk *disk) ...@@ -2900,7 +2888,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
/* Combine with controller limits */ /* Combine with controller limits */
q->limits.max_sectors = min(rw_max, queue_max_hw_sectors(q)); q->limits.max_sectors = min(rw_max, queue_max_hw_sectors(q));
set_capacity(disk, sdkp->capacity); set_capacity(disk, logical_to_sectors(sdp, sdkp->capacity));
sd_config_write_same(sdkp); sd_config_write_same(sdkp);
kfree(buffer); kfree(buffer);
......
...@@ -65,7 +65,7 @@ struct scsi_disk { ...@@ -65,7 +65,7 @@ struct scsi_disk {
struct device dev; struct device dev;
struct gendisk *disk; struct gendisk *disk;
atomic_t openers; atomic_t openers;
sector_t capacity; /* size in 512-byte sectors */ sector_t capacity; /* size in logical blocks */
u32 max_xfer_blocks; u32 max_xfer_blocks;
u32 opt_xfer_blocks; u32 opt_xfer_blocks;
u32 max_ws_blocks; u32 max_ws_blocks;
...@@ -146,6 +146,11 @@ static inline int scsi_medium_access_command(struct scsi_cmnd *scmd) ...@@ -146,6 +146,11 @@ static inline int scsi_medium_access_command(struct scsi_cmnd *scmd)
return 0; return 0;
} }
static inline sector_t logical_to_sectors(struct scsi_device *sdev, sector_t blocks)
{
return blocks << (ilog2(sdev->sector_size) - 9);
}
/* /*
* A DIF-capable target device can be formatted with different * A DIF-capable target device can be formatted with different
* protection schemes. Currently 0 through 3 are defined: * protection schemes. Currently 0 through 3 are defined:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment