]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - libxfs/xfs_dir2_block.c
xfs: convert to SPDX license tags
[thirdparty/xfsprogs-dev.git] / libxfs / xfs_dir2_block.c
index d6da2dba702178720ab5635c3374942f8c4e254b..d1ffdb391aaf7417b1cf3a0e414f6edf7613d021 100644 (file)
@@ -1,23 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
  * Copyright (c) 2013 Red Hat, Inc.
  * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
-
-#include <xfs.h>
+#include "libxfs_priv.h"
+#include "xfs_fs.h"
+#include "xfs_format.h"
+#include "xfs_log_format.h"
+#include "xfs_trans_resv.h"
+#include "xfs_mount.h"
+#include "xfs_da_format.h"
+#include "xfs_da_btree.h"
+#include "xfs_inode.h"
+#include "xfs_trans.h"
+#include "xfs_bmap.h"
+#include "xfs_dir2.h"
+#include "xfs_dir2_priv.h"
+#include "xfs_trace.h"
+#include "xfs_cksum.h"
 
 /*
  * Local function prototypes.
@@ -41,7 +42,7 @@ xfs_dir_startup(void)
        xfs_dir_hash_dotdot = xfs_da_hashname((unsigned char *)"..", 2);
 }
 
-static bool
+static xfs_failaddr_t
 xfs_dir3_block_verify(
        struct xfs_buf          *bp)
 {
@@ -50,18 +51,18 @@ xfs_dir3_block_verify(
 
        if (xfs_sb_version_hascrc(&mp->m_sb)) {
                if (hdr3->magic != cpu_to_be32(XFS_DIR3_BLOCK_MAGIC))
-                       return false;
-               if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_uuid))
-                       return false;
+                       return __this_address;
+               if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid))
+                       return __this_address;
                if (be64_to_cpu(hdr3->blkno) != bp->b_bn)
-                       return false;
+                       return __this_address;
+               if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->lsn)))
+                       return __this_address;
        } else {
                if (hdr3->magic != cpu_to_be32(XFS_DIR2_BLOCK_MAGIC))
-                       return false;
+                       return __this_address;
        }
-       if (__xfs_dir3_data_check(NULL, bp))
-               return false;
-       return true;
+       return __xfs_dir3_data_check(NULL, bp);
 }
 
 static void
@@ -69,15 +70,16 @@ xfs_dir3_block_read_verify(
        struct xfs_buf  *bp)
 {
        struct xfs_mount        *mp = bp->b_target->bt_mount;
+       xfs_failaddr_t          fa;
 
        if (xfs_sb_version_hascrc(&mp->m_sb) &&
             !xfs_buf_verify_cksum(bp, XFS_DIR3_DATA_CRC_OFF))
-               xfs_buf_ioerror(bp, -EFSBADCRC);
-       else if (!xfs_dir3_block_verify(bp))
-               xfs_buf_ioerror(bp, -EFSCORRUPTED);
-
-       if (bp->b_error)
-               xfs_verifier_error(bp);
+               xfs_verifier_error(bp, -EFSBADCRC, __this_address);
+       else {
+               fa = xfs_dir3_block_verify(bp);
+               if (fa)
+                       xfs_verifier_error(bp, -EFSCORRUPTED, fa);
+       }
 }
 
 static void
@@ -85,12 +87,13 @@ xfs_dir3_block_write_verify(
        struct xfs_buf  *bp)
 {
        struct xfs_mount        *mp = bp->b_target->bt_mount;
-       struct xfs_buf_log_item *bip = bp->b_fspriv;
+       struct xfs_buf_log_item *bip = bp->b_log_item;
        struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
+       xfs_failaddr_t          fa;
 
-       if (!xfs_dir3_block_verify(bp)) {
-               xfs_buf_ioerror(bp, -EFSCORRUPTED);
-               xfs_verifier_error(bp);
+       fa = xfs_dir3_block_verify(bp);
+       if (fa) {
+               xfs_verifier_error(bp, -EFSCORRUPTED, fa);
                return;
        }
 
@@ -104,8 +107,10 @@ xfs_dir3_block_write_verify(
 }
 
 const struct xfs_buf_ops xfs_dir3_block_buf_ops = {
+       .name = "xfs_dir3_block",
        .verify_read = xfs_dir3_block_read_verify,
        .verify_write = xfs_dir3_block_write_verify,
+       .verify_struct = xfs_dir3_block_verify,
 };
 
 int
@@ -119,7 +124,7 @@ xfs_dir3_block_read(
 
        err = xfs_da_read_buf(tp, dp, mp->m_dir_geo->datablk, -1, bpp,
                                XFS_DATA_FORK, &xfs_dir3_block_buf_ops);
-       if (!err && tp)
+       if (!err && tp && *bpp)
                xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_BLOCK_BUF);
        return err;
 }
@@ -141,7 +146,7 @@ xfs_dir3_block_init(
                hdr3->magic = cpu_to_be32(XFS_DIR3_BLOCK_MAGIC);
                hdr3->blkno = cpu_to_be64(bp->b_bn);
                hdr3->owner = cpu_to_be64(dp->i_ino);
-               uuid_copy(&hdr3->uuid, &mp->m_sb.sb_uuid);
+               uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid);
                return;
 
        }
@@ -305,7 +310,7 @@ xfs_dir2_block_compact(
         * This needs to happen before the next call to use_free.
         */
        if (needscan)
-               xfs_dir2_data_freescan(args->geo, args->dp->d_ops, hdr, needlog);
+               xfs_dir2_data_freescan(args->dp, hdr, needlog);
 }
 
 /*
@@ -334,7 +339,6 @@ xfs_dir2_block_addname(
        int                     low;            /* low index for binary srch */
        int                     lowstale;       /* low stale index */
        int                     mid=0;          /* midpoint for binary srch */
-       xfs_mount_t             *mp;            /* filesystem mount point */
        int                     needlog;        /* need to log header */
        int                     needscan;       /* need to rescan freespace */
        __be16                  *tagp;          /* pointer to tag value */
@@ -344,7 +348,6 @@ xfs_dir2_block_addname(
 
        dp = args->dp;
        tp = args->trans;
-       mp = dp->i_mount;
 
        /* Read the (one and only) directory block into bp. */
        error = xfs_dir3_block_read(tp, dp, &bp);
@@ -432,15 +435,19 @@ xfs_dir2_block_addname(
         * No stale entries, will use enddup space to hold new leaf.
         */
        if (!btp->stale) {
+               xfs_dir2_data_aoff_t    aoff;
+
                /*
                 * Mark the space needed for the new leaf entry, now in use.
                 */
-               xfs_dir2_data_use_free(args, bp, enddup,
-                       (xfs_dir2_data_aoff_t)
-                       ((char *)enddup - (char *)hdr + be16_to_cpu(enddup->length) -
-                        sizeof(*blp)),
-                       (xfs_dir2_data_aoff_t)sizeof(*blp),
-                       &needlog, &needscan);
+               aoff = (xfs_dir2_data_aoff_t)((char *)enddup - (char *)hdr +
+                               be16_to_cpu(enddup->length) - sizeof(*blp));
+               error = xfs_dir2_data_use_free(args, bp, enddup, aoff,
+                               (xfs_dir2_data_aoff_t)sizeof(*blp), &needlog,
+                               &needscan);
+               if (error)
+                       return error;
+
                /*
                 * Update the tail (entry count).
                 */
@@ -450,8 +457,7 @@ xfs_dir2_block_addname(
                 * This needs to happen before the next call to use_free.
                 */
                if (needscan) {
-                       xfs_dir2_data_freescan(args->geo, dp->d_ops, hdr,
-                                              &needlog);
+                       xfs_dir2_data_freescan(dp, hdr, &needlog);
                        needscan = 0;
                }
                /*
@@ -523,9 +529,11 @@ xfs_dir2_block_addname(
        /*
         * Mark space for the data entry used.
         */
-       xfs_dir2_data_use_free(args, bp, dup,
-               (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr),
-               (xfs_dir2_data_aoff_t)len, &needlog, &needscan);
+       error = xfs_dir2_data_use_free(args, bp, dup,
+                       (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr),
+                       (xfs_dir2_data_aoff_t)len, &needlog, &needscan);
+       if (error)
+               return error;
        /*
         * Create the new data entry.
         */
@@ -539,7 +547,7 @@ xfs_dir2_block_addname(
         * Clean up the bestfree array and log the header, tail, and entry.
         */
        if (needscan)
-               xfs_dir2_data_freescan(args->geo, dp->d_ops, hdr, &needlog);
+               xfs_dir2_data_freescan(dp, hdr, &needlog);
        if (needlog)
                xfs_dir2_data_log_header(args, bp);
        xfs_dir2_block_log_tail(tp, bp);
@@ -600,7 +608,6 @@ xfs_dir2_block_lookup(
        xfs_inode_t             *dp;            /* incore inode */
        int                     ent;            /* entry index */
        int                     error;          /* error return value */
-       xfs_mount_t             *mp;            /* filesystem mount point */
 
        trace_xfs_dir2_block_lookup(args);
 
@@ -611,7 +618,6 @@ xfs_dir2_block_lookup(
        if ((error = xfs_dir2_block_lookup_int(args, &bp, &ent)))
                return error;
        dp = args->dp;
-       mp = dp->i_mount;
        hdr = bp->b_addr;
        xfs_dir3_data_check(dp, bp);
        btp = xfs_dir2_block_tail_p(args->geo, hdr);
@@ -752,7 +758,6 @@ xfs_dir2_block_removename(
        xfs_inode_t             *dp;            /* incore inode */
        int                     ent;            /* block leaf entry index */
        int                     error;          /* error return value */
-       xfs_mount_t             *mp;            /* filesystem mount point */
        int                     needlog;        /* need to log block header */
        int                     needscan;       /* need to fixup bestfree */
        xfs_dir2_sf_hdr_t       sfh;            /* shortform header */
@@ -770,7 +775,6 @@ xfs_dir2_block_removename(
        }
        dp = args->dp;
        tp = args->trans;
-       mp = dp->i_mount;
        hdr = bp->b_addr;
        btp = xfs_dir2_block_tail_p(args->geo, hdr);
        blp = xfs_dir2_block_leaf_p(btp);
@@ -801,7 +805,7 @@ xfs_dir2_block_removename(
         * Fix up bestfree, log the header if necessary.
         */
        if (needscan)
-               xfs_dir2_data_freescan(args->geo, dp->d_ops, hdr, &needlog);
+               xfs_dir2_data_freescan(dp, hdr, &needlog);
        if (needlog)
                xfs_dir2_data_log_header(args, bp);
        xfs_dir3_data_check(dp, bp);
@@ -834,7 +838,6 @@ xfs_dir2_block_replace(
        xfs_inode_t             *dp;            /* incore inode */
        int                     ent;            /* leaf entry index */
        int                     error;          /* error return value */
-       xfs_mount_t             *mp;            /* filesystem mount point */
 
        trace_xfs_dir2_block_replace(args);
 
@@ -846,7 +849,6 @@ xfs_dir2_block_replace(
                return error;
        }
        dp = args->dp;
-       mp = dp->i_mount;
        hdr = bp->b_addr;
        btp = xfs_dir2_block_tail_p(args->geo, hdr);
        blp = xfs_dir2_block_leaf_p(btp);
@@ -985,8 +987,10 @@ xfs_dir2_leaf_to_block(
        /*
         * Use up the space at the end of the block (blp/btp).
         */
-       xfs_dir2_data_use_free(args, dbp, dup, args->geo->blksize - size, size,
-               &needlog, &needscan);
+       error = xfs_dir2_data_use_free(args, dbp, dup,
+                       args->geo->blksize - size, size, &needlog, &needscan);
+       if (error)
+               return error;
        /*
         * Initialize the block tail.
         */
@@ -1009,7 +1013,7 @@ xfs_dir2_leaf_to_block(
         * Scan the bestfree if we need it and log the data block header.
         */
        if (needscan)
-               xfs_dir2_data_freescan(args->geo, dp->d_ops, hdr, &needlog);
+               xfs_dir2_data_freescan(dp, hdr, &needlog);
        if (needlog)
                xfs_dir2_data_log_header(args, dbp);
        /*
@@ -1098,18 +1102,14 @@ xfs_dir2_sf_to_block(
         * Add block 0 to the inode.
         */
        error = xfs_dir2_grow_inode(args, XFS_DIR2_DATA_SPACE, &blkno);
-       if (error) {
-               kmem_free(sfp);
-               return error;
-       }
+       if (error)
+               goto out_free;
        /*
         * Initialize the data block, then convert it to block format.
         */
        error = xfs_dir3_data_init(args, blkno, &bp);
-       if (error) {
-               kmem_free(sfp);
-               return error;
-       }
+       if (error)
+               goto out_free;
        xfs_dir3_block_init(mp, tp, bp, dp);
        hdr = bp->b_addr;
 
@@ -1124,8 +1124,10 @@ xfs_dir2_sf_to_block(
         */
        dup = dp->d_ops->data_unused_p(hdr);
        needlog = needscan = 0;
-       xfs_dir2_data_use_free(args, bp, dup, args->geo->blksize - i,
-                              i, &needlog, &needscan);
+       error = xfs_dir2_data_use_free(args, bp, dup, args->geo->blksize - i,
+                       i, &needlog, &needscan);
+       if (error)
+               goto out_free;
        ASSERT(needscan == 0);
        /*
         * Fill in the tail.
@@ -1138,9 +1140,11 @@ xfs_dir2_sf_to_block(
        /*
         * Remove the freespace, we'll manage it.
         */
-       xfs_dir2_data_use_free(args, bp, dup,
-               (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr),
-               be16_to_cpu(dup->length), &needlog, &needscan);
+       error = xfs_dir2_data_use_free(args, bp, dup,
+                       (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr),
+                       be16_to_cpu(dup->length), &needlog, &needscan);
+       if (error)
+               goto out_free;
        /*
         * Create entry for .
         */
@@ -1244,4 +1248,7 @@ xfs_dir2_sf_to_block(
        xfs_dir2_block_log_tail(tp, bp);
        xfs_dir3_data_check(dp, bp);
        return 0;
+out_free:
+       kmem_free(sfp);
+       return error;
 }