xfs: ensure EFD trans aborts on log recovery extent free failure
[firefly-linux-kernel-4.4.55.git] / fs / xfs / xfs_log_recover.c
index 4f5784f85a5b22e4bad0946106dcb1302f817ace..434ba2cdf6e86f512a04e3d7e93b81882e32bf90 100644 (file)
@@ -147,7 +147,7 @@ xlog_put_bp(
  * Return the address of the start of the given block number's data
  * in a log buffer.  The buffer covers a log sector-aligned region.
  */
-STATIC xfs_caddr_t
+STATIC char *
 xlog_align(
        struct xlog     *log,
        xfs_daddr_t     blk_no,
@@ -203,7 +203,7 @@ xlog_bread(
        xfs_daddr_t     blk_no,
        int             nbblks,
        struct xfs_buf  *bp,
-       xfs_caddr_t     *offset)
+       char            **offset)
 {
        int             error;
 
@@ -225,9 +225,9 @@ xlog_bread_offset(
        xfs_daddr_t     blk_no,         /* block to read from */
        int             nbblks,         /* blocks to read */
        struct xfs_buf  *bp,
-       xfs_caddr_t     offset)
+       char            *offset)
 {
-       xfs_caddr_t     orig_offset = bp->b_addr;
+       char            *orig_offset = bp->b_addr;
        int             orig_len = BBTOB(bp->b_length);
        int             error, error2;
 
@@ -396,7 +396,7 @@ xlog_find_cycle_start(
        xfs_daddr_t     *last_blk,
        uint            cycle)
 {
-       xfs_caddr_t     offset;
+       char            *offset;
        xfs_daddr_t     mid_blk;
        xfs_daddr_t     end_blk;
        uint            mid_cycle;
@@ -443,7 +443,7 @@ xlog_find_verify_cycle(
        uint            cycle;
        xfs_buf_t       *bp;
        xfs_daddr_t     bufblks;
-       xfs_caddr_t     buf = NULL;
+       char            *buf = NULL;
        int             error = 0;
 
        /*
@@ -509,7 +509,7 @@ xlog_find_verify_log_record(
 {
        xfs_daddr_t             i;
        xfs_buf_t               *bp;
-       xfs_caddr_t             offset = NULL;
+       char                    *offset = NULL;
        xlog_rec_header_t       *head = NULL;
        int                     error = 0;
        int                     smallmem = 0;
@@ -616,7 +616,7 @@ xlog_find_head(
        xfs_daddr_t     *return_head_blk)
 {
        xfs_buf_t       *bp;
-       xfs_caddr_t     offset;
+       char            *offset;
        xfs_daddr_t     new_blk, first_blk, start_blk, last_blk, head_blk;
        int             num_scan_bblks;
        uint            first_half_cycle, last_half_cycle;
@@ -891,7 +891,7 @@ xlog_find_tail(
 {
        xlog_rec_header_t       *rhead;
        xlog_op_header_t        *op_head;
-       xfs_caddr_t             offset = NULL;
+       char                    *offset = NULL;
        xfs_buf_t               *bp;
        int                     error, i, found;
        xfs_daddr_t             umount_data_blk;
@@ -1099,7 +1099,7 @@ xlog_find_zeroed(
        xfs_daddr_t     *blk_no)
 {
        xfs_buf_t       *bp;
-       xfs_caddr_t     offset;
+       char            *offset;
        uint            first_cycle, last_cycle;
        xfs_daddr_t     new_blk, last_blk, start_blk;
        xfs_daddr_t     num_scan_bblks;
@@ -1199,7 +1199,7 @@ bp_err:
 STATIC void
 xlog_add_record(
        struct xlog             *log,
-       xfs_caddr_t             buf,
+       char                    *buf,
        int                     cycle,
        int                     block,
        int                     tail_cycle,
@@ -1227,7 +1227,7 @@ xlog_write_log_records(
        int             tail_cycle,
        int             tail_block)
 {
-       xfs_caddr_t     offset;
+       char            *offset;
        xfs_buf_t       *bp;
        int             balign, ealign;
        int             sectbb = log->l_sectBBsize;
@@ -1789,8 +1789,7 @@ xlog_recover_do_inode_buffer(
                        return -EFSCORRUPTED;
                }
 
-               buffer_nextp = (xfs_agino_t *)xfs_buf_offset(bp,
-                                             next_unlinked_offset);
+               buffer_nextp = xfs_buf_offset(bp, next_unlinked_offset);
                *buffer_nextp = *logged_nextp;
 
                /*
@@ -1798,7 +1797,7 @@ xlog_recover_do_inode_buffer(
                 * have to leave the inode in a consistent state for whoever
                 * reads it next....
                 */
-               xfs_dinode_calc_crc(mp, (struct xfs_dinode *)
+               xfs_dinode_calc_crc(mp,
                                xfs_buf_offset(bp, i * mp->m_sb.sb_inodesize));
 
        }
@@ -2503,8 +2502,8 @@ xlog_recover_inode_pass2(
        xfs_buf_t               *bp;
        xfs_dinode_t            *dip;
        int                     len;
-       xfs_caddr_t             src;
-       xfs_caddr_t             dest;
+       char                    *src;
+       char                    *dest;
        int                     error;
        int                     attr_index;
        uint                    fields;
@@ -2546,7 +2545,7 @@ xlog_recover_inode_pass2(
                goto out_release;
        }
        ASSERT(in_f->ilf_fields & XFS_ILOG_CORE);
-       dip = (xfs_dinode_t *)xfs_buf_offset(bp, in_f->ilf_boffset);
+       dip = xfs_buf_offset(bp, in_f->ilf_boffset);
 
        /*
         * Make sure the place we're flushing out to really looks
@@ -2885,7 +2884,7 @@ xlog_recover_dquot_pass2(
                return error;
 
        ASSERT(bp);
-       ddq = (xfs_disk_dquot_t *)xfs_buf_offset(bp, dq_f->qlf_boffset);
+       ddq = xfs_buf_offset(bp, dq_f->qlf_boffset);
 
        /*
         * If the dquot has an LSN in it, recover the dquot only if it's less
@@ -3068,12 +3067,22 @@ xlog_recover_do_icreate_pass2(
                return -EINVAL;
        }
 
-       /* existing allocation is fixed value */
-       ASSERT(count == mp->m_ialloc_inos);
-       ASSERT(length == mp->m_ialloc_blks);
-       if (count != mp->m_ialloc_inos ||
-            length != mp->m_ialloc_blks) {
-               xfs_warn(log->l_mp, "xlog_recover_do_icreate_trans: bad count 2");
+       /*
+        * The inode chunk is either full or sparse and we only support
+        * m_ialloc_min_blks sized sparse allocations at this time.
+        */
+       if (length != mp->m_ialloc_blks &&
+           length != mp->m_ialloc_min_blks) {
+               xfs_warn(log->l_mp,
+                        "%s: unsupported chunk length", __FUNCTION__);
+               return -EINVAL;
+       }
+
+       /* verify inode count is consistent with extent length */
+       if ((count >> mp->m_sb.sb_inopblog) != length) {
+               xfs_warn(log->l_mp,
+                        "%s: inconsistent inode count and chunk length",
+                        __FUNCTION__);
                return -EINVAL;
        }
 
@@ -3091,8 +3100,8 @@ xlog_recover_do_icreate_pass2(
                        XFS_AGB_TO_DADDR(mp, agno, agbno), length, 0))
                return 0;
 
-       xfs_ialloc_inode_init(mp, NULL, buffer_list, agno, agbno, length,
-                                       be32_to_cpu(icl->icl_gen));
+       xfs_ialloc_inode_init(mp, NULL, buffer_list, count, agno, agbno, length,
+                             be32_to_cpu(icl->icl_gen));
        return 0;
 }
 
@@ -3364,17 +3373,17 @@ STATIC int
 xlog_recover_add_to_cont_trans(
        struct xlog             *log,
        struct xlog_recover     *trans,
-       xfs_caddr_t             dp,
+       char                    *dp,
        int                     len)
 {
        xlog_recover_item_t     *item;
-       xfs_caddr_t             ptr, old_ptr;
+       char                    *ptr, *old_ptr;
        int                     old_len;
 
        if (list_empty(&trans->r_itemq)) {
                /* finish copying rest of trans header */
                xlog_recover_add_item(&trans->r_itemq);
-               ptr = (xfs_caddr_t) &trans->r_theader +
+               ptr = (char *)&trans->r_theader +
                                sizeof(xfs_trans_header_t) - len;
                memcpy(ptr, dp, len);
                return 0;
@@ -3410,12 +3419,12 @@ STATIC int
 xlog_recover_add_to_trans(
        struct xlog             *log,
        struct xlog_recover     *trans,
-       xfs_caddr_t             dp,
+       char                    *dp,
        int                     len)
 {
        xfs_inode_log_format_t  *in_f;                  /* any will do */
        xlog_recover_item_t     *item;
-       xfs_caddr_t             ptr;
+       char                    *ptr;
 
        if (!len)
                return 0;
@@ -3504,7 +3513,7 @@ STATIC int
 xlog_recovery_process_trans(
        struct xlog             *log,
        struct xlog_recover     *trans,
-       xfs_caddr_t             dp,
+       char                    *dp,
        unsigned int            len,
        unsigned int            flags,
        int                     pass)
@@ -3611,8 +3620,8 @@ xlog_recover_process_ophdr(
        struct hlist_head       rhash[],
        struct xlog_rec_header  *rhead,
        struct xlog_op_header   *ohead,
-       xfs_caddr_t             dp,
-       xfs_caddr_t             end,
+       char                    *dp,
+       char                    *end,
        int                     pass)
 {
        struct xlog_recover     *trans;
@@ -3661,11 +3670,11 @@ xlog_recover_process_data(
        struct xlog             *log,
        struct hlist_head       rhash[],
        struct xlog_rec_header  *rhead,
-       xfs_caddr_t             dp,
+       char                    *dp,
        int                     pass)
 {
        struct xlog_op_header   *ohead;
-       xfs_caddr_t             end;
+       char                    *end;
        int                     num_logops;
        int                     error;
 
@@ -3730,7 +3739,7 @@ xlog_recover_process_efi(
                         * free the memory associated with it.
                         */
                        set_bit(XFS_EFI_RECOVERED, &efip->efi_flags);
-                       xfs_efi_release(efip, efip->efi_format.efi_nextents);
+                       xfs_efi_release(efip);
                        return -EIO;
                }
        }
@@ -3743,19 +3752,19 @@ xlog_recover_process_efi(
 
        for (i = 0; i < efip->efi_format.efi_nextents; i++) {
                extp = &(efip->efi_format.efi_extents[i]);
-               error = xfs_free_extent(tp, extp->ext_start, extp->ext_len);
+               error = xfs_trans_free_extent(tp, efdp, extp->ext_start,
+                                             extp->ext_len);
                if (error)
                        goto abort_error;
-               xfs_trans_log_efd_extent(tp, efdp, extp->ext_start,
-                                        extp->ext_len);
+
        }
 
        set_bit(XFS_EFI_RECOVERED, &efip->efi_flags);
-       error = xfs_trans_commit(tp, 0);
+       error = xfs_trans_commit(tp);
        return error;
 
 abort_error:
-       xfs_trans_cancel(tp, XFS_TRANS_ABORT);
+       xfs_trans_cancel(tp);
        return error;
 }
 
@@ -3857,13 +3866,13 @@ xlog_recover_clear_agi_bucket(
        xfs_trans_log_buf(tp, agibp, offset,
                          (offset + sizeof(xfs_agino_t) - 1));
 
-       error = xfs_trans_commit(tp, 0);
+       error = xfs_trans_commit(tp);
        if (error)
                goto out_error;
        return;
 
 out_abort:
-       xfs_trans_cancel(tp, XFS_TRANS_ABORT);
+       xfs_trans_cancel(tp);
 out_error:
        xfs_warn(mp, "%s: failed to clear agi %d. Continuing.", __func__, agno);
        return;
@@ -4010,7 +4019,7 @@ xlog_recover_process_iunlinks(
 STATIC int
 xlog_unpack_data_crc(
        struct xlog_rec_header  *rhead,
-       xfs_caddr_t             dp,
+       char                    *dp,
        struct xlog             *log)
 {
        __le32                  crc;
@@ -4040,7 +4049,7 @@ xlog_unpack_data_crc(
 STATIC int
 xlog_unpack_data(
        struct xlog_rec_header  *rhead,
-       xfs_caddr_t             dp,
+       char                    *dp,
        struct xlog             *log)
 {
        int                     i, j, k;
@@ -4122,7 +4131,7 @@ xlog_do_recovery_pass(
 {
        xlog_rec_header_t       *rhead;
        xfs_daddr_t             blk_no;
-       xfs_caddr_t             offset;
+       char                    *offset;
        xfs_buf_t               *hbp, *dbp;
        int                     error = 0, h_size;
        int                     bblks, split_bblks;