aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_log_recover.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_log_recover.c')
-rw-r--r--fs/xfs/xfs_log_recover.c114
1 files changed, 109 insertions, 5 deletions
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 7cf5e4eafe28..6fcc910a50b9 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -45,6 +45,7 @@
45#include "xfs_cksum.h" 45#include "xfs_cksum.h"
46#include "xfs_trace.h" 46#include "xfs_trace.h"
47#include "xfs_icache.h" 47#include "xfs_icache.h"
48#include "xfs_icreate_item.h"
48 49
49/* Need all the magic numbers and buffer ops structures from these headers */ 50/* Need all the magic numbers and buffer ops structures from these headers */
50#include "xfs_symlink.h" 51#include "xfs_symlink.h"
@@ -1617,7 +1618,10 @@ xlog_recover_add_to_trans(
1617 * form the cancelled buffer table. Hence they have tobe done last. 1618 * form the cancelled buffer table. Hence they have tobe done last.
1618 * 1619 *
1619 * 3. Inode allocation buffers must be replayed before inode items that 1620 * 3. Inode allocation buffers must be replayed before inode items that
1620 * read the buffer and replay changes into it. 1621 * read the buffer and replay changes into it. For filesystems using the
1622 * ICREATE transactions, this means XFS_LI_ICREATE objects need to get
1623 * treated the same as inode allocation buffers as they create and
1624 * initialise the buffers directly.
1621 * 1625 *
1622 * 4. Inode unlink buffers must be replayed after inode items are replayed. 1626 * 4. Inode unlink buffers must be replayed after inode items are replayed.
1623 * This ensures that inodes are completely flushed to the inode buffer 1627 * This ensures that inodes are completely flushed to the inode buffer
@@ -1632,10 +1636,17 @@ xlog_recover_add_to_trans(
1632 * from all the other buffers and move them to last. 1636 * from all the other buffers and move them to last.
1633 * 1637 *
1634 * Hence, 4 lists, in order from head to tail: 1638 * Hence, 4 lists, in order from head to tail:
1635 * - buffer_list for all buffers except cancelled/inode unlink buffers 1639 * - buffer_list for all buffers except cancelled/inode unlink buffers
1636 * - item_list for all non-buffer items 1640 * - item_list for all non-buffer items
1637 * - inode_buffer_list for inode unlink buffers 1641 * - inode_buffer_list for inode unlink buffers
1638 * - cancel_list for the cancelled buffers 1642 * - cancel_list for the cancelled buffers
1643 *
1644 * Note that we add objects to the tail of the lists so that first-to-last
1645 * ordering is preserved within the lists. Adding objects to the head of the
1646 * list means when we traverse from the head we walk them in last-to-first
1647 * order. For cancelled buffers and inode unlink buffers this doesn't matter,
1648 * but for all other items there may be specific ordering that we need to
1649 * preserve.
1639 */ 1650 */
1640STATIC int 1651STATIC int
1641xlog_recover_reorder_trans( 1652xlog_recover_reorder_trans(
@@ -1655,6 +1666,9 @@ xlog_recover_reorder_trans(
1655 xfs_buf_log_format_t *buf_f = item->ri_buf[0].i_addr; 1666 xfs_buf_log_format_t *buf_f = item->ri_buf[0].i_addr;
1656 1667
1657 switch (ITEM_TYPE(item)) { 1668 switch (ITEM_TYPE(item)) {
1669 case XFS_LI_ICREATE:
1670 list_move_tail(&item->ri_list, &buffer_list);
1671 break;
1658 case XFS_LI_BUF: 1672 case XFS_LI_BUF:
1659 if (buf_f->blf_flags & XFS_BLF_CANCEL) { 1673 if (buf_f->blf_flags & XFS_BLF_CANCEL) {
1660 trace_xfs_log_recover_item_reorder_head(log, 1674 trace_xfs_log_recover_item_reorder_head(log,
@@ -2982,6 +2996,93 @@ xlog_recover_efd_pass2(
2982} 2996}
2983 2997
2984/* 2998/*
2999 * This routine is called when an inode create format structure is found in a
3000 * committed transaction in the log. It's purpose is to initialise the inodes
3001 * being allocated on disk. This requires us to get inode cluster buffers that
3002 * match the range to be intialised, stamped with inode templates and written
3003 * by delayed write so that subsequent modifications will hit the cached buffer
3004 * and only need writing out at the end of recovery.
3005 */
3006STATIC int
3007xlog_recover_do_icreate_pass2(
3008 struct xlog *log,
3009 struct list_head *buffer_list,
3010 xlog_recover_item_t *item)
3011{
3012 struct xfs_mount *mp = log->l_mp;
3013 struct xfs_icreate_log *icl;
3014 xfs_agnumber_t agno;
3015 xfs_agblock_t agbno;
3016 unsigned int count;
3017 unsigned int isize;
3018 xfs_agblock_t length;
3019
3020 icl = (struct xfs_icreate_log *)item->ri_buf[0].i_addr;
3021 if (icl->icl_type != XFS_LI_ICREATE) {
3022 xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad type");
3023 return EINVAL;
3024 }
3025
3026 if (icl->icl_size != 1) {
3027 xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad icl size");
3028 return EINVAL;
3029 }
3030
3031 agno = be32_to_cpu(icl->icl_ag);
3032 if (agno >= mp->m_sb.sb_agcount) {
3033 xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad agno");
3034 return EINVAL;
3035 }
3036 agbno = be32_to_cpu(icl->icl_agbno);
3037 if (!agbno || agbno == NULLAGBLOCK || agbno >= mp->m_sb.sb_agblocks) {
3038 xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad agbno");
3039 return EINVAL;
3040 }
3041 isize = be32_to_cpu(icl->icl_isize);
3042 if (isize != mp->m_sb.sb_inodesize) {
3043 xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad isize");
3044 return EINVAL;
3045 }
3046 count = be32_to_cpu(icl->icl_count);
3047 if (!count) {
3048 xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad count");
3049 return EINVAL;
3050 }
3051 length = be32_to_cpu(icl->icl_length);
3052 if (!length || length >= mp->m_sb.sb_agblocks) {
3053 xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad length");
3054 return EINVAL;
3055 }
3056
3057 /* existing allocation is fixed value */
3058 ASSERT(count == XFS_IALLOC_INODES(mp));
3059 ASSERT(length == XFS_IALLOC_BLOCKS(mp));
3060 if (count != XFS_IALLOC_INODES(mp) ||
3061 length != XFS_IALLOC_BLOCKS(mp)) {
3062 xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad count 2");
3063 return EINVAL;
3064 }
3065
3066 /*
3067 * Inode buffers can be freed. Do not replay the inode initialisation as
3068 * we could be overwriting something written after this inode buffer was
3069 * cancelled.
3070 *
3071 * XXX: we need to iterate all buffers and only init those that are not
3072 * cancelled. I think that a more fine grained factoring of
3073 * xfs_ialloc_inode_init may be appropriate here to enable this to be
3074 * done easily.
3075 */
3076 if (xlog_check_buffer_cancelled(log,
3077 XFS_AGB_TO_DADDR(mp, agno, agbno), length, 0))
3078 return 0;
3079
3080 xfs_ialloc_inode_init(mp, NULL, buffer_list, agno, agbno, length,
3081 be32_to_cpu(icl->icl_gen));
3082 return 0;
3083}
3084
3085/*
2985 * Free up any resources allocated by the transaction 3086 * Free up any resources allocated by the transaction
2986 * 3087 *
2987 * Remember that EFIs, EFDs, and IUNLINKs are handled later. 3088 * Remember that EFIs, EFDs, and IUNLINKs are handled later.
@@ -3023,6 +3124,7 @@ xlog_recover_commit_pass1(
3023 case XFS_LI_EFI: 3124 case XFS_LI_EFI:
3024 case XFS_LI_EFD: 3125 case XFS_LI_EFD:
3025 case XFS_LI_DQUOT: 3126 case XFS_LI_DQUOT:
3127 case XFS_LI_ICREATE:
3026 /* nothing to do in pass 1 */ 3128 /* nothing to do in pass 1 */
3027 return 0; 3129 return 0;
3028 default: 3130 default:
@@ -3053,6 +3155,8 @@ xlog_recover_commit_pass2(
3053 return xlog_recover_efd_pass2(log, item); 3155 return xlog_recover_efd_pass2(log, item);
3054 case XFS_LI_DQUOT: 3156 case XFS_LI_DQUOT:
3055 return xlog_recover_dquot_pass2(log, buffer_list, item); 3157 return xlog_recover_dquot_pass2(log, buffer_list, item);
3158 case XFS_LI_ICREATE:
3159 return xlog_recover_do_icreate_pass2(log, buffer_list, item);
3056 case XFS_LI_QUOTAOFF: 3160 case XFS_LI_QUOTAOFF:
3057 /* nothing to do in pass2 */ 3161 /* nothing to do in pass2 */
3058 return 0; 3162 return 0;