From patchwork Mon Nov 2 18:06:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Trond Myklebust X-Patchwork-Id: 11874863 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 32AA292C for ; Mon, 2 Nov 2020 18:17:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1276020786 for ; Mon, 2 Nov 2020 18:17:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604341056; bh=I+vK0bfkwW6be/+ok+6ykArjIqQDwGDRgKPHhbXv4Js=; h=From:To:Subject:Date:In-Reply-To:References:List-ID:From; b=ozHNtjoF2856lXvxzoxUHrypYgsS01yWEc/p9ToYLwPGoudJWZ7f0aYcKnXgkWbEe Ex8WwNUGXJQf93eBfEP4KCX0CHAP+7UNXH3qOUHmilw6UAjkE0WhurlvtFuU/6a7vp RIIvux8uUZNQx2EvZ7PbBbTp/0wxNr14wA9CKi5E= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726299AbgKBSRf (ORCPT ); Mon, 2 Nov 2020 13:17:35 -0500 Received: from mail.kernel.org ([198.145.29.99]:40844 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726076AbgKBSRV (ORCPT ); Mon, 2 Nov 2020 13:17:21 -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 9245B20786 for ; Mon, 2 Nov 2020 18:17:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604341040; bh=I+vK0bfkwW6be/+ok+6ykArjIqQDwGDRgKPHhbXv4Js=; h=From:To:Subject:Date:In-Reply-To:References:From; b=mGNSQNqXjVD8HcNy+Ekb8Yu/y0oE8e6k9y3ZyfQWRaUJY+g4vJ8gVctizAQ4mepZz NwVpsDH0AVZe7Khq363m32WIa36yQB6tLk1Gz1Hv5UNcrT4s44yhxaUJtETLd/Er0W j2+v/hmTKOxA7MxesL9whHlCaopQffN7P5/ojp6A= From: trondmy@kernel.org To: linux-nfs@vger.kernel.org Subject: [PATCH 01/12] NFS: Ensure contents of struct nfs_open_dir_context are consistent Date: Mon, 2 Nov 2020 13:06:47 -0500 Message-Id: <20201102180658.6218-2-trondmy@kernel.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201102180658.6218-1-trondmy@kernel.org> References: <20201102180658.6218-1-trondmy@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Trond Myklebust Ensure that the contents of struct nfs_open_dir_context are consistent by setting them under the file->f_lock from a private copy (that is known to be consistent). Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 72 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 29 deletions(-) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 4e011adaf967..67d8595cd6e5 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -144,20 +144,23 @@ struct nfs_cache_array { struct nfs_cache_array_entry array[]; }; -typedef struct { +typedef struct nfs_readdir_descriptor { struct file *file; struct page *page; struct dir_context *ctx; unsigned long page_index; - u64 *dir_cookie; + u64 dir_cookie; u64 last_cookie; + u64 dup_cookie; loff_t current_index; loff_t prev_index; unsigned long dir_verifier; unsigned long timestamp; unsigned long gencount; + unsigned long attr_gencount; unsigned int cache_entry_index; + signed char duped; bool plus; bool eof; } nfs_readdir_descriptor_t; @@ -273,7 +276,7 @@ int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descri } index = (unsigned int)diff; - *desc->dir_cookie = array->array[index].cookie; + desc->dir_cookie = array->array[index].cookie; desc->cache_entry_index = index; return 0; out_eof: @@ -298,33 +301,32 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des int status = -EAGAIN; for (i = 0; i < array->size; i++) { - if (array->array[i].cookie == *desc->dir_cookie) { + if (array->array[i].cookie == desc->dir_cookie) { struct nfs_inode *nfsi = NFS_I(file_inode(desc->file)); - struct nfs_open_dir_context *ctx = desc->file->private_data; new_pos = desc->current_index + i; - if (ctx->attr_gencount != nfsi->attr_gencount || + if (desc->attr_gencount != nfsi->attr_gencount || !nfs_readdir_inode_mapping_valid(nfsi)) { - ctx->duped = 0; - ctx->attr_gencount = nfsi->attr_gencount; + desc->duped = 0; + desc->attr_gencount = nfsi->attr_gencount; } else if (new_pos < desc->prev_index) { - if (ctx->duped > 0 - && ctx->dup_cookie == *desc->dir_cookie) { + if (desc->duped > 0 + && desc->dup_cookie == desc->dir_cookie) { if (printk_ratelimit()) { pr_notice("NFS: directory %pD2 contains a readdir loop." "Please contact your server vendor. " "The file: %.*s has duplicate cookie %llu\n", desc->file, array->array[i].string.len, - array->array[i].string.name, *desc->dir_cookie); + array->array[i].string.name, desc->dir_cookie); } status = -ELOOP; goto out; } - ctx->dup_cookie = *desc->dir_cookie; - ctx->duped = -1; + desc->dup_cookie = desc->dir_cookie; + desc->duped = -1; } if (nfs_readdir_use_cookie(desc->file)) - desc->ctx->pos = *desc->dir_cookie; + desc->ctx->pos = desc->dir_cookie; else desc->ctx->pos = new_pos; desc->prev_index = new_pos; @@ -334,7 +336,7 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des } if (array->eof_index >= 0) { status = -EBADCOOKIE; - if (*desc->dir_cookie == array->last_cookie) + if (desc->dir_cookie == array->last_cookie) desc->eof = true; } out: @@ -349,7 +351,7 @@ int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc) array = kmap(desc->page); - if (*desc->dir_cookie == 0) + if (desc->dir_cookie == 0) status = nfs_readdir_search_for_pos(array, desc); else status = nfs_readdir_search_for_cookie(array, desc); @@ -801,7 +803,6 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc) int i = 0; int res = 0; struct nfs_cache_array *array = NULL; - struct nfs_open_dir_context *ctx = file->private_data; array = kmap(desc->page); for (i = desc->cache_entry_index; i < array->size; i++) { @@ -814,22 +815,22 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc) break; } if (i < (array->size-1)) - *desc->dir_cookie = array->array[i+1].cookie; + desc->dir_cookie = array->array[i+1].cookie; else - *desc->dir_cookie = array->last_cookie; + desc->dir_cookie = array->last_cookie; if (nfs_readdir_use_cookie(file)) - desc->ctx->pos = *desc->dir_cookie; + desc->ctx->pos = desc->dir_cookie; else desc->ctx->pos++; - if (ctx->duped != 0) - ctx->duped = 1; + if (desc->duped != 0) + desc->duped = 1; } if (array->eof_index >= 0) desc->eof = true; kunmap(desc->page); dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n", - (unsigned long long)*desc->dir_cookie, res); + (unsigned long long)desc->dir_cookie, res); return res; } @@ -851,10 +852,9 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc) struct page *page = NULL; int status; struct inode *inode = file_inode(desc->file); - struct nfs_open_dir_context *ctx = desc->file->private_data; dfprintk(DIRCACHE, "NFS: uncached_readdir() searching for cookie %Lu\n", - (unsigned long long)*desc->dir_cookie); + (unsigned long long)desc->dir_cookie); page = alloc_page(GFP_HIGHUSER); if (!page) { @@ -863,9 +863,9 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc) } desc->page_index = 0; - desc->last_cookie = *desc->dir_cookie; + desc->last_cookie = desc->dir_cookie; desc->page = page; - ctx->duped = 0; + desc->duped = 0; status = nfs_readdir_xdr_to_array(desc, page, inode); if (status < 0) @@ -894,7 +894,6 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) nfs_readdir_descriptor_t my_desc = { .file = file, .ctx = ctx, - .dir_cookie = &dir_ctx->dir_cookie, .plus = nfs_use_readdirplus(inode, ctx), }, *desc = &my_desc; @@ -915,13 +914,20 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) if (res < 0) goto out; + spin_lock(&file->f_lock); + desc->dir_cookie = dir_ctx->dir_cookie; + desc->dup_cookie = dir_ctx->dup_cookie; + desc->duped = dir_ctx->duped; + desc->attr_gencount = dir_ctx->attr_gencount; + spin_unlock(&file->f_lock); + do { res = readdir_search_pagecache(desc); if (res == -EBADCOOKIE) { res = 0; /* This means either end of directory */ - if (*desc->dir_cookie && !desc->eof) { + if (desc->dir_cookie && !desc->eof) { /* Or that the server has 'lost' a cookie */ res = uncached_readdir(desc); if (res == 0) @@ -946,6 +952,14 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) if (res < 0) break; } while (!desc->eof); + + spin_lock(&file->f_lock); + dir_ctx->dir_cookie = desc->dir_cookie; + dir_ctx->dup_cookie = desc->dup_cookie; + dir_ctx->duped = desc->duped; + dir_ctx->attr_gencount = desc->attr_gencount; + spin_unlock(&file->f_lock); + out: if (res > 0) res = 0; From patchwork Mon Nov 2 18:06:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Trond Myklebust X-Patchwork-Id: 11874841 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CE3EB921 for ; Mon, 2 Nov 2020 18:17:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B080F20786 for ; Mon, 2 Nov 2020 18:17:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604341044; bh=qPfAPw7196hQ8nsK5eADV/nGuxh7pKO4LF0CbGIaxT8=; h=From:To:Subject:Date:In-Reply-To:References:List-ID:From; b=Ct348+/6I+MCfH491fAEMw8XuLw7/rmJavlJv9g0oXFL9go45ofFTwk12Vk5QtuzA C8ni2u3Be03mHBFIlbnorxWzTHO8XbZfWHuCXeJeYDOpCq+Fb8mjXvFMTocR0BEQtB yVfFufSPjS72bOG53lhMUsnea2Tw+RKX40+bbayw= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726255AbgKBSRW (ORCPT ); Mon, 2 Nov 2020 13:17:22 -0500 Received: from mail.kernel.org ([198.145.29.99]:40854 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726114AbgKBSRW (ORCPT ); Mon, 2 Nov 2020 13:17:22 -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 1EBA520731 for ; Mon, 2 Nov 2020 18:17:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604341041; bh=qPfAPw7196hQ8nsK5eADV/nGuxh7pKO4LF0CbGIaxT8=; h=From:To:Subject:Date:In-Reply-To:References:From; b=HqZ1Isuluyntnf6/Hut58x0daOf5zs3gi6EutrVlbQ9nqERG8w6otCDLhdWwLI6lD XZtBb3GywMS2T/2xwv7Xzp/u6+0GoTYPjuFdavLcrOL77tyJqvpYnsFsUo2eKKeh5o K9hcVNJ/aTM+S8N7rsMyZ6QhbSQyaJsH6QCtbbPc= From: trondmy@kernel.org To: linux-nfs@vger.kernel.org Subject: [PATCH 02/12] NFS: Clean up readdir struct nfs_cache_array Date: Mon, 2 Nov 2020 13:06:48 -0500 Message-Id: <20201102180658.6218-3-trondmy@kernel.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201102180658.6218-2-trondmy@kernel.org> References: <20201102180658.6218-1-trondmy@kernel.org> <20201102180658.6218-2-trondmy@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Trond Myklebust Since the 'eof_index' is only ever used as a flag, make it so. Also add a flag to detect if the page has been completely filled. Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 66 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 17 deletions(-) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 67d8595cd6e5..604ebe015387 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -138,9 +138,10 @@ struct nfs_cache_array_entry { }; struct nfs_cache_array { - int size; - int eof_index; u64 last_cookie; + unsigned int size; + unsigned char page_full : 1, + page_is_eof : 1; struct nfs_cache_array_entry array[]; }; @@ -172,7 +173,6 @@ void nfs_readdir_init_array(struct page *page) array = kmap_atomic(page); memset(array, 0, sizeof(struct nfs_cache_array)); - array->eof_index = -1; kunmap_atomic(array); } @@ -192,6 +192,17 @@ void nfs_readdir_clear_array(struct page *page) kunmap_atomic(array); } +static void nfs_readdir_array_set_eof(struct nfs_cache_array *array) +{ + array->page_is_eof = 1; + array->page_full = 1; +} + +static bool nfs_readdir_array_is_full(struct nfs_cache_array *array) +{ + return array->page_full; +} + /* * the caller is responsible for freeing qstr.name * when called by nfs_readdir_add_to_array, the strings will be freed in @@ -213,6 +224,23 @@ int nfs_readdir_make_qstr(struct qstr *string, const char *name, unsigned int le return 0; } +/* + * Check that the next array entry lies entirely within the page bounds + */ +static int nfs_readdir_array_can_expand(struct nfs_cache_array *array) +{ + struct nfs_cache_array_entry *cache_entry; + + if (array->page_full) + return -ENOSPC; + cache_entry = &array->array[array->size + 1]; + if ((char *)cache_entry - (char *)array > PAGE_SIZE) { + array->page_full = 1; + return -ENOSPC; + } + return 0; +} + static int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page) { @@ -220,13 +248,11 @@ int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page) struct nfs_cache_array_entry *cache_entry; int ret; - cache_entry = &array->array[array->size]; - - /* Check that this entry lies within the page bounds */ - ret = -ENOSPC; - if ((char *)&cache_entry[1] - (char *)page_address(page) > PAGE_SIZE) + ret = nfs_readdir_array_can_expand(array); + if (ret) goto out; + cache_entry = &array->array[array->size]; cache_entry->cookie = entry->prev_cookie; cache_entry->ino = entry->ino; cache_entry->d_type = entry->d_type; @@ -236,12 +262,21 @@ int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page) array->last_cookie = entry->cookie; array->size++; if (entry->eof != 0) - array->eof_index = array->size; + nfs_readdir_array_set_eof(array); out: kunmap(page); return ret; } +static void nfs_readdir_page_set_eof(struct page *page) +{ + struct nfs_cache_array *array; + + array = kmap_atomic(page); + nfs_readdir_array_set_eof(array); + kunmap_atomic(array); +} + static inline int is_32bit_api(void) { @@ -270,7 +305,7 @@ int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descri if (diff < 0) goto out_eof; if (diff >= array->size) { - if (array->eof_index >= 0) + if (array->page_is_eof) goto out_eof; return -EAGAIN; } @@ -334,7 +369,7 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des return 0; } } - if (array->eof_index >= 0) { + if (array->page_is_eof) { status = -EBADCOOKIE; if (desc->dir_cookie == array->last_cookie) desc->eof = true; @@ -566,7 +601,6 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en struct xdr_stream stream; struct xdr_buf buf; struct page *scratch; - struct nfs_cache_array *array; unsigned int count = 0; int status; @@ -604,10 +638,8 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en out_nopages: if (count == 0 || (status == -EBADCOOKIE && entry->eof != 0)) { - array = kmap(page); - array->eof_index = array->size; + nfs_readdir_page_set_eof(page); status = 0; - kunmap(page); } put_page(scratch); @@ -689,7 +721,7 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, status = 0; break; } - } while (array->eof_index < 0); + } while (!nfs_readdir_array_is_full(array)); nfs_readdir_free_pages(pages, array_size); out_release_array: @@ -825,7 +857,7 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc) if (desc->duped != 0) desc->duped = 1; } - if (array->eof_index >= 0) + if (array->page_is_eof) desc->eof = true; kunmap(desc->page); From patchwork Mon Nov 2 18:06:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Trond Myklebust X-Patchwork-Id: 11874851 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0B4BE921 for ; Mon, 2 Nov 2020 18:17:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DFE2420786 for ; Mon, 2 Nov 2020 18:17:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604341048; bh=3wr7BivWD8kq0r12G3AOEQsS0qQNPXTmf8wMwj8LqFE=; h=From:To:Subject:Date:In-Reply-To:References:List-ID:From; b=ei+Kfc2WjSBvZKKSBViUQQaWGEFpJDqq/jb8fa+iwtiFq1RKqLsmmkRIs2w/KzBnW ZMWH3ANXRfZp54OX4FYDEEf6xwcipTuyh/sjzZbjnWWXhI+3A0bG9Je9qf9Kugojz/ 5f6thrM1SzSoUcCxBSCaKLsA34yEZ1ratWC2Pq1s= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726260AbgKBSR1 (ORCPT ); Mon, 2 Nov 2020 13:17:27 -0500 Received: from mail.kernel.org ([198.145.29.99]:40860 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726171AbgKBSRW (ORCPT ); Mon, 2 Nov 2020 13:17:22 -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 9985C22243 for ; Mon, 2 Nov 2020 18:17:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604341041; bh=3wr7BivWD8kq0r12G3AOEQsS0qQNPXTmf8wMwj8LqFE=; h=From:To:Subject:Date:In-Reply-To:References:From; b=y0Jp+bWLULLpU5p+z+VBZ8UWp+c3tt3jdFRgykpLVYev5mK5nqmZLBVV+sxV4LNKu +Ht4cT3auxADK1NB63AMA7SFN79Suh82nNvaz++sRVB/YtGgaHW3QO4YxpY2G27QDY upk7vCwQX0cygFo+gBKHL/Oukwp8Y8o5qGb5NnBY= From: trondmy@kernel.org To: linux-nfs@vger.kernel.org Subject: [PATCH 03/12] NFS: Clean up nfs_readdir_page_filler() Date: Mon, 2 Nov 2020 13:06:49 -0500 Message-Id: <20201102180658.6218-4-trondmy@kernel.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201102180658.6218-3-trondmy@kernel.org> References: <20201102180658.6218-1-trondmy@kernel.org> <20201102180658.6218-2-trondmy@kernel.org> <20201102180658.6218-3-trondmy@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Trond Myklebust Clean up handling of the case where there are no entries in the readdir reply. Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 604ebe015387..68acbde3f914 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -601,16 +601,12 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en struct xdr_stream stream; struct xdr_buf buf; struct page *scratch; - unsigned int count = 0; int status; scratch = alloc_page(GFP_KERNEL); if (scratch == NULL) return -ENOMEM; - if (buflen == 0) - goto out_nopages; - xdr_init_decode_pages(&stream, &buf, xdr_pages, buflen); xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE); @@ -619,27 +615,27 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en entry->label->len = NFS4_MAXLABELLEN; status = xdr_decode(desc, entry, &stream); - if (status != 0) { - if (status == -EAGAIN) - status = 0; + if (status != 0) break; - } - - count++; if (desc->plus) nfs_prime_dcache(file_dentry(desc->file), entry, desc->dir_verifier); status = nfs_readdir_add_to_array(entry, page); - if (status != 0) - break; - } while (!entry->eof); + } while (!status && !entry->eof); -out_nopages: - if (count == 0 || (status == -EBADCOOKIE && entry->eof != 0)) { - nfs_readdir_page_set_eof(page); + switch (status) { + case -EBADCOOKIE: + if (entry->eof) { + nfs_readdir_page_set_eof(page); + status = 0; + } + break; + case -ENOSPC: + case -EAGAIN: status = 0; + break; } put_page(scratch); @@ -714,14 +710,15 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, if (status < 0) break; + pglen = status; - status = nfs_readdir_page_filler(desc, &entry, pages, page, pglen); - if (status < 0) { - if (status == -ENOSPC) - status = 0; + if (pglen == 0) { + nfs_readdir_page_set_eof(page); break; } - } while (!nfs_readdir_array_is_full(array)); + + status = nfs_readdir_page_filler(desc, &entry, pages, page, pglen); + } while (!status && !nfs_readdir_array_is_full(array)); nfs_readdir_free_pages(pages, array_size); out_release_array: From patchwork Mon Nov 2 18:06:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Trond Myklebust X-Patchwork-Id: 11874843 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 25E3F92C for ; Mon, 2 Nov 2020 18:17:25 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 09EBA22226 for ; Mon, 2 Nov 2020 18:17:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604341045; bh=MX9gUOTiRzTC7Q1Br1xS9KHS6tTZWrUZdvjwOWS+MtA=; h=From:To:Subject:Date:In-Reply-To:References:List-ID:From; b=Wc61e9HSs+faIB2Q9K7D6tO6fGBcekD9uRYLcPJKzfW9d8hDbjaY2OcTwzy8W+YjM q/NNbVCx+1FTIE38I90ZXl9UEeHsPB2WAPcnjeoOLWqWM29/s7V1/nvFZTmk9HxcBw Ktx+toSQnQRiNEHMSp4kjS8atUwEhcsPhPIsiIzc= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725927AbgKBSRY (ORCPT ); Mon, 2 Nov 2020 13:17:24 -0500 Received: from mail.kernel.org ([198.145.29.99]:40862 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726236AbgKBSRX (ORCPT ); Mon, 2 Nov 2020 13:17:23 -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 25DD720786 for ; Mon, 2 Nov 2020 18:17:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604341042; bh=MX9gUOTiRzTC7Q1Br1xS9KHS6tTZWrUZdvjwOWS+MtA=; h=From:To:Subject:Date:In-Reply-To:References:From; b=chJ7gxPjTawpPEZHj7YdQ2KlPH0YujDIpZtyutetz88LuKmdcs7ZX8+k8luMy0aCV ktWkZA8CUuukiu1hk/O2FetWUrlWYPpWCD+krguaa9v8TlKJd9opV3/9M2pwRj3I0v CBKjhOw6AJ1zXVvQfBUzKagUsS0Oa4/mmRNn+OsM= From: trondmy@kernel.org To: linux-nfs@vger.kernel.org Subject: [PATCH 04/12] NFS: Clean up directory array handling Date: Mon, 2 Nov 2020 13:06:50 -0500 Message-Id: <20201102180658.6218-5-trondmy@kernel.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201102180658.6218-4-trondmy@kernel.org> References: <20201102180658.6218-1-trondmy@kernel.org> <20201102180658.6218-2-trondmy@kernel.org> <20201102180658.6218-3-trondmy@kernel.org> <20201102180658.6218-4-trondmy@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Trond Myklebust Refactor to use pagecache_get_page() so that we can fill the page in multiple stages. Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 134 ++++++++++++++++++++++++++++----------------------- 1 file changed, 73 insertions(+), 61 deletions(-) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 68acbde3f914..89cd8d5d9d3e 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -149,7 +149,7 @@ typedef struct nfs_readdir_descriptor { struct file *file; struct page *page; struct dir_context *ctx; - unsigned long page_index; + pgoff_t page_index; u64 dir_cookie; u64 last_cookie; u64 dup_cookie; @@ -166,13 +166,18 @@ typedef struct nfs_readdir_descriptor { bool eof; } nfs_readdir_descriptor_t; -static -void nfs_readdir_init_array(struct page *page) +static void nfs_readdir_array_init(struct nfs_cache_array *array) +{ + memset(array, 0, sizeof(struct nfs_cache_array)); +} + +static void nfs_readdir_page_init_array(struct page *page, u64 last_cookie) { struct nfs_cache_array *array; array = kmap_atomic(page); - memset(array, 0, sizeof(struct nfs_cache_array)); + nfs_readdir_array_init(array); + array->last_cookie = last_cookie; kunmap_atomic(array); } @@ -188,7 +193,7 @@ void nfs_readdir_clear_array(struct page *page) array = kmap_atomic(page); for (i = 0; i < array->size; i++) kfree(array->array[i].string.name); - array->size = 0; + nfs_readdir_array_init(array); kunmap_atomic(array); } @@ -268,6 +273,45 @@ int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page) return ret; } +static struct page *nfs_readdir_page_get_locked(struct address_space *mapping, + pgoff_t index, u64 last_cookie) +{ + struct page *page; + + page = pagecache_get_page(mapping, index, FGP_LOCK|FGP_WRITE|FGP_CREAT, + mapping_gfp_mask(mapping)); + if (page && !PageUptodate(page)) { + nfs_readdir_page_init_array(page, last_cookie); + if (invalidate_inode_pages2_range(mapping, index + 1, -1) < 0) + nfs_zap_mapping(mapping->host, mapping); + SetPageUptodate(page); + } + + return page; +} + +static u64 nfs_readdir_page_last_cookie(struct page *page) +{ + struct nfs_cache_array *array; + u64 ret; + + array = kmap_atomic(page); + ret = array->last_cookie; + kunmap_atomic(array); + return ret; +} + +static bool nfs_readdir_page_needs_filling(struct page *page) +{ + struct nfs_cache_array *array; + bool ret; + + array = kmap_atomic(page); + ret = !nfs_readdir_array_is_full(array); + kunmap_atomic(array); + return ret; +} + static void nfs_readdir_page_set_eof(struct page *page) { struct nfs_cache_array *array; @@ -682,10 +726,8 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, int status = -ENOMEM; unsigned int array_size = ARRAY_SIZE(pages); - nfs_readdir_init_array(page); - entry.prev_cookie = 0; - entry.cookie = desc->last_cookie; + entry.cookie = nfs_readdir_page_last_cookie(page); entry.eof = 0; entry.fh = nfs_alloc_fhandle(); entry.fattr = nfs_alloc_fattr(); @@ -730,48 +772,18 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, return status; } -/* - * Now we cache directories properly, by converting xdr information - * to an array that can be used for lookups later. This results in - * fewer cache pages, since we can store more information on each page. - * We only need to convert from xdr once so future lookups are much simpler - */ -static -int nfs_readdir_filler(void *data, struct page* page) -{ - nfs_readdir_descriptor_t *desc = data; - struct inode *inode = file_inode(desc->file); - int ret; - - ret = nfs_readdir_xdr_to_array(desc, page, inode); - if (ret < 0) - goto error; - SetPageUptodate(page); - - if (invalidate_inode_pages2_range(inode->i_mapping, page->index + 1, -1) < 0) { - /* Should never happen */ - nfs_zap_mapping(inode, inode->i_mapping); - } - unlock_page(page); - return 0; - error: - nfs_readdir_clear_array(page); - unlock_page(page); - return ret; -} - -static -void cache_page_release(nfs_readdir_descriptor_t *desc) +static void nfs_readdir_page_put(struct nfs_readdir_descriptor *desc) { put_page(desc->page); desc->page = NULL; } -static -struct page *get_cache_page(nfs_readdir_descriptor_t *desc) +static struct page * +nfs_readdir_page_get_cached(struct nfs_readdir_descriptor *desc) { - return read_cache_page(desc->file->f_mapping, desc->page_index, - nfs_readdir_filler, desc); + return nfs_readdir_page_get_locked(desc->file->f_mapping, + desc->page_index, + desc->last_cookie); } /* @@ -785,23 +797,22 @@ int find_and_lock_cache_page(nfs_readdir_descriptor_t *desc) struct nfs_inode *nfsi = NFS_I(inode); int res; - desc->page = get_cache_page(desc); - if (IS_ERR(desc->page)) - return PTR_ERR(desc->page); - res = lock_page_killable(desc->page); - if (res != 0) - goto error; - res = -EAGAIN; - if (desc->page->mapping != NULL) { - res = nfs_readdir_search_array(desc); - if (res == 0) { - nfsi->page_index = desc->page_index; - return 0; - } + desc->page = nfs_readdir_page_get_cached(desc); + if (!desc->page) + return -ENOMEM; + if (nfs_readdir_page_needs_filling(desc->page)) { + res = nfs_readdir_xdr_to_array(desc, desc->page, inode); + if (res < 0) + goto error; + } + res = nfs_readdir_search_array(desc); + if (res == 0) { + nfsi->page_index = desc->page_index; + return 0; } - unlock_page(desc->page); error: - cache_page_release(desc); + unlock_page(desc->page); + nfs_readdir_page_put(desc); return res; } @@ -896,6 +907,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc) desc->page = page; desc->duped = 0; + nfs_readdir_page_init_array(page, desc->dir_cookie); status = nfs_readdir_xdr_to_array(desc, page, inode); if (status < 0) goto out_release; @@ -904,7 +916,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc) out_release: nfs_readdir_clear_array(desc->page); - cache_page_release(desc); + nfs_readdir_page_put(desc); out: dfprintk(DIRCACHE, "NFS: %s: returns %d\n", __func__, status); @@ -977,7 +989,7 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) res = nfs_do_filldir(desc); unlock_page(desc->page); - cache_page_release(desc); + nfs_readdir_page_put(desc); if (res < 0) break; } while (!desc->eof); From patchwork Mon Nov 2 18:06:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Trond Myklebust X-Patchwork-Id: 11874845 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D3D6D921 for ; Mon, 2 Nov 2020 18:17:25 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B260622226 for ; Mon, 2 Nov 2020 18:17:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604341045; bh=cUO8uLwT0PgEK39O+jWLvCP2qtmoUacb+JkObsCCKIM=; h=From:To:Subject:Date:In-Reply-To:References:List-ID:From; b=HP7fg83GdqQ/CxXoEZYQ3EzS0M3Cb5pGgNy0BnMwOtkazmuyIJRvab+qoyFyDBLY/ UE40t1dbkibg7P6MeE1RByI2ASRY6dCAMLgBpNewDQiyUKd0AFhhPCpDO5bixD2JYp oiWGKTzwidYQQfBSx9A5J0PiVD4oWByh7vdJPp68= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726236AbgKBSRY (ORCPT ); Mon, 2 Nov 2020 13:17:24 -0500 Received: from mail.kernel.org ([198.145.29.99]:40892 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726114AbgKBSRX (ORCPT ); Mon, 2 Nov 2020 13:17:23 -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 BB3F920731 for ; Mon, 2 Nov 2020 18:17:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604341043; bh=cUO8uLwT0PgEK39O+jWLvCP2qtmoUacb+JkObsCCKIM=; h=From:To:Subject:Date:In-Reply-To:References:From; b=tXkkDYSNsvLwOA0NXieyChd7mUEQACTz2wEZq/cjmDOvAY6f3bs485s8JdXFgWhrM weBnzgw9Wlo0gH7uKvkkNsgpP3wz7HvB7XCUnyvPrHXhUIWVDkM+I1NEjSqVqHCHUn +MBuKLS6C/zCuHz1roMIVgMWq9fa9HiJ08rj6N6g= From: trondmy@kernel.org To: linux-nfs@vger.kernel.org Subject: [PATCH 05/12] NFS: Don't discard readdir results Date: Mon, 2 Nov 2020 13:06:51 -0500 Message-Id: <20201102180658.6218-6-trondmy@kernel.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201102180658.6218-5-trondmy@kernel.org> References: <20201102180658.6218-1-trondmy@kernel.org> <20201102180658.6218-2-trondmy@kernel.org> <20201102180658.6218-3-trondmy@kernel.org> <20201102180658.6218-4-trondmy@kernel.org> <20201102180658.6218-5-trondmy@kernel.org> MIME-Version: 1.0 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 | 45 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 89cd8d5d9d3e..6f84038735a1 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -321,6 +321,21 @@ static void nfs_readdir_page_set_eof(struct page *page) kunmap_atomic(array); } +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; + unlock_page(page); + put_page(page); + } + return NULL; +} + static inline int is_32bit_api(void) { @@ -638,13 +653,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 +684,21 @@ 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) { + unlock_page(page); + put_page(page); + } + page = new; + status = nfs_readdir_add_to_array(entry, page); } while (!status && !entry->eof); switch (status) { @@ -682,6 +714,11 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en break; } + if (page != fillme) { + unlock_page(page); + put_page(page); + } + put_page(scratch); return status; } From patchwork Mon Nov 2 18:06:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Trond Myklebust X-Patchwork-Id: 11874847 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C413292C for ; Mon, 2 Nov 2020 18:17:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9C57E20786 for ; Mon, 2 Nov 2020 18:17:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604341047; bh=kerKzjIvafmw3bS9/iH3h6ChBScraTFc//G5vJ1W18M=; h=From:To:Subject:Date:In-Reply-To:References:List-ID:From; b=uVPMeTZSLphxO7/5yLbqnU1Lu+qiyp0BB6uHxemANjYZ/NLQMn521Zv8DcDCXjX00 /4RGsECGqZD8+q3V/qaLMCQ8EPA2x1sbZP6d+IqN+dE/SdA9NmERAxacoOTSdNwZzT T7vNu+2Akz8iLpHWhr0j/7mAbwjF4JuivCblNCKY= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726114AbgKBSRZ (ORCPT ); Mon, 2 Nov 2020 13:17:25 -0500 Received: from mail.kernel.org ([198.145.29.99]:40900 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725797AbgKBSRY (ORCPT ); Mon, 2 Nov 2020 13:17:24 -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 500012222B for ; Mon, 2 Nov 2020 18:17:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604341043; bh=kerKzjIvafmw3bS9/iH3h6ChBScraTFc//G5vJ1W18M=; h=From:To:Subject:Date:In-Reply-To:References:From; b=iiPG8N5Z8QYE3TX6cyf3nCC1BV7ipjA5hit9rj1laXWnictZhY/BWOz1hnlJrGSUH IX20XNSICTi7xjOqKlqrxmarZJBKqbuc6J66ovodOsjYDqF/IYj4kJ/Tq0MCn6d2Kd hWQCMlP2GIwPVOIslpgGEB5AUZDnheF2HZHDZBuE= From: trondmy@kernel.org To: linux-nfs@vger.kernel.org Subject: [PATCH 06/12] NFS: Remove unnecessary kmap in nfs_readdir_xdr_to_array() Date: Mon, 2 Nov 2020 13:06:52 -0500 Message-Id: <20201102180658.6218-7-trondmy@kernel.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201102180658.6218-6-trondmy@kernel.org> References: <20201102180658.6218-1-trondmy@kernel.org> <20201102180658.6218-2-trondmy@kernel.org> <20201102180658.6218-3-trondmy@kernel.org> <20201102180658.6218-4-trondmy@kernel.org> <20201102180658.6218-5-trondmy@kernel.org> <20201102180658.6218-6-trondmy@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Trond Myklebust The kmapped pointer is only used once per loop to check if we need to exit. Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 6f84038735a1..560a9c1553e5 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -759,7 +759,6 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, struct page *pages[NFS_MAX_READDIR_PAGES]; struct nfs_entry entry; struct file *file = desc->file; - struct nfs_cache_array *array; int status = -ENOMEM; unsigned int array_size = ARRAY_SIZE(pages); @@ -778,11 +777,9 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, goto out; } - array = kmap(page); - status = nfs_readdir_alloc_pages(pages, array_size); if (status < 0) - goto out_release_array; + goto out_release_label; do { unsigned int pglen; status = nfs_readdir_xdr_filler(pages, desc, &entry, file, inode); @@ -797,11 +794,10 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, } status = nfs_readdir_page_filler(desc, &entry, pages, page, pglen); - } while (!status && !nfs_readdir_array_is_full(array)); + } while (!status && nfs_readdir_page_needs_filling(page)); nfs_readdir_free_pages(pages, array_size); -out_release_array: - kunmap(page); +out_release_label: nfs4_label_free(entry.label); out: nfs_free_fattr(entry.fattr); From patchwork Mon Nov 2 18:06:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Trond Myklebust X-Patchwork-Id: 11874857 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id AF27915E6 for ; Mon, 2 Nov 2020 18:17:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 90C6B20786 for ; Mon, 2 Nov 2020 18:17:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604341050; bh=uN1IRuZs3frQ5fasnLTY20rW+4Tdu5UaBopqQniHe7Y=; h=From:To:Subject:Date:In-Reply-To:References:List-ID:From; b=tUvTEoeq9MOIIBd2FKjwlXANs+7uvFIwwmB3FcEU6za6R3jL3FpY9yvNLY9QJS60z q98pfjUpNg3LcEOnKVf9I9Ii1LaowsWgJ157f1zuvxfwM62F1A4HouViEkc/ij7c5w Qvb0LHwK3l8Nntorx3CWlE7nEbxcB0SID8++S9TQ= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725797AbgKBSRZ (ORCPT ); Mon, 2 Nov 2020 13:17:25 -0500 Received: from mail.kernel.org ([198.145.29.99]:40892 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726283AbgKBSRY (ORCPT ); Mon, 2 Nov 2020 13:17:24 -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 C4D6E22226 for ; Mon, 2 Nov 2020 18:17:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604341044; bh=uN1IRuZs3frQ5fasnLTY20rW+4Tdu5UaBopqQniHe7Y=; h=From:To:Subject:Date:In-Reply-To:References:From; b=wzDoK/49PGnE8x8C0zgbGlnenBOSvta1Gl1CzZJLSk5XAdYZ+riijDZs3lXzox+5Y kJGEwoy77WOeVZ8U6gr+1kNmtMbq567mSWRGiH54nce0RRt2QcyOtam/fJWgdzCjTL Je+ie+Z39DxpOe5jvZ5yhP9VVx9+bDRPP4zqrCow= From: trondmy@kernel.org To: linux-nfs@vger.kernel.org Subject: [PATCH 07/12] NFS: Replace kmap() with kmap_atomic() in nfs_readdir_search_array() Date: Mon, 2 Nov 2020 13:06:53 -0500 Message-Id: <20201102180658.6218-8-trondmy@kernel.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201102180658.6218-7-trondmy@kernel.org> References: <20201102180658.6218-1-trondmy@kernel.org> <20201102180658.6218-2-trondmy@kernel.org> <20201102180658.6218-3-trondmy@kernel.org> <20201102180658.6218-4-trondmy@kernel.org> <20201102180658.6218-5-trondmy@kernel.org> <20201102180658.6218-6-trondmy@kernel.org> <20201102180658.6218-7-trondmy@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Trond Myklebust Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 560a9c1553e5..a91f9ea87611 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -443,7 +443,7 @@ int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc) struct nfs_cache_array *array; int status; - array = kmap(desc->page); + array = kmap_atomic(desc->page); if (desc->dir_cookie == 0) status = nfs_readdir_search_for_pos(array, desc); @@ -455,7 +455,7 @@ int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc) desc->current_index += array->size; desc->page_index++; } - kunmap(desc->page); + kunmap_atomic(array); return status; } From patchwork Mon Nov 2 18:06:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Trond Myklebust X-Patchwork-Id: 11874849 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6573915E6 for ; Mon, 2 Nov 2020 18:17:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 437EC20786 for ; Mon, 2 Nov 2020 18:17:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604341048; bh=dhy8SWVBTv52epzoDjAtFn5LTxuP0LqdundAR6q1KbM=; h=From:To:Subject:Date:In-Reply-To:References:List-ID:From; b=JIel7pB6hlsTCCAZnXP0aZc9plv62pqMZnIc+TekkBH+xeXoF52TlKmnXYQKPSJFz BQFF5yvUvPk6NUo7BibbWFtlyR8LwVq9wfVviPLVyIPRuMdDjzLrDiW9RDzZAdD/WJ 543wpBYAXpWhEvRz2flt4752NjjjO7m483GnveDA= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726306AbgKBSRZ (ORCPT ); Mon, 2 Nov 2020 13:17:25 -0500 Received: from mail.kernel.org ([198.145.29.99]:40862 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726260AbgKBSRZ (ORCPT ); Mon, 2 Nov 2020 13:17:25 -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 6B7DD22265 for ; Mon, 2 Nov 2020 18:17:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604341044; bh=dhy8SWVBTv52epzoDjAtFn5LTxuP0LqdundAR6q1KbM=; h=From:To:Subject:Date:In-Reply-To:References:From; b=PYNHqYBSQ1m3aJ1EDVcpw1hMAHMd2GprPgHxOAkrKNXHttMQLXbh/zVTldCVoqthU tmkQjsuqPy38sO5ZKUtqZGag/qOGulQq2IyAzmn9tQyVyhNv+6std4kGPdr0vwX9tc dpDcGPtMZM5s22fQx0quzFMHYQVKq0QRRKD6cb1k= From: trondmy@kernel.org To: linux-nfs@vger.kernel.org Subject: [PATCH 08/12] NFS: Simplify struct nfs_cache_array_entry Date: Mon, 2 Nov 2020 13:06:54 -0500 Message-Id: <20201102180658.6218-9-trondmy@kernel.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201102180658.6218-8-trondmy@kernel.org> References: <20201102180658.6218-1-trondmy@kernel.org> <20201102180658.6218-2-trondmy@kernel.org> <20201102180658.6218-3-trondmy@kernel.org> <20201102180658.6218-4-trondmy@kernel.org> <20201102180658.6218-5-trondmy@kernel.org> <20201102180658.6218-6-trondmy@kernel.org> <20201102180658.6218-7-trondmy@kernel.org> <20201102180658.6218-8-trondmy@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Trond Myklebust We don't need to store a hash, so replace struct qstr with a simple const char pointer and length. Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 46 +++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index a91f9ea87611..c82f1bde4f13 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -133,7 +133,8 @@ nfs_closedir(struct inode *inode, struct file *filp) struct nfs_cache_array_entry { u64 cookie; u64 ino; - struct qstr string; + const char *name; + unsigned int name_len; unsigned char d_type; }; @@ -192,7 +193,7 @@ void nfs_readdir_clear_array(struct page *page) array = kmap_atomic(page); for (i = 0; i < array->size; i++) - kfree(array->array[i].string.name); + kfree(array->array[i].name); nfs_readdir_array_init(array); kunmap_atomic(array); } @@ -213,20 +214,17 @@ static bool nfs_readdir_array_is_full(struct nfs_cache_array *array) * when called by nfs_readdir_add_to_array, the strings will be freed in * nfs_clear_readdir_array() */ -static -int nfs_readdir_make_qstr(struct qstr *string, const char *name, unsigned int len) +static const char *nfs_readdir_copy_name(const char *name, unsigned int len) { - string->len = len; - string->name = kmemdup_nul(name, len, GFP_KERNEL); - if (string->name == NULL) - return -ENOMEM; + const char *ret = kmemdup_nul(name, len, GFP_KERNEL); + /* * Avoid a kmemleak false positive. The pointer to the name is stored * in a page cache page which kmemleak does not scan. */ - kmemleak_not_leak(string->name); - string->hash = full_name_hash(NULL, name, len); - return 0; + if (ret != NULL) + kmemleak_not_leak(ret); + return ret; } /* @@ -249,27 +247,34 @@ static int nfs_readdir_array_can_expand(struct nfs_cache_array *array) static int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page) { - struct nfs_cache_array *array = kmap(page); + struct nfs_cache_array *array; struct nfs_cache_array_entry *cache_entry; + const char *name; int ret; + name = nfs_readdir_copy_name(entry->name, entry->len); + if (!name) + return -ENOMEM; + + array = kmap_atomic(page); ret = nfs_readdir_array_can_expand(array); - if (ret) + if (ret) { + kfree(name); goto out; + } cache_entry = &array->array[array->size]; cache_entry->cookie = entry->prev_cookie; cache_entry->ino = entry->ino; cache_entry->d_type = entry->d_type; - ret = nfs_readdir_make_qstr(&cache_entry->string, entry->name, entry->len); - if (ret) - goto out; + cache_entry->name_len = entry->len; + cache_entry->name = name; array->last_cookie = entry->cookie; array->size++; if (entry->eof != 0) nfs_readdir_array_set_eof(array); out: - kunmap(page); + kunmap_atomic(array); return ret; } @@ -409,9 +414,8 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des if (printk_ratelimit()) { pr_notice("NFS: directory %pD2 contains a readdir loop." "Please contact your server vendor. " - "The file: %.*s has duplicate cookie %llu\n", - desc->file, array->array[i].string.len, - array->array[i].string.name, desc->dir_cookie); + "The file: %s has duplicate cookie %llu\n", + desc->file, array->array[i].name, desc->dir_cookie); } status = -ELOOP; goto out; @@ -882,7 +886,7 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc) struct nfs_cache_array_entry *ent; ent = &array->array[i]; - if (!dir_emit(desc->ctx, ent->string.name, ent->string.len, + if (!dir_emit(desc->ctx, ent->name, ent->name_len, nfs_compat_user_ino64(ent->ino), ent->d_type)) { desc->eof = true; break; From patchwork Mon Nov 2 18:06:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Trond Myklebust X-Patchwork-Id: 11874861 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id ECC5615E6 for ; Mon, 2 Nov 2020 18:17:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CD6A120786 for ; Mon, 2 Nov 2020 18:17:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604341051; bh=P+gKQ4MjV3jdvlWiXWP8qEdbKRV5Fl83U5wVoIuPAt0=; h=From:To:Subject:Date:In-Reply-To:References:List-ID:From; b=xy+8cgP6VXaxpMGq8FHrpeZJb28BOcVRiFPWr8E4Mym27YZHBRd1fLZX9Jwz2dPka 7jvCUCX47bR1xQ7gewLioqI66vDwxy9LzUxhg3zN/tPuLPshubsPav9bHMX0CLPVkm 0z5ZXiD6Ywdq3XCi1ZL19PzUSXFjjWApnhfzqfAo= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726337AbgKBSRa (ORCPT ); Mon, 2 Nov 2020 13:17:30 -0500 Received: from mail.kernel.org ([198.145.29.99]:40860 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726302AbgKBSR0 (ORCPT ); Mon, 2 Nov 2020 13:17:26 -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 E873120731 for ; Mon, 2 Nov 2020 18:17:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604341045; bh=P+gKQ4MjV3jdvlWiXWP8qEdbKRV5Fl83U5wVoIuPAt0=; h=From:To:Subject:Date:In-Reply-To:References:From; b=BzGYq66v9UpAv2Ig7v6Je0i5/6YNeXAwnvqiyd/vUlZgjar3X8LUwFtYB+Wussoeb mCJTnltii+rOpdH0gXJmIEy+Q4r9RhaHG6OW6b1/W+vUQF6yA0oyf7Jel47k9K9pld HM3/QxRBFqcAOmtIbURoFqnYCaXpcAgkWXrpHqBo= From: trondmy@kernel.org To: linux-nfs@vger.kernel.org Subject: [PATCH 09/12] NFS: Support larger readdir buffers Date: Mon, 2 Nov 2020 13:06:55 -0500 Message-Id: <20201102180658.6218-10-trondmy@kernel.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201102180658.6218-9-trondmy@kernel.org> References: <20201102180658.6218-1-trondmy@kernel.org> <20201102180658.6218-2-trondmy@kernel.org> <20201102180658.6218-3-trondmy@kernel.org> <20201102180658.6218-4-trondmy@kernel.org> <20201102180658.6218-5-trondmy@kernel.org> <20201102180658.6218-6-trondmy@kernel.org> <20201102180658.6218-7-trondmy@kernel.org> <20201102180658.6218-8-trondmy@kernel.org> <20201102180658.6218-9-trondmy@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Trond Myklebust Support readdir buffers of up to 1MB in size so that we can read large directories using few RPC calls. Signed-off-by: Trond Myklebust --- fs/nfs/client.c | 4 ++-- fs/nfs/dir.c | 33 +++++++++++++++++++-------------- fs/nfs/internal.h | 6 ------ 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 4b8cc93913f7..f6454ba53d05 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -781,8 +781,8 @@ static void nfs_server_set_fsinfo(struct nfs_server *server, server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL); server->dtsize = nfs_block_size(fsinfo->dtpref, NULL); - if (server->dtsize > PAGE_SIZE * NFS_MAX_READDIR_PAGES) - server->dtsize = PAGE_SIZE * NFS_MAX_READDIR_PAGES; + if (server->dtsize > NFS_MAX_FILE_IO_SIZE) + server->dtsize = NFS_MAX_FILE_IO_SIZE; if (server->dtsize > server->rsize) server->dtsize = server->rsize; diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index c82f1bde4f13..272b856147af 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -727,44 +727,47 @@ static int nfs_readdir_page_filler(struct nfs_readdir_descriptor *desc, return status; } -static -void nfs_readdir_free_pages(struct page **pages, unsigned int npages) +static void nfs_readdir_free_pages(struct page **pages, size_t npages) { - unsigned int i; - for (i = 0; i < npages; i++) - put_page(pages[i]); + while (npages--) + put_page(pages[npages]); + kfree(pages); } /* * nfs_readdir_alloc_pages() will allocate pages that must be freed with a call * to nfs_readdir_free_pages() */ -static -int nfs_readdir_alloc_pages(struct page **pages, unsigned int npages) +static struct page **nfs_readdir_alloc_pages(size_t npages) { - unsigned int i; + struct page **pages; + size_t i; + pages = kmalloc_array(npages, sizeof(*pages), GFP_KERNEL); + if (!pages) + return NULL; for (i = 0; i < npages; i++) { struct page *page = alloc_page(GFP_KERNEL); if (page == NULL) goto out_freepages; pages[i] = page; } - return 0; + return pages; out_freepages: nfs_readdir_free_pages(pages, i); - return -ENOMEM; + return NULL; } static int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, struct inode *inode) { - struct page *pages[NFS_MAX_READDIR_PAGES]; + struct page **pages; struct nfs_entry entry; struct file *file = desc->file; + size_t array_size; + size_t dtsize = NFS_SERVER(inode)->dtsize; int status = -ENOMEM; - unsigned int array_size = ARRAY_SIZE(pages); entry.prev_cookie = 0; entry.cookie = nfs_readdir_page_last_cookie(page); @@ -781,9 +784,11 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, goto out; } - status = nfs_readdir_alloc_pages(pages, array_size); - if (status < 0) + array_size = (dtsize + PAGE_SIZE - 1) >> PAGE_SHIFT; + pages = nfs_readdir_alloc_pages(array_size); + if (!pages) goto out_release_label; + do { unsigned int pglen; status = nfs_readdir_xdr_filler(pages, desc, &entry, file, inode); diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 6673a77884d9..b840d0a91c9d 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -56,12 +56,6 @@ static inline bool nfs_lookup_is_soft_revalidate(const struct dentry *dentry) #define NFS_UNSPEC_RETRANS (UINT_MAX) #define NFS_UNSPEC_TIMEO (UINT_MAX) -/* - * Maximum number of pages that readdir can use for creating - * a vmapped array of pages. - */ -#define NFS_MAX_READDIR_PAGES 8 - struct nfs_client_initdata { unsigned long init_flags; const char *hostname; /* Hostname of the server */ From patchwork Mon Nov 2 18:06:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Trond Myklebust X-Patchwork-Id: 11874853 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3B38115E6 for ; Mon, 2 Nov 2020 18:17:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1CB0B22226 for ; Mon, 2 Nov 2020 18:17:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604341049; bh=/NZbFtpjQ9LNrTj2o/4jqBMF+yFXx0mmLcSITwPNazc=; h=From:To:Subject:Date:In-Reply-To:References:List-ID:From; b=qFJuKRsszmTsAsZtK4QeMO8uf9RTHB5ncNrr0upeeo2INKhqxzMK/SY6PcDmP1fc5 C/v+ZhmA/OVxkkKNZTmqm9kMwbpT98dxmwGTnkRfLELdiSkK9WpT6kv39E+bGbqd88 W67jlL2NIdl8WESIZFK7z/jCABBMbeNsPMq/Eh3E= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726171AbgKBSR1 (ORCPT ); Mon, 2 Nov 2020 13:17:27 -0500 Received: from mail.kernel.org ([198.145.29.99]:40900 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726283AbgKBSR0 (ORCPT ); Mon, 2 Nov 2020 13:17:26 -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 64DB320786 for ; Mon, 2 Nov 2020 18:17:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604341045; bh=/NZbFtpjQ9LNrTj2o/4jqBMF+yFXx0mmLcSITwPNazc=; h=From:To:Subject:Date:In-Reply-To:References:From; b=Rc5WLURzTBSYUxbKS4aG8yfE2LJGozi/c7y498No8dl1Vg+xWyFuR74xpYdOVsLjf Y+BInsLwi3swHrwb6tydPivovXQlYRBGhNEpEdxyE/MdyTREQ05+Yi8uea+UvFHEyF nnJ/UIo5ne0EtxYariaA6KLDxOJx6W2UtKyshVn8= From: trondmy@kernel.org To: linux-nfs@vger.kernel.org Subject: [PATCH 10/12] NFS: More readdir cleanups Date: Mon, 2 Nov 2020 13:06:56 -0500 Message-Id: <20201102180658.6218-11-trondmy@kernel.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201102180658.6218-10-trondmy@kernel.org> References: <20201102180658.6218-1-trondmy@kernel.org> <20201102180658.6218-2-trondmy@kernel.org> <20201102180658.6218-3-trondmy@kernel.org> <20201102180658.6218-4-trondmy@kernel.org> <20201102180658.6218-5-trondmy@kernel.org> <20201102180658.6218-6-trondmy@kernel.org> <20201102180658.6218-7-trondmy@kernel.org> <20201102180658.6218-8-trondmy@kernel.org> <20201102180658.6218-9-trondmy@kernel.org> <20201102180658.6218-10-trondmy@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Trond Myklebust Remove the redundant caching of the credential in struct nfs_open_dir_context. Pass the buffer size as an argument to nfs_readdir_xdr_filler(). Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 25 +++++++++++-------------- include/linux/nfs_fs.h | 1 - 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 272b856147af..564e737ef93e 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -68,7 +68,7 @@ const struct address_space_operations nfs_dir_aops = { .freepage = nfs_readdir_clear_array, }; -static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct inode *dir, const struct cred *cred) +static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct inode *dir) { struct nfs_inode *nfsi = NFS_I(dir); struct nfs_open_dir_context *ctx; @@ -78,7 +78,6 @@ static struct nfs_open_dir_context *alloc_nfs_open_dir_context(struct inode *dir ctx->attr_gencount = nfsi->attr_gencount; ctx->dir_cookie = 0; ctx->dup_cookie = 0; - ctx->cred = get_cred(cred); spin_lock(&dir->i_lock); if (list_empty(&nfsi->open_files) && (nfsi->cache_validity & NFS_INO_DATA_INVAL_DEFER)) @@ -96,7 +95,6 @@ static void put_nfs_open_dir_context(struct inode *dir, struct nfs_open_dir_cont spin_lock(&dir->i_lock); list_del(&ctx->list); spin_unlock(&dir->i_lock); - put_cred(ctx->cred); kfree(ctx); } @@ -113,7 +111,7 @@ nfs_opendir(struct inode *inode, struct file *filp) nfs_inc_stats(inode, NFSIOS_VFSOPEN); - ctx = alloc_nfs_open_dir_context(inode, current_cred()); + ctx = alloc_nfs_open_dir_context(inode); if (IS_ERR(ctx)) { res = PTR_ERR(ctx); goto out; @@ -464,12 +462,12 @@ int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc) } /* Fill a page with xdr information before transferring to the cache page */ -static -int nfs_readdir_xdr_filler(struct page **pages, nfs_readdir_descriptor_t *desc, - struct nfs_entry *entry, struct file *file, struct inode *inode) +static int nfs_readdir_xdr_filler(struct nfs_readdir_descriptor *desc, + u64 cookie, struct page **pages, + size_t bufsize) { - struct nfs_open_dir_context *ctx = file->private_data; - const struct cred *cred = ctx->cred; + struct file *file = desc->file; + struct inode *inode = file_inode(file); unsigned long timestamp, gencount; int error; @@ -477,8 +475,8 @@ int nfs_readdir_xdr_filler(struct page **pages, nfs_readdir_descriptor_t *desc, timestamp = jiffies; gencount = nfs_inc_attr_generation_counter(); desc->dir_verifier = nfs_save_change_attribute(inode); - error = NFS_PROTO(inode)->readdir(file_dentry(file), cred, entry->cookie, pages, - NFS_SERVER(inode)->dtsize, desc->plus); + error = NFS_PROTO(inode)->readdir(file_dentry(file), file->f_cred, + cookie, pages, bufsize, desc->plus); if (error < 0) { /* We requested READDIRPLUS, but the server doesn't grok it */ if (error == -ENOTSUPP && desc->plus) { @@ -764,7 +762,6 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, { struct page **pages; struct nfs_entry entry; - struct file *file = desc->file; size_t array_size; size_t dtsize = NFS_SERVER(inode)->dtsize; int status = -ENOMEM; @@ -791,8 +788,8 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, do { unsigned int pglen; - status = nfs_readdir_xdr_filler(pages, desc, &entry, file, inode); - + status = nfs_readdir_xdr_filler(desc, entry.cookie, + pages, dtsize); if (status < 0) break; diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index a2c6455ea3fa..dd6b463dda80 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -88,7 +88,6 @@ struct nfs_open_context { struct nfs_open_dir_context { struct list_head list; - const struct cred *cred; unsigned long attr_gencount; __u64 dir_cookie; __u64 dup_cookie; From patchwork Mon Nov 2 18:06:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Trond Myklebust X-Patchwork-Id: 11874859 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 55DCB921 for ; Mon, 2 Nov 2020 18:17:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 35D9420731 for ; Mon, 2 Nov 2020 18:17:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604341051; bh=/yoJMgJe/NfX5jVwRvuhIyPkCnQJFVnd/8JyXo6l/54=; h=From:To:Subject:Date:In-Reply-To:References:List-ID:From; b=SFU/QRiA8VhsyMF520JgM6DBL2CBg+Y9ibqkWZvbf3qLoRK4HmNURyiVGO86zXofo Eqox7RAGGKp2BqFXzrPdvVHTkc8hH1GTH8EI7nA2o0ZCjjdFc1ZNMkAbu8n9sLmJl4 I3DsCLic4DGwhn5pyMBr+bBs6ES4eHsewCpRuYxQ= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726324AbgKBSRa (ORCPT ); Mon, 2 Nov 2020 13:17:30 -0500 Received: from mail.kernel.org ([198.145.29.99]:40892 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726338AbgKBSR0 (ORCPT ); Mon, 2 Nov 2020 13:17:26 -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 DAFF722226 for ; Mon, 2 Nov 2020 18:17:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604341046; bh=/yoJMgJe/NfX5jVwRvuhIyPkCnQJFVnd/8JyXo6l/54=; h=From:To:Subject:Date:In-Reply-To:References:From; b=YHt/+mBfUxw5KKh1YXKOlCWZ4keitrjIm+weXlrZO2HR5G3ax38MaKj4hGqIE1cix 0hYFzzFK2JAx0Q4SvYGG1Kqnolwutn0L+SHNFsayFDBCnr7fbNe8OqiXiuIMmonHo+ mF/lAwBK5VioLOdMi8/NiNaWXUeQg0ob38Lobp94= From: trondmy@kernel.org To: linux-nfs@vger.kernel.org Subject: [PATCH 11/12] NFS: nfs_do_filldir() does not return a value Date: Mon, 2 Nov 2020 13:06:57 -0500 Message-Id: <20201102180658.6218-12-trondmy@kernel.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201102180658.6218-11-trondmy@kernel.org> References: <20201102180658.6218-1-trondmy@kernel.org> <20201102180658.6218-2-trondmy@kernel.org> <20201102180658.6218-3-trondmy@kernel.org> <20201102180658.6218-4-trondmy@kernel.org> <20201102180658.6218-5-trondmy@kernel.org> <20201102180658.6218-6-trondmy@kernel.org> <20201102180658.6218-7-trondmy@kernel.org> <20201102180658.6218-8-trondmy@kernel.org> <20201102180658.6218-9-trondmy@kernel.org> <20201102180658.6218-10-trondmy@kernel.org> <20201102180658.6218-11-trondmy@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Trond Myklebust Clean up nfs_do_filldir(). Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 564e737ef93e..a2cebd365948 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -875,13 +875,11 @@ int readdir_search_pagecache(nfs_readdir_descriptor_t *desc) /* * Once we've found the start of the dirent within a page: fill 'er up... */ -static -int nfs_do_filldir(nfs_readdir_descriptor_t *desc) +static void nfs_do_filldir(struct nfs_readdir_descriptor *desc) { struct file *file = desc->file; - int i = 0; - int res = 0; - struct nfs_cache_array *array = NULL; + struct nfs_cache_array *array; + unsigned int i = 0; array = kmap(desc->page); for (i = desc->cache_entry_index; i < array->size; i++) { @@ -908,9 +906,8 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc) desc->eof = true; kunmap(desc->page); - dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n", - (unsigned long long)desc->dir_cookie, res); - return res; + dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %llu\n", + (unsigned long long)desc->dir_cookie); } /* @@ -951,7 +948,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc) if (status < 0) goto out_release; - status = nfs_do_filldir(desc); + nfs_do_filldir(desc); out_release: nfs_readdir_clear_array(desc->page); @@ -1026,11 +1023,9 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) if (res < 0) break; - res = nfs_do_filldir(desc); + nfs_do_filldir(desc); unlock_page(desc->page); nfs_readdir_page_put(desc); - if (res < 0) - break; } while (!desc->eof); spin_lock(&file->f_lock); @@ -1041,8 +1036,6 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) spin_unlock(&file->f_lock); out: - if (res > 0) - res = 0; dfprintk(FILE, "NFS: readdir(%pD2) returns %d\n", file, res); return res; } From patchwork Mon Nov 2 18:06:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Trond Myklebust X-Patchwork-Id: 11874855 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3A89292C for ; Mon, 2 Nov 2020 18:17:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1DF7420786 for ; Mon, 2 Nov 2020 18:17:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604341050; bh=XVXBt4Tj7nqalGynpZA6CSK0J9bdcHzViYb2QRauuk4=; h=From:To:Subject:Date:In-Reply-To:References:List-ID:From; b=jh8u0r8fn4cfupo8azN8XexKuYoMFlPn9e6AxXQPZO15CIDJWss13PnxThwmWK1C7 eGlAFQVAUnsfwTqfaCGHzEppP0tagQSrwhbpZekRDQiCDGyAJz2a5LK0Lz7RlxOBB+ G7Mp0PswRViQgUjXQHBvWmHUCN78akrm9ZBmAdCA= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726283AbgKBSR2 (ORCPT ); Mon, 2 Nov 2020 13:17:28 -0500 Received: from mail.kernel.org ([198.145.29.99]:40862 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726342AbgKBSR1 (ORCPT ); Mon, 2 Nov 2020 13:17:27 -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 5FE402222B for ; Mon, 2 Nov 2020 18:17:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1604341046; bh=XVXBt4Tj7nqalGynpZA6CSK0J9bdcHzViYb2QRauuk4=; h=From:To:Subject:Date:In-Reply-To:References:From; b=k6rLGh6GwPmS8ff+9KocyWM4cmzA+7QX3RzZc6qAO8zRP9XueXGGkDwsIckEakatQ 3qfc9z669Y1Fls5fZCrlPU7GZwpRCQh2D++oxAISkDucrGzJrnw1AHG1ZR2Ko+ZPNd X5MzSWQ4uoBPdJhaQgkFRvw5p0P0Tj3nhgyt3b64= From: trondmy@kernel.org To: linux-nfs@vger.kernel.org Subject: [PATCH 12/12] NFS: Reduce readdir stack usage Date: Mon, 2 Nov 2020 13:06:58 -0500 Message-Id: <20201102180658.6218-13-trondmy@kernel.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201102180658.6218-12-trondmy@kernel.org> References: <20201102180658.6218-1-trondmy@kernel.org> <20201102180658.6218-2-trondmy@kernel.org> <20201102180658.6218-3-trondmy@kernel.org> <20201102180658.6218-4-trondmy@kernel.org> <20201102180658.6218-5-trondmy@kernel.org> <20201102180658.6218-6-trondmy@kernel.org> <20201102180658.6218-7-trondmy@kernel.org> <20201102180658.6218-8-trondmy@kernel.org> <20201102180658.6218-9-trondmy@kernel.org> <20201102180658.6218-10-trondmy@kernel.org> <20201102180658.6218-11-trondmy@kernel.org> <20201102180658.6218-12-trondmy@kernel.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org From: Trond Myklebust The descriptor and the struct nfs_entry are both large structures, so don't allocate them from the stack. Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 88 +++++++++++++++++++++++++++------------------------- 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index a2cebd365948..966e8fc6c9b7 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -144,7 +144,7 @@ struct nfs_cache_array { struct nfs_cache_array_entry array[]; }; -typedef struct nfs_readdir_descriptor { +struct nfs_readdir_descriptor { struct file *file; struct page *page; struct dir_context *ctx; @@ -163,7 +163,7 @@ typedef struct nfs_readdir_descriptor { signed char duped; bool plus; bool eof; -} nfs_readdir_descriptor_t; +}; static void nfs_readdir_array_init(struct nfs_cache_array *array) { @@ -358,8 +358,8 @@ bool nfs_readdir_use_cookie(const struct file *filp) return true; } -static -int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc) +static int nfs_readdir_search_for_pos(struct nfs_cache_array *array, + struct nfs_readdir_descriptor *desc) { loff_t diff = desc->ctx->pos - desc->current_index; unsigned int index; @@ -390,8 +390,8 @@ nfs_readdir_inode_mapping_valid(struct nfs_inode *nfsi) return !test_bit(NFS_INO_INVALIDATING, &nfsi->flags); } -static -int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc) +static int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, + struct nfs_readdir_descriptor *desc) { int i; loff_t new_pos; @@ -439,8 +439,7 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des return status; } -static -int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc) +static int nfs_readdir_search_array(struct nfs_readdir_descriptor *desc) { struct nfs_cache_array *array; int status; @@ -493,7 +492,7 @@ static int nfs_readdir_xdr_filler(struct nfs_readdir_descriptor *desc, return error; } -static int xdr_decode(nfs_readdir_descriptor_t *desc, +static int xdr_decode(struct nfs_readdir_descriptor *desc, struct nfs_entry *entry, struct xdr_stream *xdr) { struct inode *inode = file_inode(desc->file); @@ -757,27 +756,28 @@ static struct page **nfs_readdir_alloc_pages(size_t npages) return NULL; } -static -int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, struct inode *inode) +static int nfs_readdir_xdr_to_array(struct nfs_readdir_descriptor *desc, + struct page *page, struct inode *inode) { struct page **pages; - struct nfs_entry entry; + struct nfs_entry *entry; size_t array_size; size_t dtsize = NFS_SERVER(inode)->dtsize; int status = -ENOMEM; - entry.prev_cookie = 0; - entry.cookie = nfs_readdir_page_last_cookie(page); - entry.eof = 0; - entry.fh = nfs_alloc_fhandle(); - entry.fattr = nfs_alloc_fattr(); - entry.server = NFS_SERVER(inode); - if (entry.fh == NULL || entry.fattr == NULL) + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; + entry->cookie = nfs_readdir_page_last_cookie(page); + entry->fh = nfs_alloc_fhandle(); + entry->fattr = nfs_alloc_fattr(); + entry->server = NFS_SERVER(inode); + if (entry->fh == NULL || entry->fattr == NULL) goto out; - entry.label = nfs4_label_alloc(NFS_SERVER(inode), GFP_NOWAIT); - if (IS_ERR(entry.label)) { - status = PTR_ERR(entry.label); + entry->label = nfs4_label_alloc(NFS_SERVER(inode), GFP_NOWAIT); + if (IS_ERR(entry->label)) { + status = PTR_ERR(entry->label); goto out; } @@ -788,7 +788,7 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, do { unsigned int pglen; - status = nfs_readdir_xdr_filler(desc, entry.cookie, + status = nfs_readdir_xdr_filler(desc, entry->cookie, pages, dtsize); if (status < 0) break; @@ -799,15 +799,16 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, break; } - status = nfs_readdir_page_filler(desc, &entry, pages, page, pglen); + status = nfs_readdir_page_filler(desc, entry, pages, page, pglen); } while (!status && nfs_readdir_page_needs_filling(page)); nfs_readdir_free_pages(pages, array_size); out_release_label: - nfs4_label_free(entry.label); + nfs4_label_free(entry->label); out: - nfs_free_fattr(entry.fattr); - nfs_free_fhandle(entry.fh); + nfs_free_fattr(entry->fattr); + nfs_free_fhandle(entry->fh); + kfree(entry); return status; } @@ -829,8 +830,7 @@ nfs_readdir_page_get_cached(struct nfs_readdir_descriptor *desc) * Returns 0 if desc->dir_cookie was found on page desc->page_index * and locks the page to prevent removal from the page cache. */ -static -int find_and_lock_cache_page(nfs_readdir_descriptor_t *desc) +static int find_and_lock_cache_page(struct nfs_readdir_descriptor *desc) { struct inode *inode = file_inode(desc->file); struct nfs_inode *nfsi = NFS_I(inode); @@ -856,8 +856,7 @@ int find_and_lock_cache_page(nfs_readdir_descriptor_t *desc) } /* Search for desc->dir_cookie from the beginning of the page cache */ -static inline -int readdir_search_pagecache(nfs_readdir_descriptor_t *desc) +static int readdir_search_pagecache(struct nfs_readdir_descriptor *desc) { int res; @@ -922,8 +921,7 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc) * we should already have a complete representation of the * directory in the page cache by the time we get here. */ -static inline -int uncached_readdir(nfs_readdir_descriptor_t *desc) +static int uncached_readdir(struct nfs_readdir_descriptor *desc) { struct page *page = NULL; int status; @@ -968,13 +966,8 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) struct dentry *dentry = file_dentry(file); struct inode *inode = d_inode(dentry); struct nfs_open_dir_context *dir_ctx = file->private_data; - nfs_readdir_descriptor_t my_desc = { - .file = file, - .ctx = ctx, - .plus = nfs_use_readdirplus(inode, ctx), - }, - *desc = &my_desc; - int res = 0; + struct nfs_readdir_descriptor *desc; + int res; dfprintk(FILE, "NFS: readdir(%pD2) starting at cookie %llu\n", file, (long long)ctx->pos); @@ -986,10 +979,19 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) * to either find the entry with the appropriate number or * revalidate the cookie. */ - if (ctx->pos == 0 || nfs_attribute_cache_expired(inode)) + if (ctx->pos == 0 || nfs_attribute_cache_expired(inode)) { res = nfs_revalidate_mapping(inode, file->f_mapping); - if (res < 0) + if (res < 0) + goto out; + } + + res = -ENOMEM; + desc = kzalloc(sizeof(*desc), GFP_KERNEL); + if (!desc) goto out; + desc->file = file; + desc->ctx = ctx; + desc->plus = nfs_use_readdirplus(inode, ctx); spin_lock(&file->f_lock); desc->dir_cookie = dir_ctx->dir_cookie; @@ -1035,6 +1037,8 @@ static int nfs_readdir(struct file *file, struct dir_context *ctx) dir_ctx->attr_gencount = desc->attr_gencount; spin_unlock(&file->f_lock); + kfree(desc); + out: dfprintk(FILE, "NFS: readdir(%pD2) returns %d\n", file, res); return res;