Received: by 2002:ad5:4acb:0:0:0:0:0 with SMTP id n11csp1018084imw; Wed, 13 Jul 2022 12:14:25 -0700 (PDT) X-Google-Smtp-Source: AGRyM1tb1VHjIit7r9rLlH1SPCcfgNXpOtl0S4KjWXhleLKEvyx29OovNJpKoAux0tpao9HxDD+T X-Received: by 2002:a05:6402:4c3:b0:43a:f612:179d with SMTP id n3-20020a05640204c300b0043af612179dmr7131963edw.422.1657739664892; Wed, 13 Jul 2022 12:14:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1657739664; cv=none; d=google.com; s=arc-20160816; b=vDY/kOtnX13VFTTUd4ySzDvUScOv5xnEQibHOisf0U5TCfP6HfN7qwiyjWMSqolDpL Ca4K4D+ZHSJ9RpJI+43PIDLJey4pwFmpP+J5e4TrW35fWQnlGIiP/vLSUV/ZwIerA3Zy oxhyYnPhFscSKbXaBBY9Fvo5q7o1glBVLxnvUoxjgKPEo5/MckDtOSOCFahfhawayz1h xwLPH+p1dY3ymfpJ2hmSWljp3CRNMv+pVp+GTspYv31vsfDvDGmT+nbKmvUS0viBf1kd 70dhhcZg5DnsiJuicq8+uXup1EuGsGRyaimoyhxU3K7gN4UWIeTnkuHb065Fil48JIbU 9JWg== 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 :dkim-signature; bh=LfS4aZziK1Y2nu2+BiLf2Z5T5/dho5bSNuggdmKiDq8=; b=p9573smYBfWdcGlF84195n8bmQheRGEYi7zHcVyoErD2r7MxSf5UTmgdDJ/YSVDQcs btzDmi037zux6guoCxNC5UrYoVfbPdiKFJoN4xzmKiR7g1nIpqgsSQxB018KlSsPCBPe kx49IEIUw4tmsy0xRqJ9VMuvhy1H2blAi75FJAsdMgsZsjOxzDEhlOPq6O3wPuUabvN5 LpTtIsItwg0Q0UyymynDRkZBglbSX7bz4G1wQJ1bDm0CwKF6iSOo4QR0fDEuEcqK2Gxn 15PcdJHPBIt3DWui3hobVjfvRAdL44vKqMsrzRra5NW0pOymG0QvmqLyRXiRPp8rs/op nwMQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=mHtqT6gv; spf=pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id b23-20020aa7df97000000b0043ab4f56513si17779928edy.592.2022.07.13.12.13.47; Wed, 13 Jul 2022 12:14:24 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=mHtqT6gv; spf=pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230481AbiGMTIb (ORCPT + 99 others); Wed, 13 Jul 2022 15:08:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33874 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230414AbiGMTIa (ORCPT ); Wed, 13 Jul 2022 15:08:30 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 774DD2CDEA for ; Wed, 13 Jul 2022 12:08:29 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 0776961DC6 for ; Wed, 13 Jul 2022 19:08:29 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1DAE0C3411E; Wed, 13 Jul 2022 19:08:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1657739308; bh=OH9h/JTS87YVQ2CrWGISefPug2oRlihUAgfsHSj3hOM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mHtqT6gvMMyqsLwxITvxgbOpSoiG/H6QQ1y4dzrPltiP9BFFxdG2lBvFsZaVkNoLh +EfjQYayG69C/74Txu7a6oxkDVcDvnuYXBCWomOrC4VYxbNYer/DaRyn07Zs578+sH zgRLV94f8mFOfOo2zsGIiVlVbjPRdIBgOp3JCeFCzJMJ+lnhUUZiOzpuP68bVZGyWZ orJh9tjVuEVJ1Amsut/9wVnxTssGEpq2lN/a//NoQ0nzl9R5eistlcbF5AKSXGm0nv jme4n+5DKZ5AgtUBfUWYG2upOzUVLYvFlqkGk/T7+S/AxzdzKCV0zSAikZKdjYhStV 3lxWXomEl959g== From: Anna Schumaker To: linux-nfs@vger.kernel.org, chuck.lever@oracle.com Cc: anna@kernel.org Subject: [PATCH v2 1/6] SUNRPC: Introduce xdr_stream_move_subsegment() Date: Wed, 13 Jul 2022 15:08:20 -0400 Message-Id: <20220713190825.615678-2-anna@kernel.org> X-Mailer: git-send-email 2.37.0 In-Reply-To: <20220713190825.615678-1-anna@kernel.org> References: <20220713190825.615678-1-anna@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-7.7 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Anna Schumaker I do this by creating an xdr subsegment for the range we will be operating over. This lets me shift data to the correct place without potentially overwriting anything already there. Signed-off-by: Anna Schumaker --- include/linux/sunrpc/xdr.h | 2 ++ net/sunrpc/xdr.c | 59 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h index 5860f32e3958..7dcc6c31fe29 100644 --- a/include/linux/sunrpc/xdr.h +++ b/include/linux/sunrpc/xdr.h @@ -262,6 +262,8 @@ extern unsigned int xdr_align_data(struct xdr_stream *, unsigned int offset, uns extern unsigned int xdr_expand_hole(struct xdr_stream *, unsigned int offset, unsigned int length); extern bool xdr_stream_subsegment(struct xdr_stream *xdr, struct xdr_buf *subbuf, unsigned int len); +extern unsigned int xdr_stream_move_subsegment(struct xdr_stream *xdr, unsigned int offset, + unsigned int target, unsigned int length); /** * xdr_set_scratch_buffer - Attach a scratch buffer for decoding data. diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 5d2b3e6979fb..8ba11a754297 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -775,6 +775,34 @@ static void xdr_buf_pages_shift_left(const struct xdr_buf *buf, xdr_buf_tail_copy_left(buf, 0, len - buf->page_len, shift); } +static void xdr_buf_head_shift_left(const struct xdr_buf *buf, + unsigned int base, unsigned int len, + unsigned int shift) +{ + const struct kvec *head = buf->head; + unsigned int bytes; + + if (!shift || !len) + return; + + if (shift > base) { + bytes = (shift - base); + if (bytes >= len) + return; + base += bytes; + len -= bytes; + } + + if (base < head->iov_len) { + bytes = min_t(unsigned int, len, head->iov_len - base); + memmove(head->iov_base + (base - shift), + head->iov_base + base, bytes); + base += bytes; + len -= bytes; + } + xdr_buf_pages_shift_left(buf, base - head->iov_len, len, shift); +} + /** * xdr_shrink_bufhead * @buf: xdr_buf @@ -1680,6 +1708,37 @@ bool xdr_stream_subsegment(struct xdr_stream *xdr, struct xdr_buf *subbuf, } EXPORT_SYMBOL_GPL(xdr_stream_subsegment); +/** + * xdr_stream_move_subsegment - Move part of a stream to another position + * @xdr: the source xdr_stream + * @offset: the source offset of the segment + * @target: the target offset of the segment + * @length: the number of bytes to move + * + * Moves @length bytes from @offset to @target in the xdr_stream, overwriting + * anything in its space. Returns the number of bytes in the segment. + */ +unsigned int xdr_stream_move_subsegment(struct xdr_stream *xdr, unsigned int offset, + unsigned int target, unsigned int length) +{ + struct xdr_buf buf; + unsigned int shift; + + if (offset < target) { + shift = target - offset; + if (xdr_buf_subsegment(xdr->buf, &buf, offset, shift + length) < 0) + return 0; + xdr_buf_head_shift_right(&buf, 0, length, shift); + } else if (offset > target) { + shift = offset - target; + if (xdr_buf_subsegment(xdr->buf, &buf, target, shift + length) < 0) + return 0; + xdr_buf_head_shift_left(&buf, shift, length, shift); + } + return length; +} +EXPORT_SYMBOL_GPL(xdr_stream_move_subsegment); + /** * xdr_buf_trim - lop at most "len" bytes off the end of "buf" * @buf: buf to be trimmed -- 2.37.0