From 785447147576fae4dc390d9dbfddf45a089fb9fb Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Tue, 12 Sep 2017 12:06:03 -0700 Subject: [PATCH] scoutfs: fix server wq destory warning We were seeing warnings in destroy_workqueue() which meant that work was queued on the server workqueue after it was drained and before it was finally destroyed. The only work that wasn't properly waited for was the commit work. It looks like it'd be idle because the server receive threads all wait for their request processing work to finish. But the way the commit work is batched means that a request can have its commit processed by executing commit work while leaving the work queued for another run. Fix this by specifically waiting for the commit work to finish after the server work has waited for all the recv and compaction work to finish. I wasn't able to reliably trigger the assertion in repeated xfstests runs. This survived many runs also, let's see if it stops the destroy_workqueue() assertion from triggering in the future. Signed-off-by: Zach Brown --- kmod/src/server.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/kmod/src/server.c b/kmod/src/server.c index aa2d7588..d42012b0 100644 --- a/kmod/src/server.c +++ b/kmod/src/server.c @@ -96,6 +96,11 @@ struct commit_waiter { * that the caller can be sure to be woken by the next commit after they * queue and release the lock. * + * It's important to realize that the caller's commit_waiter list node + * might be serviced by a currently running commit work while queueing + * another work run in the future. This caller can return from + * wait_for_commit() while the commit_work is still queued. + * * This could queue delayed work but we're first trying to have batching * work by having concurrent modification line up behind a commit in * flight. Once the commit finishes it'll unlock and hopefully everyone @@ -1077,6 +1082,9 @@ void scoutfs_server_destroy(struct super_block *sb) /* wait for server work to wait for everything to shut down */ cancel_delayed_work_sync(&server->dwork); + /* recv work/compaction could have left commit_work queued */ + cancel_work_sync(&server->commit_work); + destroy_workqueue(server->wq); kfree(server);