Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.com>2019-08-15 09:53:33 +1000
committerNeilBrown <neilb@suse.com>2019-08-15 09:53:33 +1000
commitff722c49f36a22e81e8ae3ed4aae3f379174b568 (patch)
treee7b77797bac10112669db513607ba4805319b172
parentee7b95e1b424614b101636374a429657614d0a87 (diff)
NFS: Fix the inode request accounting when pages have
subrequests (bsc#1140012).
-rw-r--r--patches.fixes/NFS-Fix-the-inode-request-accounting-when-pages-have.patch79
-rw-r--r--series.conf1
2 files changed, 80 insertions, 0 deletions
diff --git a/patches.fixes/NFS-Fix-the-inode-request-accounting-when-pages-have.patch b/patches.fixes/NFS-Fix-the-inode-request-accounting-when-pages-have.patch
new file mode 100644
index 0000000000..b2a8a61880
--- /dev/null
+++ b/patches.fixes/NFS-Fix-the-inode-request-accounting-when-pages-have.patch
@@ -0,0 +1,79 @@
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+Date: Tue, 18 Jul 2017 15:22:12 -0400
+Subject: [PATCH] NFS: Fix the inode request accounting when pages have
+ subrequests
+Git-commit: b66aaa8dfeda7b5c7df513cf3b36e1290fa84055
+Patch-mainline: v4.14
+References: bsc#1140012
+
+Both nfs_destroy_unlinked_subrequests() and nfs_lock_and_join_requests()
+manipulate the inode flags adjusting the NFS_I(inode)->nrequests.
+
+Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
+Acked-by: NeilBrown <neilb@suse.com>
+
+---
+ fs/nfs/write.c | 27 +++++++++++++++------------
+ 1 file changed, 15 insertions(+), 12 deletions(-)
+
+--- a/fs/nfs/write.c
++++ b/fs/nfs/write.c
+@@ -362,7 +362,8 @@ nfs_unroll_locks_and_wait(struct inode *
+ */
+ static void
+ nfs_destroy_unlinked_subrequests(struct nfs_page *destroy_list,
+- struct nfs_page *old_head)
++ struct nfs_page *old_head,
++ struct inode *inode)
+ {
+ while (destroy_list) {
+ struct nfs_page *subreq = destroy_list;
+@@ -387,9 +388,12 @@ nfs_destroy_unlinked_subrequests(struct
+ nfs_page_group_clear_bits(subreq);
+
+ /* release the PG_INODE_REF reference */
+- if (test_and_clear_bit(PG_INODE_REF, &subreq->wb_flags))
++ if (test_and_clear_bit(PG_INODE_REF, &subreq->wb_flags)) {
+ nfs_release_request(subreq);
+- else
++ spin_lock(&inode->i_lock);
++ NFS_I(inode)->nrequests--;
++ spin_unlock(&inode->i_lock);
++ } else
+ WARN_ON_ONCE(1);
+ } else {
+ WARN_ON_ONCE(test_bit(PG_CLEAN, &subreq->wb_flags));
+@@ -518,25 +522,24 @@ try_again:
+ head->wb_bytes = total_bytes;
+ }
+
++ /* Postpone destruction of this request */
++ if (test_and_clear_bit(PG_REMOVE, &head->wb_flags)) {
++ set_bit(PG_INODE_REF, &head->wb_flags);
++ kref_get(&head->wb_kref);
++ NFS_I(inode)->nrequests++;
++ }
++
+ /*
+ * prepare head request to be added to new pgio descriptor
+ */
+ nfs_page_group_clear_bits(head);
+
+- /*
+- * some part of the group was still on the inode list - otherwise
+- * the group wouldn't be involved in async write.
+- * grab a reference for the head request, iff it needs one.
+- */
+- if (!test_and_set_bit(PG_INODE_REF, &head->wb_flags))
+- kref_get(&head->wb_kref);
+-
+ nfs_page_group_unlock(head);
+
+ /* drop lock to clean uprequests on destroy list */
+ spin_unlock(&inode->i_lock);
+
+- nfs_destroy_unlinked_subrequests(destroy_list, head);
++ nfs_destroy_unlinked_subrequests(destroy_list, head, inode);
+
+ /* still holds ref on head from nfs_page_find_head_request_locked
+ * and still has lock on head from lock loop */
diff --git a/series.conf b/series.conf
index 802f30f299..ab87b14fce 100644
--- a/series.conf
+++ b/series.conf
@@ -6869,6 +6869,7 @@
patches.drivers/libnvdimm-btt-clean-up-warning-and-error-messages.patch
patches.drivers/libnvdimm-btt-fix-format-string-warnings.patch
patches.arch/signal-testing-Don-t-look-for-__SI_FAULT-in-userspac.patch
+ patches.fixes/NFS-Fix-the-inode-request-accounting-when-pages-have.patch
patches.fixes/0001-NFSv4.1-don-t-use-machine-credentials-for-CLOSE-when.patch
patches.fixes/0001-NFS-Fix-NFSv2-security-settings.patch
patches.fixes/0001-NFS-flush-data-when-locking-a-file-to-ensure-cache-c.patch