Skip to content

Commit

Permalink
ocfs2: Fix sleep-with-spinlock recovery regression
Browse files Browse the repository at this point in the history
This fixes a bug introduced with 539d826:
    [PATCH 2/2] ocfs2: Fix race between mount and recovery

ocfs2_mark_dead_nodes() was reading journal inodes while holding the
spinlock protecting our in-memory recovery state. The fix is very simple -
the disk state is protected by a cluster lock that's already held, so we
just move the spinlock down past the read.

Reviewed-by: Joel Becker <joel.becker@oracle.com>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
  • Loading branch information
Mark Fasheh committed Aug 22, 2008
1 parent a57a874 commit a1af7d1
Showing 1 changed file with 14 additions and 9 deletions.
23 changes: 14 additions & 9 deletions fs/ocfs2/journal.c
Original file line number Diff line number Diff line change
Expand Up @@ -1418,13 +1418,13 @@ int ocfs2_mark_dead_nodes(struct ocfs2_super *osb)
{
unsigned int node_num;
int status, i;
u32 gen;
struct buffer_head *bh = NULL;
struct ocfs2_dinode *di;

/* This is called with the super block cluster lock, so we
* know that the slot map can't change underneath us. */

spin_lock(&osb->osb_lock);
for (i = 0; i < osb->max_slots; i++) {
/* Read journal inode to get the recovery generation */
status = ocfs2_read_journal_inode(osb, i, &bh, NULL);
Expand All @@ -1433,23 +1433,31 @@ int ocfs2_mark_dead_nodes(struct ocfs2_super *osb)
goto bail;
}
di = (struct ocfs2_dinode *)bh->b_data;
osb->slot_recovery_generations[i] =
ocfs2_get_recovery_generation(di);
gen = ocfs2_get_recovery_generation(di);
brelse(bh);
bh = NULL;

spin_lock(&osb->osb_lock);
osb->slot_recovery_generations[i] = gen;

mlog(0, "Slot %u recovery generation is %u\n", i,
osb->slot_recovery_generations[i]);

if (i == osb->slot_num)
if (i == osb->slot_num) {
spin_unlock(&osb->osb_lock);
continue;
}

status = ocfs2_slot_to_node_num_locked(osb, i, &node_num);
if (status == -ENOENT)
if (status == -ENOENT) {
spin_unlock(&osb->osb_lock);
continue;
}

if (__ocfs2_recovery_map_test(osb, node_num))
if (__ocfs2_recovery_map_test(osb, node_num)) {
spin_unlock(&osb->osb_lock);
continue;
}
spin_unlock(&osb->osb_lock);

/* Ok, we have a slot occupied by another node which
Expand All @@ -1465,10 +1473,7 @@ int ocfs2_mark_dead_nodes(struct ocfs2_super *osb)
mlog_errno(status);
goto bail;
}

spin_lock(&osb->osb_lock);
}
spin_unlock(&osb->osb_lock);

status = 0;
bail:
Expand Down

0 comments on commit a1af7d1

Please sign in to comment.