summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2020-10-15 11:05:01 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-10-29 10:11:50 +0100
commit34a3fc1ec41c92002511109abd2c939a3bb7486a (patch)
treedd7f3164ec575cbde06207de3e4cdd7d79226052 /fs
parentf339eda9b90e49e82043c145ac628d679d913638 (diff)
downloadlinux-stable-34a3fc1ec41c92002511109abd2c939a3bb7486a.tar.gz
linux-stable-34a3fc1ec41c92002511109abd2c939a3bb7486a.tar.bz2
linux-stable-34a3fc1ec41c92002511109abd2c939a3bb7486a.zip
afs: Fix cell purging with aliases
[ Upstream commit 286377f6bdf71568a4cf07104fe44006ae0dba6d ] When the afs module is removed, one of the things that has to be done is to purge the cell database. afs_cell_purge() cancels the management timer and then starts the cell manager work item to do the purging. This does a single run through and then assumes that all cells are now purged - but this is no longer the case. With the introduction of alias detection, a later cell in the database can now be holding an active count on an earlier cell (cell->alias_of). The purge scan passes by the earlier cell first, but this can't be got rid of until it has discarded the alias. Ordinarily, afs_unuse_cell() would handle this by setting the management timer to trigger another pass - but afs_set_cell_timer() doesn't do anything if the namespace is being removed (net->live == false). rmmod then hangs in the wait on cells_outstanding in afs_cell_purge(). Fix this by making afs_set_cell_timer() directly queue the cell manager if net->live is false. This causes additional management passes. Queueing the cell manager increments cells_outstanding to make sure the wait won't complete until all cells are destroyed. Fixes: 8a070a964877 ("afs: Detect cell aliases 1 - Cells with root volumes") Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/afs/cell.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/fs/afs/cell.c b/fs/afs/cell.c
index c906000b0ff8..1944be78e9b0 100644
--- a/fs/afs/cell.c
+++ b/fs/afs/cell.c
@@ -19,6 +19,7 @@ static unsigned __read_mostly afs_cell_gc_delay = 10;
static unsigned __read_mostly afs_cell_min_ttl = 10 * 60;
static unsigned __read_mostly afs_cell_max_ttl = 24 * 60 * 60;
+static void afs_queue_cell_manager(struct afs_net *);
static void afs_manage_cell_work(struct work_struct *);
static void afs_dec_cells_outstanding(struct afs_net *net)
@@ -37,6 +38,8 @@ static void afs_set_cell_timer(struct afs_net *net, time64_t delay)
atomic_inc(&net->cells_outstanding);
if (timer_reduce(&net->cells_timer, jiffies + delay * HZ))
afs_dec_cells_outstanding(net);
+ } else {
+ afs_queue_cell_manager(net);
}
}