Received: by 2002:a6b:500f:0:0:0:0:0 with SMTP id e15csp3298269iob; Mon, 16 May 2022 18:33:32 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzyTSSZQolc5V7EiB4FJNCTNLzCZDUpYKBRN/qupw0slN8njgaq+sM7RgZ+r2jEWsH57xgs X-Received: by 2002:aa7:c404:0:b0:42a:bfc2:4735 with SMTP id j4-20020aa7c404000000b0042abfc24735mr3468875edq.237.1652751212250; Mon, 16 May 2022 18:33:32 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1652751212; cv=none; d=google.com; s=arc-20160816; b=gNHYxI2t+pFGOVJ6cStQwPUagfjj9nlzejWeBXfpJWxXx9mlzy6rJey2u3MLfAkalR y5PA74Td1tgnk8pptc82kA2ZrLEkc82YW845g9PxKuwPjr9Yi2cx6jSnf0Gj/XnwxYk5 mAOa/KV3JuKdYdb60ig/XAFgILCeAWri/AhzFzxqD6jbDNKdmREhQCNcZxE2/ShZzk4X bMW9IKTNJ9YttKJSJdtpC44h25g/vGWbeOBeIy9eGxXDU5UwVI6bdo8OscJeOlCt8ZUA 2zJxNM5iWu+hGy3Y58VcmRDni8D+R0+G8YZe6QCk6v2ZHNFvxPBEI0FDmJti2Mu3ILpS P3Rw== 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=wAqMvQsAh7V9dqEawcYDDGWnyq6OkRHlVm2v1PFVGdc=; b=lyGTX5EVdlkOQcr++yr4bEjHTV7t/+FXs7ZcKyW9poyTqEVGGFqk2rIEw3iBzLD+r6 zlW85VcxZSdJi4a/BYCoGnhGksjhZuRmUyvoL4+82BWkW3/t3nzrDMqPwNOJtaqDxBdr 0A7akPGPxuHf6uJEKZG/gUnQDA3MND5Em2OaDLracGA/82yzOPGgnObY/a3NZVeA/ueI YMcYZbTalPueTzytvyqUvDPmSdCh2KGZEEb42JXSwl9Wga4OO4FKM9A62XMtsFPefmxh k6keVg1CLypRqaETq+WcJMJmk/DJOmcU/Z0ayKeLdQQkzELjc6eZEwsauydQeshvwVpE iPUA== ARC-Authentication-Results: i=1; mx.google.com; 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=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=netapp.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id nb39-20020a1709071ca700b006e7f255f245si1274012ejc.36.2022.05.16.18.32.54; Mon, 16 May 2022 18:33:32 -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; 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=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=netapp.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348537AbiEPVCE (ORCPT + 99 others); Mon, 16 May 2022 17:02:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41786 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1348993AbiEPVBC (ORCPT ); Mon, 16 May 2022 17:01:02 -0400 Received: from sin.source.kernel.org (sin.source.kernel.org [IPv6:2604:1380:40e1:4800::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A3B192AD0 for ; Mon, 16 May 2022 13:35:54 -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 sin.source.kernel.org (Postfix) with ESMTPS id 0C781CE17F9 for ; Mon, 16 May 2022 20:35:53 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2361AC34100; Mon, 16 May 2022 20:35:51 +0000 (UTC) From: Anna.Schumaker@Netapp.com To: steved@redhat.com, linux-nfs@vger.kernel.org Cc: Anna.Schumaker@Netapp.com Subject: [PATCH v1 1/6] SUNRPC: Introduce xdr_stream_move_segment() Date: Mon, 16 May 2022 16:35:44 -0400 Message-Id: <20220516203549.2605575-2-Anna.Schumaker@Netapp.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220516203549.2605575-1-Anna.Schumaker@Netapp.com> References: <20220516203549.2605575-1-Anna.Schumaker@Netapp.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-6.7 required=5.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,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 outside the region. 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 4417f667c757..04d47a096f8a 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_segment(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 df194cc07035..26559c08f68f 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 @@ -1671,6 +1699,37 @@ bool xdr_stream_subsegment(struct xdr_stream *xdr, struct xdr_buf *subbuf, } EXPORT_SYMBOL_GPL(xdr_stream_subsegment); +/** + * xdr_stream_move_segment - 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_segment(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_segment); + /** * xdr_buf_trim - lop at most "len" bytes off the end of "buf" * @buf: buf to be trimmed -- 2.36.1