mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-10 23:29:46 +00:00
gfs2: fix race between gfs2_freeze_func and unmount
As part of the freeze operation, gfs2_freeze_func() is left blocking on a request to hold the sd_freeze_gl in SH. This glock is held in EX by the gfs2_freeze() code. A subsequent call to gfs2_unfreeze() releases the EXclusively held sd_freeze_gl, which allows gfs2_freeze_func() to acquire it in SH and resume its operation. gfs2_unfreeze(), however, doesn't wait for gfs2_freeze_func() to complete. If a umount is issued right after unfreeze, it could result in an inconsistent filesystem because some journal data (statfs update) isn't written out. Refer to commit 24972557b12c for a more detailed explanation of how freeze/unfreeze work. This patch causes gfs2_unfreeze() to wait for gfs2_freeze_func() to complete before returning to the user. Signed-off-by: Abhi Das <adas@redhat.com> Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
This commit is contained in:
parent
fbb27873f2
commit
8f91821990
@ -621,6 +621,7 @@ enum {
|
||||
SDF_SKIP_DLM_UNLOCK = 8,
|
||||
SDF_FORCE_AIL_FLUSH = 9,
|
||||
SDF_AIL1_IO_ERROR = 10,
|
||||
SDF_FS_FROZEN = 11,
|
||||
};
|
||||
|
||||
enum gfs2_freeze_state {
|
||||
|
@ -973,8 +973,7 @@ void gfs2_freeze_func(struct work_struct *work)
|
||||
if (error) {
|
||||
printk(KERN_INFO "GFS2: couldn't get freeze lock : %d\n", error);
|
||||
gfs2_assert_withdraw(sdp, 0);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
atomic_set(&sdp->sd_freeze_state, SFS_UNFROZEN);
|
||||
error = thaw_super(sb);
|
||||
if (error) {
|
||||
@ -987,6 +986,8 @@ void gfs2_freeze_func(struct work_struct *work)
|
||||
gfs2_glock_dq_uninit(&freeze_gh);
|
||||
}
|
||||
deactivate_super(sb);
|
||||
clear_bit_unlock(SDF_FS_FROZEN, &sdp->sd_flags);
|
||||
wake_up_bit(&sdp->sd_flags, SDF_FS_FROZEN);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1029,6 +1030,7 @@ static int gfs2_freeze(struct super_block *sb)
|
||||
msleep(1000);
|
||||
}
|
||||
error = 0;
|
||||
set_bit(SDF_FS_FROZEN, &sdp->sd_flags);
|
||||
out:
|
||||
mutex_unlock(&sdp->sd_freeze_mutex);
|
||||
return error;
|
||||
@ -1053,7 +1055,7 @@ static int gfs2_unfreeze(struct super_block *sb)
|
||||
|
||||
gfs2_glock_dq_uninit(&sdp->sd_freeze_gh);
|
||||
mutex_unlock(&sdp->sd_freeze_mutex);
|
||||
return 0;
|
||||
return wait_on_bit(&sdp->sd_flags, SDF_FS_FROZEN, TASK_INTERRUPTIBLE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user