Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755117AbcD0Aat (ORCPT ); Tue, 26 Apr 2016 20:30:49 -0400 Received: from shadbolt.e.decadent.org.uk ([88.96.1.126]:39841 "EHLO shadbolt.e.decadent.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753752AbcDZXNl (ORCPT ); Tue, 26 Apr 2016 19:13:41 -0400 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 From: Ben Hutchings To: linux-kernel@vger.kernel.org, stable@vger.kernel.org CC: akpm@linux-foundation.org, "Martin K. Petersen" , "Hannes Reinecke" , "Ewan Milne" Date: Wed, 27 Apr 2016 01:02:21 +0200 Message-ID: X-Mailer: LinuxStableQueue (scripts by bwh) Subject: [PATCH 3.16 158/217] sd: Fix excessive capacity printing on devices with blocks bigger than 512 bytes In-Reply-To: X-SA-Exim-Connect-IP: 2a02:8426:ae4:c500:9cba:69ae:962d:6167 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3558 Lines: 106 3.16.35-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: "Martin K. Petersen" commit f08bb1e0dbdd0297258d0b8cd4dbfcc057e57b2a upstream. 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: Martin K. Petersen Reported-by: Hannes Reinecke Reviewed-by: Hannes Reinicke Reviewed-by: Ewan Milne Signed-off-by: Martin K. Petersen [bwh: Backported to 3.16: - logical_to_sectors() is a new function - Adjust context] Signed-off-by: Ben Hutchings --- --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1245,18 +1245,19 @@ static int sd_getgeo(struct block_device struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk); struct scsi_device *sdp = sdkp->device; struct Scsi_Host *host = sdp->host; + sector_t capacity = logical_to_sectors(sdp, sdkp->capacity); int diskinfo[4]; /* default to most commonly used values */ - diskinfo[0] = 0x40; /* 1 << 6 */ - diskinfo[1] = 0x20; /* 1 << 5 */ - diskinfo[2] = sdkp->capacity >> 11; - + diskinfo[0] = 0x40; /* 1 << 6 */ + diskinfo[1] = 0x20; /* 1 << 5 */ + diskinfo[2] = capacity >> 11; + /* override with calculated, extended default, or driver values */ if (host->hostt->bios_param) - host->hostt->bios_param(sdp, bdev, sdkp->capacity, diskinfo); + host->hostt->bios_param(sdp, bdev, capacity, diskinfo); else - scsicam_bios_param(bdev, sdkp->capacity, diskinfo); + scsicam_bios_param(bdev, capacity, diskinfo); geo->heads = diskinfo[0]; geo->sectors = diskinfo[1]; @@ -2235,14 +2236,6 @@ got_data: sdp->use_16_for_rw = (sdkp->capacity > 0xffffffff); - /* 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, sdkp->physical_block_size); sdkp->device->sector_size = sector_size; @@ -2766,7 +2759,7 @@ static int sd_revalidate_disk(struct gen blk_queue_flush(sdkp->disk->queue, flush); - set_capacity(disk, sdkp->capacity); + set_capacity(disk, logical_to_sectors(sdp, sdkp->capacity)); sd_config_write_same(sdkp); kfree(buffer); --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -63,7 +63,7 @@ struct scsi_disk { struct device dev; struct gendisk *disk; atomic_t openers; - sector_t capacity; /* size in 512-byte sectors */ + sector_t capacity; /* size in logical blocks */ u32 max_ws_blocks; u32 max_unmap_blocks; u32 unmap_granularity; @@ -142,6 +142,11 @@ static inline int scsi_medium_access_com 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 * protection schemes. Currently 0 through 3 are defined: