]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - fs/xfs/xfs_log_recover.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/czankel/xtensa-2.6
[mv-sheeva.git] / fs / xfs / xfs_log_recover.c
index b552676ca5c447fd1d2038ad209a13e187912840..35cca98bd94c90c926dd3db7ae49974661577a4c 100644 (file)
@@ -36,7 +36,6 @@
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
 #include "xfs_inode_item.h"
-#include "xfs_imap.h"
 #include "xfs_alloc.h"
 #include "xfs_ialloc.h"
 #include "xfs_log_priv.h"
@@ -268,21 +267,16 @@ STATIC void
 xlog_recover_iodone(
        struct xfs_buf  *bp)
 {
-       xfs_mount_t     *mp;
-
-       ASSERT(XFS_BUF_FSPRIVATE(bp, void *));
-
        if (XFS_BUF_GETERROR(bp)) {
                /*
                 * We're not going to bother about retrying
                 * this during recovery. One strike!
                 */
-               mp = XFS_BUF_FSPRIVATE(bp, xfs_mount_t *);
                xfs_ioerror_alert("xlog_recover_iodone",
-                                 mp, bp, XFS_BUF_ADDR(bp));
-               xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
+                                 bp->b_mount, bp, XFS_BUF_ADDR(bp));
+               xfs_force_shutdown(bp->b_mount, SHUTDOWN_META_IO_ERROR);
        }
-       XFS_BUF_SET_FSPRIVATE(bp, NULL);
+       bp->b_mount = NULL;
        XFS_BUF_CLR_IODONE_FUNC(bp);
        xfs_biodone(bp);
 }
@@ -2226,9 +2220,8 @@ xlog_recover_do_buffer_trans(
                XFS_BUF_STALE(bp);
                error = xfs_bwrite(mp, bp);
        } else {
-               ASSERT(XFS_BUF_FSPRIVATE(bp, void *) == NULL ||
-                      XFS_BUF_FSPRIVATE(bp, xfs_mount_t *) == mp);
-               XFS_BUF_SET_FSPRIVATE(bp, mp);
+               ASSERT(bp->b_mount == NULL || bp->b_mount == mp);
+               bp->b_mount = mp;
                XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone);
                xfs_bdwrite(mp, bp);
        }
