From patchwork Thu Dec 10 17:30:44 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mikulas Patocka X-Patchwork-Id: 7820811 Return-Path: X-Original-To: patchwork-linux-block@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 198479F3E6 for ; Thu, 10 Dec 2015 17:33:43 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 0E5ED20524 for ; Thu, 10 Dec 2015 17:33:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id EF6BE20576 for ; Thu, 10 Dec 2015 17:33:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755126AbbLJRau (ORCPT ); Thu, 10 Dec 2015 12:30:50 -0500 Received: from mx1.redhat.com ([209.132.183.28]:45159 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754716AbbLJRap (ORCPT ); Thu, 10 Dec 2015 12:30:45 -0500 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (Postfix) with ESMTPS id 2D277C105B43; Thu, 10 Dec 2015 17:30:45 +0000 (UTC) Received: from file01.intranet.prod.int.rdu2.redhat.com (file01.intranet.prod.int.rdu2.redhat.com [10.11.5.7]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id tBAHUinI029202 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 10 Dec 2015 12:30:44 -0500 Received: from file01.intranet.prod.int.rdu2.redhat.com (localhost [127.0.0.1]) by file01.intranet.prod.int.rdu2.redhat.com (8.14.4/8.14.4) with ESMTP id tBAHUiPv001159; Thu, 10 Dec 2015 12:30:44 -0500 Received: from localhost (mpatocka@localhost) by file01.intranet.prod.int.rdu2.redhat.com (8.14.4/8.14.4/Submit) with ESMTP id tBAHUiTJ001154; Thu, 10 Dec 2015 12:30:44 -0500 X-Authentication-Warning: file01.intranet.prod.int.rdu2.redhat.com: mpatocka owned process doing -bs Date: Thu, 10 Dec 2015 12:30:44 -0500 (EST) From: Mikulas Patocka X-X-Sender: mpatocka@file01.intranet.prod.int.rdu2.redhat.com To: "James E.J. Bottomley" , "Martin K. Petersen" , Jens Axboe , Mike Snitzer , Jonathan Brassow cc: dm-devel@redhat.com, linux-scsi@vger.kernel.org, linux-kernel@vger.kernel.org, linux-block@vger.kernel.org Subject: [PATCH 8/15] block copy: introduce "copy_boundary" limits In-Reply-To: Message-ID: References: User-Agent: Alpine 2.02 (LRH 1266 2009-07-14) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@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=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 There is no way to split copy requests, so the creator of the requests (the function blkdev_issue_copy) must make requests with proper size. Device mapper splits the requests at a boundary between targets or at a boundary specified by each target driver. We must make sure that the copy requets do not cross these boundaries. This patch introduces a new queue limit "copy_boundary", it is log2 of the boundary in sectors that the request must not cross. Device mapper will use this limit to propagate its requirements through the device stack. Signed-off-by: Mikulas Patocka --- block/blk-lib.c | 21 ++++++++++++++++++++- block/blk-settings.c | 17 +++++++++++++++++ block/blk-sysfs.c | 13 +++++++++++++ include/linux/blkdev.h | 1 + 4 files changed, 51 insertions(+), 1 deletion(-) -- To unsubscribe from this list: send the line "unsubscribe linux-block" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Index: linux-4.4-rc4/block/blk-settings.c =================================================================== --- linux-4.4-rc4.orig/block/blk-settings.c 2015-12-10 17:04:30.000000000 +0100 +++ linux-4.4-rc4/block/blk-settings.c 2015-12-10 17:04:54.000000000 +0100 @@ -96,6 +96,7 @@ void blk_set_default_limits(struct queue lim->chunk_sectors = 0; lim->max_write_same_sectors = 0; lim->max_copy_sectors = 0; + lim->copy_boundary = 63; lim->max_discard_sectors = 0; lim->max_hw_discard_sectors = 0; lim->discard_granularity = 0; @@ -311,6 +312,18 @@ void blk_queue_max_copy_sectors(struct r EXPORT_SYMBOL(blk_queue_max_copy_sectors); /** + * blk_queue_copy_boundary - set a boundary for copy operations. No copy + * operation may cross the boundary + * @q: the request queue for the device + * @copy_boundary: log2 of the copy boundary in sectors + **/ +void blk_queue_copy_boundary(struct request_queue *q, + unsigned char copy_boundary) +{ + q->limits.copy_boundary = copy_boundary; +} + +/** * blk_queue_max_segments - set max hw segments for a request for this queue * @q: the request queue for the device * @max_segments: max number of segments @@ -552,6 +565,10 @@ int blk_stack_limits(struct queue_limits t->max_segment_size = min_not_zero(t->max_segment_size, b->max_segment_size); + t->copy_boundary = min(t->copy_boundary, b->copy_boundary); + if (start) + t->copy_boundary = min(t->copy_boundary, (unsigned char)__ffs64(start)); + t->misaligned |= b->misaligned; alignment = queue_limit_alignment_offset(b, start); Index: linux-4.4-rc4/block/blk-sysfs.c =================================================================== --- linux-4.4-rc4.orig/block/blk-sysfs.c 2015-12-10 17:04:30.000000000 +0100 +++ linux-4.4-rc4/block/blk-sysfs.c 2015-12-10 17:04:54.000000000 +0100 @@ -199,6 +199,13 @@ static ssize_t queue_copy_max_show(struc (unsigned long long)q->limits.max_copy_sectors << 9); } +static ssize_t queue_copy_boundary_show(struct request_queue *q, char *page) +{ + return sprintf(page, "%llu\n", + !q->limits.max_copy_sectors || q->limits.copy_boundary == 63 ? + 0ULL : 512ULL << q->limits.copy_boundary); +} + static ssize_t queue_max_sectors_store(struct request_queue *q, const char *page, size_t count) { @@ -453,6 +460,11 @@ static struct queue_sysfs_entry queue_co .show = queue_copy_max_show, }; +static struct queue_sysfs_entry queue_copy_boundary_entry = { + .attr = {.name = "copy_boundary_bytes", .mode = S_IRUGO }, + .show = queue_copy_boundary_show, +}; + static struct queue_sysfs_entry queue_nonrot_entry = { .attr = {.name = "rotational", .mode = S_IRUGO | S_IWUSR }, .show = queue_show_nonrot, @@ -509,6 +521,7 @@ static struct attribute *default_attrs[] &queue_discard_zeroes_data_entry.attr, &queue_write_same_max_entry.attr, &queue_copy_max_entry.attr, + &queue_copy_boundary_entry.attr, &queue_nonrot_entry.attr, &queue_nomerges_entry.attr, &queue_rq_affinity_entry.attr, Index: linux-4.4-rc4/include/linux/blkdev.h =================================================================== --- linux-4.4-rc4.orig/include/linux/blkdev.h 2015-12-10 17:04:46.000000000 +0100 +++ linux-4.4-rc4/include/linux/blkdev.h 2015-12-10 17:04:54.000000000 +0100 @@ -273,6 +273,7 @@ struct queue_limits { unsigned short max_segments; unsigned short max_integrity_segments; + unsigned char copy_boundary; unsigned char misaligned; unsigned char discard_misaligned; unsigned char cluster; Index: linux-4.4-rc4/block/blk-lib.c =================================================================== --- linux-4.4-rc4.orig/block/blk-lib.c 2015-12-10 17:04:46.000000000 +0100 +++ linux-4.4-rc4/block/blk-lib.c 2015-12-10 17:04:54.000000000 +0100 @@ -447,6 +447,12 @@ int blkdev_issue_copy(struct block_devic goto end_callback; } + /* + * TODO: if copy_boundary is too small, we'd better reject this + * request and let the caller perform copy manually. The threshold + * should be determined experimentally. + */ + if (src_sector + nr_sects < src_sector || dst_sector + nr_sects < dst_sector) { ret = -EINVAL; @@ -484,7 +490,20 @@ int blkdev_issue_copy(struct block_devic while (nr_sects && !ACCESS_ONCE(batch->async_error)) { struct bio *read_bio, *write_bio; struct bio_copy *bc; - unsigned chunk = (unsigned)min(nr_sects, (sector_t)max_copy_sectors); + unsigned chunk; + u64 boundary, max_io; + + chunk = (unsigned)min(nr_sects, (sector_t)max_copy_sectors); + + boundary = 1ULL << sq->limits.copy_boundary; + max_io = boundary - (src_sector & (boundary - 1)); + if (chunk > max_io) + chunk = max_io; + + boundary = 1ULL << dq->limits.copy_boundary; + max_io = boundary - (dst_sector & (boundary - 1)); + if (chunk > max_io) + chunk = max_io; bc = kmalloc(sizeof(struct bio_copy), gfp_mask); if (!bc) {