Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp2114858pxb; Mon, 18 Jan 2021 08:34:56 -0800 (PST) X-Google-Smtp-Source: ABdhPJyRiC8iJfsLm+u4R3ntV8g2NFwCwjxuPQA3lslEj34ew0h60l1I5S84QBveQTWqAk0k+ZHQ X-Received: by 2002:aa7:c308:: with SMTP id l8mr248110edq.246.1610987696247; Mon, 18 Jan 2021 08:34:56 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1610987696; cv=none; d=google.com; s=arc-20160816; b=yYeFcb6R2ZBII33/2JSAiIDh0eDYbdbw1XalcGK6aKPdY7aYeCP5MhyTi1x0nMD7cM rNAObLhzQDZ8hVQOBOVe2rvwQKjwsNwq3Imi8xeck8w2USUtI84mw0T9dYScsLAWwfpT nXY8SW0yNx56jDQO+5tDIoEMQMXegYfD1hzAGZ5ewGf3VNv6m1IVLSPFba4jsmRPrCB4 p5/eN1M9Do9wl9Ji2y1UWgEzge/u8UsAbOYtyLsyHtMDu0TdJMuXnMEc3pSddF18UR2P 9DkZ5UDWzh77J8Tz4594iHGno/UeW4Urf72ITlJs/Ka1rMI640gt1FxC71riONMa8S8F FmbQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=rij4nVFsP4aDatFsXirQ1CX83Dw3gYSeeCyPuXfGs6M=; b=zzsaSx+JKveMvsnNJXyCDw51SLsT6xV1UkpejTs1twOdLp0TrHJ1+lcSXdf4Q6YPzp 7ouM3t7E30o3vQzaw8mELM9uxdEHBor1+FY8VdQAbVRz7OQIGKP+mZg+QtPWioO26EbG GlxLA4GfDrfH0c5W0SoJ1kmw4N2WcBfQ34kZ0/hguGwxtshEXVnyWUeZ5Pt0YgpEubt+ AKY3ocZFz/N4Agn9GBY/PeCLmcbBjbKiDjGcnx5hIdEdFll8jhAamZQNcCtvP6lyQei1 MZpU1CxTTmbCjWZNf1v2d+Tn19pJKemTDsqNKI92EptX6wfh/VjEEafUtziRfF5HRaDO U2xg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id w3si2572193edu.384.2021.01.18.08.34.32; Mon, 18 Jan 2021 08:34:56 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2406089AbhARQcX (ORCPT + 99 others); Mon, 18 Jan 2021 11:32:23 -0500 Received: from smtp.infotech.no ([82.134.31.41]:45737 "EHLO smtp.infotech.no" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2406765AbhARQbM (ORCPT ); Mon, 18 Jan 2021 11:31:12 -0500 Received: from localhost (localhost [127.0.0.1]) by smtp.infotech.no (Postfix) with ESMTP id 5D26820416A; Mon, 18 Jan 2021 17:30:24 +0100 (CET) X-Virus-Scanned: by amavisd-new-2.6.6 (20110518) (Debian) at infotech.no Received: from smtp.infotech.no ([127.0.0.1]) by localhost (smtp.infotech.no [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 9HtaCAwBWUUz; Mon, 18 Jan 2021 17:30:21 +0100 (CET) Received: from xtwo70.bingwo.ca (host-104-157-204-209.dyn.295.ca [104.157.204.209]) by smtp.infotech.no (Postfix) with ESMTPA id E7E8B204295; Mon, 18 Jan 2021 17:30:17 +0100 (CET) From: Douglas Gilbert To: linux-scsi@vger.kernel.org, linux-block@vger.kernel.org, target-devel@vger.kernel.org, linux-rdma@vger.kernel.org, linux-kernel@vger.kernel.org Cc: martin.petersen@oracle.com, jejb@linux.vnet.ibm.com, bostroesser@gmail.com, ddiss@suse.de, bvanassche@acm.org, jgg@ziepe.ca Subject: [PATCH v6 2/4] scatterlist: add sgl_copy_sgl() function Date: Mon, 18 Jan 2021 11:30:04 -0500 Message-Id: <20210118163006.61659-3-dgilbert@interlog.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210118163006.61659-1-dgilbert@interlog.com> References: <20210118163006.61659-1-dgilbert@interlog.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Both the SCSI and NVMe subsystems receive user data from the block layer in scatterlist_s (aka scatter gather lists (sgl) which are often arrays). If drivers in those subsystems represent storage (e.g. a ramdisk) or cache "hot" user data then they may also choose to use scatterlist_s. Currently there are no sgl to sgl operations in the kernel. Start with a sgl to sgl copy. Stops when the first of the number of requested bytes to copy, or the source sgl, or the destination sgl is exhausted. So the destination sgl will _not_ grow. Reviewed-by: Bodo Stroesser Signed-off-by: Douglas Gilbert --- include/linux/scatterlist.h | 4 ++ lib/scatterlist.c | 74 +++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index 8adff41f7cfa..3f836a3246aa 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h @@ -321,6 +321,10 @@ size_t sg_pcopy_to_buffer(struct scatterlist *sgl, unsigned int nents, size_t sg_zero_buffer(struct scatterlist *sgl, unsigned int nents, size_t buflen, off_t skip); +size_t sgl_copy_sgl(struct scatterlist *d_sgl, unsigned int d_nents, off_t d_skip, + struct scatterlist *s_sgl, unsigned int s_nents, off_t s_skip, + size_t n_bytes); + /* * Maximum number of entries that will be allocated in one piece, if * a list larger than this is required then chaining will be utilized. diff --git a/lib/scatterlist.c b/lib/scatterlist.c index 24ea2d31a405..c06f8caaff91 100644 --- a/lib/scatterlist.c +++ b/lib/scatterlist.c @@ -1057,3 +1057,77 @@ size_t sg_zero_buffer(struct scatterlist *sgl, unsigned int nents, return offset; } EXPORT_SYMBOL(sg_zero_buffer); + +/** + * sgl_copy_sgl - Copy over a destination sgl from a source sgl + * @d_sgl: Destination sgl + * @d_nents: Number of SG entries in destination sgl + * @d_skip: Number of bytes to skip in destination before starting + * @s_sgl: Source sgl + * @s_nents: Number of SG entries in source sgl + * @s_skip: Number of bytes to skip in source before starting + * @n_bytes: The (maximum) number of bytes to copy + * + * Returns: + * The number of copied bytes. + * + * Notes: + * Destination arguments appear before the source arguments, as with memcpy(). + * + * Stops copying if either d_sgl, s_sgl or n_bytes is exhausted. + * + * Since memcpy() is used, overlapping copies (where d_sgl and s_sgl belong + * to the same sgl and the copy regions overlap) are not supported. + * + * Large copies are broken into copy segments whose sizes may vary. Those + * copy segment sizes are chosen by the min3() statement in the code below. + * Since SG_MITER_ATOMIC is used for both sides, each copy segment is started + * with kmap_atomic() [in sg_miter_next()] and completed with kunmap_atomic() + * [in sg_miter_stop()]. This means pre-emption is inhibited for relatively + * short periods even in very large copies. + * + * If d_skip is large, potentially spanning multiple d_nents then some + * integer arithmetic to adjust d_sgl may improve performance. For example + * if d_sgl is built using sgl_alloc_order(chainable=false) then the sgl + * will be an array with equally sized segments facilitating that + * arithmetic. The suggestion applies to s_skip, s_sgl and s_nents as well. + * + **/ +size_t sgl_copy_sgl(struct scatterlist *d_sgl, unsigned int d_nents, off_t d_skip, + struct scatterlist *s_sgl, unsigned int s_nents, off_t s_skip, + size_t n_bytes) +{ + size_t len; + size_t offset = 0; + struct sg_mapping_iter d_iter, s_iter; + + if (n_bytes == 0) + return 0; + sg_miter_start(&s_iter, s_sgl, s_nents, SG_MITER_ATOMIC | SG_MITER_FROM_SG); + sg_miter_start(&d_iter, d_sgl, d_nents, SG_MITER_ATOMIC | SG_MITER_TO_SG); + if (!sg_miter_skip(&s_iter, s_skip)) + goto fini; + if (!sg_miter_skip(&d_iter, d_skip)) + goto fini; + + while (offset < n_bytes) { + if (!sg_miter_next(&s_iter)) + break; + if (!sg_miter_next(&d_iter)) + break; + len = min3(d_iter.length, s_iter.length, n_bytes - offset); + + memcpy(d_iter.addr, s_iter.addr, len); + offset += len; + /* LIFO order (stop d_iter before s_iter) needed with SG_MITER_ATOMIC */ + d_iter.consumed = len; + sg_miter_stop(&d_iter); + s_iter.consumed = len; + sg_miter_stop(&s_iter); + } +fini: + sg_miter_stop(&d_iter); + sg_miter_stop(&s_iter); + return offset; +} +EXPORT_SYMBOL(sgl_copy_sgl); -- 2.25.1