aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/journal.c
diff options
context:
space:
mode:
authorMark Fasheh <mfasheh@suse.com>2008-08-19 20:20:28 -0400
committerMark Fasheh <mfasheh@suse.com>2008-08-22 14:08:38 -0400
commita1af7d15a18d1e375b0a6fee93789a0bbfe088b4 (patch)
tree24af83391b39cf787b7579859682c4050970ed76 /fs/ocfs2/journal.c
parenta57a874b04e27cb530a0e18c244387452e73ccce (diff)
ocfs2: Fix sleep-with-spinlock recovery regression
This fixes a bug introduced with 539d8264093560b917ee3afe4c7f74e5da09d6a5: [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>
Diffstat (limited to 'fs/ocfs2/journal.c')
-rw-r--r--fs/ocfs2/journal.c23
1 files changed, 14 insertions, 9 deletions
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index 7a37240f7a31..c47bc2a809c2 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -1418,13 +1418,13 @@ int ocfs2_mark_dead_nodes(struct ocfs2_super *osb)
1418{ 1418{
1419 unsigned int node_num; 1419 unsigned int node_num;
1420 int status, i; 1420 int status, i;
1421 u32 gen;
1421 struct buffer_head *bh = NULL; 1422 struct buffer_head *bh = NULL;
1422 struct ocfs2_dinode *di; 1423 struct ocfs2_dinode *di;
1423 1424
1424 /* This is called with the super block cluster lock, so we 1425 /* This is called with the super block cluster lock, so we
1425 * know that the slot map can't change underneath us. */ 1426 * know that the slot map can't change underneath us. */
1426 1427
1427 spin_lock(&osb->osb_lock);
1428 for (i = 0; i < osb->max_slots; i++) { 1428 for (i = 0; i < osb->max_slots; i++) {
1429 /* Read journal inode to get the recovery generation */ 1429 /* Read journal inode to get the recovery generation */
1430 status = ocfs2_read_journal_inode(osb, i, &bh, NULL); 1430 status = ocfs2_read_journal_inode(osb, i, &bh, NULL);
@@ -1433,23 +1433,31 @@ int ocfs2_mark_dead_nodes(struct ocfs2_super *osb)
1433 goto bail; 1433 goto bail;
1434 } 1434 }
1435 di = (struct ocfs2_dinode *)bh->b_data; 1435 di = (struct ocfs2_dinode *)bh->b_data;
1436 osb->slot_recovery_generations[i] = 1436 gen = ocfs2_get_recovery_generation(di);
1437 ocfs2_get_recovery_generation(di);
1438 brelse(bh); 1437 brelse(bh);
1439 bh = NULL; 1438 bh = NULL;
1440 1439
1440 spin_lock(&osb->osb_lock);
1441 osb->slot_recovery_generations[i] = gen;
1442
1441 mlog(0, "Slot %u recovery generation is %u\n", i, 1443 mlog(0, "Slot %u recovery generation is %u\n", i,
1442 osb->slot_recovery_generations[i]); 1444 osb->slot_recovery_generations[i]);
1443 1445
1444 if (i == osb->slot_num) 1446 if (i == osb->slot_num) {
1447 spin_unlock(&osb->osb_lock);
1445 continue; 1448 continue;
1449 }
1446 1450
1447 status = ocfs2_slot_to_node_num_locked(osb, i, &node_num); 1451 status = ocfs2_slot_to_node_num_locked(osb, i, &node_num);
1448 if (status == -ENOENT) 1452 if (status == -ENOENT) {
1453 spin_unlock(&osb->osb_lock);
1449 continue; 1454 continue;
1455 }
1450 1456
1451 if (__ocfs2_recovery_map_test(osb, node_num)) 1457 if (__ocfs2_recovery_map_test(osb, node_num)) {
1458 spin_unlock(&osb->osb_lock);
1452 continue; 1459 continue;
1460 }
1453 spin_unlock(&osb->osb_lock); 1461 spin_unlock(&osb->osb_lock);
1454 1462
1455 /* Ok, we have a slot occupied by another node which 1463 /* Ok, we have a slot occupied by another node which
@@ -1465,10 +1473,7 @@ int ocfs2_mark_dead_nodes(struct ocfs2_super *osb)
1465 mlog_errno(status); 1473 mlog_errno(status);
1466 goto bail; 1474 goto bail;
1467 } 1475 }
1468
1469 spin_lock(&osb->osb_lock);
1470 } 1476 }
1471 spin_unlock(&osb->osb_lock);
1472 1477
1473 status = 0; 1478 status = 0;
1474bail: 1479bail: