]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/xfs/xfs_dir2_leaf.c
Merge tag 'v3.9-rc3' into next
[karo-tx-linux.git] / fs / xfs / xfs_dir2_leaf.c
index 0b296253bd018d450f5773d6df3bdbcc03d55db5..60cd2fa4e047b3266b4abffa935663788b1d0388 100644 (file)
@@ -48,6 +48,83 @@ static void xfs_dir2_leaf_log_bests(struct xfs_trans *tp, struct xfs_buf *bp,
                                    int first, int last);
 static void xfs_dir2_leaf_log_tail(struct xfs_trans *tp, struct xfs_buf *bp);
 
+static void
+xfs_dir2_leaf_verify(
+       struct xfs_buf          *bp,
+       __be16                  magic)
+{
+       struct xfs_mount        *mp = bp->b_target->bt_mount;
+       struct xfs_dir2_leaf_hdr *hdr = bp->b_addr;
+       int                     block_ok = 0;
+
+       block_ok = hdr->info.magic == magic;
+       if (!block_ok) {
+               XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, hdr);
+               xfs_buf_ioerror(bp, EFSCORRUPTED);
+       }
+}
+
+static void
+xfs_dir2_leaf1_read_verify(
+       struct xfs_buf  *bp)
+{
+       xfs_dir2_leaf_verify(bp, cpu_to_be16(XFS_DIR2_LEAF1_MAGIC));
+}
+
+static void
+xfs_dir2_leaf1_write_verify(
+       struct xfs_buf  *bp)
+{
+       xfs_dir2_leaf_verify(bp, cpu_to_be16(XFS_DIR2_LEAF1_MAGIC));
+}
+
+void
+xfs_dir2_leafn_read_verify(
+       struct xfs_buf  *bp)
+{
+       xfs_dir2_leaf_verify(bp, cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
+}
+
+void
+xfs_dir2_leafn_write_verify(
+       struct xfs_buf  *bp)
+{
+       xfs_dir2_leaf_verify(bp, cpu_to_be16(XFS_DIR2_LEAFN_MAGIC));
+}
+
+static const struct xfs_buf_ops xfs_dir2_leaf1_buf_ops = {
+       .verify_read = xfs_dir2_leaf1_read_verify,
+       .verify_write = xfs_dir2_leaf1_write_verify,
+};
+
+const struct xfs_buf_ops xfs_dir2_leafn_buf_ops = {
+       .verify_read = xfs_dir2_leafn_read_verify,
+       .verify_write = xfs_dir2_leafn_write_verify,
+};
+
+static int
+xfs_dir2_leaf_read(
+       struct xfs_trans        *tp,
+       struct xfs_inode        *dp,
+       xfs_dablk_t             fbno,
+       xfs_daddr_t             mappedbno,
+       struct xfs_buf          **bpp)
+{
+       return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp,
+                               XFS_DATA_FORK, &xfs_dir2_leaf1_buf_ops);
+}
+
+int
+xfs_dir2_leafn_read(
+       struct xfs_trans        *tp,
+       struct xfs_inode        *dp,
+       xfs_dablk_t             fbno,
+       xfs_daddr_t             mappedbno,
+       struct xfs_buf          **bpp)
+{
+       return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp,
+                               XFS_DATA_FORK, &xfs_dir2_leafn_buf_ops);
+}
 
 /*
  * Convert a block form directory to a leaf form directory.
@@ -125,6 +202,7 @@ xfs_dir2_block_to_leaf(
        /*
         * Fix up the block header, make it a data block.
         */
+       dbp->b_ops = &xfs_dir2_data_buf_ops;
        hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);
        if (needscan)
                xfs_dir2_data_freescan(mp, hdr, &needlog);
@@ -311,15 +389,11 @@ xfs_dir2_leaf_addname(
        dp = args->dp;
        tp = args->trans;
        mp = dp->i_mount;
-       /*
-        * Read the leaf block.
-        */
-       error = xfs_da_read_buf(tp, dp, mp->m_dirleafblk, -1, &lbp,
-               XFS_DATA_FORK);
-       if (error) {
+
+       error = xfs_dir2_leaf_read(tp, dp, mp->m_dirleafblk, -1, &lbp);
+       if (error)
                return error;
-       }
-       ASSERT(lbp != NULL);
+
        /*
         * Look up the entry by hash value and name.
         * We know it's not there, our caller has already done a lookup.
@@ -494,22 +568,21 @@ xfs_dir2_leaf_addname(
                hdr = dbp->b_addr;
                bestsp[use_block] = hdr->bestfree[0].length;
                grown = 1;
-       }
-       /*
-        * Already had space in some data block.
-        * Just read that one in.
-        */
-       else {
-               if ((error =
-                   xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, use_block),
-                           -1, &dbp, XFS_DATA_FORK))) {
+       } else {
+               /*
+                * Already had space in some data block.
+                * Just read that one in.
+                */
+               error = xfs_dir2_data_read(tp, dp,
+                                          xfs_dir2_db_to_da(mp, use_block),
+                                          -1, &dbp);
+               if (error) {
                        xfs_trans_brelse(tp, lbp);
                        return error;
                }
                hdr = dbp->b_addr;
                grown = 0;
        }
-       xfs_dir2_data_check(dp, dbp);
        /*
         * Point to the biggest freespace in our data block.
         */
@@ -892,10 +965,9 @@ xfs_dir2_leaf_readbuf(
         * Read the directory block starting at the first mapping.
         */
        mip->curdb = xfs_dir2_da_to_db(mp, map->br_startoff);
-       error = xfs_da_read_buf(NULL, dp, map->br_startoff,
+       error = xfs_dir2_data_read(NULL, dp, map->br_startoff,
                        map->br_blockcount >= mp->m_dirblkfsbs ?
-                           XFS_FSB_TO_DADDR(mp, map->br_startblock) : -1,
-                       &bp, XFS_DATA_FORK);
+                           XFS_FSB_TO_DADDR(mp, map->br_startblock) : -1, &bp);
 
        /*
         * Should just skip over the data block instead of giving up.
@@ -922,11 +994,11 @@ xfs_dir2_leaf_readbuf(
                 */
                if (i > mip->ra_current &&
                    map[mip->ra_index].br_blockcount >= mp->m_dirblkfsbs) {
-                       xfs_buf_readahead(mp->m_ddev_targp,
+                       xfs_dir2_data_readahead(NULL, dp,
+                               map[mip->ra_index].br_startoff + mip->ra_offset,
                                XFS_FSB_TO_DADDR(mp,
                                        map[mip->ra_index].br_startblock +
-                                                       mip->ra_offset),
-                               (int)BTOBB(mp->m_dirblksize));
+                                                       mip->ra_offset));
                        mip->ra_current = i;
                }
 
@@ -935,10 +1007,9 @@ xfs_dir2_leaf_readbuf(
                 * use our mapping, but this is a very rare case.
                 */
                else if (i > mip->ra_current) {
-                       xfs_da_reada_buf(NULL, dp,
+                       xfs_dir2_data_readahead(NULL, dp,
                                        map[mip->ra_index].br_startoff +
-                                                       mip->ra_offset,
-                                       XFS_DATA_FORK);
+                                                       mip->ra_offset, -1);
                        mip->ra_current = i;
                }
 
@@ -1177,15 +1248,14 @@ xfs_dir2_leaf_init(
         * Get the buffer for the block.
         */
        error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, bno), -1, &bp,
-               XFS_DATA_FORK);
-       if (error) {
+                              XFS_DATA_FORK);
+       if (error)
                return error;
-       }
-       ASSERT(bp != NULL);
-       leaf = bp->b_addr;
+
        /*
         * Initialize the header.
         */
+       leaf = bp->b_addr;
        leaf->hdr.info.magic = cpu_to_be16(magic);
        leaf->hdr.info.forw = 0;
        leaf->hdr.info.back = 0;
