]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - repair/dir2.c
xfsprogs: Release v6.8.0
[thirdparty/xfsprogs-dev.git] / repair / dir2.c
index 4ac0084e1480bbd1162b6a0cced805dda7258e22..e46ae9ae46f71146e5fa361124d2a45347149f25 100644 (file)
  * Known bad inode list.  These are seen when the leaf and node
  * block linkages are incorrect.
  */
-typedef struct dir2_bad {
+struct dir2_bad {
        xfs_ino_t       ino;
        struct dir2_bad *next;
-} dir2_bad_t;
+};
 
-static dir2_bad_t *dir2_bad_list;
+static struct dir2_bad *dir2_bad_list;
+pthread_mutex_t                dir2_bad_list_lock = PTHREAD_MUTEX_INITIALIZER;
 
 static void
 dir2_add_badlist(
        xfs_ino_t       ino)
 {
-       dir2_bad_t      *l;
+       struct dir2_bad *l;
 
-       if ((l = malloc(sizeof(dir2_bad_t))) == NULL) {
+       l = malloc(sizeof(*l));
+       if (!l) {
                do_error(
 _("malloc failed (%zu bytes) dir2_add_badlist:ino %" PRIu64 "\n"),
-                       sizeof(dir2_bad_t), ino);
+                       sizeof(*l), ino);
                exit(1);
        }
+       pthread_mutex_lock(&dir2_bad_list_lock);
        l->next = dir2_bad_list;
        dir2_bad_list = l;
        l->ino = ino;
+       pthread_mutex_unlock(&dir2_bad_list_lock);
 }
 
