From patchwork Tue Mar 17 18:08:11 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Stern X-Patchwork-Id: 6033531 Return-Path: X-Original-To: patchwork-linux-scsi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 5FF079F399 for ; Tue, 17 Mar 2015 18:08:16 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 62F40203DA for ; Tue, 17 Mar 2015 18:08:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 4627520364 for ; Tue, 17 Mar 2015 18:08:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752928AbbCQSIN (ORCPT ); Tue, 17 Mar 2015 14:08:13 -0400 Received: from iolanthe.rowland.org ([192.131.102.54]:35632 "HELO iolanthe.rowland.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1752069AbbCQSIM (ORCPT ); Tue, 17 Mar 2015 14:08:12 -0400 Received: (qmail 1430 invoked by uid 2102); 17 Mar 2015 14:08:11 -0400 Received: from localhost (sendmail-bs@127.0.0.1) by localhost with SMTP; 17 Mar 2015 14:08:11 -0400 Date: Tue, 17 Mar 2015 14:08:11 -0400 (EDT) From: Alan Stern X-X-Sender: stern@iolanthe.rowland.org To: James Bottomley cc: SCSI development list Subject: [PATCH] scsi: sd: add a capacity_override attribute Message-ID: MIME-Version: 1.0 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch provides a sysfs interface allowing users to override the capacity of a SCSI disk. This will help in situations where a buggy USB-SATA adapter fails to support READ CAPACITY(16) and reports only the low 32 bits of the capacity in its READ CAPACITY(10) reply. For an example, see this thread: http://marc.info/?l=linux-scsi&m=140908235510961&w=2 The interface is awkward because it requires the user to tell the system to re-read the disk's partition table afterward, but at least it provides a way to handle deficient hardware. Signed-off-by: Alan Stern CC: Dale R. Worley Reviewed-by: Ewan D. Milne --- [as1777] Documentation/ABI/testing/sysfs-class-scsi_disk | 19 ++++++++++++ drivers/scsi/sd.c | 37 ++++++++++++++++++++++++ drivers/scsi/sd.h | 1 3 files changed, 57 insertions(+) -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Index: usb-4.0/Documentation/ABI/testing/sysfs-class-scsi_disk =================================================================== --- /dev/null +++ usb-4.0/Documentation/ABI/testing/sysfs-class-scsi_disk @@ -0,0 +1,19 @@ +What: /sys/class/scsi_disk/HOST:CHANNEL:TARGET:LUN/capacity_override +Date: March 2015 +KernelVersion: 4.1 +Contact: Alan Stern +Description: + This file provides a way for users to override the + automatically determined disk capacity. For example, some + buggy USB-SATA adapters report only the low 32 bits of a + drive's block count, resulting in a calculated capacity + value that is the actual capacity modulo 2 TB. + + After the correct capacity (in native-size blocks -- often + 512 bytes per block but sometimes 4096) is written to this + file, the user must tell the system to re-read the disk's + partition table by running the command: + + /usr/sbin/blockdev --rereadpt /dev/sdX + + where X is the disk's drive letter. Index: usb-4.0/drivers/scsi/sd.h =================================================================== --- usb-4.0.orig/drivers/scsi/sd.h +++ usb-4.0/drivers/scsi/sd.h @@ -66,6 +66,7 @@ struct scsi_disk { struct gendisk *disk; atomic_t openers; sector_t capacity; /* size in 512-byte sectors */ + sector_t capacity_override; /* in native-size blocks */ u32 max_xfer_blocks; u32 max_ws_blocks; u32 max_unmap_blocks; Index: usb-4.0/drivers/scsi/sd.c =================================================================== --- usb-4.0.orig/drivers/scsi/sd.c +++ usb-4.0/drivers/scsi/sd.c @@ -477,6 +477,35 @@ max_write_same_blocks_store(struct devic } static DEVICE_ATTR_RW(max_write_same_blocks); +static ssize_t +capacity_override_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct scsi_disk *sdkp = to_scsi_disk(dev); + + return sprintf(buf, "%llu\n", + (unsigned long long) sdkp->capacity_override); +} + +static ssize_t +capacity_override_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct scsi_disk *sdkp = to_scsi_disk(dev); + unsigned long long cap; + int err; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + err = kstrtoull(buf, 10, &cap); + if (err) + return err; + sdkp->capacity_override = cap; + return count; +} +static DEVICE_ATTR_RW(capacity_override); + static struct attribute *sd_disk_attrs[] = { &dev_attr_cache_type.attr, &dev_attr_FUA.attr, @@ -489,6 +518,7 @@ static struct attribute *sd_disk_attrs[] &dev_attr_provisioning_mode.attr, &dev_attr_max_write_same_blocks.attr, &dev_attr_max_medium_access_timeouts.attr, + &dev_attr_capacity_override.attr, NULL, }; ATTRIBUTE_GROUPS(sd_disk); @@ -2152,6 +2182,13 @@ sd_read_capacity(struct scsi_disk *sdkp, struct scsi_device *sdp = sdkp->device; sector_t old_capacity = sdkp->capacity; + /* Did the user override the reported capacity? */ + if (!sdkp->first_scan && sdkp->capacity_override) { + sector_size = sdkp->device->sector_size; + sdkp->capacity = sdkp->capacity_override; + goto got_data; + } + if (sd_try_rc16_first(sdp)) { sector_size = read_capacity_16(sdkp, sdp, buffer); if (sector_size == -EOVERFLOW)