From 5b3a9f348bc58f0e13cebcf3e583c7d2f2499d6a Mon Sep 17 00:00:00 2001 From: Bob Peterson Date: Fri, 26 Apr 2019 08:11:27 -0600 Subject: [PATCH] gfs2: kthread and remount improvements Before this patch, gfs2 saved the pointers to the two daemon threads (logd and quotad) in the superblock, but they were never cleared, even if the threads were stopped (e.g. on remount -o ro). That meant that certain error conditions (like a withdrawn file system) could race. For example, xfstests generic/361 caused an IO error during remount -o ro, which caused the kthreads to be stopped, then the error flagged. Later, when the test unmounted the file system, it would try to stop the threads a second time with kthread_stop. This patch does two things: First, every time it stops the threads it zeroes out the thread pointer, and also checks whether it's NULL before trying to stop it. Second, in function gfs2_remount_fs, it was returning if an error was logged by either of the two functions for gfs2_make_fs_ro and _rw, which caused it to bypass the online uevent at the bottom of the function. This removes that bypass in favor of just running the whole function, then returning the error. That way, unmounts and remounts won't hang forever. Signed-off-by: Bob Peterson Signed-off-by: Andreas Gruenbacher --- fs/gfs2/super.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index b70cea5c8c59..31147d89399d 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -394,6 +394,7 @@ static int init_threads(struct gfs2_sbd *sdp) fail: kthread_stop(sdp->sd_logd_process); + sdp->sd_logd_process = NULL; return error; } @@ -451,8 +452,12 @@ fail: freeze_gh.gh_flags |= GL_NOCACHE; gfs2_glock_dq_uninit(&freeze_gh); fail_threads: - kthread_stop(sdp->sd_quotad_process); - kthread_stop(sdp->sd_logd_process); + if (sdp->sd_quotad_process) + kthread_stop(sdp->sd_quotad_process); + sdp->sd_quotad_process = NULL; + if (sdp->sd_logd_process) + kthread_stop(sdp->sd_logd_process); + sdp->sd_logd_process = NULL; return error; } @@ -853,8 +858,12 @@ static int gfs2_make_fs_ro(struct gfs2_sbd *sdp) return error; flush_workqueue(gfs2_delete_workqueue); - kthread_stop(sdp->sd_quotad_process); - kthread_stop(sdp->sd_logd_process); + if (sdp->sd_quotad_process) + kthread_stop(sdp->sd_quotad_process); + sdp->sd_quotad_process = NULL; + if (sdp->sd_logd_process) + kthread_stop(sdp->sd_logd_process); + sdp->sd_logd_process = NULL; gfs2_quota_sync(sdp->sd_vfs, 0); gfs2_statfs_sync(sdp->sd_vfs, 0); @@ -1273,8 +1282,6 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data) error = gfs2_make_fs_ro(sdp); else error = gfs2_make_fs_rw(sdp); - if (error) - return error; } sdp->sd_args = args; @@ -1300,7 +1307,7 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data) spin_unlock(>->gt_spin); gfs2_online_uevent(sdp); - return 0; + return error; } /**