@@ -2245,7 +2238,6 @@ xlog_recover_do_inode_trans(
        xfs_inode_log_format_t  *in_f;
        xfs_mount_t             *mp;
        xfs_buf_t               *bp;
-       xfs_imap_t              imap;
        xfs_dinode_t            *dip;
        xfs_ino_t               ino;
        int                     len;
@@ -2273,54 +2265,35 @@ xlog_recover_do_inode_trans(
        }
        ino = in_f->ilf_ino;
        mp = log->l_mp;
-       if (ITEM_TYPE(item) == XFS_LI_INODE) {
-               imap.im_blkno = (xfs_daddr_t)in_f->ilf_blkno;
-               imap.im_len = in_f->ilf_len;
-               imap.im_boffset = in_f->ilf_boffset;
-       } else {
-               /*
-                * It's an old inode format record.  We don't know where
-                * its cluster is located on disk, and we can't allow
-                * xfs_imap() to figure it out because the inode btrees
-                * are not ready to be used.  Therefore do not pass the
-                * XFS_IMAP_LOOKUP flag to xfs_imap().  This will give
-                * us only the single block in which the inode lives
-                * rather than its cluster, so we must make sure to
-                * invalidate the buffer when we write it out below.
-                */
-               imap.im_blkno = 0;
-               error = xfs_imap(log->l_mp, NULL, ino, &imap, 0);
-               if (error)
-                       goto error;
-       }
 
        /*
         * Inode buffers can be freed, look out for it,
         * and do not replay the inode.
         */
-       if (xlog_check_buffer_cancelled(log, imap.im_blkno, imap.im_len, 0)) {
+       if (xlog_check_buffer_cancelled(log, in_f->ilf_blkno,
+                                       in_f->ilf_len, 0)) {
                error = 0;
                goto error;
        }
 
-       bp = xfs_buf_read_flags(mp->m_ddev_targp, imap.im_blkno, imap.im_len,
-                                                               XFS_BUF_LOCK);
+       bp = xfs_buf_read_flags(mp->m_ddev_targp, in_f->ilf_blkno,
+                               in_f->ilf_len, XFS_BUF_LOCK);
        if (XFS_BUF_ISERROR(bp)) {
                xfs_ioerror_alert("xlog_recover_do..(read#2)", mp,
-                                 bp, imap.im_blkno);
+                                 bp, in_f->ilf_blkno);
                error = XFS_BUF_GETERROR(bp);
                xfs_buf_relse(bp);
                goto error;
        }
        error = 0;
        ASSERT(in_f->ilf_fields & XFS_ILOG_CORE);
-       dip = (xfs_dinode_t *)xfs_buf_offset(bp, imap.im_boffset);
+       dip = (xfs_dinode_t *)xfs_buf_offset(bp, in_f->ilf_boffset);
 
        /*
         * Make sure the place we're flushing out to really looks
         * like an inode!
         */
-       if (unlikely(be16_to_cpu(dip->di_core.di_magic) != XFS_DINODE_MAGIC)) {
+       if (unlikely(be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC)) {
                xfs_buf_relse(bp);
                xfs_fs_cmn_err(CE_ALERT, mp,
                        "xfs_inode_recover: Bad inode magic number, dino ptr = 0x%p, dino bp = 0x%p, ino = %Ld",
@@ -2343,12 +2316,12 @@ xlog_recover_do_inode_trans(
        }
 
        /* Skip replay when the on disk inode is newer than the log one */
-       if (dicp->di_flushiter < be16_to_cpu(dip->di_core.di_flushiter)) {
+       if (dicp->di_flushiter < be16_to_cpu(dip->di_flushiter)) {
                /*
                 * Deal with the wrap case, DI_MAX_FLUSH is less
                 * than smaller numbers
                 */
-               if (be16_to_cpu(dip->di_core.di_flushiter) == DI_MAX_FLUSH &&
+               if (be16_to_cpu(dip->di_flushiter) == DI_MAX_FLUSH &&
                    dicp->di_flushiter < (DI_MAX_FLUSH >> 1)) {
                        /* do nothing */
                } else {
@@ -2408,7 +2381,7 @@ xlog_recover_do_inode_trans(
                error = EFSCORRUPTED;
                goto error;
        }
-       if (unlikely(item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t))) {
+       if (unlikely(item->ri_buf[1].i_len > sizeof(struct xfs_icdinode))) {
                XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(7)",
                                     XFS_ERRLEVEL_LOW, mp, dicp);
                xfs_buf_relse(bp);
@@ -2420,23 +2393,24 @@ xlog_recover_do_inode_trans(
        }
 
        /* The core is in in-core format */
-       xfs_dinode_to_disk(&dip->di_core,
-               (xfs_icdinode_t *)item->ri_buf[1].i_addr);
+       xfs_dinode_to_disk(dip, (xfs_icdinode_t *)item->ri_buf[1].i_addr);
 
        /* the rest is in on-disk format */
-       if (item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t)) {
-               memcpy((xfs_caddr_t) dip + sizeof(xfs_dinode_core_t),
-                       item->ri_buf[1].i_addr + sizeof(xfs_dinode_core_t),
-                       item->ri_buf[1].i_len  - sizeof(xfs_dinode_core_t));
+       if (item->ri_buf[1].i_len > sizeof(struct xfs_icdinode)) {
+               memcpy((xfs_caddr_t) dip + sizeof(struct xfs_icdinode),
+                       item->ri_buf[1].i_addr + sizeof(struct xfs_icdinode),
+                       item->ri_buf[1].i_len  - sizeof(struct xfs_icdinode));
        }
 
        fields = in_f->ilf_fields;
        switch (fields & (XFS_ILOG_DEV | XFS_ILOG_UUID)) {
        case XFS_ILOG_DEV:
-               dip->di_u.di_dev = cpu_to_be32(in_f->ilf_u.ilfu_rdev);
+               xfs_dinode_put_rdev(dip, in_f->ilf_u.ilfu_rdev);
                break;
        case XFS_ILOG_UUID:
-               dip->di_u.di_muuid = in_f->ilf_u.ilfu_uuid;
+               memcpy(XFS_DFORK_DPTR(dip),
+                      &in_f->ilf_u.ilfu_uuid,
+                      sizeof(uuid_t));
                break;
        }
 
@@ -2452,12 +2426,12 @@ xlog_recover_do_inode_trans(
        switch (fields & XFS_ILOG_DFORK) {
        case XFS_ILOG_DDATA:
        case XFS_ILOG_DEXT:
-               memcpy(&dip->di_u, src, len);
+               memcpy(XFS_DFORK_DPTR(dip), src, len);
                break;
 
        case XFS_ILOG_DBROOT:
                xfs_bmbt_to_bmdr(mp, (struct xfs_btree_block *)src, len,
-                                &dip->di_u.di_bmbt,
+                                (xfs_bmdr_block_t *)XFS_DFORK_DPTR(dip),
                                 XFS_DFORK_DSIZE(dip, mp));
                break;
 
@@ -2510,9 +2484,8 @@ xlog_recover_do_inode_trans(
 
 write_inode_buffer:
        if (ITEM_TYPE(item) == XFS_LI_INODE) {
-               ASSERT(XFS_BUF_FSPRIVATE(bp, void *) == NULL ||
-                      XFS_BUF_FSPRIVATE(bp, xfs_mount_t *) == mp);
-               XFS_BUF_SET_FSPRIVATE(bp, mp);
+               ASSERT(bp->b_mount == NULL || bp->b_mount == mp);
+               bp->b_mount = mp;
                XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone);
                xfs_bdwrite(mp, bp);
        } else {
@@ -2643,9 +2616,8 @@ xlog_recover_do_dquot_trans(
        memcpy(ddq, recddq, item->ri_buf[1].i_len);
 
        ASSERT(dq_f->qlf_size == 2);
-       ASSERT(XFS_BUF_FSPRIVATE(bp, void *) == NULL ||
-              XFS_BUF_FSPRIVATE(bp, xfs_mount_t *) == mp);
-       XFS_BUF_SET_FSPRIVATE(bp, mp);
+       ASSERT(bp->b_mount == NULL || bp->b_mount == mp);
+       bp->b_mount = mp;
        XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone);
        xfs_bdwrite(mp, bp);
 
@@ -3146,6 +3118,62 @@ out_error:
        return;
 }
 
+STATIC xfs_agino_t
+xlog_recover_process_one_iunlink(
+       struct xfs_mount                *mp,
+       xfs_agnumber_t                  agno,
+       xfs_agino_t                     agino,
+       int                             bucket)
+{
+       struct xfs_buf                  *ibp;
+       struct xfs_dinode               *dip;
+       struct xfs_inode                *ip;
+       xfs_ino_t                       ino;
+       int                             error;
+
+       ino = XFS_AGINO_TO_INO(mp, agno, agino);
+       error = xfs_iget(mp, NULL, ino, 0, 0, &ip, 0);
+       if (error)
+               goto fail;
+
+       /*
+        * Get the on disk inode to find the next inode in the bucket.
+        */
+       error = xfs_itobp(mp, NULL, ip, &dip, &ibp, XFS_BUF_LOCK);
+       if (error)
+               goto fail_iput;
+
+       ASSERT(ip->i_d.di_nlink == 0);
+       ASSERT(ip->i_d.di_mode != 0);
+
+       /* setup for the next pass */
+       agino = be32_to_cpu(dip->di_next_unlinked);
+       xfs_buf_relse(ibp);
+
+       /*
+        * Prevent any DMAPI event from being sent when the reference on
+        * the inode is dropped.
+        */
+       ip->i_d.di_dmevmask = 0;
+
+       IRELE(ip);
+       return agino;
+
+ fail_iput:
+       IRELE(ip);
+ fail:
+       /*
+        * We can't read in the inode this bucket points to, or this inode
+        * is messed up.  Just ditch this bucket of inodes.  We will lose
+        * some inodes and space, but at least we won't hang.
+        *
+        * Call xlog_recover_clear_agi_bucket() to perform a transaction to
+        * clear the inode pointer in the bucket.
+        */
+       xlog_recover_clear_agi_bucket(mp, agno, bucket);
+       return NULLAGINO;
+}
+
 /*
  * xlog_iunlink_recover
  *
@@ -3166,11 +3194,7 @@ xlog_recover_process_iunlinks(
        xfs_agnumber_t  agno;
        xfs_agi_t       *agi;
        xfs_buf_t       *agibp;
-       xfs_buf_t       *ibp;
-       xfs_dinode_t    *dip;
-       xfs_inode_t     *ip;
        xfs_agino_t     agino;
-       xfs_ino_t       ino;
        int             bucket;
        int             error;
        uint            mp_dmevmask;
@@ -3200,10 +3224,8 @@ xlog_recover_process_iunlinks(
                agi = XFS_BUF_TO_AGI(agibp);
 
                for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) {
-
                        agino = be32_to_cpu(agi->agi_unlinked[bucket]);
                        while (agino != NULLAGINO) {
-
                                /*
                                 * Release the agi buffer so that it can
                                 * be acquired in the normal course of the
@@ -3211,68 +3233,8 @@ xlog_recover_process_iunlinks(
                                 */
                                xfs_buf_relse(agibp);
 
-                               ino = XFS_AGINO_TO_INO(mp, agno, agino);
-                               error = xfs_iget(mp, NULL, ino, 0, 0, &ip, 0);
-                               ASSERT(error || (ip != NULL));
-
-                               if (!error) {
-                                       /*
-                                        * Get the on disk inode to find the
-                                        * next inode in the bucket.
-                                        */
-                                       error = xfs_itobp(mp, NULL, ip, &dip,
-                                                       &ibp, 0, 0,
-                                                       XFS_BUF_LOCK);
-                                       ASSERT(error || (dip != NULL));
-                               }
-
-                               if (!error) {
-                                       ASSERT(ip->i_d.di_nlink == 0);
-
-                                       /* setup for the next pass */
-                                       agino = be32_to_cpu(
-                                                       dip->di_next_unlinked);
-                                       xfs_buf_relse(ibp);
-                                       /*
-                                        * Prevent any DMAPI event from
-                                        * being sent when the
-                                        * reference on the inode is
-                                        * dropped.
-                                        */
-                                       ip->i_d.di_dmevmask = 0;
-
-                                       /*
-                                        * If this is a new inode, handle
-                                        * it specially.  Otherwise,
-                                        * just drop our reference to the
-                                        * inode.  If there are no
-                                        * other references, this will
-                                        * send the inode to
-                                        * xfs_inactive() which will
-                                        * truncate the file and free
-                                        * the inode.
-                                        */
-                                       if (ip->i_d.di_mode == 0)
-                                               xfs_iput_new(ip, 0);
-                                       else
-                                               IRELE(ip);
-                               } else {
-                                       /*
-                                        * We can't read in the inode
-                                        * this bucket points to, or
-                                        * this inode is messed up.  Just
-                                        * ditch this bucket of inodes.  We
-                                        * will lose some inodes and space,
-                                        * but at least we won't hang.  Call
-                                        * xlog_recover_clear_agi_bucket()
-                                        * to perform a transaction to clear
-                                        * the inode pointer in the bucket.
-                                        */
-                                       xlog_recover_clear_agi_bucket(mp, agno,
-                                                       bucket);
-
-                                       agino = NULLAGINO;
-                               }
+                               agino = xlog_recover_process_one_iunlink(mp,
+                                                       agno, agino, bucket);
 
                                /*
                                 * Reacquire the agibuffer and continue around
@@ -3332,7 +3294,6 @@ xlog_pack_data(
        int                     size = iclog->ic_offset + roundoff;
        __be32                  cycle_lsn;
        xfs_caddr_t             dp;
-       xlog_in_core_2_t        *xhdr;
 
        xlog_pack_data_checksum(log, iclog, size);
 
@@ -3347,7 +3308,8 @@ xlog_pack_data(
        }
 
        if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) {
-               xhdr = (xlog_in_core_2_t *)&iclog->ic_header;
+               xlog_in_core_2_t *xhdr = iclog->ic_data;
+
                for ( ; i < BTOBB(size); i++) {
                        j = i / (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
                        k = i % (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
@@ -3405,7 +3367,6 @@ xlog_unpack_data(
        xlog_t                  *log)
 {
        int                     i, j, k;
-       xlog_in_core_2_t        *xhdr;
 
        for (i = 0; i < BTOBB(be32_to_cpu(rhead->h_len)) &&
                  i < (XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++) {
@@ -3414,7 +3375,7 @@ xlog_unpack_data(
        }
 
        if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) {
-               xhdr = (xlog_in_core_2_t *)rhead;
+               xlog_in_core_2_t *xhdr = (xlog_in_core_2_t *)rhead;
                for ( ; i < BTOBB(be32_to_cpu(rhead->h_len)); i++) {
                        j = i / (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
                        k = i % (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
@@ -3970,7 +3931,6 @@ xlog_recover_check_summary(
        xfs_agf_t       *agfp;
        xfs_buf_t       *agfbp;
        xfs_buf_t       *agibp;
-       xfs_daddr_t     agfdaddr;
        xfs_buf_t       *sbbp;
 #ifdef XFS_LOUD_RECOVERY
        xfs_sb_t        *sbp;
@@ -3987,21 +3947,18 @@ xlog_recover_check_summary(
        itotal = 0LL;
        ifree = 0LL;
        for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
-               agfdaddr = XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp));
-               agfbp = xfs_buf_read(mp->m_ddev_targp, agfdaddr,
-                               XFS_FSS_TO_BB(mp, 1), 0);
-               if (XFS_BUF_ISERROR(agfbp)) {
-                       xfs_ioerror_alert("xlog_recover_check_summary(agf)",
-                                               mp, agfbp, agfdaddr);
+               error = xfs_read_agf(mp, NULL, agno, 0, &agfbp);
+               if (error) {
+                       xfs_fs_cmn_err(CE_ALERT, mp,
+                                       "xlog_recover_check_summary(agf)"
+                                       "agf read failed agno %d error %d",
+                                                       agno, error);
+               } else {
+                       agfp = XFS_BUF_TO_AGF(agfbp);
+                       freeblks += be32_to_cpu(agfp->agf_freeblks) +
+                                   be32_to_cpu(agfp->agf_flcount);
+                       xfs_buf_relse(agfbp);
                }
-               agfp = XFS_BUF_TO_AGF(agfbp);
-               ASSERT(XFS_AGF_MAGIC == be32_to_cpu(agfp->agf_magicnum));
-               ASSERT(XFS_AGF_GOOD_VERSION(be32_to_cpu(agfp->agf_versionnum)));
-               ASSERT(be32_to_cpu(agfp->agf_seqno) == agno);
-
-               freeblks += be32_to_cpu(agfp->agf_freeblks) +
-                           be32_to_cpu(agfp->agf_flcount);
-               xfs_buf_relse(agfbp);
 
                error = xfs_read_agi(mp, NULL, agno, &agibp);
                if (!error) {