diff options
Diffstat (limited to 'fs/jbd2/journal.c')
| -rw-r--r-- | fs/jbd2/journal.c | 103 |
1 files changed, 63 insertions, 40 deletions
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 8207a01c4edb..783de118de92 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
| @@ -597,13 +597,9 @@ int jbd2_journal_bmap(journal_t *journal, unsigned long blocknr, | |||
| 597 | if (ret) | 597 | if (ret) |
| 598 | *retp = ret; | 598 | *retp = ret; |
| 599 | else { | 599 | else { |
| 600 | char b[BDEVNAME_SIZE]; | ||
| 601 | |||
| 602 | printk(KERN_ALERT "%s: journal block not found " | 600 | printk(KERN_ALERT "%s: journal block not found " |
| 603 | "at offset %lu on %s\n", | 601 | "at offset %lu on %s\n", |
| 604 | __func__, | 602 | __func__, blocknr, journal->j_devname); |
| 605 | blocknr, | ||
| 606 | bdevname(journal->j_dev, b)); | ||
| 607 | err = -EIO; | 603 | err = -EIO; |
| 608 | __journal_abort_soft(journal, err); | 604 | __journal_abort_soft(journal, err); |
| 609 | } | 605 | } |
| @@ -901,10 +897,7 @@ static struct proc_dir_entry *proc_jbd2_stats; | |||
| 901 | 897 | ||
| 902 | static void jbd2_stats_proc_init(journal_t *journal) | 898 | static void jbd2_stats_proc_init(journal_t *journal) |
| 903 | { | 899 | { |
| 904 | char name[BDEVNAME_SIZE]; | 900 | journal->j_proc_entry = proc_mkdir(journal->j_devname, proc_jbd2_stats); |
| 905 | |||
| 906 | bdevname(journal->j_dev, name); | ||
| 907 | journal->j_proc_entry = proc_mkdir(name, proc_jbd2_stats); | ||
| 908 | if (journal->j_proc_entry) { | 901 | if (journal->j_proc_entry) { |
| 909 | proc_create_data("history", S_IRUGO, journal->j_proc_entry, | 902 | proc_create_data("history", S_IRUGO, journal->j_proc_entry, |
| 910 | &jbd2_seq_history_fops, journal); | 903 | &jbd2_seq_history_fops, journal); |
| @@ -915,12 +908,9 @@ static void jbd2_stats_proc_init(journal_t *journal) | |||
| 915 | 908 | ||
| 916 | static void jbd2_stats_proc_exit(journal_t *journal) | 909 | static void jbd2_stats_proc_exit(journal_t *journal) |
| 917 | { | 910 | { |
| 918 | char name[BDEVNAME_SIZE]; | ||
| 919 | |||
| 920 | bdevname(journal->j_dev, name); | ||
| 921 | remove_proc_entry("info", journal->j_proc_entry); | 911 | remove_proc_entry("info", journal->j_proc_entry); |
| 922 | remove_proc_entry("history", journal->j_proc_entry); | 912 | remove_proc_entry("history", journal->j_proc_entry); |
| 923 | remove_proc_entry(name, proc_jbd2_stats); | 913 | remove_proc_entry(journal->j_devname, proc_jbd2_stats); |
| 924 | } | 914 | } |
| 925 | 915 | ||
| 926 | static void journal_init_stats(journal_t *journal) | 916 | static void journal_init_stats(journal_t *journal) |
| @@ -1018,6 +1008,7 @@ journal_t * jbd2_journal_init_dev(struct block_device *bdev, | |||
| 1018 | { | 1008 | { |
| 1019 | journal_t *journal = journal_init_common(); | 1009 | journal_t *journal = journal_init_common(); |
| 1020 | struct buffer_head *bh; | 1010 | struct buffer_head *bh; |
| 1011 | char *p; | ||
| 1021 | int n; | 1012 | int n; |
| 1022 | 1013 | ||
| 1023 | if (!journal) | 1014 | if (!journal) |
| @@ -1039,6 +1030,10 @@ journal_t * jbd2_journal_init_dev(struct block_device *bdev, | |||
| 1039 | journal->j_fs_dev = fs_dev; | 1030 | journal->j_fs_dev = fs_dev; |
| 1040 | journal->j_blk_offset = start; | 1031 | journal->j_blk_offset = start; |
| 1041 | journal->j_maxlen = len; | 1032 | journal->j_maxlen = len; |
| 1033 | bdevname(journal->j_dev, journal->j_devname); | ||
| 1034 | p = journal->j_devname; | ||
| 1035 | while ((p = strchr(p, '/'))) | ||
| 1036 | *p = '!'; | ||
| 1042 | jbd2_stats_proc_init(journal); | 1037 | jbd2_stats_proc_init(journal); |
| 1043 | 1038 | ||
| 1044 | bh = __getblk(journal->j_dev, start, journal->j_blocksize); | 1039 | bh = __getblk(journal->j_dev, start, journal->j_blocksize); |
| @@ -1061,6 +1056,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode) | |||
| 1061 | { | 1056 | { |
| 1062 | struct buffer_head *bh; | 1057 | struct buffer_head *bh; |
| 1063 | journal_t *journal = journal_init_common(); | 1058 | journal_t *journal = journal_init_common(); |
| 1059 | char *p; | ||
| 1064 | int err; | 1060 | int err; |
| 1065 | int n; | 1061 | int n; |
| 1066 | unsigned long long blocknr; | 1062 | unsigned long long blocknr; |
| @@ -1070,6 +1066,12 @@ journal_t * jbd2_journal_init_inode (struct inode *inode) | |||
| 1070 | 1066 | ||
| 1071 | journal->j_dev = journal->j_fs_dev = inode->i_sb->s_bdev; | 1067 | journal->j_dev = journal->j_fs_dev = inode->i_sb->s_bdev; |
| 1072 | journal->j_inode = inode; | 1068 | journal->j_inode = inode; |
| 1069 | bdevname(journal->j_dev, journal->j_devname); | ||
| 1070 | p = journal->j_devname; | ||
| 1071 | while ((p = strchr(p, '/'))) | ||
| 1072 | *p = '!'; | ||
| 1073 | p = journal->j_devname + strlen(journal->j_devname); | ||
| 1074 | sprintf(p, ":%lu", journal->j_inode->i_ino); | ||
| 1073 | jbd_debug(1, | 1075 | jbd_debug(1, |
| 1074 | "journal %p: inode %s/%ld, size %Ld, bits %d, blksize %ld\n", | 1076 | "journal %p: inode %s/%ld, size %Ld, bits %d, blksize %ld\n", |
| 1075 | journal, inode->i_sb->s_id, inode->i_ino, | 1077 | journal, inode->i_sb->s_id, inode->i_ino, |
| @@ -1253,6 +1255,22 @@ void jbd2_journal_update_superblock(journal_t *journal, int wait) | |||
| 1253 | goto out; | 1255 | goto out; |
| 1254 | } | 1256 | } |
| 1255 | 1257 | ||
| 1258 | if (buffer_write_io_error(bh)) { | ||
| 1259 | /* | ||
| 1260 | * Oh, dear. A previous attempt to write the journal | ||
| 1261 | * superblock failed. This could happen because the | ||
| 1262 | * USB device was yanked out. Or it could happen to | ||
| 1263 | * be a transient write error and maybe the block will | ||
| 1264 | * be remapped. Nothing we can do but to retry the | ||
| 1265 | * write and hope for the best. | ||
| 1266 | */ | ||
| 1267 | printk(KERN_ERR "JBD2: previous I/O error detected " | ||
| 1268 | "for journal superblock update for %s.\n", | ||
| 1269 | journal->j_devname); | ||
| 1270 | clear_buffer_write_io_error(bh); | ||
| 1271 | set_buffer_uptodate(bh); | ||
| 1272 | } | ||
| 1273 | |||
| 1256 | spin_lock(&journal->j_state_lock); | 1274 | spin_lock(&journal->j_state_lock); |
| 1257 | jbd_debug(1,"JBD: updating superblock (start %ld, seq %d, errno %d)\n", | 1275 | jbd_debug(1,"JBD: updating superblock (start %ld, seq %d, errno %d)\n", |
| 1258 | journal->j_tail, journal->j_tail_sequence, journal->j_errno); | 1276 | journal->j_tail, journal->j_tail_sequence, journal->j_errno); |
| @@ -1264,9 +1282,16 @@ void jbd2_journal_update_superblock(journal_t *journal, int wait) | |||
| 1264 | 1282 | ||
| 1265 | BUFFER_TRACE(bh, "marking dirty"); | 1283 | BUFFER_TRACE(bh, "marking dirty"); |
| 1266 | mark_buffer_dirty(bh); | 1284 | mark_buffer_dirty(bh); |
| 1267 | if (wait) | 1285 | if (wait) { |
| 1268 | sync_dirty_buffer(bh); | 1286 | sync_dirty_buffer(bh); |
| 1269 | else | 1287 | if (buffer_write_io_error(bh)) { |
| 1288 | printk(KERN_ERR "JBD2: I/O error detected " | ||
| 1289 | "when updating journal superblock for %s.\n", | ||
| 1290 | journal->j_devname); | ||
| 1291 | clear_buffer_write_io_error(bh); | ||
| 1292 | set_buffer_uptodate(bh); | ||
| 1293 | } | ||
| 1294 | } else | ||
| 1270 | ll_rw_block(SWRITE, 1, &bh); | 1295 | ll_rw_block(SWRITE, 1, &bh); |
| 1271 | 1296 | ||
| 1272 | out: | 1297 | out: |
| @@ -1426,9 +1451,12 @@ recovery_error: | |||
| 1426 | * | 1451 | * |
| 1427 | * Release a journal_t structure once it is no longer in use by the | 1452 | * Release a journal_t structure once it is no longer in use by the |
| 1428 | * journaled object. | 1453 | * journaled object. |
| 1454 | * Return <0 if we couldn't clean up the journal. | ||
| 1429 | */ | 1455 | */ |
| 1430 | void jbd2_journal_destroy(journal_t *journal) | 1456 | int jbd2_journal_destroy(journal_t *journal) |
| 1431 | { | 1457 | { |
| 1458 | int err = 0; | ||
| 1459 | |||
| 1432 | /* Wait for the commit thread to wake up and die. */ | 1460 | /* Wait for the commit thread to wake up and die. */ |
| 1433 | journal_kill_thread(journal); | 1461 | journal_kill_thread(journal); |
| 1434 | 1462 | ||
| @@ -1451,11 +1479,16 @@ void jbd2_journal_destroy(journal_t *journal) | |||
| 1451 | J_ASSERT(journal->j_checkpoint_transactions == NULL); | 1479 | J_ASSERT(journal->j_checkpoint_transactions == NULL); |
| 1452 | spin_unlock(&journal->j_list_lock); | 1480 | spin_unlock(&journal->j_list_lock); |
| 1453 | 1481 | ||
| 1454 | /* We can now mark the journal as empty. */ | ||
| 1455 | journal->j_tail = 0; | ||
| 1456 | journal->j_tail_sequence = ++journal->j_transaction_sequence; | ||
| 1457 | if (journal->j_sb_buffer) { | 1482 | if (journal->j_sb_buffer) { |
| 1458 | jbd2_journal_update_superblock(journal, 1); | 1483 | if (!is_journal_aborted(journal)) { |
| 1484 | /* We can now mark the journal as empty. */ | ||
| 1485 | journal->j_tail = 0; | ||
| 1486 | journal->j_tail_sequence = | ||
| 1487 | ++journal->j_transaction_sequence; | ||
| 1488 | jbd2_journal_update_superblock(journal, 1); | ||
| 1489 | } else { | ||
| 1490 | err = -EIO; | ||
| 1491 | } | ||
| 1459 | brelse(journal->j_sb_buffer); | 1492 | brelse(journal->j_sb_buffer); |
| 1460 | } | 1493 | } |
| 1461 | 1494 | ||
| @@ -1467,6 +1500,8 @@ void jbd2_journal_destroy(journal_t *journal) | |||
| 1467 | jbd2_journal_destroy_revoke(journal); | 1500 | jbd2_journal_destroy_revoke(journal); |
| 1468 | kfree(journal->j_wbuf); | 1501 | kfree(journal->j_wbuf); |
| 1469 | kfree(journal); | 1502 | kfree(journal); |
| 1503 | |||
| 1504 | return err; | ||
| 1470 | } | 1505 | } |
| 1471 | 1506 | ||
| 1472 | 1507 | ||
| @@ -1692,10 +1727,16 @@ int jbd2_journal_flush(journal_t *journal) | |||
| 1692 | spin_lock(&journal->j_list_lock); | 1727 | spin_lock(&journal->j_list_lock); |
| 1693 | while (!err && journal->j_checkpoint_transactions != NULL) { | 1728 | while (!err && journal->j_checkpoint_transactions != NULL) { |
| 1694 | spin_unlock(&journal->j_list_lock); | 1729 | spin_unlock(&journal->j_list_lock); |
| 1730 | mutex_lock(&journal->j_checkpoint_mutex); | ||
| 1695 | err = jbd2_log_do_checkpoint(journal); | 1731 | err = jbd2_log_do_checkpoint(journal); |
| 1732 | mutex_unlock(&journal->j_checkpoint_mutex); | ||
| 1696 | spin_lock(&journal->j_list_lock); | 1733 | spin_lock(&journal->j_list_lock); |
| 1697 | } | 1734 | } |
| 1698 | spin_unlock(&journal->j_list_lock); | 1735 | spin_unlock(&journal->j_list_lock); |
| 1736 | |||
| 1737 | if (is_journal_aborted(journal)) | ||
| 1738 | return -EIO; | ||
| 1739 | |||
| 1699 | jbd2_cleanup_journal_tail(journal); | 1740 | jbd2_cleanup_journal_tail(journal); |
| 1700 | 1741 | ||
| 1701 | /* Finally, mark the journal as really needing no recovery. | 1742 | /* Finally, mark the journal as really needing no recovery. |
| @@ -1717,7 +1758,7 @@ int jbd2_journal_flush(journal_t *journal) | |||
| 1717 | J_ASSERT(journal->j_head == journal->j_tail); | 1758 | J_ASSERT(journal->j_head == journal->j_tail); |
| 1718 | J_ASSERT(journal->j_tail_sequence == journal->j_transaction_sequence); | 1759 | J_ASSERT(journal->j_tail_sequence == journal->j_transaction_sequence); |
| 1719 | spin_unlock(&journal->j_state_lock); | 1760 | spin_unlock(&journal->j_state_lock); |
| 1720 | return err; | 1761 | return 0; |
| 1721 | } | 1762 | } |
| 1722 | 1763 | ||
| 1723 | /** | 1764 | /** |
| @@ -1761,23 +1802,6 @@ int jbd2_journal_wipe(journal_t *journal, int write) | |||
| 1761 | } | 1802 | } |
| 1762 | 1803 | ||
| 1763 | /* | 1804 | /* |
| 1764 | * journal_dev_name: format a character string to describe on what | ||
| 1765 | * device this journal is present. | ||
| 1766 | */ | ||
| 1767 | |||
| 1768 | static const char *journal_dev_name(journal_t *journal, char *buffer) | ||
| 1769 | { | ||
| 1770 | struct block_device *bdev; | ||
| 1771 | |||
| 1772 | if (journal->j_inode) | ||
| 1773 | bdev = journal->j_inode->i_sb->s_bdev; | ||
| 1774 | else | ||
| 1775 | bdev = journal->j_dev; | ||
| 1776 | |||
| 1777 | return bdevname(bdev, buffer); | ||
| 1778 | } | ||
| 1779 | |||
| 1780 | /* | ||
| 1781 | * Journal abort has very specific semantics, which we describe | 1805 | * Journal abort has very specific semantics, which we describe |
| 1782 | * for journal abort. | 1806 | * for journal abort. |
| 1783 | * | 1807 | * |
| @@ -1793,13 +1817,12 @@ static const char *journal_dev_name(journal_t *journal, char *buffer) | |||
| 1793 | void __jbd2_journal_abort_hard(journal_t *journal) | 1817 | void __jbd2_journal_abort_hard(journal_t *journal) |
| 1794 | { | 1818 | { |
| 1795 | transaction_t *transaction; | 1819 | transaction_t *transaction; |
| 1796 | char b[BDEVNAME_SIZE]; | ||
| 1797 | 1820 | ||
| 1798 | if (journal->j_flags & JBD2_ABORT) | 1821 | if (journal->j_flags & JBD2_ABORT) |
| 1799 | return; | 1822 | return; |
| 1800 | 1823 | ||
| 1801 | printk(KERN_ERR "Aborting journal on device %s.\n", | 1824 | printk(KERN_ERR "Aborting journal on device %s.\n", |
| 1802 | journal_dev_name(journal, b)); | 1825 | journal->j_devname); |
| 1803 | 1826 | ||
| 1804 | spin_lock(&journal->j_state_lock); | 1827 | spin_lock(&journal->j_state_lock); |
| 1805 | journal->j_flags |= JBD2_ABORT; | 1828 | journal->j_flags |= JBD2_ABORT; |