@@ -1198,10 +1268,12 @@ xfs_dir2_leaf_init(
         * the block.
         */
        if (magic == XFS_DIR2_LEAF1_MAGIC) {
+               bp->b_ops = &xfs_dir2_leaf1_buf_ops;
                ltp = xfs_dir2_leaf_tail_p(mp, leaf);
                ltp->bestcount = 0;
                xfs_dir2_leaf_log_tail(tp, bp);
-       }
+       } else
+               bp->b_ops = &xfs_dir2_leafn_buf_ops;
        *bpp = bp;
        return 0;
 }
@@ -1372,13 +1444,11 @@ xfs_dir2_leaf_lookup_int(
        dp = args->dp;
        tp = args->trans;
        mp = dp->i_mount;
-       /*
-        * Read the leaf block into the buffer.
-        */
-       error = xfs_da_read_buf(tp, dp, mp->m_dirleafblk, -1, &lbp,
-                                                       XFS_DATA_FORK);
+
+       error = xfs_dir2_leaf_read(tp, dp, mp->m_dirleafblk, -1, &lbp);
        if (error)
                return error;
+
        *lbpp = lbp;
        leaf = lbp->b_addr;
        xfs_dir2_leaf_check(dp, lbp);
@@ -1409,14 +1479,13 @@ xfs_dir2_leaf_lookup_int(
                if (newdb != curdb) {
                        if (dbp)
                                xfs_trans_brelse(tp, dbp);
-                       error = xfs_da_read_buf(tp, dp,
-                                               xfs_dir2_db_to_da(mp, newdb),
-                                               -1, &dbp, XFS_DATA_FORK);
+                       error = xfs_dir2_data_read(tp, dp,
+                                                  xfs_dir2_db_to_da(mp, newdb),
+                                                  -1, &dbp);
                        if (error) {
                                xfs_trans_brelse(tp, lbp);
                                return error;
                        }
-                       xfs_dir2_data_check(dp, dbp);
                        curdb = newdb;
                }
                /*
@@ -1451,9 +1520,9 @@ xfs_dir2_leaf_lookup_int(
                ASSERT(cidb != -1);
                if (cidb != curdb) {
                        xfs_trans_brelse(tp, dbp);
-                       error = xfs_da_read_buf(tp, dp,
-                                               xfs_dir2_db_to_da(mp, cidb),
-                                               -1, &dbp, XFS_DATA_FORK);
+                       error = xfs_dir2_data_read(tp, dp,
+                                                  xfs_dir2_db_to_da(mp, cidb),
+                                                  -1, &dbp);
                        if (error) {
                                xfs_trans_brelse(tp, lbp);
                                return error;
@@ -1738,10 +1807,9 @@ xfs_dir2_leaf_trim_data(
        /*
         * Read the offending data block.  We need its buffer.
         */
-       if ((error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, db), -1, &dbp,
-                       XFS_DATA_FORK))) {
+       error = xfs_dir2_data_read(tp, dp, xfs_dir2_db_to_da(mp, db), -1, &dbp);
+       if (error)
                return error;
-       }
 
        leaf = lbp->b_addr;
        ltp = xfs_dir2_leaf_tail_p(mp, leaf);
@@ -1864,10 +1932,9 @@ xfs_dir2_node_to_leaf(
        /*
         * Read the freespace block.
         */
-       if ((error = xfs_da_read_buf(tp, dp, mp->m_dirfreeblk, -1, &fbp,
-                       XFS_DATA_FORK))) {
+       error = xfs_dir2_free_read(tp, dp,  mp->m_dirfreeblk, &fbp);
+       if (error)
                return error;
-       }
        free = fbp->b_addr;
        ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
        ASSERT(!free->hdr.firstdb);
@@ -1890,7 +1957,10 @@ xfs_dir2_node_to_leaf(
                xfs_dir2_leaf_compact(args, lbp);
        else
                xfs_dir2_leaf_log_header(tp, lbp);
+
+       lbp->b_ops = &xfs_dir2_leaf1_buf_ops;
        leaf->hdr.info.magic = cpu_to_be16(XFS_DIR2_LEAF1_MAGIC);
+
        /*
         * Set up the leaf tail from the freespace block.
         */