btrfs: qgroup: exit the rescan worker during umount
I was hitting a consistent NULL pointer dereference during shutdown that showed the trace running through end_workqueue_bio(). I traced it back to the endio_meta_workers workqueue being poked after it had already been destroyed. Eventually I found that the root cause was a qgroup rescan that was still in progress while we were stopping all the btrfs workers. Currently we explicitly pause balance and scrub operations in close_ctree(), but we do nothing to stop the qgroup rescan. We should probably be doing the same for qgroup rescan, but that's a much larger change. This small change is good enough to allow me to unmount without crashing. Signed-off-by: Justin Maggard <jmaggard@netgear.com> Reviewed-by: Filipe Manana <fdmanana@suse.com>
This commit is contained in:
parent
9c9464cc92
commit
7343dd61fd
|
@ -3780,6 +3780,9 @@ void close_ctree(struct btrfs_root *root)
|
|||
fs_info->closing = 1;
|
||||
smp_mb();
|
||||
|
||||
/* wait for the qgroup rescan worker to stop */
|
||||
btrfs_qgroup_wait_for_completion(fs_info);
|
||||
|
||||
/* wait for the uuid_scan task to finish */
|
||||
down(&fs_info->uuid_tree_rescan_sem);
|
||||
/* avoid complains from lockdep et al., set sem back to initial state */
|
||||
|
|
|
@ -2286,7 +2286,7 @@ static void btrfs_qgroup_rescan_worker(struct btrfs_work *work)
|
|||
goto out;
|
||||
|
||||
err = 0;
|
||||
while (!err) {
|
||||
while (!err && !btrfs_fs_closing(fs_info)) {
|
||||
trans = btrfs_start_transaction(fs_info->fs_root, 0);
|
||||
if (IS_ERR(trans)) {
|
||||
err = PTR_ERR(trans);
|
||||
|
@ -2307,7 +2307,8 @@ out:
|
|||
btrfs_free_path(path);
|
||||
|
||||
mutex_lock(&fs_info->qgroup_rescan_lock);
|
||||
fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_RESCAN;
|
||||
if (!btrfs_fs_closing(fs_info))
|
||||
fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_RESCAN;
|
||||
|
||||
if (err > 0 &&
|
||||
fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT) {
|
||||
|
@ -2336,7 +2337,9 @@ out:
|
|||
}
|
||||
btrfs_end_transaction(trans, fs_info->quota_root);
|
||||
|
||||
if (err >= 0) {
|
||||
if (btrfs_fs_closing(fs_info)) {
|
||||
btrfs_info(fs_info, "qgroup scan paused");
|
||||
} else if (err >= 0) {
|
||||
btrfs_info(fs_info, "qgroup scan completed%s",
|
||||
err > 0 ? " (inconsistency flag cleared)" : "");
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue