diff options
Diffstat (limited to 'fs/xfs/xfs_log_recover.c')
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 620 |
1 files changed, 243 insertions, 377 deletions
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 966d3f97458c..204d8e5fa7fa 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -53,6 +53,17 @@ STATIC void xlog_recover_check_summary(xlog_t *); | |||
53 | #endif | 53 | #endif |
54 | 54 | ||
55 | /* | 55 | /* |
56 | * This structure is used during recovery to record the buf log items which | ||
57 | * have been canceled and should not be replayed. | ||
58 | */ | ||
59 | struct xfs_buf_cancel { | ||
60 | xfs_daddr_t bc_blkno; | ||
61 | uint bc_len; | ||
62 | int bc_refcount; | ||
63 | struct list_head bc_list; | ||
64 | }; | ||
65 | |||
66 | /* | ||
56 | * Sector aligned buffer routines for buffer create/read/write/access | 67 | * Sector aligned buffer routines for buffer create/read/write/access |
57 | */ | 68 | */ |
58 | 69 | ||
@@ -925,12 +936,12 @@ xlog_find_tail( | |||
925 | log->l_curr_cycle = be32_to_cpu(rhead->h_cycle); | 936 | log->l_curr_cycle = be32_to_cpu(rhead->h_cycle); |
926 | if (found == 2) | 937 | if (found == 2) |
927 | log->l_curr_cycle++; | 938 | log->l_curr_cycle++; |
928 | log->l_tail_lsn = be64_to_cpu(rhead->h_tail_lsn); | 939 | atomic64_set(&log->l_tail_lsn, be64_to_cpu(rhead->h_tail_lsn)); |
929 | log->l_last_sync_lsn = be64_to_cpu(rhead->h_lsn); | 940 | atomic64_set(&log->l_last_sync_lsn, be64_to_cpu(rhead->h_lsn)); |
930 | log->l_grant_reserve_cycle = log->l_curr_cycle; | 941 | xlog_assign_grant_head(&log->l_grant_reserve_head, log->l_curr_cycle, |
931 | log->l_grant_reserve_bytes = BBTOB(log->l_curr_block); | 942 | BBTOB(log->l_curr_block)); |
932 | log->l_grant_write_cycle = log->l_curr_cycle; | 943 | xlog_assign_grant_head(&log->l_grant_write_head, log->l_curr_cycle, |
933 | log->l_grant_write_bytes = BBTOB(log->l_curr_block); | 944 | BBTOB(log->l_curr_block)); |
934 | 945 | ||
935 | /* | 946 | /* |
936 | * Look for unmount record. If we find it, then we know there | 947 | * Look for unmount record. If we find it, then we know there |
@@ -960,7 +971,7 @@ xlog_find_tail( | |||
960 | } | 971 | } |
961 | after_umount_blk = (i + hblks + (int) | 972 | after_umount_blk = (i + hblks + (int) |
962 | BTOBB(be32_to_cpu(rhead->h_len))) % log->l_logBBsize; | 973 | BTOBB(be32_to_cpu(rhead->h_len))) % log->l_logBBsize; |
963 | tail_lsn = log->l_tail_lsn; | 974 | tail_lsn = atomic64_read(&log->l_tail_lsn); |
964 | if (*head_blk == after_umount_blk && | 975 | if (*head_blk == after_umount_blk && |
965 | be32_to_cpu(rhead->h_num_logops) == 1) { | 976 | be32_to_cpu(rhead->h_num_logops) == 1) { |
966 | umount_data_blk = (i + hblks) % log->l_logBBsize; | 977 | umount_data_blk = (i + hblks) % log->l_logBBsize; |
@@ -975,12 +986,10 @@ xlog_find_tail( | |||
975 | * log records will point recovery to after the | 986 | * log records will point recovery to after the |
976 | * current unmount record. | 987 | * current unmount record. |
977 | */ | 988 | */ |
978 | log->l_tail_lsn = | 989 | xlog_assign_atomic_lsn(&log->l_tail_lsn, |
979 | xlog_assign_lsn(log->l_curr_cycle, | 990 | log->l_curr_cycle, after_umount_blk); |
980 | after_umount_blk); | 991 | xlog_assign_atomic_lsn(&log->l_last_sync_lsn, |
981 | log->l_last_sync_lsn = | 992 | log->l_curr_cycle, after_umount_blk); |
982 | xlog_assign_lsn(log->l_curr_cycle, | ||
983 | after_umount_blk); | ||
984 | *tail_blk = after_umount_blk; | 993 | *tail_blk = after_umount_blk; |
985 | 994 | ||
986 | /* | 995 | /* |
@@ -1605,82 +1614,45 @@ xlog_recover_reorder_trans( | |||
1605 | * record in the table to tell us how many times we expect to see this | 1614 | * record in the table to tell us how many times we expect to see this |
1606 | * record during the second pass. | 1615 | * record during the second pass. |
1607 | */ | 1616 | */ |
1608 | STATIC void | 1617 | STATIC int |
1609 | xlog_recover_do_buffer_pass1( | 1618 | xlog_recover_buffer_pass1( |
1610 | xlog_t *log, | 1619 | struct log *log, |
1611 | xfs_buf_log_format_t *buf_f) | 1620 | xlog_recover_item_t *item) |
1612 | { | 1621 | { |
1613 | xfs_buf_cancel_t *bcp; | 1622 | xfs_buf_log_format_t *buf_f = item->ri_buf[0].i_addr; |
1614 | xfs_buf_cancel_t *nextp; | 1623 | struct list_head *bucket; |
1615 | xfs_buf_cancel_t *prevp; | 1624 | struct xfs_buf_cancel *bcp; |
1616 | xfs_buf_cancel_t **bucket; | ||
1617 | xfs_daddr_t blkno = 0; | ||
1618 | uint len = 0; | ||
1619 | ushort flags = 0; | ||
1620 | |||
1621 | switch (buf_f->blf_type) { | ||
1622 | case XFS_LI_BUF: | ||
1623 | blkno = buf_f->blf_blkno; | ||
1624 | len = buf_f->blf_len; | ||
1625 | flags = buf_f->blf_flags; | ||
1626 | break; | ||
1627 | } | ||
1628 | 1625 | ||
1629 | /* | 1626 | /* |
1630 | * If this isn't a cancel buffer item, then just return. | 1627 | * If this isn't a cancel buffer item, then just return. |
1631 | */ | 1628 | */ |
1632 | if (!(flags & XFS_BLF_CANCEL)) { | 1629 | if (!(buf_f->blf_flags & XFS_BLF_CANCEL)) { |
1633 | trace_xfs_log_recover_buf_not_cancel(log, buf_f); | 1630 | trace_xfs_log_recover_buf_not_cancel(log, buf_f); |
1634 | return; | 1631 | return 0; |
1635 | } | ||
1636 | |||
1637 | /* | ||
1638 | * Insert an xfs_buf_cancel record into the hash table of | ||
1639 | * them. If there is already an identical record, bump | ||
1640 | * its reference count. | ||
1641 | */ | ||
1642 | bucket = &log->l_buf_cancel_table[(__uint64_t)blkno % | ||
1643 | XLOG_BC_TABLE_SIZE]; | ||
1644 | /* | ||
1645 | * If the hash bucket is empty then just insert a new record into | ||
1646 | * the bucket. | ||
1647 | */ | ||
1648 | if (*bucket == NULL) { | ||
1649 | bcp = (xfs_buf_cancel_t *)kmem_alloc(sizeof(xfs_buf_cancel_t), | ||
1650 | KM_SLEEP); | ||
1651 | bcp->bc_blkno = blkno; | ||
1652 | bcp->bc_len = len; | ||
1653 | bcp->bc_refcount = 1; | ||
1654 | bcp->bc_next = NULL; | ||
1655 | *bucket = bcp; | ||
1656 | return; | ||
1657 | } | 1632 | } |
1658 | 1633 | ||
1659 | /* | 1634 | /* |
1660 | * The hash bucket is not empty, so search for duplicates of our | 1635 | * Insert an xfs_buf_cancel record into the hash table of them. |
1661 | * record. If we find one them just bump its refcount. If not | 1636 | * If there is already an identical record, bump its reference count. |
1662 | * then add us at the end of the list. | ||
1663 | */ | 1637 | */ |
1664 | prevp = NULL; | 1638 | bucket = XLOG_BUF_CANCEL_BUCKET(log, buf_f->blf_blkno); |
1665 | nextp = *bucket; | 1639 | list_for_each_entry(bcp, bucket, bc_list) { |
1666 | while (nextp != NULL) { | 1640 | if (bcp->bc_blkno == buf_f->blf_blkno && |
1667 | if (nextp->bc_blkno == blkno && nextp->bc_len == len) { | 1641 | bcp->bc_len == buf_f->blf_len) { |
1668 | nextp->bc_refcount++; | 1642 | bcp->bc_refcount++; |
1669 | trace_xfs_log_recover_buf_cancel_ref_inc(log, buf_f); | 1643 | trace_xfs_log_recover_buf_cancel_ref_inc(log, buf_f); |
1670 | return; | 1644 | return 0; |
1671 | } | 1645 | } |
1672 | prevp = nextp; | 1646 | } |
1673 | nextp = nextp->bc_next; | 1647 | |
1674 | } | 1648 | bcp = kmem_alloc(sizeof(struct xfs_buf_cancel), KM_SLEEP); |
1675 | ASSERT(prevp != NULL); | 1649 | bcp->bc_blkno = buf_f->blf_blkno; |
1676 | bcp = (xfs_buf_cancel_t *)kmem_alloc(sizeof(xfs_buf_cancel_t), | 1650 | bcp->bc_len = buf_f->blf_len; |
1677 | KM_SLEEP); | ||
1678 | bcp->bc_blkno = blkno; | ||
1679 | bcp->bc_len = len; | ||
1680 | bcp->bc_refcount = 1; | 1651 | bcp->bc_refcount = 1; |
1681 | bcp->bc_next = NULL; | 1652 | list_add_tail(&bcp->bc_list, bucket); |
1682 | prevp->bc_next = bcp; | 1653 | |
1683 | trace_xfs_log_recover_buf_cancel_add(log, buf_f); | 1654 | trace_xfs_log_recover_buf_cancel_add(log, buf_f); |
1655 | return 0; | ||
1684 | } | 1656 | } |
1685 | 1657 | ||
1686 | /* | 1658 | /* |
@@ -1698,14 +1670,13 @@ xlog_recover_do_buffer_pass1( | |||
1698 | */ | 1670 | */ |
1699 | STATIC int | 1671 | STATIC int |
1700 | xlog_check_buffer_cancelled( | 1672 | xlog_check_buffer_cancelled( |
1701 | xlog_t *log, | 1673 | struct log *log, |
1702 | xfs_daddr_t blkno, | 1674 | xfs_daddr_t blkno, |
1703 | uint len, | 1675 | uint len, |
1704 | ushort flags) | 1676 | ushort flags) |
1705 | { | 1677 | { |
1706 | xfs_buf_cancel_t *bcp; | 1678 | struct list_head *bucket; |
1707 | xfs_buf_cancel_t *prevp; | 1679 | struct xfs_buf_cancel *bcp; |
1708 | xfs_buf_cancel_t **bucket; | ||
1709 | 1680 | ||
1710 | if (log->l_buf_cancel_table == NULL) { | 1681 | if (log->l_buf_cancel_table == NULL) { |
1711 | /* | 1682 | /* |
@@ -1716,128 +1687,70 @@ xlog_check_buffer_cancelled( | |||
1716 | return 0; | 1687 | return 0; |
1717 | } | 1688 | } |
1718 | 1689 | ||
1719 | bucket = &log->l_buf_cancel_table[(__uint64_t)blkno % | ||
1720 | XLOG_BC_TABLE_SIZE]; | ||
1721 | bcp = *bucket; | ||
1722 | if (bcp == NULL) { | ||
1723 | /* | ||
1724 | * There is no corresponding entry in the table built | ||
1725 | * in pass one, so this buffer has not been cancelled. | ||
1726 | */ | ||
1727 | ASSERT(!(flags & XFS_BLF_CANCEL)); | ||
1728 | return 0; | ||
1729 | } | ||
1730 | |||
1731 | /* | 1690 | /* |
1732 | * Search for an entry in the buffer cancel table that | 1691 | * Search for an entry in the cancel table that matches our buffer. |
1733 | * matches our buffer. | ||
1734 | */ | 1692 | */ |
1735 | prevp = NULL; | 1693 | bucket = XLOG_BUF_CANCEL_BUCKET(log, blkno); |
1736 | while (bcp != NULL) { | 1694 | list_for_each_entry(bcp, bucket, bc_list) { |
1737 | if (bcp->bc_blkno == blkno && bcp->bc_len == len) { | 1695 | if (bcp->bc_blkno == blkno && bcp->bc_len == len) |
1738 | /* | 1696 | goto found; |
1739 | * We've go a match, so return 1 so that the | ||
1740 | * recovery of this buffer is cancelled. | ||
1741 | * If this buffer is actually a buffer cancel | ||
1742 | * log item, then decrement the refcount on the | ||
1743 | * one in the table and remove it if this is the | ||
1744 | * last reference. | ||
1745 | */ | ||
1746 | if (flags & XFS_BLF_CANCEL) { | ||
1747 | bcp->bc_refcount--; | ||
1748 | if (bcp->bc_refcount == 0) { | ||
1749 | if (prevp == NULL) { | ||
1750 | *bucket = bcp->bc_next; | ||
1751 | } else { | ||
1752 | prevp->bc_next = bcp->bc_next; | ||
1753 | } | ||
1754 | kmem_free(bcp); | ||
1755 | } | ||
1756 | } | ||
1757 | return 1; | ||
1758 | } | ||
1759 | prevp = bcp; | ||
1760 | bcp = bcp->bc_next; | ||
1761 | } | 1697 | } |
1698 | |||
1762 | /* | 1699 | /* |
1763 | * We didn't find a corresponding entry in the table, so | 1700 | * We didn't find a corresponding entry in the table, so return 0 so |
1764 | * return 0 so that the buffer is NOT cancelled. | 1701 | * that the buffer is NOT cancelled. |
1765 | */ | 1702 | */ |
1766 | ASSERT(!(flags & XFS_BLF_CANCEL)); | 1703 | ASSERT(!(flags & XFS_BLF_CANCEL)); |
1767 | return 0; | 1704 | return 0; |
1768 | } | ||
1769 | 1705 | ||
1770 | STATIC int | 1706 | found: |
1771 | xlog_recover_do_buffer_pass2( | 1707 | /* |
1772 | xlog_t *log, | 1708 | * We've go a match, so return 1 so that the recovery of this buffer |
1773 | xfs_buf_log_format_t *buf_f) | 1709 | * is cancelled. If this buffer is actually a buffer cancel log |
1774 | { | 1710 | * item, then decrement the refcount on the one in the table and |
1775 | xfs_daddr_t blkno = 0; | 1711 | * remove it if this is the last reference. |
1776 | ushort flags = 0; | 1712 | */ |
1777 | uint len = 0; | 1713 | if (flags & XFS_BLF_CANCEL) { |
1778 | 1714 | if (--bcp->bc_refcount == 0) { | |
1779 | switch (buf_f->blf_type) { | 1715 | list_del(&bcp->bc_list); |
1780 | case XFS_LI_BUF: | 1716 | kmem_free(bcp); |
1781 | blkno = buf_f->blf_blkno; | 1717 | } |
1782 | flags = buf_f->blf_flags; | ||
1783 | len = buf_f->blf_len; | ||
1784 | break; | ||
1785 | } | 1718 | } |
1786 | 1719 | return 1; | |
1787 | return xlog_check_buffer_cancelled(log, blkno, len, flags); | ||
1788 | } | 1720 | } |
1789 | 1721 | ||
1790 | /* | 1722 | /* |
1791 | * Perform recovery for a buffer full of inodes. In these buffers, | 1723 | * Perform recovery for a buffer full of inodes. In these buffers, the only |
1792 | * the only data which should be recovered is that which corresponds | 1724 | * data which should be recovered is that which corresponds to the |
1793 | * to the di_next_unlinked pointers in the on disk inode structures. | 1725 | * di_next_unlinked pointers in the on disk inode structures. The rest of the |
1794 | * The rest of the data for the inodes is always logged through the | 1726 | * data for the inodes is always logged through the inodes themselves rather |
1795 | * inodes themselves rather than the inode buffer and is recovered | 1727 | * than the inode buffer and is recovered in xlog_recover_inode_pass2(). |
1796 | * in xlog_recover_do_inode_trans(). | ||
1797 | * | 1728 | * |
1798 | * The only time when buffers full of inodes are fully recovered is | 1729 | * The only time when buffers full of inodes are fully recovered is when the |
1799 | * when the buffer is full of newly allocated inodes. In this case | 1730 | * buffer is full of newly allocated inodes. In this case the buffer will |
1800 | * the buffer will not be marked as an inode buffer and so will be | 1731 | * not be marked as an inode buffer and so will be sent to |
1801 | * sent to xlog_recover_do_reg_buffer() below during recovery. | 1732 | * xlog_recover_do_reg_buffer() below during recovery. |
1802 | */ | 1733 | */ |
1803 | STATIC int | 1734 | STATIC int |
1804 | xlog_recover_do_inode_buffer( | 1735 | xlog_recover_do_inode_buffer( |
1805 | xfs_mount_t *mp, | 1736 | struct xfs_mount *mp, |
1806 | xlog_recover_item_t *item, | 1737 | xlog_recover_item_t *item, |
1807 | xfs_buf_t *bp, | 1738 | struct xfs_buf *bp, |
1808 | xfs_buf_log_format_t *buf_f) | 1739 | xfs_buf_log_format_t *buf_f) |
1809 | { | 1740 | { |
1810 | int i; | 1741 | int i; |
1811 | int item_index; | 1742 | int item_index = 0; |
1812 | int bit; | 1743 | int bit = 0; |
1813 | int nbits; | 1744 | int nbits = 0; |
1814 | int reg_buf_offset; | 1745 | int reg_buf_offset = 0; |
1815 | int reg_buf_bytes; | 1746 | int reg_buf_bytes = 0; |
1816 | int next_unlinked_offset; | 1747 | int next_unlinked_offset; |
1817 | int inodes_per_buf; | 1748 | int inodes_per_buf; |
1818 | xfs_agino_t *logged_nextp; | 1749 | xfs_agino_t *logged_nextp; |
1819 | xfs_agino_t *buffer_nextp; | 1750 | xfs_agino_t *buffer_nextp; |
1820 | unsigned int *data_map = NULL; | ||
1821 | unsigned int map_size = 0; | ||
1822 | 1751 | ||
1823 | trace_xfs_log_recover_buf_inode_buf(mp->m_log, buf_f); | 1752 | trace_xfs_log_recover_buf_inode_buf(mp->m_log, buf_f); |
1824 | 1753 | ||
1825 | switch (buf_f->blf_type) { | ||
1826 | case XFS_LI_BUF: | ||
1827 | data_map = buf_f->blf_data_map; | ||
1828 | map_size = buf_f->blf_map_size; | ||
1829 | break; | ||
1830 | } | ||
1831 | /* | ||
1832 | * Set the variables corresponding to the current region to | ||
1833 | * 0 so that we'll initialize them on the first pass through | ||
1834 | * the loop. | ||
1835 | */ | ||
1836 | reg_buf_offset = 0; | ||
1837 | reg_buf_bytes = 0; | ||
1838 | bit = 0; | ||
1839 | nbits = 0; | ||
1840 | item_index = 0; | ||
1841 | inodes_per_buf = XFS_BUF_COUNT(bp) >> mp->m_sb.sb_inodelog; | 1754 | inodes_per_buf = XFS_BUF_COUNT(bp) >> mp->m_sb.sb_inodelog; |
1842 | for (i = 0; i < inodes_per_buf; i++) { | 1755 | for (i = 0; i < inodes_per_buf; i++) { |
1843 | next_unlinked_offset = (i * mp->m_sb.sb_inodesize) + | 1756 | next_unlinked_offset = (i * mp->m_sb.sb_inodesize) + |
@@ -1852,18 +1765,18 @@ xlog_recover_do_inode_buffer( | |||
1852 | * the current di_next_unlinked field. | 1765 | * the current di_next_unlinked field. |
1853 | */ | 1766 | */ |
1854 | bit += nbits; | 1767 | bit += nbits; |
1855 | bit = xfs_next_bit(data_map, map_size, bit); | 1768 | bit = xfs_next_bit(buf_f->blf_data_map, |
1769 | buf_f->blf_map_size, bit); | ||
1856 | 1770 | ||
1857 | /* | 1771 | /* |
1858 | * If there are no more logged regions in the | 1772 | * If there are no more logged regions in the |
1859 | * buffer, then we're done. | 1773 | * buffer, then we're done. |
1860 | */ | 1774 | */ |
1861 | if (bit == -1) { | 1775 | if (bit == -1) |
1862 | return 0; | 1776 | return 0; |
1863 | } | ||
1864 | 1777 | ||
1865 | nbits = xfs_contig_bits(data_map, map_size, | 1778 | nbits = xfs_contig_bits(buf_f->blf_data_map, |
1866 | bit); | 1779 | buf_f->blf_map_size, bit); |
1867 | ASSERT(nbits > 0); | 1780 | ASSERT(nbits > 0); |
1868 | reg_buf_offset = bit << XFS_BLF_SHIFT; | 1781 | reg_buf_offset = bit << XFS_BLF_SHIFT; |
1869 | reg_buf_bytes = nbits << XFS_BLF_SHIFT; | 1782 | reg_buf_bytes = nbits << XFS_BLF_SHIFT; |
@@ -1875,9 +1788,8 @@ xlog_recover_do_inode_buffer( | |||
1875 | * di_next_unlinked field, then move on to the next | 1788 | * di_next_unlinked field, then move on to the next |
1876 | * di_next_unlinked field. | 1789 | * di_next_unlinked field. |
1877 | */ | 1790 | */ |
1878 | if (next_unlinked_offset < reg_buf_offset) { | 1791 | if (next_unlinked_offset < reg_buf_offset) |
1879 | continue; | 1792 | continue; |
1880 | } | ||
1881 | 1793 | ||
1882 | ASSERT(item->ri_buf[item_index].i_addr != NULL); | 1794 | ASSERT(item->ri_buf[item_index].i_addr != NULL); |
1883 | ASSERT((item->ri_buf[item_index].i_len % XFS_BLF_CHUNK) == 0); | 1795 | ASSERT((item->ri_buf[item_index].i_len % XFS_BLF_CHUNK) == 0); |
@@ -1913,36 +1825,29 @@ xlog_recover_do_inode_buffer( | |||
1913 | * given buffer. The bitmap in the buf log format structure indicates | 1825 | * given buffer. The bitmap in the buf log format structure indicates |
1914 | * where to place the logged data. | 1826 | * where to place the logged data. |
1915 | */ | 1827 | */ |
1916 | /*ARGSUSED*/ | ||
1917 | STATIC void | 1828 | STATIC void |
1918 | xlog_recover_do_reg_buffer( | 1829 | xlog_recover_do_reg_buffer( |
1919 | struct xfs_mount *mp, | 1830 | struct xfs_mount *mp, |
1920 | xlog_recover_item_t *item, | 1831 | xlog_recover_item_t *item, |
1921 | xfs_buf_t *bp, | 1832 | struct xfs_buf *bp, |
1922 | xfs_buf_log_format_t *buf_f) | 1833 | xfs_buf_log_format_t *buf_f) |
1923 | { | 1834 | { |
1924 | int i; | 1835 | int i; |
1925 | int bit; | 1836 | int bit; |
1926 | int nbits; | 1837 | int nbits; |
1927 | unsigned int *data_map = NULL; | ||
1928 | unsigned int map_size = 0; | ||
1929 | int error; | 1838 | int error; |
1930 | 1839 | ||
1931 | trace_xfs_log_recover_buf_reg_buf(mp->m_log, buf_f); | 1840 | trace_xfs_log_recover_buf_reg_buf(mp->m_log, buf_f); |
1932 | 1841 | ||
1933 | switch (buf_f->blf_type) { | ||
1934 | case XFS_LI_BUF: | ||
1935 | data_map = buf_f->blf_data_map; | ||
1936 | map_size = buf_f->blf_map_size; | ||
1937 | break; | ||
1938 | } | ||
1939 | bit = 0; | 1842 | bit = 0; |
1940 | i = 1; /* 0 is the buf format structure */ | 1843 | i = 1; /* 0 is the buf format structure */ |
1941 | while (1) { | 1844 | while (1) { |
1942 | bit = xfs_next_bit(data_map, map_size, bit); | 1845 | bit = xfs_next_bit(buf_f->blf_data_map, |
1846 | buf_f->blf_map_size, bit); | ||
1943 | if (bit == -1) | 1847 | if (bit == -1) |
1944 | break; | 1848 | break; |
1945 | nbits = xfs_contig_bits(data_map, map_size, bit); | 1849 | nbits = xfs_contig_bits(buf_f->blf_data_map, |
1850 | buf_f->blf_map_size, bit); | ||
1946 | ASSERT(nbits > 0); | 1851 | ASSERT(nbits > 0); |
1947 | ASSERT(item->ri_buf[i].i_addr != NULL); | 1852 | ASSERT(item->ri_buf[i].i_addr != NULL); |
1948 | ASSERT(item->ri_buf[i].i_len % XFS_BLF_CHUNK == 0); | 1853 | ASSERT(item->ri_buf[i].i_len % XFS_BLF_CHUNK == 0); |
@@ -2176,77 +2081,46 @@ xlog_recover_do_dquot_buffer( | |||
2176 | * for more details on the implementation of the table of cancel records. | 2081 | * for more details on the implementation of the table of cancel records. |
2177 | */ | 2082 | */ |
2178 | STATIC int | 2083 | STATIC int |
2179 | xlog_recover_do_buffer_trans( | 2084 | xlog_recover_buffer_pass2( |
2180 | xlog_t *log, | 2085 | xlog_t *log, |
2181 | xlog_recover_item_t *item, | 2086 | xlog_recover_item_t *item) |
2182 | int pass) | ||
2183 | { | 2087 | { |
2184 | xfs_buf_log_format_t *buf_f = item->ri_buf[0].i_addr; | 2088 | xfs_buf_log_format_t *buf_f = item->ri_buf[0].i_addr; |
2185 | xfs_mount_t *mp; | 2089 | xfs_mount_t *mp = log->l_mp; |
2186 | xfs_buf_t *bp; | 2090 | xfs_buf_t *bp; |
2187 | int error; | 2091 | int error; |
2188 | int cancel; | ||
2189 | xfs_daddr_t blkno; | ||
2190 | int len; | ||
2191 | ushort flags; | ||
2192 | uint buf_flags; | 2092 | uint buf_flags; |
2193 | 2093 | ||
2194 | if (pass == XLOG_RECOVER_PASS1) { | 2094 | /* |
2195 | /* | 2095 | * In this pass we only want to recover all the buffers which have |
2196 | * In this pass we're only looking for buf items | 2096 | * not been cancelled and are not cancellation buffers themselves. |
2197 | * with the XFS_BLF_CANCEL bit set. | 2097 | */ |
2198 | */ | 2098 | if (xlog_check_buffer_cancelled(log, buf_f->blf_blkno, |
2199 | xlog_recover_do_buffer_pass1(log, buf_f); | 2099 | buf_f->blf_len, buf_f->blf_flags)) { |
2100 | trace_xfs_log_recover_buf_cancel(log, buf_f); | ||
2200 | return 0; | 2101 | return 0; |
2201 | } else { | ||
2202 | /* | ||
2203 | * In this pass we want to recover all the buffers | ||
2204 | * which have not been cancelled and are not | ||
2205 | * cancellation buffers themselves. The routine | ||
2206 | * we call here will tell us whether or not to | ||
2207 | * continue with the replay of this buffer. | ||
2208 | */ | ||
2209 | cancel = xlog_recover_do_buffer_pass2(log, buf_f); | ||
2210 | if (cancel) { | ||
2211 | trace_xfs_log_recover_buf_cancel(log, buf_f); | ||
2212 | return 0; | ||
2213 | } | ||
2214 | } | 2102 | } |
2103 | |||
2215 | trace_xfs_log_recover_buf_recover(log, buf_f); | 2104 | trace_xfs_log_recover_buf_recover(log, buf_f); |
2216 | switch (buf_f->blf_type) { | ||
2217 | case XFS_LI_BUF: | ||
2218 | blkno = buf_f->blf_blkno; | ||
2219 | len = buf_f->blf_len; | ||
2220 | flags = buf_f->blf_flags; | ||
2221 | break; | ||
2222 | default: | ||
2223 | xfs_fs_cmn_err(CE_ALERT, log->l_mp, | ||
2224 | "xfs_log_recover: unknown buffer type 0x%x, logdev %s", | ||
2225 | buf_f->blf_type, log->l_mp->m_logname ? | ||
2226 | log->l_mp->m_logname : "internal"); | ||
2227 | XFS_ERROR_REPORT("xlog_recover_do_buffer_trans", | ||
2228 | XFS_ERRLEVEL_LOW, log->l_mp); | ||
2229 | return XFS_ERROR(EFSCORRUPTED); | ||
2230 | } | ||
2231 | 2105 | ||
2232 | mp = log->l_mp; | ||
2233 | buf_flags = XBF_LOCK; | 2106 | buf_flags = XBF_LOCK; |
2234 | if (!(flags & XFS_BLF_INODE_BUF)) | 2107 | if (!(buf_f->blf_flags & XFS_BLF_INODE_BUF)) |
2235 | buf_flags |= XBF_MAPPED; | 2108 | buf_flags |= XBF_MAPPED; |
2236 | 2109 | ||
2237 | bp = xfs_buf_read(mp->m_ddev_targp, blkno, len, buf_flags); | 2110 | bp = xfs_buf_read(mp->m_ddev_targp, buf_f->blf_blkno, buf_f->blf_len, |
2111 | buf_flags); | ||
2238 | if (XFS_BUF_ISERROR(bp)) { | 2112 | if (XFS_BUF_ISERROR(bp)) { |
2239 | xfs_ioerror_alert("xlog_recover_do..(read#1)", log->l_mp, | 2113 | xfs_ioerror_alert("xlog_recover_do..(read#1)", mp, |
2240 | bp, blkno); | 2114 | bp, buf_f->blf_blkno); |
2241 | error = XFS_BUF_GETERROR(bp); | 2115 | error = XFS_BUF_GETERROR(bp); |
2242 | xfs_buf_relse(bp); | 2116 | xfs_buf_relse(bp); |
2243 | return error; | 2117 | return error; |
2244 | } | 2118 | } |
2245 | 2119 | ||
2246 | error = 0; | 2120 | error = 0; |
2247 | if (flags & XFS_BLF_INODE_BUF) { | 2121 | if (buf_f->blf_flags & XFS_BLF_INODE_BUF) { |
2248 | error = xlog_recover_do_inode_buffer(mp, item, bp, buf_f); | 2122 | error = xlog_recover_do_inode_buffer(mp, item, bp, buf_f); |
2249 | } else if (flags & | 2123 | } else if (buf_f->blf_flags & |
2250 | (XFS_BLF_UDQUOT_BUF|XFS_BLF_PDQUOT_BUF|XFS_BLF_GDQUOT_BUF)) { | 2124 | (XFS_BLF_UDQUOT_BUF|XFS_BLF_PDQUOT_BUF|XFS_BLF_GDQUOT_BUF)) { |
2251 | xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f); | 2125 | xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f); |
2252 | } else { | 2126 | } else { |
@@ -2286,16 +2160,14 @@ xlog_recover_do_buffer_trans( | |||
2286 | } | 2160 | } |
2287 | 2161 | ||
2288 | STATIC int | 2162 | STATIC int |
2289 | xlog_recover_do_inode_trans( | 2163 | xlog_recover_inode_pass2( |
2290 | xlog_t *log, | 2164 | xlog_t *log, |
2291 | xlog_recover_item_t *item, | 2165 | xlog_recover_item_t *item) |
2292 | int pass) | ||
2293 | { | 2166 | { |
2294 | xfs_inode_log_format_t *in_f; | 2167 | xfs_inode_log_format_t *in_f; |
2295 | xfs_mount_t *mp; | 2168 | xfs_mount_t *mp = log->l_mp; |
2296 | xfs_buf_t *bp; | 2169 | xfs_buf_t *bp; |
2297 | xfs_dinode_t *dip; | 2170 | xfs_dinode_t *dip; |
2298 | xfs_ino_t ino; | ||
2299 | int len; | 2171 | int len; |
2300 | xfs_caddr_t src; | 2172 | xfs_caddr_t src; |
2301 | xfs_caddr_t dest; | 2173 | xfs_caddr_t dest; |
@@ -2305,10 +2177,6 @@ xlog_recover_do_inode_trans( | |||
2305 | xfs_icdinode_t *dicp; | 2177 | xfs_icdinode_t *dicp; |
2306 | int need_free = 0; | 2178 | int need_free = 0; |
2307 | 2179 | ||
2308 | if (pass == XLOG_RECOVER_PASS1) { | ||
2309 | return 0; | ||
2310 | } | ||
2311 | |||
2312 | if (item->ri_buf[0].i_len == sizeof(xfs_inode_log_format_t)) { | 2180 | if (item->ri_buf[0].i_len == sizeof(xfs_inode_log_format_t)) { |
2313 | in_f = item->ri_buf[0].i_addr; | 2181 | in_f = item->ri_buf[0].i_addr; |
2314 | } else { | 2182 | } else { |
@@ -2318,8 +2186,6 @@ xlog_recover_do_inode_trans( | |||
2318 | if (error) | 2186 | if (error) |
2319 | goto error; | 2187 | goto error; |
2320 | } | 2188 | } |
2321 | ino = in_f->ilf_ino; | ||
2322 | mp = log->l_mp; | ||
2323 | 2189 | ||
2324 | /* | 2190 | /* |
2325 | * Inode buffers can be freed, look out for it, | 2191 | * Inode buffers can be freed, look out for it, |
@@ -2354,8 +2220,8 @@ xlog_recover_do_inode_trans( | |||
2354 | xfs_buf_relse(bp); | 2220 | xfs_buf_relse(bp); |
2355 | xfs_fs_cmn_err(CE_ALERT, mp, | 2221 | xfs_fs_cmn_err(CE_ALERT, mp, |
2356 | "xfs_inode_recover: Bad inode magic number, dino ptr = 0x%p, dino bp = 0x%p, ino = %Ld", | 2222 | "xfs_inode_recover: Bad inode magic number, dino ptr = 0x%p, dino bp = 0x%p, ino = %Ld", |
2357 | dip, bp, ino); | 2223 | dip, bp, in_f->ilf_ino); |
2358 | XFS_ERROR_REPORT("xlog_recover_do_inode_trans(1)", | 2224 | XFS_ERROR_REPORT("xlog_recover_inode_pass2(1)", |
2359 | XFS_ERRLEVEL_LOW, mp); | 2225 | XFS_ERRLEVEL_LOW, mp); |
2360 | error = EFSCORRUPTED; | 2226 | error = EFSCORRUPTED; |
2361 | goto error; | 2227 | goto error; |
@@ -2365,8 +2231,8 @@ xlog_recover_do_inode_trans( | |||
2365 | xfs_buf_relse(bp); | 2231 | xfs_buf_relse(bp); |
2366 | xfs_fs_cmn_err(CE_ALERT, mp, | 2232 | xfs_fs_cmn_err(CE_ALERT, mp, |
2367 | "xfs_inode_recover: Bad inode log record, rec ptr 0x%p, ino %Ld", | 2233 | "xfs_inode_recover: Bad inode log record, rec ptr 0x%p, ino %Ld", |
2368 | item, ino); | 2234 | item, in_f->ilf_ino); |
2369 | XFS_ERROR_REPORT("xlog_recover_do_inode_trans(2)", | 2235 | XFS_ERROR_REPORT("xlog_recover_inode_pass2(2)", |
2370 | XFS_ERRLEVEL_LOW, mp); | 2236 | XFS_ERRLEVEL_LOW, mp); |
2371 | error = EFSCORRUPTED; | 2237 | error = EFSCORRUPTED; |
2372 | goto error; | 2238 | goto error; |
@@ -2394,12 +2260,12 @@ xlog_recover_do_inode_trans( | |||
2394 | if (unlikely((dicp->di_mode & S_IFMT) == S_IFREG)) { | 2260 | if (unlikely((dicp->di_mode & S_IFMT) == S_IFREG)) { |
2395 | if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) && | 2261 | if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) && |
2396 | (dicp->di_format != XFS_DINODE_FMT_BTREE)) { | 2262 | (dicp->di_format != XFS_DINODE_FMT_BTREE)) { |
2397 | XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(3)", | 2263 | XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(3)", |
2398 | XFS_ERRLEVEL_LOW, mp, dicp); | 2264 | XFS_ERRLEVEL_LOW, mp, dicp); |
2399 | xfs_buf_relse(bp); | 2265 | xfs_buf_relse(bp); |
2400 | xfs_fs_cmn_err(CE_ALERT, mp, | 2266 | xfs_fs_cmn_err(CE_ALERT, mp, |
2401 | "xfs_inode_recover: Bad regular inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", | 2267 | "xfs_inode_recover: Bad regular inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", |
2402 | item, dip, bp, ino); | 2268 | item, dip, bp, in_f->ilf_ino); |
2403 | error = EFSCORRUPTED; | 2269 | error = EFSCORRUPTED; |
2404 | goto error; | 2270 | goto error; |
2405 | } | 2271 | } |
@@ -2407,40 +2273,40 @@ xlog_recover_do_inode_trans( | |||
2407 | if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) && | 2273 | if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) && |
2408 | (dicp->di_format != XFS_DINODE_FMT_BTREE) && | 2274 | (dicp->di_format != XFS_DINODE_FMT_BTREE) && |
2409 | (dicp->di_format != XFS_DINODE_FMT_LOCAL)) { | 2275 | (dicp->di_format != XFS_DINODE_FMT_LOCAL)) { |
2410 | XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(4)", | 2276 | XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(4)", |
2411 | XFS_ERRLEVEL_LOW, mp, dicp); | 2277 | XFS_ERRLEVEL_LOW, mp, dicp); |
2412 | xfs_buf_relse(bp); | 2278 | xfs_buf_relse(bp); |
2413 | xfs_fs_cmn_err(CE_ALERT, mp, | 2279 | xfs_fs_cmn_err(CE_ALERT, mp, |
2414 | "xfs_inode_recover: Bad dir inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", | 2280 | "xfs_inode_recover: Bad dir inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", |
2415 | item, dip, bp, ino); | 2281 | item, dip, bp, in_f->ilf_ino); |
2416 | error = EFSCORRUPTED; | 2282 | error = EFSCORRUPTED; |
2417 | goto error; | 2283 | goto error; |
2418 | } | 2284 | } |
2419 | } | 2285 | } |
2420 | if (unlikely(dicp->di_nextents + dicp->di_anextents > dicp->di_nblocks)){ | 2286 | if (unlikely(dicp->di_nextents + dicp->di_anextents > dicp->di_nblocks)){ |
2421 | XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(5)", | 2287 | XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(5)", |
2422 | XFS_ERRLEVEL_LOW, mp, dicp); | 2288 | XFS_ERRLEVEL_LOW, mp, dicp); |
2423 | xfs_buf_relse(bp); | 2289 | xfs_buf_relse(bp); |
2424 | xfs_fs_cmn_err(CE_ALERT, mp, | 2290 | xfs_fs_cmn_err(CE_ALERT, mp, |
2425 | "xfs_inode_recover: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, total extents = %d, nblocks = %Ld", | 2291 | "xfs_inode_recover: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, total extents = %d, nblocks = %Ld", |
2426 | item, dip, bp, ino, | 2292 | item, dip, bp, in_f->ilf_ino, |
2427 | dicp->di_nextents + dicp->di_anextents, | 2293 | dicp->di_nextents + dicp->di_anextents, |
2428 | dicp->di_nblocks); | 2294 | dicp->di_nblocks); |
2429 | error = EFSCORRUPTED; | 2295 | error = EFSCORRUPTED; |
2430 | goto error; | 2296 | goto error; |
2431 | } | 2297 | } |
2432 | if (unlikely(dicp->di_forkoff > mp->m_sb.sb_inodesize)) { | 2298 | if (unlikely(dicp->di_forkoff > mp->m_sb.sb_inodesize)) { |
2433 | XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(6)", | 2299 | XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(6)", |
2434 | XFS_ERRLEVEL_LOW, mp, dicp); | 2300 | XFS_ERRLEVEL_LOW, mp, dicp); |
2435 | xfs_buf_relse(bp); | 2301 | xfs_buf_relse(bp); |
2436 | xfs_fs_cmn_err(CE_ALERT, mp, | 2302 | xfs_fs_cmn_err(CE_ALERT, mp, |
2437 | "xfs_inode_recover: Bad inode log rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, forkoff 0x%x", | 2303 | "xfs_inode_recover: Bad inode log rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, forkoff 0x%x", |
2438 | item, dip, bp, ino, dicp->di_forkoff); | 2304 | item, dip, bp, in_f->ilf_ino, dicp->di_forkoff); |
2439 | error = EFSCORRUPTED; | 2305 | error = EFSCORRUPTED; |
2440 | goto error; | 2306 | goto error; |
2441 | } | 2307 | } |
2442 | if (unlikely(item->ri_buf[1].i_len > sizeof(struct xfs_icdinode))) { | 2308 | if (unlikely(item->ri_buf[1].i_len > sizeof(struct xfs_icdinode))) { |
2443 | XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(7)", | 2309 | XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(7)", |
2444 | XFS_ERRLEVEL_LOW, mp, dicp); | 2310 | XFS_ERRLEVEL_LOW, mp, dicp); |
2445 | xfs_buf_relse(bp); | 2311 | xfs_buf_relse(bp); |
2446 | xfs_fs_cmn_err(CE_ALERT, mp, | 2312 | xfs_fs_cmn_err(CE_ALERT, mp, |
@@ -2532,7 +2398,7 @@ xlog_recover_do_inode_trans( | |||
2532 | break; | 2398 | break; |
2533 | 2399 | ||
2534 | default: | 2400 | default: |
2535 | xlog_warn("XFS: xlog_recover_do_inode_trans: Invalid flag"); | 2401 | xlog_warn("XFS: xlog_recover_inode_pass2: Invalid flag"); |
2536 | ASSERT(0); | 2402 | ASSERT(0); |
2537 | xfs_buf_relse(bp); | 2403 | xfs_buf_relse(bp); |
2538 | error = EIO; | 2404 | error = EIO; |
@@ -2556,18 +2422,11 @@ error: | |||
2556 | * of that type. | 2422 | * of that type. |
2557 | */ | 2423 | */ |
2558 | STATIC int | 2424 | STATIC int |
2559 | xlog_recover_do_quotaoff_trans( | 2425 | xlog_recover_quotaoff_pass1( |
2560 | xlog_t *log, | 2426 | xlog_t *log, |
2561 | xlog_recover_item_t *item, | 2427 | xlog_recover_item_t *item) |
2562 | int pass) | ||
2563 | { | 2428 | { |
2564 | xfs_qoff_logformat_t *qoff_f; | 2429 | xfs_qoff_logformat_t *qoff_f = item->ri_buf[0].i_addr; |
2565 | |||
2566 | if (pass == XLOG_RECOVER_PASS2) { | ||
2567 | return (0); | ||
2568 | } | ||
2569 | |||
2570 | qoff_f = item->ri_buf[0].i_addr; | ||
2571 | ASSERT(qoff_f); | 2430 | ASSERT(qoff_f); |
2572 | 2431 | ||
2573 | /* | 2432 | /* |
@@ -2588,22 +2447,17 @@ xlog_recover_do_quotaoff_trans( | |||
2588 | * Recover a dquot record | 2447 | * Recover a dquot record |
2589 | */ | 2448 | */ |
2590 | STATIC int | 2449 | STATIC int |
2591 | xlog_recover_do_dquot_trans( | 2450 | xlog_recover_dquot_pass2( |
2592 | xlog_t *log, | 2451 | xlog_t *log, |
2593 | xlog_recover_item_t *item, | 2452 | xlog_recover_item_t *item) |
2594 | int pass) | ||
2595 | { | 2453 | { |
2596 | xfs_mount_t *mp; | 2454 | xfs_mount_t *mp = log->l_mp; |
2597 | xfs_buf_t *bp; | 2455 | xfs_buf_t *bp; |
2598 | struct xfs_disk_dquot *ddq, *recddq; | 2456 | struct xfs_disk_dquot *ddq, *recddq; |
2599 | int error; | 2457 | int error; |
2600 | xfs_dq_logformat_t *dq_f; | 2458 | xfs_dq_logformat_t *dq_f; |
2601 | uint type; | 2459 | uint type; |
2602 | 2460 | ||
2603 | if (pass == XLOG_RECOVER_PASS1) { | ||
2604 | return 0; | ||
2605 | } | ||
2606 | mp = log->l_mp; | ||
2607 | 2461 | ||
2608 | /* | 2462 | /* |
2609 | * Filesystems are required to send in quota flags at mount time. | 2463 | * Filesystems are required to send in quota flags at mount time. |
@@ -2647,7 +2501,7 @@ xlog_recover_do_dquot_trans( | |||
2647 | if ((error = xfs_qm_dqcheck(recddq, | 2501 | if ((error = xfs_qm_dqcheck(recddq, |
2648 | dq_f->qlf_id, | 2502 | dq_f->qlf_id, |
2649 | 0, XFS_QMOPT_DOWARN, | 2503 | 0, XFS_QMOPT_DOWARN, |
2650 | "xlog_recover_do_dquot_trans (log copy)"))) { | 2504 | "xlog_recover_dquot_pass2 (log copy)"))) { |
2651 | return XFS_ERROR(EIO); | 2505 | return XFS_ERROR(EIO); |
2652 | } | 2506 | } |
2653 | ASSERT(dq_f->qlf_len == 1); | 2507 | ASSERT(dq_f->qlf_len == 1); |
@@ -2670,7 +2524,7 @@ xlog_recover_do_dquot_trans( | |||
2670 | * minimal initialization then. | 2524 | * minimal initialization then. |
2671 | */ | 2525 | */ |
2672 | if (xfs_qm_dqcheck(ddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN, | 2526 | if (xfs_qm_dqcheck(ddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN, |
2673 | "xlog_recover_do_dquot_trans")) { | 2527 | "xlog_recover_dquot_pass2")) { |
2674 | xfs_buf_relse(bp); | 2528 | xfs_buf_relse(bp); |
2675 | return XFS_ERROR(EIO); | 2529 | return XFS_ERROR(EIO); |
2676 | } | 2530 | } |
@@ -2693,38 +2547,31 @@ xlog_recover_do_dquot_trans( | |||
2693 | * LSN. | 2547 | * LSN. |
2694 | */ | 2548 | */ |
2695 | STATIC int | 2549 | STATIC int |
2696 | xlog_recover_do_efi_trans( | 2550 | xlog_recover_efi_pass2( |
2697 | xlog_t *log, | 2551 | xlog_t *log, |
2698 | xlog_recover_item_t *item, | 2552 | xlog_recover_item_t *item, |
2699 | xfs_lsn_t lsn, | 2553 | xfs_lsn_t lsn) |
2700 | int pass) | ||
2701 | { | 2554 | { |
2702 | int error; | 2555 | int error; |
2703 | xfs_mount_t *mp; | 2556 | xfs_mount_t *mp = log->l_mp; |
2704 | xfs_efi_log_item_t *efip; | 2557 | xfs_efi_log_item_t *efip; |
2705 | xfs_efi_log_format_t *efi_formatp; | 2558 | xfs_efi_log_format_t *efi_formatp; |
2706 | 2559 | ||
2707 | if (pass == XLOG_RECOVER_PASS1) { | ||
2708 | return 0; | ||
2709 | } | ||
2710 | |||
2711 | efi_formatp = item->ri_buf[0].i_addr; | 2560 | efi_formatp = item->ri_buf[0].i_addr; |
2712 | 2561 | ||
2713 | mp = log->l_mp; | ||
2714 | efip = xfs_efi_init(mp, efi_formatp->efi_nextents); | 2562 | efip = xfs_efi_init(mp, efi_formatp->efi_nextents); |
2715 | if ((error = xfs_efi_copy_format(&(item->ri_buf[0]), | 2563 | if ((error = xfs_efi_copy_format(&(item->ri_buf[0]), |
2716 | &(efip->efi_format)))) { | 2564 | &(efip->efi_format)))) { |
2717 | xfs_efi_item_free(efip); | 2565 | xfs_efi_item_free(efip); |
2718 | return error; | 2566 | return error; |
2719 | } | 2567 | } |
2720 | efip->efi_next_extent = efi_formatp->efi_nextents; | 2568 | atomic_set(&efip->efi_next_extent, efi_formatp->efi_nextents); |
2721 | efip->efi_flags |= XFS_EFI_COMMITTED; | ||
2722 | 2569 | ||
2723 | spin_lock(&log->l_ailp->xa_lock); | 2570 | spin_lock(&log->l_ailp->xa_lock); |
2724 | /* | 2571 | /* |
2725 | * xfs_trans_ail_update() drops the AIL lock. | 2572 | * xfs_trans_ail_update() drops the AIL lock. |
2726 | */ | 2573 | */ |
2727 | xfs_trans_ail_update(log->l_ailp, (xfs_log_item_t *)efip, lsn); | 2574 | xfs_trans_ail_update(log->l_ailp, &efip->efi_item, lsn); |
2728 | return 0; | 2575 | return 0; |
2729 | } | 2576 | } |
2730 | 2577 | ||
@@ -2737,11 +2584,10 @@ xlog_recover_do_efi_trans( | |||
2737 | * efd format structure. If we find it, we remove the efi from the | 2584 | * efd format structure. If we find it, we remove the efi from the |
2738 | * AIL and free it. | 2585 | * AIL and free it. |
2739 | */ | 2586 | */ |
2740 | STATIC void | 2587 | STATIC int |
2741 | xlog_recover_do_efd_trans( | 2588 | xlog_recover_efd_pass2( |
2742 | xlog_t *log, | 2589 | xlog_t *log, |
2743 | xlog_recover_item_t *item, | 2590 | xlog_recover_item_t *item) |
2744 | int pass) | ||
2745 | { | 2591 | { |
2746 | xfs_efd_log_format_t *efd_formatp; | 2592 | xfs_efd_log_format_t *efd_formatp; |
2747 | xfs_efi_log_item_t *efip = NULL; | 2593 | xfs_efi_log_item_t *efip = NULL; |
@@ -2750,10 +2596,6 @@ xlog_recover_do_efd_trans( | |||
2750 | struct xfs_ail_cursor cur; | 2596 | struct xfs_ail_cursor cur; |
2751 | struct xfs_ail *ailp = log->l_ailp; | 2597 | struct xfs_ail *ailp = log->l_ailp; |
2752 | 2598 | ||
2753 | if (pass == XLOG_RECOVER_PASS1) { | ||
2754 | return; | ||
2755 | } | ||
2756 | |||
2757 | efd_formatp = item->ri_buf[0].i_addr; | 2599 | efd_formatp = item->ri_buf[0].i_addr; |
2758 | ASSERT((item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_32_t) + | 2600 | ASSERT((item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_32_t) + |
2759 | ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_32_t)))) || | 2601 | ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_32_t)))) || |
@@ -2785,62 +2627,6 @@ xlog_recover_do_efd_trans( | |||
2785 | } | 2627 | } |
2786 | xfs_trans_ail_cursor_done(ailp, &cur); | 2628 | xfs_trans_ail_cursor_done(ailp, &cur); |
2787 | spin_unlock(&ailp->xa_lock); | 2629 | spin_unlock(&ailp->xa_lock); |
2788 | } | ||
2789 | |||
2790 | /* | ||
2791 | * Perform the transaction | ||
2792 | * | ||
2793 | * If the transaction modifies a buffer or inode, do it now. Otherwise, | ||
2794 | * EFIs and EFDs get queued up by adding entries into the AIL for them. | ||
2795 | */ | ||
2796 | STATIC int | ||
2797 | xlog_recover_do_trans( | ||
2798 | xlog_t *log, | ||
2799 | xlog_recover_t *trans, | ||
2800 | int pass) | ||
2801 | { | ||
2802 | int error = 0; | ||
2803 | xlog_recover_item_t *item; | ||
2804 | |||
2805 | error = xlog_recover_reorder_trans(log, trans, pass); | ||
2806 | if (error) | ||
2807 | return error; | ||
2808 | |||
2809 | list_for_each_entry(item, &trans->r_itemq, ri_list) { | ||
2810 | trace_xfs_log_recover_item_recover(log, trans, item, pass); | ||
2811 | switch (ITEM_TYPE(item)) { | ||
2812 | case XFS_LI_BUF: | ||
2813 | error = xlog_recover_do_buffer_trans(log, item, pass); | ||
2814 | break; | ||
2815 | case XFS_LI_INODE: | ||
2816 | error = xlog_recover_do_inode_trans(log, item, pass); | ||
2817 | break; | ||
2818 | case XFS_LI_EFI: | ||
2819 | error = xlog_recover_do_efi_trans(log, item, | ||
2820 | trans->r_lsn, pass); | ||
2821 | break; | ||
2822 | case XFS_LI_EFD: | ||
2823 | xlog_recover_do_efd_trans(log, item, pass); | ||
2824 | error = 0; | ||
2825 | break; | ||
2826 | case XFS_LI_DQUOT: | ||
2827 | error = xlog_recover_do_dquot_trans(log, item, pass); | ||
2828 | break; | ||
2829 | case XFS_LI_QUOTAOFF: | ||
2830 | error = xlog_recover_do_quotaoff_trans(log, item, | ||
2831 | pass); | ||
2832 | break; | ||
2833 | default: | ||
2834 | xlog_warn( | ||
2835 | "XFS: invalid item type (%d) xlog_recover_do_trans", ITEM_TYPE(item)); | ||
2836 | ASSERT(0); | ||
2837 | error = XFS_ERROR(EIO); | ||
2838 | break; | ||
2839 | } | ||
2840 | |||
2841 | if (error) | ||
2842 | return error; | ||
2843 | } | ||
2844 | 2630 | ||
2845 | return 0; | 2631 | return 0; |
2846 | } | 2632 | } |
@@ -2852,7 +2638,7 @@ xlog_recover_do_trans( | |||
2852 | */ | 2638 | */ |
2853 | STATIC void | 2639 | STATIC void |
2854 | xlog_recover_free_trans( | 2640 | xlog_recover_free_trans( |
2855 | xlog_recover_t *trans) | 2641 | struct xlog_recover *trans) |
2856 | { | 2642 | { |
2857 | xlog_recover_item_t *item, *n; | 2643 | xlog_recover_item_t *item, *n; |
2858 | int i; | 2644 | int i; |
@@ -2871,17 +2657,95 @@ xlog_recover_free_trans( | |||
2871 | } | 2657 | } |
2872 | 2658 | ||
2873 | STATIC int | 2659 | STATIC int |
2660 | xlog_recover_commit_pass1( | ||
2661 | struct log *log, | ||
2662 | struct xlog_recover *trans, | ||
2663 | xlog_recover_item_t *item) | ||
2664 | { | ||
2665 | trace_xfs_log_recover_item_recover(log, trans, item, XLOG_RECOVER_PASS1); | ||
2666 | |||
2667 | switch (ITEM_TYPE(item)) { | ||
2668 | case XFS_LI_BUF: | ||
2669 | return xlog_recover_buffer_pass1(log, item); | ||
2670 | case XFS_LI_QUOTAOFF: | ||
2671 | return xlog_recover_quotaoff_pass1(log, item); | ||
2672 | case XFS_LI_INODE: | ||
2673 | case XFS_LI_EFI: | ||
2674 | case XFS_LI_EFD: | ||
2675 | case XFS_LI_DQUOT: | ||
2676 | /* nothing to do in pass 1 */ | ||
2677 | return 0; | ||
2678 | default: | ||
2679 | xlog_warn( | ||
2680 | "XFS: invalid item type (%d) xlog_recover_commit_pass1", | ||
2681 | ITEM_TYPE(item)); | ||
2682 | ASSERT(0); | ||
2683 | return XFS_ERROR(EIO); | ||
2684 | } | ||
2685 | } | ||
2686 | |||
2687 | STATIC int | ||
2688 | xlog_recover_commit_pass2( | ||
2689 | struct log *log, | ||
2690 | struct xlog_recover *trans, | ||
2691 | xlog_recover_item_t *item) | ||
2692 | { | ||
2693 | trace_xfs_log_recover_item_recover(log, trans, item, XLOG_RECOVER_PASS2); | ||
2694 | |||
2695 | switch (ITEM_TYPE(item)) { | ||
2696 | case XFS_LI_BUF: | ||
2697 | return xlog_recover_buffer_pass2(log, item); | ||
2698 | case XFS_LI_INODE: | ||
2699 | return xlog_recover_inode_pass2(log, item); | ||
2700 | case XFS_LI_EFI: | ||
2701 | return xlog_recover_efi_pass2(log, item, trans->r_lsn); | ||
2702 | case XFS_LI_EFD: | ||
2703 | return xlog_recover_efd_pass2(log, item); | ||
2704 | case XFS_LI_DQUOT: | ||
2705 | return xlog_recover_dquot_pass2(log, item); | ||
2706 | case XFS_LI_QUOTAOFF: | ||
2707 | /* nothing to do in pass2 */ | ||
2708 | return 0; | ||
2709 | default: | ||
2710 | xlog_warn( | ||
2711 | "XFS: invalid item type (%d) xlog_recover_commit_pass2", | ||
2712 | ITEM_TYPE(item)); | ||
2713 | ASSERT(0); | ||
2714 | return XFS_ERROR(EIO); | ||
2715 | } | ||
2716 | } | ||
2717 | |||
2718 | /* | ||
2719 | * Perform the transaction. | ||
2720 | * | ||
2721 | * If the transaction modifies a buffer or inode, do it now. Otherwise, | ||
2722 | * EFIs and EFDs get queued up by adding entries into the AIL for them. | ||
2723 | */ | ||
2724 | STATIC int | ||
2874 | xlog_recover_commit_trans( | 2725 | xlog_recover_commit_trans( |
2875 | xlog_t *log, | 2726 | struct log *log, |
2876 | xlog_recover_t *trans, | 2727 | struct xlog_recover *trans, |
2877 | int pass) | 2728 | int pass) |
2878 | { | 2729 | { |
2879 | int error; | 2730 | int error = 0; |
2731 | xlog_recover_item_t *item; | ||
2880 | 2732 | ||
2881 | hlist_del(&trans->r_list); | 2733 | hlist_del(&trans->r_list); |
2882 | if ((error = xlog_recover_do_trans(log, trans, pass))) | 2734 | |
2735 | error = xlog_recover_reorder_trans(log, trans, pass); | ||
2736 | if (error) | ||
2883 | return error; | 2737 | return error; |
2884 | xlog_recover_free_trans(trans); /* no error */ | 2738 | |
2739 | list_for_each_entry(item, &trans->r_itemq, ri_list) { | ||
2740 | if (pass == XLOG_RECOVER_PASS1) | ||
2741 | error = xlog_recover_commit_pass1(log, trans, item); | ||
2742 | else | ||
2743 | error = xlog_recover_commit_pass2(log, trans, item); | ||
2744 | if (error) | ||
2745 | return error; | ||
2746 | } | ||
2747 | |||
2748 | xlog_recover_free_trans(trans); | ||
2885 | return 0; | 2749 | return 0; |
2886 | } | 2750 | } |
2887 | 2751 | ||
@@ -3011,7 +2875,7 @@ xlog_recover_process_efi( | |||
3011 | xfs_extent_t *extp; | 2875 | xfs_extent_t *extp; |
3012 | xfs_fsblock_t startblock_fsb; | 2876 | xfs_fsblock_t startblock_fsb; |
3013 | 2877 | ||
3014 | ASSERT(!(efip->efi_flags & XFS_EFI_RECOVERED)); | 2878 | ASSERT(!test_bit(XFS_EFI_RECOVERED, &efip->efi_flags)); |
3015 | 2879 | ||
3016 | /* | 2880 | /* |
3017 | * First check the validity of the extents described by the | 2881 | * First check the validity of the extents described by the |
@@ -3050,7 +2914,7 @@ xlog_recover_process_efi( | |||
3050 | extp->ext_len); | 2914 | extp->ext_len); |
3051 | } | 2915 | } |
3052 | 2916 | ||
3053 | efip->efi_flags |= XFS_EFI_RECOVERED; | 2917 | set_bit(XFS_EFI_RECOVERED, &efip->efi_flags); |
3054 | error = xfs_trans_commit(tp, 0); | 2918 | error = xfs_trans_commit(tp, 0); |
3055 | return error; | 2919 | return error; |
3056 | 2920 | ||
@@ -3107,7 +2971,7 @@ xlog_recover_process_efis( | |||
3107 | * Skip EFIs that we've already processed. | 2971 | * Skip EFIs that we've already processed. |
3108 | */ | 2972 | */ |
3109 | efip = (xfs_efi_log_item_t *)lip; | 2973 | efip = (xfs_efi_log_item_t *)lip; |
3110 | if (efip->efi_flags & XFS_EFI_RECOVERED) { | 2974 | if (test_bit(XFS_EFI_RECOVERED, &efip->efi_flags)) { |
3111 | lip = xfs_trans_ail_cursor_next(ailp, &cur); | 2975 | lip = xfs_trans_ail_cursor_next(ailp, &cur); |
3112 | continue; | 2976 | continue; |
3113 | } | 2977 | } |
@@ -3724,7 +3588,7 @@ xlog_do_log_recovery( | |||
3724 | xfs_daddr_t head_blk, | 3588 | xfs_daddr_t head_blk, |
3725 | xfs_daddr_t tail_blk) | 3589 | xfs_daddr_t tail_blk) |
3726 | { | 3590 | { |
3727 | int error; | 3591 | int error, i; |
3728 | 3592 | ||
3729 | ASSERT(head_blk != tail_blk); | 3593 | ASSERT(head_blk != tail_blk); |
3730 | 3594 | ||
@@ -3732,10 +3596,12 @@ xlog_do_log_recovery( | |||
3732 | * First do a pass to find all of the cancelled buf log items. | 3596 | * First do a pass to find all of the cancelled buf log items. |
3733 | * Store them in the buf_cancel_table for use in the second pass. | 3597 | * Store them in the buf_cancel_table for use in the second pass. |
3734 | */ | 3598 | */ |
3735 | log->l_buf_cancel_table = | 3599 | log->l_buf_cancel_table = kmem_zalloc(XLOG_BC_TABLE_SIZE * |
3736 | (xfs_buf_cancel_t **)kmem_zalloc(XLOG_BC_TABLE_SIZE * | 3600 | sizeof(struct list_head), |
3737 | sizeof(xfs_buf_cancel_t*), | ||
3738 | KM_SLEEP); | 3601 | KM_SLEEP); |
3602 | for (i = 0; i < XLOG_BC_TABLE_SIZE; i++) | ||
3603 | INIT_LIST_HEAD(&log->l_buf_cancel_table[i]); | ||
3604 | |||
3739 | error = xlog_do_recovery_pass(log, head_blk, tail_blk, | 3605 | error = xlog_do_recovery_pass(log, head_blk, tail_blk, |
3740 | XLOG_RECOVER_PASS1); | 3606 | XLOG_RECOVER_PASS1); |
3741 | if (error != 0) { | 3607 | if (error != 0) { |
@@ -3754,7 +3620,7 @@ xlog_do_log_recovery( | |||
3754 | int i; | 3620 | int i; |
3755 | 3621 | ||
3756 | for (i = 0; i < XLOG_BC_TABLE_SIZE; i++) | 3622 | for (i = 0; i < XLOG_BC_TABLE_SIZE; i++) |
3757 | ASSERT(log->l_buf_cancel_table[i] == NULL); | 3623 | ASSERT(list_empty(&log->l_buf_cancel_table[i])); |
3758 | } | 3624 | } |
3759 | #endif /* DEBUG */ | 3625 | #endif /* DEBUG */ |
3760 | 3626 | ||