Stable Archive on lore.kernel.org
 help / color / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Trond Myklebust <trond.myklebust@hammerspace.com>,
	John Hubbard <jhubbard@nvidia.com>,
	Sasha Levin <sashal@kernel.org>,
	linux-nfs@vger.kernel.org
Subject: [PATCH AUTOSEL 4.4 18/28] NFSv4: Fix a potential sleep while atomic in nfs4_do_reclaim()
Date: Tue, 13 Aug 2019 22:25:40 -0400
Message-ID: <20190814022550.17463-18-sashal@kernel.org> (raw)
In-Reply-To: <20190814022550.17463-1-sashal@kernel.org>

From: Trond Myklebust <trond.myklebust@hammerspace.com>

[ Upstream commit c77e22834ae9a11891cb613bd9a551be1b94f2bc ]

John Hubbard reports seeing the following stack trace:

nfs4_do_reclaim
   rcu_read_lock /* we are now in_atomic() and must not sleep */
       nfs4_purge_state_owners
           nfs4_free_state_owner
               nfs4_destroy_seqid_counter
                   rpc_destroy_wait_queue
                       cancel_delayed_work_sync
                           __cancel_work_timer
                               __flush_work
                                   start_flush_work
                                       might_sleep:
                                        (kernel/workqueue.c:2975: BUG)

The solution is to separate out the freeing of the state owners
from nfs4_purge_state_owners(), and perform that outside the atomic
context.

Reported-by: John Hubbard <jhubbard@nvidia.com>
Fixes: 0aaaf5c424c7f ("NFS: Cache state owners after files are closed")
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 fs/nfs/nfs4_fs.h    |  3 ++-
 fs/nfs/nfs4client.c |  5 ++++-
 fs/nfs/nfs4state.c  | 27 ++++++++++++++++++++++-----
 3 files changed, 28 insertions(+), 7 deletions(-)

diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 4afdee420d253..9f15696f55b9f 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -416,7 +416,8 @@ static inline void nfs4_schedule_session_recovery(struct nfs4_session *session,
 
 extern struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *, gfp_t);
 extern void nfs4_put_state_owner(struct nfs4_state_owner *);
