From patchwork Sat Jun 20 17:12:10 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Yan X-Patchwork-Id: 6650871 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 E8626C05AC for ; Sat, 20 Jun 2015 17:12:15 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D8ECD20671 for ; Sat, 20 Jun 2015 17:12:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 9FEE82066F for ; Sat, 20 Jun 2015 17:12:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932757AbbFTRMM (ORCPT ); Sat, 20 Jun 2015 13:12:12 -0400 Received: from mail-qk0-f174.google.com ([209.85.220.174]:34373 "EHLO mail-qk0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932423AbbFTRML (ORCPT ); Sat, 20 Jun 2015 13:12:11 -0400 Received: by qkeo142 with SMTP id o142so60490895qke.1; Sat, 20 Jun 2015 10:12:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:date:message-id:subject:from:to:content-type; bh=I+AZ9JtfO1xA9m0mN/rAfX3OK6dycfa5KkHfqnoBos8=; b=Kcr/m038R2r0lur8LfCfddve4i2Ijdp153qBMesFkuWvQiS4p14ngpArXs/3AC89gF fKX0gaUIBJZHHOumdCvrRdUgcItpmkoco/N45D/fAAk585XH7Nwh1zNPwjuf0frmlPgt JtGFE2xG+n/kSyUqQhwcyUTswLuVTVBWlOAFpfulG7lGgRfJ+UyEaraFtKZfQwwvUb9/ 4V/433+NwI/+9edsvytK41n7mkMz65Duvdo1XQcnUXoSFRCImSWLkm86UxALS3nSxD/m Ufwn/eqTjv4mYsr+8aRCJaNaDYWbWQsPgPPXJiYBhVpEpMQuzh8dqrxRul9LDwbzz9Zk UO7A== MIME-Version: 1.0 X-Received: by 10.140.235.145 with SMTP id g139mr30079272qhc.81.1434820330212; Sat, 20 Jun 2015 10:12:10 -0700 (PDT) Received: by 10.96.48.1 with HTTP; Sat, 20 Jun 2015 10:12:10 -0700 (PDT) Date: Sun, 21 Jun 2015 01:12:10 +0800 Message-ID: Subject: configurable discard parameters From: Tom Yan To: linux-scsi@vger.kernel.org, linux-ide@vger.kernel.org Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Spam-Status: No, score=-7.4 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, T_TVD_MIME_EPI,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 Today I check if blkdiscard really does a full device trim/wipe for my Intel 530 SSD (240gb) with hexdump. I end up found that it fail to do so because it report garbage info on its block limits VPD. [tom@localhost ~]$ sudo sg_vpd -p 0xb0 /dev/sda Block limits VPD page (SBC): Write same non-zero (WSNZ): 0 Maximum compare and write length: 0 blocks Optimal transfer length granularity: 1 blocks Maximum transfer length: 0 blocks Optimal transfer length: 0 blocks Maximum prefetch length: 0 blocks Maximum unmap LBA count: 0 Maximum unmap block descriptor count: 0 Optimal unmap granularity: 1 Unmap granularity alignment valid: 0 Unmap granularity alignment: 0 Maximum write same length: 0x3fffc0 blocks Maximum atomic transfer length: 0 Atomic alignment: 0 Atomic transfer length granularity: 0 The fact is, in each iteration, for this drive, blkdiscard can only trim a maximum of 65528 sectors, which is the largest multiple of 8 sectors, which is the minimum possible. (In fact 65535 sectors seems to be some sort of limit of ATA TRIM commands. It's also the maximum of WRITE SAME (10).) With `blkdiscard`, I can still workaround this with the "--step" option, but for discard mount options, I don't think I have any way to deal with it. Although it's basically the reponsibility of Intel (Well I tried to find a way to complain to them but even their website is borked as always), but still I would like to know why the kernel doesn't allow "discard_granularity" and "discard_max_bytes" to be configurable for users. Also wanna share about this in case nobody ever noticed. Another case is, I have a SanDisk Extreme USB (32gb, w/o UASP), which is sort of a SATA SSD with USB bridge. I can basically TRIM the drive with hdparm (although there's a minor issue: https://sourceforge.net/p/hdparm/bugs/63/), but I can't do it with blkdiscard. At first I thought it was only because its VPD doesn't provide limits of discard: [tom@localhost ~]$ sudo sg_vpd -p 0xb0 /dev/sdc Block limits VPD page (SBC): Write same non-zero (WSNZ): 0 Maximum compare and write length: 0 blocks Optimal transfer length granularity: 0 blocks Maximum transfer length: 8388607 blocks Optimal transfer length: 8388607 blocks Maximum prefetch length: 0 blocks but then I try to use the attached patch to force some value for it, blkdiscard still gives me "I/O error" instead of "NOT SUPPROTED". So what's the requirement of the current discard way in the kernel? Does it work differently on SATA drives than on USB drives because of the controller (like involvement of libata)? Does it require capability of one of the three scsi unmap ways? Or did I just miss some other dirty hacking bits? diff --git a/drivers/scsi/sd.c~ b/drivers/scsi/sd.c index a661d33..a9cdfb6 100644 --- a/drivers/scsi/sd.c~ +++ b/drivers/scsi/sd.c @@ -99,6 +99,7 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC); #endif static void sd_config_discard(struct scsi_disk *, unsigned int); +static void sd_config_discard_novpd(struct scsi_disk *); static void sd_config_write_same(struct scsi_disk *); static int sd_revalidate_disk(struct gendisk *); static void sd_unlock_native_capacity(struct gendisk *disk); @@ -700,6 +701,22 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode) queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); } +static void sd_config_discard_novpd(struct scsi_disk *sdkp) +{ + struct request_queue *q = sdkp->disk->queue; + unsigned int logical_block_size = sdkp->device->sector_size; + unsigned int max_blocks = (u32)SD_MAX_WS16_BLOCKS; + + q->limits.discard_zeroes_data = 0; + q->limits.discard_alignment = 0; + q->limits.discard_granularity = sdkp->physical_block_size; + + sdkp->provisioning_mode = SD_LBP_WS16; + + q->limits.max_discard_sectors = max_blocks * (logical_block_size >> 9); + queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); +} + /** * sd_setup_discard_cmnd - unmap blocks on thinly provisioned device * @sdp: scsi device to operate one @@ -2776,6 +2793,9 @@ static int sd_revalidate_disk(struct gendisk *disk) sd_read_block_limits(sdkp); sd_read_block_characteristics(sdkp); } + else { + sd_config_discard_novpd(sdkp); + } sd_read_write_protect_flag(sdkp, buffer); sd_read_cache_type(sdkp, buffer);