summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2019-02-14 16:27:14 -0500
committerTheodore Ts'o <tytso@mit.edu>2019-02-14 16:27:14 -0500
commit538bcaa6261b77e71d37f5596c33127c1a3ec3f7 (patch)
treec6e4ab8e25697940e42ff620ad2d4d2413bcc639
parentf96c3ac8dfc24b4e38fc4c2eba5fea2107b929d1 (diff)
jbd2: fix race when writing superblock
The jbd2 superblock is lockless now, so there is probably a race condition between writing it so disk and modifing contents of it, which may lead to checksum error. The following race is the one case that we have captured. jbd2 fsstress jbd2_journal_commit_transaction jbd2_journal_update_sb_log_tail jbd2_write_superblock jbd2_superblock_csum_set jbd2_journal_revoke jbd2_journal_set_features(revork) modify superblock submit_bh(checksum incorrect) Fix this by locking the buffer head before modifing it. We always write the jbd2 superblock after we modify it, so this just means calling the lock_buffer() a little earlier. This checksum corruption problem can be reproduced by xfstests generic/475. Reported-by: zhangyi (F) <yi.zhang@huawei.com> Suggested-by: Jan Kara <jack@suse.cz> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r--fs/jbd2/journal.c52
1 files changed, 27 insertions, 25 deletions
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index 88d8f22d2cba..67ac91b53050 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -1356,6 +1356,10 @@ static int journal_reset(journal_t *journal)
1356 return jbd2_journal_start_thread(journal); 1356 return jbd2_journal_start_thread(journal);
1357} 1357}
1358 1358
1359/*
1360 * This function expects that the caller will have locked the journal
1361 * buffer head, and will return with it unlocked
1362 */
1359static int jbd2_write_superblock(journal_t *journal, int write_flags) 1363static int jbd2_write_superblock(journal_t *journal, int write_flags)
1360{ 1364{
1361 struct buffer_head *bh = journal->j_sb_buffer; 1365 struct buffer_head *bh = journal->j_sb_buffer;
@@ -1365,7 +1369,6 @@ static int jbd2_write_superblock(journal_t *journal, int write_flags)
1365 trace_jbd2_write_superblock(journal, write_flags); 1369 trace_jbd2_write_superblock(journal, write_flags);
1366 if (!(journal->j_flags & JBD2_BARRIER)) 1370 if (!(journal->j_flags & JBD2_BARRIER))
1367 write_flags &= ~(REQ_FUA | REQ_PREFLUSH); 1371 write_flags &= ~(REQ_FUA | REQ_PREFLUSH);
1368 lock_buffer(bh);
1369 if (buffer_write_io_error(bh)) { 1372 if (buffer_write_io_error(bh)) {
1370 /* 1373 /*
1371 * Oh, dear. A previous attempt to write the journal 1374 * Oh, dear. A previous attempt to write the journal
@@ -1424,6 +1427,7 @@ int jbd2_journal_update_sb_log_tail(journal_t *journal, tid_t tail_tid,
1424 jbd_debug(1, "JBD2: updating superblock (start %lu, seq %u)\n", 1427 jbd_debug(1, "JBD2: updating superblock (start %lu, seq %u)\n",
1425 tail_block, tail_tid); 1428 tail_block, tail_tid);
1426 1429
1430 lock_buffer(journal->j_sb_buffer);
1427 sb->s_sequence = cpu_to_be32(tail_tid); 1431 sb->s_sequence = cpu_to_be32(tail_tid);
1428 sb->s_start = cpu_to_be32(tail_block); 1432 sb->s_start = cpu_to_be32(tail_block);
1429 1433
@@ -1454,18 +1458,17 @@ static void jbd2_mark_journal_empty(journal_t *journal, int write_op)
1454 journal_superblock_t *sb = journal->j_superblock; 1458 journal_superblock_t *sb = journal->j_superblock;
1455 1459
1456 BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex)); 1460 BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex));
1457 read_lock(&journal->j_state_lock); 1461 lock_buffer(journal->j_sb_buffer);
1458 /* Is it already empty? */ 1462 if (sb->s_start == 0) { /* Is it already empty? */
1459 if (sb->s_start == 0) { 1463 unlock_buffer(journal->j_sb_buffer);
1460 read_unlock(&journal->j_state_lock);
1461 return; 1464 return;
1462 } 1465 }
1466
1463 jbd_debug(1, "JBD2: Marking journal as empty (seq %d)\n", 1467 jbd_debug(1, "JBD2: Marking journal as empty (seq %d)\n",
1464 journal->j_tail_sequence); 1468 journal->j_tail_sequence);
1465 1469
1466 sb->s_sequence = cpu_to_be32(journal->j_tail_sequence); 1470 sb->s_sequence = cpu_to_be32(journal->j_tail_sequence);
1467 sb->s_start = cpu_to_be32(0); 1471 sb->s_start = cpu_to_be32(0);
1468 read_unlock(&journal->j_state_lock);
1469 1472
1470 jbd2_write_superblock(journal, write_op); 1473 jbd2_write_superblock(journal, write_op);
1471 1474
@@ -1488,9 +1491,8 @@ void jbd2_journal_update_sb_errno(journal_t *journal)
1488 journal_superblock_t *sb = journal->j_superblock; 1491 journal_superblock_t *sb = journal->j_superblock;
1489 int errcode; 1492 int errcode;
1490 1493
1491 read_lock(&journal->j_state_lock); 1494 lock_buffer(journal->j_sb_buffer);
1492 errcode = journal->j_errno; 1495 errcode = journal->j_errno;
1493 read_unlock(&journal->j_state_lock);
1494 if (errcode == -ESHUTDOWN) 1496 if (errcode == -ESHUTDOWN)
1495 errcode = 0; 1497 errcode = 0;
1496 jbd_debug(1, "JBD2: updating superblock error (errno %d)\n", errcode); 1498 jbd_debug(1, "JBD2: updating superblock error (errno %d)\n", errcode);
@@ -1894,28 +1896,27 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat,
1894 1896
1895 sb = journal->j_superblock; 1897 sb = journal->j_superblock;
1896 1898
1899 /* Load the checksum driver if necessary */
1900 if ((journal->j_chksum_driver == NULL) &&
1901 INCOMPAT_FEATURE_ON(JBD2_FEATURE_INCOMPAT_CSUM_V3)) {
1902 journal->j_chksum_driver = crypto_alloc_shash("crc32c", 0, 0);
1903 if (IS_ERR(journal->j_chksum_driver)) {
1904 printk(KERN_ERR "JBD2: Cannot load crc32c driver.\n");
1905 journal->j_chksum_driver = NULL;
1906 return 0;
1907 }
1908 /* Precompute checksum seed for all metadata */
1909 journal->j_csum_seed = jbd2_chksum(journal, ~0, sb->s_uuid,
1910 sizeof(sb->s_uuid));
1911 }
1912
1913 lock_buffer(journal->j_sb_buffer);
1914
1897 /* If enabling v3 checksums, update superblock */ 1915 /* If enabling v3 checksums, update superblock */
1898 if (INCOMPAT_FEATURE_ON(JBD2_FEATURE_INCOMPAT_CSUM_V3)) { 1916 if (INCOMPAT_FEATURE_ON(JBD2_FEATURE_INCOMPAT_CSUM_V3)) {
1899 sb->s_checksum_type = JBD2_CRC32C_CHKSUM; 1917 sb->s_checksum_type = JBD2_CRC32C_CHKSUM;
1900 sb->s_feature_compat &= 1918 sb->s_feature_compat &=
1901 ~cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM); 1919 ~cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM);
1902
1903 /* Load the checksum driver */
1904 if (journal->j_chksum_driver == NULL) {
1905 journal->j_chksum_driver = crypto_alloc_shash("crc32c",
1906 0, 0);
1907 if (IS_ERR(journal->j_chksum_driver)) {
1908 printk(KERN_ERR "JBD2: Cannot load crc32c "
1909 "driver.\n");
1910 journal->j_chksum_driver = NULL;
1911 return 0;
1912 }
1913
1914 /* Precompute checksum seed for all metadata */
1915 journal->j_csum_seed = jbd2_chksum(journal, ~0,
1916 sb->s_uuid,
1917 sizeof(sb->s_uuid));
1918 }
1919 } 1920 }
1920 1921
1921 /* If enabling v1 checksums, downgrade superblock */ 1922 /* If enabling v1 checksums, downgrade superblock */
@@ -1927,6 +1928,7 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat,
1927 sb->s_feature_compat |= cpu_to_be32(compat); 1928 sb->s_feature_compat |= cpu_to_be32(compat);
1928 sb->s_feature_ro_compat |= cpu_to_be32(ro); 1929 sb->s_feature_ro_compat |= cpu_to_be32(ro);
1929 sb->s_feature_incompat |= cpu_to_be32(incompat); 1930 sb->s_feature_incompat |= cpu_to_be32(incompat);
1931 unlock_buffer(journal->j_sb_buffer);
1930 1932
1931 return 1; 1933 return 1;
1932#undef COMPAT_FEATURE_ON 1934#undef COMPAT_FEATURE_ON