From patchwork Fri Jul 31 13:36:15 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hannes Reinecke X-Patchwork-Id: 6911561 Return-Path: X-Original-To: patchwork-linux-scsi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id CE6F7C05AC for ; Fri, 31 Jul 2015 13:38:21 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id DF19120452 for ; Fri, 31 Jul 2015 13:38:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E8ABB203B8 for ; Fri, 31 Jul 2015 13:38:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751262AbbGaNgo (ORCPT ); Fri, 31 Jul 2015 09:36:44 -0400 Received: from mx2.suse.de ([195.135.220.15]:59631 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751267AbbGaNgZ (ORCPT ); Fri, 31 Jul 2015 09:36:25 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id F10FFAD9F; Fri, 31 Jul 2015 13:36:21 +0000 (UTC) From: Hannes Reinecke To: James Bottomley Cc: Christoph Hellwig , linux-scsi@vger.kernel.org, Jens Axboe , linux-kernel@vger.kernel.org, Hannes Reinecke , Hannes Reinecke Subject: [PATCH 3/8] sd: Set chunk_sectors to zone size Date: Fri, 31 Jul 2015 15:36:15 +0200 Message-Id: <1438349780-116429-4-git-send-email-hare@suse.de> X-Mailer: git-send-email 1.8.5.2 In-Reply-To: <1438349780-116429-1-git-send-email-hare@suse.de> References: <1438349780-116429-1-git-send-email-hare@suse.de> Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Spam-Status: No, score=-8.3 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable 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 For ZBC devices I/O must not cross zone boundaries, so setup the 'chunk_sectors' block queue setting to the zone size. This is only valid for REPORT ZONES SAME type 2 or 3; for other types the zone sizes might be different for individual zones. So issue a warning if the type is found to be different. Signed-off-by: Hannes Reinecke --- drivers/scsi/sd.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/sd.h | 1 + 2 files changed, 77 insertions(+) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 3b2fcb4..b5d412a 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1861,6 +1861,45 @@ sd_spinup_disk(struct scsi_disk *sdkp) } } +static int +sd_zbc_report_zones(struct scsi_disk *sdkp, sector_t start_lba, + unsigned char *buffer, int bufflen ) +{ + struct scsi_device *sdp = sdkp->device; + const int timeout = sdp->request_queue->rq_timeout + * SD_FLUSH_TIMEOUT_MULTIPLIER; + struct scsi_sense_hdr sshdr; + unsigned char cmd[16]; + int result; + + if (!scsi_device_online(sdp)) { + sd_printk(KERN_INFO, sdkp, "device not online\n"); + return -ENODEV; + } + + sd_printk(KERN_INFO, sdkp, "REPORT ZONES lba %zu len %d\n", + start_lba, bufflen); + + memset(cmd, 0, 16); + cmd[0] = ZBC_IN; + cmd[1] = ZI_REPORT_ZONES; + put_unaligned_be64(start_lba, &cmd[2]); + put_unaligned_be32(bufflen, &cmd[10]); + memset(buffer, 0, bufflen); + + result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE, + buffer, bufflen, &sshdr, + timeout, SD_MAX_RETRIES, NULL); + + if (result) { + sd_printk(KERN_NOTICE, sdkp, + "REPORT ZONES lba %zu failed with %d/%d\n", + start_lba, host_byte(result), driver_byte(result)); + + return -EIO; + } + return 0; +} /* * Determine whether disk supports Data Integrity Field. @@ -2631,6 +2670,7 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp) queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, sdkp->disk->queue); } + sdkp->zoned = (buffer[8] >> 4) & 3; out: kfree(buffer); } @@ -2692,6 +2732,41 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer) sdkp->ws10 = 1; } +static void sd_read_zones(struct scsi_disk *sdkp, unsigned char *buffer) +{ + int retval; + unsigned char *desc; + u32 rep_len; + u8 same; + u64 zone_len; + + if (sdkp->zoned != 1) + /* Device managed, no special handling required */ + return; + + retval = sd_zbc_report_zones(sdkp, 0, buffer, SD_BUF_SIZE); + if (retval < 0) + return; + + rep_len = get_unaligned_be32(&buffer[0]); + same = buffer[4] & 0xf; + if (same != 2 && same != 3) { + sd_printk(KERN_WARNING, sdkp, + "REPORT ZONES SAME type %d not supported\n", same); + return; + } + if (rep_len < 64) { + sd_printk(KERN_WARNING, sdkp, + "REPORT ZONES report invalid length %u\n", + rep_len); + return; + } + /* Read the zone length from the first zone descriptor */ + desc = &buffer[64]; + zone_len = get_unaligned_be64(&desc[8]); + blk_queue_chunk_sectors(sdkp->disk->queue, zone_len); +} + static int sd_try_extended_inquiry(struct scsi_device *sdp) { /* Attempt VPD inquiry if the device blacklist explicitly calls @@ -2757,6 +2832,7 @@ static int sd_revalidate_disk(struct gendisk *disk) sd_read_cache_type(sdkp, buffer); sd_read_app_tag_own(sdkp, buffer); sd_read_write_same(sdkp, buffer); + sd_read_zones(sdkp, buffer); } sdkp->first_scan = 0; diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 63ba5ca..6500d51 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -93,6 +93,7 @@ struct scsi_disk { unsigned lbpvpd : 1; unsigned ws10 : 1; unsigned ws16 : 1; + unsigned zoned: 2; /* ZONED field */ }; #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)