Received: by 2002:a05:6622:f08:0:0:0:0 with SMTP id l8csp4280498ivc; Tue, 3 Nov 2020 07:44:19 -0800 (PST) X-Google-Smtp-Source: ABdhPJzBGDRzE9DRLenH4i3TLLYWbrUYOjnP7WD+UleDGGoNnPpuTQIox4GNruHUqI/tWpcpSoX5 X-Received: by 2002:a17:906:f296:: with SMTP id gu22mr15175686ejb.475.1604418259612; Tue, 03 Nov 2020 07:44:19 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1604418259; cv=none; d=google.com; s=arc-20160816; b=Qdf6fZ1UDNAVEKuzlWqg76zBAs8+hYGWMgfZR567hTb06ScM3ceGikSyV4IFYJTdcg acCyGfqRZz9833M3i5034TI80zYRbeaf3efdGAA6GaBJ0vYV13J82p5VaYHYHD9yJFia es0TCTVu7lr6k/D0j1mnKWpZNqMccK73w8bLlljDReA2Kqhl4CjjcojeTLuHkgwwffTP P4a5+2pjnSZQ9d5R+bzOKNQNkSLFkmPVcjCkW4nVQ9XzV9nVeKkbpjLx7rZ8HQ6QPvJB Kc3w2YJfIq3EgHx/a92E/+HZkh+NvQA8btLxQQEK9bhgLlQuXZl8okAznt731w3xFcG7 1zOQ== 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:to:from :dkim-signature; bh=mDZCR1yMxOaIsPljd2oCiGQ2g5z/kjP22AdDSZewwyk=; b=qZgEArfe7YHL4jO1oxgxjYOdszLtpqDwAnHyt+FVO3Q9e957qBF4prLC4d4fl+ET9d bvfwclH0p2dW4rYBewt74uoyf1j4N9UgUMPWJHtT9AFFCaJU45/7lap3ROcx/ohqk+N0 U3DsQ0bQq4wC6bWKz23L19Q/cksb8PrVfzij//XwhvXZ5GZOUUsWOnoTNsQ4+LtRO2eq lFKXNU64a5z9uBv0LXz9eZJjuHk3Mper++3Ei6WVjzZX2zmh+P/P+SQF0kMMqIB6nPf2 a9ySPtaXRds7xnJ9pLzC5ftVi/L2dCu8alker4769xR84jncT0LqBkdM6IeUT5H4RP2l fUSQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b="sRB/iRek"; 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=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id d20si8825591ejb.226.2020.11.03.07.43.52; Tue, 03 Nov 2020 07:44:19 -0800 (PST) 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; dkim=pass header.i=@kernel.org header.s=default header.b="sRB/iRek"; 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=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728274AbgKCPnn (ORCPT + 99 others); Tue, 3 Nov 2020 10:43:43 -0500 Received: from mail.kernel.org ([198.145.29.99]:39138 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728275AbgKCPnn (ORCPT ); Tue, 3 Nov 2020 10:43:43 -0500 Received: from localhost.localdomain (c-68-36-133-222.hsd1.mi.comcast.net [68.36.133.222]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id C86E120780 for ; Tue, 3 Nov 2020 15:43:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604418223; bh=ABicvRzGH776VY0sINCLtXLG73UOddTfLgXTNLcrawI=; h=From:To:Subject:Date:In-Reply-To:References:From; b=sRB/iRek1qPqn5ihEEpOXW70vgIK62abbh69A8GJwPV6ltcusGg62/6GJxhnglF3D feog1pioUBQxH8KZbFTu3QOyV1N7cDyGF3ftujOpfKbGTQEhBBKW57Cz3oL/n3cwYU cdR6xFQsIdY7vAfxn+Oe1cpSyvEFYFZ05oO1yvqk= From: trondmy@kernel.org To: linux-nfs@vger.kernel.org Subject: [PATCH v2 05/16] NFS: Don't discard readdir results Date: Tue, 3 Nov 2020 10:33:18 -0500 Message-Id: <20201103153329.531942-6-trondmy@kernel.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201103153329.531942-5-trondmy@kernel.org> References: <20201103153329.531942-1-trondmy@kernel.org> <20201103153329.531942-2-trondmy@kernel.org> <20201103153329.531942-3-trondmy@kernel.org> <20201103153329.531942-4-trondmy@kernel.org> <20201103153329.531942-5-trondmy@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Trond Myklebust If a readdir call returns more data than we can fit into one page cache page, then allocate a new one for that data rather than discarding the data. Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 46 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index b4861a33ad60..788c2a2eeaa3 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -321,6 +321,26 @@ static void nfs_readdir_page_set_eof(struct page *page) kunmap_atomic(array); } +static void nfs_readdir_page_unlock_and_put(struct page *page) +{ + unlock_page(page); + put_page(page); +} + +static struct page *nfs_readdir_page_get_next(struct address_space *mapping, + pgoff_t index, u64 cookie) +{ + struct page *page; + + page = nfs_readdir_page_get_locked(mapping, index, cookie); + if (page) { + if (nfs_readdir_page_last_cookie(page) == cookie) + return page; + nfs_readdir_page_unlock_and_put(page); + } + return NULL; +} + static inline int is_32bit_api(void) { @@ -638,13 +658,15 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry, } /* Perform conversion from xdr to cache array */ -static -int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, - struct page **xdr_pages, struct page *page, unsigned int buflen) +static int nfs_readdir_page_filler(struct nfs_readdir_descriptor *desc, + struct nfs_entry *entry, + struct page **xdr_pages, + struct page *fillme, unsigned int buflen) { + struct address_space *mapping = desc->file->f_mapping; struct xdr_stream stream; struct xdr_buf buf; - struct page *scratch; + struct page *scratch, *new, *page = fillme; int status; scratch = alloc_page(GFP_KERNEL); @@ -667,6 +689,19 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en desc->dir_verifier); status = nfs_readdir_add_to_array(entry, page); + if (status != -ENOSPC) + continue; + + if (page->mapping != mapping) + break; + new = nfs_readdir_page_get_next(mapping, page->index + 1, + entry->prev_cookie); + if (!new) + break; + if (page != fillme) + nfs_readdir_page_unlock_and_put(page); + page = new; + status = nfs_readdir_add_to_array(entry, page); } while (!status && !entry->eof); switch (status) { @@ -682,6 +717,9 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en break; } + if (page != fillme) + nfs_readdir_page_unlock_and_put(page); + put_page(scratch); return status; } -- 2.28.0