-int
+bool
 dir2_is_badino(
        xfs_ino_t       ino)
 {
-       dir2_bad_t      *l;
+       struct dir2_bad *l;
+       bool            ret = false;
 
-       for (l = dir2_bad_list; l; l = l->next)
-               if (l->ino == ino)
-                       return 1;
-       return 0;
+       pthread_mutex_lock(&dir2_bad_list_lock);
+       for (l = dir2_bad_list; l; l = l->next) {
+               if (l->ino == ino) {
+                       ret = true;
+                       break;
+               }
+       }
+       pthread_mutex_unlock(&dir2_bad_list_lock);
+       return ret;
 }
 
 /*
@@ -84,8 +94,8 @@ process_sf_dir2_fixi8(
        memmove(oldsfp, newsfp, oldsize);
        newsfp->count = oldsfp->count;
        newsfp->i8count = 0;
-       ino = M_DIROPS(mp)->sf_get_parent_ino(sfp);
-       M_DIROPS(mp)->sf_put_parent_ino(newsfp, ino);
+       ino = libxfs_dir2_sf_get_parent_ino(oldsfp);
+       libxfs_dir2_sf_put_parent_ino(newsfp, ino);
        oldsfep = xfs_dir2_sf_firstentry(oldsfp);
        newsfep = xfs_dir2_sf_firstentry(newsfp);
        while ((int)((char *)oldsfep - (char *)oldsfp) < oldsize) {
@@ -93,10 +103,10 @@ process_sf_dir2_fixi8(
                xfs_dir2_sf_put_offset(newsfep,
                        xfs_dir2_sf_get_offset(oldsfep));
                memmove(newsfep->name, oldsfep->name, newsfep->namelen);
-               ino = M_DIROPS(mp)->sf_get_ino(oldsfp, oldsfep);
-               M_DIROPS(mp)->sf_put_ino(newsfp, newsfep, ino);
-               oldsfep = M_DIROPS(mp)->sf_nextentry(oldsfp, oldsfep);
-               newsfep = M_DIROPS(mp)->sf_nextentry(newsfp, newsfep);
+               ino = libxfs_dir2_sf_get_ino(mp, oldsfp, oldsfep);
+               libxfs_dir2_sf_put_ino(mp, newsfp, newsfep, ino);
+               oldsfep = libxfs_dir2_sf_nextentry(mp, oldsfp, oldsfep);
+               newsfep = libxfs_dir2_sf_nextentry(mp, newsfp, newsfep);
        }
        *next_sfep = newsfep;
        free(oldsfp);
@@ -107,8 +117,8 @@ process_sf_dir2_fixi8(
  */
 static void
 process_sf_dir2_fixoff(
-       xfs_mount_t     *mp,
-       xfs_dinode_t    *dip)
+       xfs_mount_t             *mp,
+       struct xfs_dinode       *dip)
 {
        int                     i;
        int                     offset;
@@ -117,12 +127,12 @@ process_sf_dir2_fixoff(
 
        sfp = (struct xfs_dir2_sf_hdr *)XFS_DFORK_DPTR(dip);
        sfep = xfs_dir2_sf_firstentry(sfp);
-       offset = M_DIROPS(mp)->data_first_offset;
+       offset = mp->m_dir_geo->data_first_offset;
 
        for (i = 0; i < sfp->count; i++) {
                xfs_dir2_sf_put_offset(sfep, offset);
-               offset += M_DIROPS(mp)->data_entsize(sfep->namelen);
-               sfep = M_DIROPS(mp)->sf_nextentry(sfp, sfep);
+               offset += libxfs_dir2_data_entsize(mp, sfep->namelen);
+               sfep = libxfs_dir2_sf_nextentry(mp, sfp, sfep);
        }
 }
 
@@ -135,14 +145,14 @@ process_sf_dir2_fixoff(
 /* ARGSUSED */
 static int
 process_sf_dir2(
-       xfs_mount_t     *mp,
-       xfs_ino_t       ino,
-       xfs_dinode_t    *dip,
-       int             ino_discovery,
-       int             *dino_dirty,    /* out - 1 if dinode buffer dirty */
-       char            *dirname,       /* directory pathname */
-       xfs_ino_t       *parent,        /* out - NULLFSINO if entry not exist */
-       int             *repair)        /* out - 1 if dir was fixed up */
+       xfs_mount_t             *mp,
+       xfs_ino_t               ino,
+       struct xfs_dinode       *dip,
+       int                     ino_discovery,
+       int                     *dino_dirty, /* out: 1 if dinode buffer dirty */
+       char                    *dirname,    /* directory pathname */
+       xfs_ino_t               *parent,     /* out: NULLFSINO if no entry */
+       int                     *repair)     /* out: 1 if dir was fixed up */
 {
        int                     bad_offset;
        int                     bad_sfnamelen;
@@ -165,13 +175,12 @@ process_sf_dir2(
        int                     tmp_elen;
        int                     tmp_len;
        xfs_dir2_sf_entry_t     *tmp_sfep;
-       xfs_ino_t               zero = 0;
 
        sfp = (struct xfs_dir2_sf_hdr *)XFS_DFORK_DPTR(dip);
        max_size = XFS_DFORK_DSIZE(dip, mp);
        num_entries = sfp->count;
        ino_dir_size = be64_to_cpu(dip->di_size);
-       offset = M_DIROPS(mp)->data_first_offset;
+       offset = mp->m_dir_geo->data_first_offset;
        bad_offset = *repair = 0;
 
        ASSERT(ino_dir_size <= max_size);
@@ -179,12 +188,12 @@ process_sf_dir2(
        /*
         * Initialize i8 based on size of parent inode number.
         */
-       i8 = (M_DIROPS(mp)->sf_get_parent_ino(sfp) > XFS_DIR2_MAX_SHORT_INUM);
+       i8 = (libxfs_dir2_sf_get_parent_ino(sfp) > XFS_DIR2_MAX_SHORT_INUM);
 
        /*
         * check for bad entry count
         */
-       if (num_entries * M_DIROPS(mp)->sf_entsize(sfp, 1) +
+       if (num_entries * libxfs_dir2_sf_entsize(mp, sfp, 1) +
                    xfs_dir2_sf_hdr_size(0) > max_size || num_entries == 0)
                num_entries = 0xFF;
 
@@ -200,7 +209,7 @@ process_sf_dir2(
                sfep = next_sfep;
                junkit = 0;
                bad_sfnamelen = 0;
-               lino = M_DIROPS(mp)->sf_get_ino(sfp, sfep);
+               lino = libxfs_dir2_sf_get_ino(mp, sfp, sfep);
                /*
                 * if entry points to self, junk it since only '.' or '..'
                 * should do that and shortform dirs don't contain either
@@ -215,7 +224,7 @@ process_sf_dir2(
                if (lino == ino) {
                        junkit = 1;
                        junkreason = _("current");
-               } else if (verify_inum(mp, lino)) {
+               } else if (!libxfs_verify_dir_ino(mp, lino)) {
                        junkit = 1;
                        junkreason = _("invalid");
                } else if (lino == mp->m_sb.sb_rbmino)  {
@@ -281,7 +290,7 @@ _("entry \"%*.*s\" in shortform directory %" PRIu64 " references %s inode %" PRI
                        junkreason = _("is zero length");
                        bad_sfnamelen = 1;
                } else if ((intptr_t) sfep - (intptr_t) sfp +
-                               M_DIROPS(mp)->sf_entsize(sfp, sfep->namelen)
+                               libxfs_dir2_sf_entsize(mp, sfp, sfep->namelen)
                                                        > ino_dir_size)  {
                        junkreason = _("extends past end of dir");
                        bad_sfnamelen = 1;
@@ -327,7 +336,7 @@ _("entry contains offset out of order in shortform dir %" PRIu64 "\n"),
                        bad_offset = 1;
                }
                offset = xfs_dir2_sf_get_offset(sfep) +
-                                       M_DIROPS(mp)->data_entsize(namelen);
+                                       libxfs_dir2_data_entsize(mp, namelen);
 
                /*
                 * junk the entry by copying up the rest of the
@@ -344,7 +353,7 @@ _("entry contains offset out of order in shortform dir %" PRIu64 "\n"),
                        name[namelen] = '\0';
 
                        if (!no_modify)  {
-                               tmp_elen = M_DIROPS(mp)->sf_entsize(sfp,
+                               tmp_elen = libxfs_dir2_sf_entsize(mp, sfp,
                                                                sfep->namelen);
                                be64_add_cpu(&dip->di_size, -tmp_elen);
                                ino_dir_size -= tmp_elen;
@@ -398,8 +407,8 @@ _("would have junked entry \"%s\" in directory inode %" PRIu64 "\n"),
                next_sfep = (tmp_sfep == NULL)
                        ? (xfs_dir2_sf_entry_t *) ((intptr_t) sfep
                                                        + ((!bad_sfnamelen)
-                               ? M_DIROPS(mp)->sf_entsize(sfp, sfep->namelen)
-                               : M_DIROPS(mp)->sf_entsize(sfp, namelen)))
+                               ? libxfs_dir2_sf_entsize(mp, sfp, sfep->namelen)
+                               : libxfs_dir2_sf_entsize(mp, sfp, namelen)))
                        : tmp_sfep;
        }
 
@@ -479,15 +488,23 @@ _("corrected entry offsets in directory %" PRIu64 "\n"),
        /*
         * check parent (..) entry
         */
-       *parent = M_DIROPS(mp)->sf_get_parent_ino(sfp);
+       *parent = libxfs_dir2_sf_get_parent_ino(sfp);
+       /*
+        * If this function is called during inode discovery (phase 3), it will
+        * set a bad sf dir parent pointer to the root directory. This fixes
+        * the directory enough to pass the inode fork verifier in phase 6 when
+        * we try to reset the parent pointer to the correct value. There is no
+        * need to re-check the parent pointer during phase 4.
+        */
+       if (!ino_discovery)
+               return 0;
 
        /*
         * if parent entry is bogus, null it out.  we'll fix it later .
         * If the validation fails for the root inode we fix it in
         * the next else case.
         */
-       if (verify_inum(mp, *parent) && ino != mp->m_sb.sb_rootino)  {
-
+       if (!libxfs_verify_dir_ino(mp, *parent) && ino != mp->m_sb.sb_rootino) {
                do_warn(
 _("bogus .. inode number (%" PRIu64 ") in directory inode %" PRIu64 ", "),
                                *parent, ino);
@@ -495,7 +512,7 @@ _("bogus .. inode number (%" PRIu64 ") in directory inode %" PRIu64 ", "),
                if (!no_modify)  {
                        do_warn(_("clearing inode number\n"));
 
-                       M_DIROPS(mp)->sf_put_parent_ino(sfp, zero);
+                       libxfs_dir2_sf_put_parent_ino(sfp, mp->m_sb.sb_rootino);
                        *dino_dirty = 1;
                        *repair = 1;
                } else  {
@@ -510,7 +527,7 @@ _("bogus .. inode number (%" PRIu64 ") in directory inode %" PRIu64 ", "),
 _("corrected root directory %" PRIu64 " .. entry, was %" PRIu64 ", now %" PRIu64 "\n"),
                                ino, *parent, ino);
                        *parent = ino;
-                       M_DIROPS(mp)->sf_put_parent_ino(sfp, ino);
+                       libxfs_dir2_sf_put_parent_ino(sfp, ino);
                        *dino_dirty = 1;
                        *repair = 1;
                } else  {
@@ -530,7 +547,7 @@ _("bad .. entry in directory inode %" PRIu64 ", points to self, "),
                if (!no_modify)  {
                        do_warn(_("clearing inode number\n"));
 
-                       M_DIROPS(mp)->sf_put_parent_ino(sfp, zero);
+                       libxfs_dir2_sf_put_parent_ino(sfp, mp->m_sb.sb_rootino);
                        *dino_dirty = 1;
                        *repair = 1;
                } else  {
@@ -547,18 +564,18 @@ _("bad .. entry in directory inode %" PRIu64 ", points to self, "),
 /* ARGSUSED */
 static int
 process_dir2_data(
-       xfs_mount_t     *mp,
-       xfs_ino_t       ino,
-       xfs_dinode_t    *dip,
-       int             ino_discovery,
-       char            *dirname,       /* directory pathname */
-       xfs_ino_t       *parent,        /* out - NULLFSINO if entry not exist */
-       struct xfs_buf  *bp,
-       int             *dot,           /* out - 1 if there is a dot, else 0 */
-       int             *dotdot,        /* out - 1 if there's a dotdot, else 0 */
-       xfs_dablk_t     da_bno,
-       char            *endptr,
-       int             *dirty)
+       xfs_mount_t             *mp,
+       xfs_ino_t               ino,
+       struct xfs_dinode       *dip,
+       int                     ino_discovery,
+       char                    *dirname, /* directory pathname */
+       xfs_ino_t               *parent,  /* out: NULLFSINO if entry not exist*/
+       struct xfs_buf          *bp,
+       int                     *dot,     /* out: 1 if there's a dot else 0 */
+       int                     *dotdot,  /* out: 1 if there's a dotdot else 0*/
+       xfs_dablk_t             da_bno,
+       char                    *endptr,
+       int                     *dirty)
 {
        int                     badbest;
        xfs_dir2_data_free_t    *bf;
@@ -579,8 +596,8 @@ process_dir2_data(
        xfs_ino_t               ent_ino;
 
        d = bp->b_addr;
-       bf = M_DIROPS(mp)->data_bestfree_p(d);
-       ptr = (char *)M_DIROPS(mp)->data_entry_p(d);
+       bf = libxfs_dir2_data_bestfree_p(mp, d);
+       ptr = (char *)d + mp->m_dir_geo->data_entry_offset;
        badbest = lastfree = freeseen = 0;
        if (be16_to_cpu(bf[0].length) == 0) {
                badbest |= be16_to_cpu(bf[0].offset) != 0;
@@ -625,12 +642,12 @@ process_dir2_data(
                        continue;
                }
                dep = (xfs_dir2_data_entry_t *)ptr;
-               if (ptr + M_DIROPS(mp)->data_entsize(dep->namelen) > endptr)
+               if (ptr + libxfs_dir2_data_entsize(mp, dep->namelen) > endptr)
                        break;
-               if (be16_to_cpu(*M_DIROPS(mp)->data_entry_tag_p(dep)) !=
+               if (be16_to_cpu(*libxfs_dir2_data_entry_tag_p(mp, dep)) !=
                                                (char *)dep - (char *)d)
                        break;
-               ptr += M_DIROPS(mp)->data_entsize(dep->namelen);
+               ptr += libxfs_dir2_data_entsize(mp, dep->namelen);
                lastfree = 0;
        }
        /*
@@ -646,7 +663,7 @@ process_dir2_data(
                        do_warn(_("\twould junk block\n"));
                return 1;
        }
-       ptr = (char *)M_DIROPS(mp)->data_entry_p(d);
+       ptr = (char *)d + mp->m_dir_geo->data_entry_offset;
        /*
         * Process the entries now.
         */
@@ -674,7 +691,7 @@ process_dir2_data(
                         * (or did it ourselves) during phase 3.
                         */
                        clearino = 0;
-               } else if (verify_inum(mp, ent_ino)) {
+               } else if (!libxfs_verify_dir_ino(mp, ent_ino)) {
                        /*
                         * Bad inode number.  Clear the inode number and the
                         * entry will get removed later.  We don't trash the
@@ -917,7 +934,7 @@ _("entry \"%*.*s\" in directory inode %" PRIu64 " points to self: "),
                /*
                 * Advance to the next entry.
                 */
-               ptr += M_DIROPS(mp)->data_entsize(dep->namelen);
+               ptr += libxfs_dir2_data_entsize(mp, dep->namelen);
        }
        /*
         * Check the bestfree table.
@@ -928,8 +945,7 @@ _("bad bestfree table in block %u in directory inode %" PRIu64 ": "),
                        da_bno, ino);
                if (!no_modify) {
                        do_warn(_("repairing table\n"));
-                       libxfs_dir2_data_freescan_int(mp->m_dir_geo,
-                                       M_DIROPS(mp), d, &i);
+                       libxfs_dir2_data_freescan(mp, d, &i);
                        *dirty = 1;
                } else {
                        do_warn(_("would repair table\n"));
@@ -944,17 +960,17 @@ _("bad bestfree table in block %u in directory inode %" PRIu64 ": "),
 /* ARGSUSED */
 static int
 process_block_dir2(
-       xfs_mount_t     *mp,
-       xfs_ino_t       ino,
-       xfs_dinode_t    *dip,
-       int             ino_discovery,
-       int             *dino_dirty,    /* out - 1 if dinode buffer dirty */
-       char            *dirname,       /* directory pathname */
-       xfs_ino_t       *parent,        /* out - NULLFSINO if entry not exist */
-       blkmap_t        *blkmap,
-       int             *dot,           /* out - 1 if there is a dot, else 0 */
-       int             *dotdot,        /* out - 1 if there's a dotdot, else 0 */
-       int             *repair)        /* out - 1 if something was fixed */
+       xfs_mount_t             *mp,
+       xfs_ino_t               ino,
+       struct xfs_dinode       *dip,
+       int                     ino_discovery,
+       int                     *dino_dirty, /* out: 1 if dinode buffer dirty */
+       char                    *dirname,    /* directory pathname */
+       xfs_ino_t               *parent,     /* out: NULLFSINO if no entry */
+       blkmap_t                *blkmap,
+       int                     *dot,        /* out: 1 if there's a dot else 0 */
+       int                     *dotdot,     /* out: 1 if there's a dotdot else 0 */
+       int                     *repair)     /* out: 1 if something was fixed */
 {
        struct xfs_dir2_data_hdr *block;
        xfs_dir2_leaf_entry_t   *blp;
@@ -985,6 +1001,13 @@ _("can't read block %u for directory inode %" PRIu64 "\n"),
                        mp->m_dir_geo->datablk, ino);
                return 1;
        }
+       if (bp->b_error == -EFSCORRUPTED) {
+               do_warn(
+_("corrupt directory block %u for inode %" PRIu64 "\n"),
+                       mp->m_dir_geo->datablk, ino);
+               libxfs_buf_relse(bp);
+               return 1;
+       }
        /*
         * Verify the block
         */
@@ -1012,9 +1035,10 @@ _("bad directory block magic # %#x in block %u for directory inode %" PRIu64 "\n
                dirty = 1;
        if (dirty && !no_modify) {
                *repair = 1;
-               libxfs_writebuf(bp, 0);
+               libxfs_buf_mark_dirty(bp);
+               libxfs_buf_relse(bp);
        } else
-               libxfs_putbuf(bp);
+               libxfs_buf_relse(bp);
        return rval;
 }
 
@@ -1038,8 +1062,8 @@ process_leaf_block_dir2(
        struct xfs_dir2_leaf_entry *ents;
        struct xfs_dir3_icleaf_hdr leafhdr;
 
-       M_DIROPS(mp)->leaf_hdr_from_disk(&leafhdr, leaf);
-       ents = M_DIROPS(mp)->leaf_ents_p(leaf);
+       libxfs_dir2_leaf_hdr_from_disk(mp, &leafhdr, leaf);
+       ents = leafhdr.ents;
 
        for (i = stale = 0; i < leafhdr.count; i++) {
                if ((char *)&ents[i] >= (char *)leaf + mp->m_dir_geo->blksize) {
@@ -1123,8 +1147,15 @@ _("can't read file block %u for directory inode %" PRIu64 "\n"),
                                da_bno, ino);
                        goto error_out;
                }
+               if (bp->b_error == -EFSCORRUPTED) {
+                       do_warn(
+_("corrupt directory leafn block %u for inode %" PRIu64 "\n"),
+                               da_bno, ino);
+                       libxfs_buf_relse(bp);
+                       goto error_out;
+               }
                leaf = bp->b_addr;
-               M_DIROPS(mp)->leaf_hdr_from_disk(&leafhdr, leaf);
+               libxfs_dir2_leaf_hdr_from_disk(mp, &leafhdr, leaf);
                /*
                 * Check magic number for leaf directory btree block.
                 */
@@ -1133,7 +1164,7 @@ _("can't read file block %u for directory inode %" PRIu64 "\n"),
                        do_warn(
 _("bad directory leaf magic # %#x for directory inode %" PRIu64 " block %u\n"),
                                leafhdr.magic, ino, da_bno);
-                       libxfs_putbuf(bp);
+                       libxfs_buf_relse(bp);
                        goto error_out;
                }
                buf_dirty = 0;
@@ -1143,7 +1174,7 @@ _("bad directory leaf magic # %#x for directory inode %" PRIu64 " block %u\n"),
                 */
                if (process_leaf_block_dir2(mp, leaf, da_bno, ino,
                                current_hashval, &greatest_hashval)) {
-                       libxfs_putbuf(bp);
+                       libxfs_buf_relse(bp);
                        goto error_out;
                }
                /*
@@ -1161,14 +1192,14 @@ _("bad directory leaf magic # %#x for directory inode %" PRIu64 " block %u\n"),
                        do_warn(
 _("bad sibling back pointer for block %u in directory inode %" PRIu64 "\n"),
                                da_bno, ino);
-                       libxfs_putbuf(bp);
+                       libxfs_buf_relse(bp);
                        goto error_out;
                }
                prev_bno = da_bno;
                da_bno = leafhdr.forw;
                if (da_bno != 0) {
                        if (verify_da_path(mp, da_cursor, 0, XFS_DATA_FORK)) {
-                               libxfs_putbuf(bp);
+                               libxfs_buf_relse(bp);
                                goto error_out;
                        }
                }
@@ -1182,9 +1213,10 @@ _("bad sibling back pointer for block %u in directory inode %" PRIu64 "\n"),
                ASSERT(buf_dirty == 0 || (buf_dirty && !no_modify));
                if (buf_dirty && !no_modify) {
                        *repair = 1;
-                       libxfs_writebuf(bp, 0);
+                       libxfs_buf_mark_dirty(bp);
+                       libxfs_buf_relse(bp);
                } else
-                       libxfs_putbuf(bp);
+                       libxfs_buf_relse(bp);
        } while (da_bno != 0);
        if (verify_final_da_path(mp, da_cursor, 0, XFS_DATA_FORK)) {
                /*
@@ -1215,11 +1247,11 @@ error_out:
  */
 static int
 process_node_dir2(
-       xfs_mount_t     *mp,
-       xfs_ino_t       ino,
-       xfs_dinode_t    *dip,
-       blkmap_t        *blkmap,
-       int             *repair)
+       xfs_mount_t             *mp,
+       xfs_ino_t               ino,
+       struct xfs_dinode       *dip,
+       blkmap_t                *blkmap,
+       int                     *repair)
 {
        xfs_dablk_t             bno;
        da_bt_cursor_t          da_cursor;
@@ -1275,17 +1307,17 @@ process_node_dir2(
  */
 static int
 process_leaf_node_dir2(
-       xfs_mount_t     *mp,
-       xfs_ino_t       ino,
-       xfs_dinode_t    *dip,
-       int             ino_discovery,
-       char            *dirname,       /* directory pathname */
-       xfs_ino_t       *parent,        /* out - NULLFSINO if entry not exist */
-       blkmap_t        *blkmap,
-       int             *dot,           /* out - 1 if there is a dot, else 0 */
-       int             *dotdot,        /* out - 1 if there's a dotdot, else 0 */
-       int             *repair,        /* out - 1 if something was fixed */
-       int             isnode)         /* node directory not leaf */
+       xfs_mount_t             *mp,
+       xfs_ino_t               ino,
+       struct xfs_dinode       *dip,
+       int                     ino_discovery,
+       char                    *dirname, /* directory pathname */
+       xfs_ino_t               *parent,  /* out: NULLFSINO if no entry */
+       blkmap_t                *blkmap,
+       int                     *dot,     /* out: 1 if there's a dot else 0 */
+       int                     *dotdot,  /* out: 1 if there's a dotdot else 0*/
+       int                     *repair,  /* out: 1 if something was fixed */
+       int                     isnode)   /* node directory not leaf */
 {
        bmap_ext_t              *bmp;
        struct xfs_buf          *bp;
@@ -1295,7 +1327,7 @@ process_leaf_node_dir2(
        int                     i;
        xfs_fileoff_t           ndbno;
        int                     nex;
-       int                     t;
+       xfs_extnum_t            t;
        bmap_ext_t              lbmp;
        int                     dirty = 0;
 
@@ -1324,6 +1356,13 @@ _("can't read block %" PRIu64 " for directory inode %" PRIu64 "\n"),
                                dbno, ino);
                        continue;
                }
+               if (bp->b_error == -EFSCORRUPTED) {
+                       do_warn(
+_("corrupt directory data block %" PRIu64 " for inode %" PRIu64 "\n"),
+                               dbno, ino);
+                       libxfs_buf_relse(bp);
+                       continue;
+               }
                data = bp->b_addr;
                if (!(be32_to_cpu(data->magic) == XFS_DIR2_DATA_MAGIC ||
                      be32_to_cpu(data->magic) == XFS_DIR3_DATA_MAGIC))
@@ -1341,9 +1380,10 @@ _("bad directory block magic # %#x in block %" PRIu64 " for directory inode %" P
                }
                if (dirty && !no_modify) {
                        *repair = 1;
-                       libxfs_writebuf(bp, 0);
+                       libxfs_buf_mark_dirty(bp);
+                       libxfs_buf_relse(bp);
                } else
-                       libxfs_putbuf(bp);
+                       libxfs_buf_relse(bp);
        }
        if (good == 0)
                return 1;
@@ -1365,20 +1405,20 @@ _("bad directory block magic # %#x in block %" PRIu64 " for directory inode %" P
  */
 int
 process_dir2(
-       xfs_mount_t     *mp,
-       xfs_ino_t       ino,
-       xfs_dinode_t    *dip,
-       int             ino_discovery,
-       int             *dino_dirty,
-       char            *dirname,
-       xfs_ino_t       *parent,
-       blkmap_t        *blkmap)
+       xfs_mount_t             *mp,
+       xfs_ino_t               ino,
+       struct xfs_dinode       *dip,
+       int                     ino_discovery,
+       int                     *dino_dirty,
+       char                    *dirname,
+       xfs_ino_t               *parent,
+       blkmap_t                *blkmap)
 {
-       int             dot;
-       int             dotdot;
-       xfs_fileoff_t   last;
-       int             repair;
-       int             res;
+       int                     dot;
+       int                     dotdot;
+       xfs_fileoff_t           last;
+       int                     repair;
+       int                     res;
 
        *parent = NULLFSINO;
        dot = dotdot = 0;