[PATCH 2/2] ocfs2: Fix race between mount and recovery
As the fs recovery is asynchronous, there is a small chance that another
node can mount (and thus recover) the slot before the recovery thread
gets to it.
If this happens, the recovery thread will block indefinitely on the
journal/slot lock as that lock will be held for the duration of the mount
(by design) by the node assigned to that slot.
The solution implemented is to keep track of the journal replays using
a recovery generation in the journal inode, which will be incremented by the
thread replaying that journal. The recovery thread, before attempting the
blocking lock on the journal/slot lock, will compare the generation on disk
with what it has cached and skip recovery if it does not match.
This bug appears to have been inadvertently introduced during the mount/umount
vote removal by mainline commit 34d024f843
. In the
mount voting scheme, the messaging would indirectly indicate that the slot
was being recovered.
Signed-off-by: Sunil Mushran <sunil.mushran@oracle.com>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
This commit is contained in:
committed by
Mark Fasheh
parent
c69991aac7
commit
539d826409
@ -1442,6 +1442,15 @@ static int ocfs2_initialize_super(struct super_block *sb,
|
||||
}
|
||||
mlog(0, "max_slots for this device: %u\n", osb->max_slots);
|
||||
|
||||
osb->slot_recovery_generations =
|
||||
kcalloc(osb->max_slots, sizeof(*osb->slot_recovery_generations),
|
||||
GFP_KERNEL);
|
||||
if (!osb->slot_recovery_generations) {
|
||||
status = -ENOMEM;
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
init_waitqueue_head(&osb->osb_wipe_event);
|
||||
osb->osb_orphan_wipes = kcalloc(osb->max_slots,
|
||||
sizeof(*osb->osb_orphan_wipes),
|
||||
@ -1703,7 +1712,7 @@ static int ocfs2_check_volume(struct ocfs2_super *osb)
|
||||
local = ocfs2_mount_local(osb);
|
||||
|
||||
/* will play back anything left in the journal. */
|
||||
status = ocfs2_journal_load(osb->journal, local);
|
||||
status = ocfs2_journal_load(osb->journal, local, dirty);
|
||||
if (status < 0) {
|
||||
mlog(ML_ERROR, "ocfs2 journal load failed! %d\n", status);
|
||||
goto finally;
|
||||
@ -1768,6 +1777,7 @@ static void ocfs2_delete_osb(struct ocfs2_super *osb)
|
||||
ocfs2_free_slot_info(osb);
|
||||
|
||||
kfree(osb->osb_orphan_wipes);
|
||||
kfree(osb->slot_recovery_generations);
|
||||
/* FIXME
|
||||
* This belongs in journal shutdown, but because we have to
|
||||
* allocate osb->journal at the start of ocfs2_initalize_osb(),
|
||||
|
Reference in New Issue
Block a user