From patchwork Tue Mar 28 08:39:25 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Liu, Changpeng" X-Patchwork-Id: 743656 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3vs6XG2dJCz9rvt for ; Mon, 27 Mar 2017 19:25:01 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="key not found in DNS" (0-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="cIznk2Dy"; dkim-atps=neutral Received: from localhost ([::1]:45028 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1csPxP-0004e3-4a for incoming@patchwork.ozlabs.org; Mon, 27 Mar 2017 04:24:55 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35371) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1csPx9-0004dy-KR for qemu-devel@nongnu.org; Mon, 27 Mar 2017 04:24:40 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1csPx4-0003zM-NL for qemu-devel@nongnu.org; Mon, 27 Mar 2017 04:24:39 -0400 Received: from mga02.intel.com ([134.134.136.20]:57810) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1csPx4-0003z3-8Z for qemu-devel@nongnu.org; Mon, 27 Mar 2017 04:24:34 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=intel.com; i=@intel.com; q=dns/txt; s=intel; t=1490603074; x=1522139074; h=from:to:cc:subject:date:message-id; bh=bep8/fNfrQ6QsJTiNEQGWtBB1eKTsdHlQviXf1OGIZ8=; b=cIznk2Dyktav6yqJ7abwzCWRYrq3OeW48VmF0LSI1/fcuPSsrj1QpWbR UlH1vNsg2CaY6NoIpHWY5V4EEK0/fQ==; Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 27 Mar 2017 01:24:32 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos; i="5.36,229,1486454400"; d="scan'208"; a="1112471644" Received: from fedora.sh.intel.com ([10.239.67.161]) by orsmga001.jf.intel.com with ESMTP; 27 Mar 2017 01:24:30 -0700 From: Changpeng Liu To: virtio-dev@lists.oasis-open.org, virtualization@lists.linux-foundation.org, linux-kernel@vger.kernel.org, hch@lst.de Date: Tue, 28 Mar 2017 16:39:25 +0800 Message-Id: <1490690365-21109-1-git-send-email-changpeng.liu@intel.com> X-Mailer: git-send-email 1.9.3 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 134.134.136.20 Subject: [Qemu-devel] [PATCH] virtio-blk: add DISCARD support to virtio-blk driver X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Currently virtio-blk driver does not provide discard feature flag, so the filesystems which built on top of the block device will not send discard command. This is okay for HDD backend, but it will impact the performance for SSD backend. Add a feature flag VIRTIO_BLK_F_DISCARD and command VIRTIO_BLK_T_DISCARD to extend exist virtio-blk protocol. virtio-blk protocol uses a single 8 bytes descriptor containing type,reserved and sector, currently Linux uses the reserved field as IO priority, here we also re-use the reserved field as number of discard sectors. Signed-off-by: Changpeng Liu --- drivers/block/virtio_blk.c | 38 +++++++++++++++++++++++++++++--------- include/uapi/linux/virtio_blk.h | 12 ++++++++++-- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 1d4c9f8..550cfe7 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -241,6 +241,9 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, case REQ_OP_FLUSH: type = VIRTIO_BLK_T_FLUSH; break; + case REQ_OP_DISCARD: + type = VIRTIO_BLK_T_DISCARD; + break; case REQ_OP_SCSI_IN: case REQ_OP_SCSI_OUT: type = VIRTIO_BLK_T_SCSI_CMD; @@ -256,16 +259,24 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, vbr->out_hdr.type = cpu_to_virtio32(vblk->vdev, type); vbr->out_hdr.sector = type ? 0 : cpu_to_virtio64(vblk->vdev, blk_rq_pos(req)); - vbr->out_hdr.ioprio = cpu_to_virtio32(vblk->vdev, req_get_ioprio(req)); + vbr->out_hdr.u.ioprio = cpu_to_virtio32(vblk->vdev, req_get_ioprio(req)); blk_mq_start_request(req); - num = blk_rq_map_sg(hctx->queue, req, vbr->sg); - if (num) { - if (rq_data_dir(req) == WRITE) - vbr->out_hdr.type |= cpu_to_virtio32(vblk->vdev, VIRTIO_BLK_T_OUT); - else - vbr->out_hdr.type |= cpu_to_virtio32(vblk->vdev, VIRTIO_BLK_T_IN); + if (type == VIRTIO_BLK_T_DISCARD) { + vbr->out_hdr.u.discard_nr_sectors = cpu_to_virtio32(vblk->vdev, + blk_rq_sectors(req)); + num = 0; + } else { + num = blk_rq_map_sg(hctx->queue, req, vbr->sg); + if (num) { + if (rq_data_dir(req) == WRITE) + vbr->out_hdr.type |= cpu_to_virtio32(vblk->vdev, + VIRTIO_BLK_T_OUT); + else + vbr->out_hdr.type |= cpu_to_virtio32(vblk->vdev, + VIRTIO_BLK_T_IN); + } } spin_lock_irqsave(&vblk->vqs[qid].lock, flags); @@ -775,6 +786,15 @@ static int virtblk_probe(struct virtio_device *vdev) if (!err && opt_io_size) blk_queue_io_opt(q, blk_size * opt_io_size); + if (virtio_has_feature(vdev, VIRTIO_BLK_F_DISCARD)) { + q->limits.discard_zeroes_data = 0; + q->limits.discard_alignment = blk_size; + q->limits.discard_granularity = blk_size; + blk_queue_max_discard_sectors(q, UINT_MAX); + blk_queue_max_discard_segments(q, 1); + queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); + } + virtio_device_ready(vdev); device_add_disk(&vdev->dev, vblk->disk); @@ -882,14 +902,14 @@ static int virtblk_restore(struct virtio_device *vdev) VIRTIO_BLK_F_SCSI, #endif VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE, - VIRTIO_BLK_F_MQ, + VIRTIO_BLK_F_MQ, VIRTIO_BLK_F_DISCARD, } ; static unsigned int features[] = { VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE, - VIRTIO_BLK_F_MQ, + VIRTIO_BLK_F_MQ, VIRTIO_BLK_F_DISCARD, }; static struct virtio_driver virtio_blk = { diff --git a/include/uapi/linux/virtio_blk.h b/include/uapi/linux/virtio_blk.h index 9ebe4d9..d608649 100644 --- a/include/uapi/linux/virtio_blk.h +++ b/include/uapi/linux/virtio_blk.h @@ -38,6 +38,7 @@ #define VIRTIO_BLK_F_BLK_SIZE 6 /* Block size of disk is available*/ #define VIRTIO_BLK_F_TOPOLOGY 10 /* Topology information is available */ #define VIRTIO_BLK_F_MQ 12 /* support more than one vq */ +#define VIRTIO_BLK_F_DISCARD 13 /* DISCARD command is supported */ /* Legacy feature bits */ #ifndef VIRTIO_BLK_NO_LEGACY @@ -114,6 +115,9 @@ struct virtio_blk_config { /* Get device ID command */ #define VIRTIO_BLK_T_GET_ID 8 +/* Discard command */ +#define VIRTIO_BLK_T_DISCARD 16 + #ifndef VIRTIO_BLK_NO_LEGACY /* Barrier before this op. */ #define VIRTIO_BLK_T_BARRIER 0x80000000 @@ -127,8 +131,12 @@ struct virtio_blk_config { struct virtio_blk_outhdr { /* VIRTIO_BLK_T* */ __virtio32 type; - /* io priority. */ - __virtio32 ioprio; + union { + /* io priority. */ + __virtio32 ioprio; + /* discard number of sectors */ + __virtio32 discard_nr_sectors; + } u; /* Sector (ie. 512 byte offset) */ __virtio64 sector; };