Received: by 2002:a05:6a10:f3d0:0:0:0:0 with SMTP id a16csp3211955pxv; Mon, 12 Jul 2021 12:00:28 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwJPZcjJKtkux/POa5Kd14gKOIIjSJsa70YS1E419wZktxgYHr5fQtJko5hANgY4+A7fFVu X-Received: by 2002:aa7:c801:: with SMTP id a1mr344667edt.293.1626116427939; Mon, 12 Jul 2021 12:00:27 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1626116427; cv=none; d=google.com; s=arc-20160816; b=JFsL8TxpQVSrKUrNULp51XBUp7t8QIhdzE85ZVF4olwdkkt/QaOnBjp0dGwaWH5sfM vXncFELQGQZKUUDfQ9uXw+5nv3CeUNaM1Ps5wVWe1njIp51DrGWpJg+YG6ufAG9kYel2 0REg0lLEk9kZDE0MKHFXOn2c4Tfn6t6xgB9QXoIU1Gb5a7FmK9jYVcZkgp0Jo/D5mzUC bPpio06tmx9plAIjOrlYruEeBqTfSVTngIsEClmMf3cUK7s/MvL1XPG7g/+Dj7P3sRbS nC3tvB89OkTqhoC5/Q5TDcflM4rRD5AfNA+qjzds6zlETkBjdzcPmu8snV1a3LP0XzwM H/gQ== 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 :user-agent:references:in-reply-to:message-id:date:cc:to:from :subject; bh=jv7LR5UHzjjq99ZjBdtT75aObXmYdQbQwE0abjepNtA=; b=ELzp7aSaYAp8418JJ0bxzEfaBst4cSWCn7HspmZn+ny2Xx04QibVwdcwjSXr4GibNi amFixeR88J4OHd+YJlpFQjKYu7srXOoX1YBgn60jC56SFgmXBP5jZU2AVO9yOPzlbx0x yPt5gfIX1nAaY/dZDrS/UJrP+k/aXVFNc0cBOH8hmluowxf4WBsD+8sRvdNSQcA/6IyF dDAiRZq5Vw2GKVasCOcVFxgdXe0z8j7CpzgUi9RTahBrMucIGmnroHxSe6jsLRKzGMPN k4DCwwWW1y7g8PJTc7yENwGFCsfbqdDS4iYnR1dG32c/KzSAz22RMg90KCbVxB6SElQn ik8Q== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-nfs-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=oracle.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id w11si18815725ejc.453.2021.07.12.12.00.04; Mon, 12 Jul 2021 12:00:27 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-nfs-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-nfs-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-nfs-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=oracle.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235253AbhGLTAs (ORCPT + 99 others); Mon, 12 Jul 2021 15:00:48 -0400 Received: from mail.kernel.org ([198.145.29.99]:54486 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230409AbhGLTAs (ORCPT ); Mon, 12 Jul 2021 15:00:48 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 2CAA16120A; Mon, 12 Jul 2021 18:57:59 +0000 (UTC) Subject: [PATCH v4 2/3] SUNRPC: Add svc_rqst_replace_page() API From: Chuck Lever To: linux-nfs@vger.kernel.org, linux-mm@kvack.org Cc: neilb@suse.de Date: Mon, 12 Jul 2021 14:57:58 -0400 Message-ID: <162611627845.1416.14661720296610549505.stgit@klimt.1015granger.net> In-Reply-To: <162611520339.1416.14646909890289253420.stgit@klimt.1015granger.net> References: <162611520339.1416.14646909890289253420.stgit@klimt.1015granger.net> User-Agent: StGit/1.1 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org Replacing a page in rq_pages[] requires a get_page(), which is a bus-locked operation, and a put_page(), which can be even more costly. To reduce the cost of replacing a page in rq_pages[], batch the put_page() operations by collecting "freed" pages in a pagevec, and then release those pages when the pagevec is full. This pagevec is also emptied when each RPC completes. Signed-off-by: Chuck Lever --- include/linux/sunrpc/svc.h | 4 ++++ net/sunrpc/svc.c | 21 +++++++++++++++++++++ net/sunrpc/svc_xprt.c | 3 +++ 3 files changed, 28 insertions(+) diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index e91d51ea028b..ab9afbf0a0d8 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -19,6 +19,7 @@ #include #include #include +#include /* statistics for svc_pool structures */ struct svc_pool_stats { @@ -256,6 +257,7 @@ struct svc_rqst { struct page * *rq_next_page; /* next reply page to use */ struct page * *rq_page_end; /* one past the last page */ + struct pagevec rq_pvec; struct kvec rq_vec[RPCSVC_MAXPAGES]; /* generally useful.. */ struct bio_vec rq_bvec[RPCSVC_MAXPAGES]; @@ -502,6 +504,8 @@ struct svc_rqst *svc_rqst_alloc(struct svc_serv *serv, struct svc_pool *pool, int node); struct svc_rqst *svc_prepare_thread(struct svc_serv *serv, struct svc_pool *pool, int node); +void svc_rqst_replace_page(struct svc_rqst *rqstp, + struct page *page); void svc_rqst_free(struct svc_rqst *); void svc_exit_thread(struct svc_rqst *); unsigned int svc_pool_map_get(void); diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 0de918cb3d90..d2d412d43827 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -838,6 +838,27 @@ svc_set_num_threads_sync(struct svc_serv *serv, struct svc_pool *pool, int nrser } EXPORT_SYMBOL_GPL(svc_set_num_threads_sync); +/** + * svc_rqst_replace_page - Replace one page in rq_pages[] + * @rqstp: svc_rqst with pages to replace + * @page: replacement page + * + * When replacing a page in rq_pages, batch the release of the + * replaced pages to avoid hammering the page allocator. + */ +void svc_rqst_replace_page(struct svc_rqst *rqstp, struct page *page) +{ + if (*rqstp->rq_next_page) { + if (!pagevec_space(&rqstp->rq_pvec)) + __pagevec_release(&rqstp->rq_pvec); + pagevec_add(&rqstp->rq_pvec, *rqstp->rq_next_page); + } + + get_page(page); + *(rqstp->rq_next_page++) = page; +} +EXPORT_SYMBOL_GPL(svc_rqst_replace_page); + /* * Called from a server thread as it's exiting. Caller must hold the "service * mutex" for the service. diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index d66a8e44a1ae..682058a5ec13 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -539,6 +539,7 @@ static void svc_xprt_release(struct svc_rqst *rqstp) kfree(rqstp->rq_deferred); rqstp->rq_deferred = NULL; + pagevec_release(&rqstp->rq_pvec); svc_free_res_pages(rqstp); rqstp->rq_res.page_len = 0; rqstp->rq_res.page_base = 0; @@ -664,6 +665,8 @@ static int svc_alloc_arg(struct svc_rqst *rqstp) struct xdr_buf *arg = &rqstp->rq_arg; unsigned long pages, filled; + pagevec_init(&rqstp->rq_pvec); + pages = (serv->sv_max_mesg + 2 * PAGE_SIZE) >> PAGE_SHIFT; if (pages > RPCSVC_MAXPAGES) { pr_warn_once("svc: warning: pages=%lu > RPCSVC_MAXPAGES=%lu\n",