Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8f918219 authored by Abhi Das's avatar Abhi Das Committed by Andreas Gruenbacher
Browse files

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 24972557 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: default avatarAbhi Das <adas@redhat.com>
Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
parent fbb27873
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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 {
+5 −3
Original line number Diff line number Diff line
@@ -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);
}

/**