-extern void nfs4_purge_state_owners(struct nfs_server *);
+extern void nfs4_purge_state_owners(struct nfs_server *, struct list_head *);
+extern void nfs4_free_state_owners(struct list_head *head);
 extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *);
 extern void nfs4_put_open_state(struct nfs4_state *);
 extern void nfs4_close_state(struct nfs4_state *, fmode_t);
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index ae91d1e450be7..dac20f31f01f8 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -685,9 +685,12 @@ int nfs41_walk_client_list(struct nfs_client *new,
 
 static void nfs4_destroy_server(struct nfs_server *server)
 {
+	LIST_HEAD(freeme);
+
 	nfs_server_return_all_delegations(server);
 	unset_pnfs_layoutdriver(server);
-	nfs4_purge_state_owners(server);
+	nfs4_purge_state_owners(server, &freeme);
+	nfs4_free_state_owners(&freeme);
 }
 
 /*
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 5be61affeefd8..ef3ed2b1fd278 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -611,24 +611,39 @@ void nfs4_put_state_owner(struct nfs4_state_owner *sp)
 /**
  * nfs4_purge_state_owners - Release all cached state owners
  * @server: nfs_server with cached state owners to release
+ * @head: resulting list of state owners
  *
  * Called at umount time.  Remaining state owners will be on
  * the LRU with ref count of zero.
+ * Note that the state owners are not freed, but are added
+ * to the list @head, which can later be used as an argument
+ * to nfs4_free_state_owners.
  */
-void nfs4_purge_state_owners(struct nfs_server *server)
+void nfs4_purge_state_owners(struct nfs_server *server, struct list_head *head)
 {
 	struct nfs_client *clp = server->nfs_client;
 	struct nfs4_state_owner *sp, *tmp;
-	LIST_HEAD(doomed);
 
 	spin_lock(&clp->cl_lock);
 	list_for_each_entry_safe(sp, tmp, &server->state_owners_lru, so_lru) {
-		list_move(&sp->so_lru, &doomed);
+		list_move(&sp->so_lru, head);
 		nfs4_remove_state_owner_locked(sp);
 	}
 	spin_unlock(&clp->cl_lock);
+}
 
-	list_for_each_entry_safe(sp, tmp, &doomed, so_lru) {
+/**
+ * nfs4_purge_state_owners - Release all cached state owners
+ * @head: resulting list of state owners
+ *
+ * Frees a list of state owners that was generated by
+ * nfs4_purge_state_owners
+ */
+void nfs4_free_state_owners(struct list_head *head)
+{
+	struct nfs4_state_owner *sp, *tmp;
+
+	list_for_each_entry_safe(sp, tmp, head, so_lru) {
 		list_del(&sp->so_lru);
 		nfs4_free_state_owner(sp);
 	}
@@ -1724,12 +1739,13 @@ static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recov
 	struct nfs4_state_owner *sp;
 	struct nfs_server *server;
 	struct rb_node *pos;
+	LIST_HEAD(freeme);
 	int status = 0;
 
 restart:
 	rcu_read_lock();
 	list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
-		nfs4_purge_state_owners(server);
+		nfs4_purge_state_owners(server, &freeme);
 		spin_lock(&clp->cl_lock);
 		for (pos = rb_first(&server->state_owners);
 		     pos != NULL;
@@ -1758,6 +1774,7 @@ static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recov
 		spin_unlock(&clp->cl_lock);
 	}
 	rcu_read_unlock();
+	nfs4_free_state_owners(&freeme);
 	return 0;
 }
 
-- 
2.20.1


  parent reply index

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-08-14  2:25 [PATCH AUTOSEL 4.4 01/28] HID: Add 044f:b320 ThrustMaster, Inc. 2 in 1 DT Sasha Levin
2019-08-14  2:25 ` [PATCH AUTOSEL 4.4 02/28] MIPS: kernel: only use i8253 clocksource with periodic clockevent Sasha Levin
2019-08-14  2:25 ` [PATCH AUTOSEL 4.4 03/28] netfilter: ebtables: fix a memory leak bug in compat Sasha Levin
2019-08-14  2:25 ` [PATCH AUTOSEL 4.4 04/28] bonding: Force slave speed check after link state recovery for 802.3ad Sasha Levin
2019-08-14  2:25 ` [PATCH AUTOSEL 4.4 05/28] can: dev: call netif_carrier_off() in register_candev() Sasha Levin
2019-08-14  2:25 ` [PATCH AUTOSEL 4.4 06/28] ASoC: Fail card instantiation if DAI format setup fails Sasha Levin
2019-08-14  2:25 ` [PATCH AUTOSEL 4.4 07/28] st21nfca_connectivity_event_received: null check the allocation Sasha Levin
2019-08-14  2:25 ` [PATCH AUTOSEL 4.4 08/28] st_nci_hci_connectivity_event_received: " Sasha Levin
2019-08-14  2:25 ` [PATCH AUTOSEL 4.4 09/28] ASoC: ti: davinci-mcasp: Correct slot_width posed constraint Sasha Levin
2019-08-14  2:25 ` [PATCH AUTOSEL 4.4 10/28] net: usb: qmi_wwan: Add the BroadMobi BM818 card Sasha Levin
2019-08-14  2:25 ` [PATCH AUTOSEL 4.4 11/28] isdn: mISDN: hfcsusb: Fix possible null-pointer dereferences in start_isoc_chain() Sasha Levin
2019-08-14  2:25 ` [PATCH AUTOSEL 4.4 12/28] isdn: hfcsusb: Fix mISDN driver crash caused by transfer buffer on the stack Sasha Levin
2019-08-14  2:25 ` [PATCH AUTOSEL 4.4 13/28] perf bench numa: Fix cpu0 binding Sasha Levin
2019-08-14  2:25 ` [PATCH AUTOSEL 4.4 14/28] Input: kbtab - sanity check for endpoint type Sasha Levin
2019-08-14  2:25 ` [PATCH AUTOSEL 4.4 15/28] net: usb: pegasus: fix improper read if get_registers() fail Sasha Levin
2019-08-14  2:25 ` [PATCH AUTOSEL 4.4 16/28] can: sja1000: force the string buffer NULL-terminated Sasha Levin
2019-08-14  2:25 ` [PATCH AUTOSEL 4.4 17/28] can: peak_usb: " Sasha Levin
2019-08-14  2:25 ` Sasha Levin [this message]
2019-08-14  2:25 ` [PATCH AUTOSEL 4.4 19/28] HID: holtek: test for sanity of intfdata Sasha Levin
2019-08-14  2:25 ` [PATCH AUTOSEL 4.4 20/28] HID: hiddev: avoid opening a disconnected device Sasha Levin
2019-08-14  2:25 ` [PATCH AUTOSEL 4.4 21/28] HID: hiddev: do cleanup in failure of opening a device Sasha Levin
2019-08-14  2:25 ` [PATCH AUTOSEL 4.4 22/28] Input: iforce - add sanity checks Sasha Levin
2019-08-14  2:25 ` [PATCH AUTOSEL 4.4 23/28] net: cxgb3_main: Fix a resource leak in a error path in 'init_one()' Sasha Levin
2019-08-14  2:25 ` [PATCH AUTOSEL 4.4 24/28] net: hisilicon: make hip04_tx_reclaim non-reentrant Sasha Levin
2019-08-14  2:25 ` [PATCH AUTOSEL 4.4 25/28] net: hisilicon: fix hip04-xmit never return TX_BUSY Sasha Levin
2019-08-14  2:25 ` [PATCH AUTOSEL 4.4 26/28] net: hisilicon: Fix dma_map_single failed on arm64 Sasha Levin
2019-08-14  2:25 ` [PATCH AUTOSEL 4.4 27/28] libata: add SG safety checks in SFF pio transfers Sasha Levin
2019-08-14  2:25 ` [PATCH AUTOSEL 4.4 28/28] selftests: kvm: Adding config fragments Sasha Levin

Reply instructions:

You may reply publically to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190814022550.17463-18-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=jhubbard@nvidia.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-nfs@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=trond.myklebust@hammerspace.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Stable Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/stable/0 stable/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 stable stable/ https://lore.kernel.org/stable \
		stable@vger.kernel.org stable@archiver.kernel.org
	public-inbox-index stable


Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.stable


AGPL code for this site: git clone https://public-inbox.org/ public-inbox