]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
Don't trash lost+found in phase 4
authorBarry Naujok <bnaujok@sgi.com>
Mon, 16 Jul 2007 15:53:42 +0000 (15:53 +0000)
committerBarry Naujok <bnaujok@sgi.com>
Mon, 16 Jul 2007 15:53:42 +0000 (15:53 +0000)
Merge of master-melb:xfs-cmds:29144a by kenmcd.

  Update critical error message

libxfs/util.c
repair/dino_chunks.c
repair/dir.c
repair/dir2.c
repair/globals.h
repair/phase1.c
repair/phase4.c
repair/phase6.c
repair/phase7.c

index 8477d7f1af05e0aa1fbf982506533347851c181b..d7aa5799257f1bd7ab19f06612724d63f81ae1d7 100644 (file)
@@ -824,7 +824,8 @@ xfs_fs_repair_cmn_err(int level, xfs_mount_t *mp, char *fmt, ...)
        va_start(ap, fmt);
        vfprintf(stderr, fmt, ap);
        fprintf(stderr, "  This is a bug.\n");
-       fprintf(stderr, "Please report it to xfs@oss.sgi.com.\n");
+       fprintf(stderr, "Please capture the filesystem metadata with "
+                       "xfs_metadump and\nreport it to xfs@oss.sgi.com.\n");
        va_end(ap);
 }
 
index 2a316b68c4883a30dc67b4fd7bfe79329e619bd2..aa05b1569f4c4d72ad7a0c50e7637066ed18e9c0 100644 (file)
@@ -762,18 +762,14 @@ process_inode_chunk(xfs_mount_t *mp, xfs_agnumber_t agno, int num_inos,
                 */
                if (is_used)  {
                        if (is_inode_free(ino_rec, irec_offset))  {
-                               if (verbose || no_modify ||
-                                   XFS_AGINO_TO_INO(mp, agno, agino) !=
-                                                       old_orphanage_ino)  {
+                               if (verbose || no_modify)  {
                                        do_warn(_("imap claims in-use inode "
                                                  "%llu is free, "),
                                                XFS_AGINO_TO_INO(mp, agno,
                                                agino));
                                }
 
-                               if (verbose || (!no_modify &&
-                                   XFS_AGINO_TO_INO(mp, agno, agino) !=
-                                               old_orphanage_ino))
+                               if (verbose || !no_modify)
                                        do_warn(_("correcting imap\n"));
                                else
                                        do_warn(_("would correct imap\n"));
index 2117bb4e284d093a70057e9401cba25877c53371..a1a8095833025d12c9e31d1e40d99380e6c9821d 100644 (file)
@@ -1952,12 +1952,6 @@ _("entry #%d, bno %d in directory %llu references group quota inode %llu\n"),
                                _("\twould clear ino number in entry %d...\n"),
                                        i);
                        }
-               } else if (lino == old_orphanage_ino)  {
-                       /*
-                        * do nothing, silently ignore it, entry has
-                        * already been marked TBD since old_orphanage_ino
-                        * is set non-zero.
-                        */
                } else if ((irec_p = find_inode_rec(
                                XFS_INO_TO_AGNO(mp, lino),
                                XFS_INO_TO_AGINO(mp, lino))) != NULL)  {
index 46240769ff0b0337982c1d389350237154a74805..b471de098ddfcbb23067cf283f4e201266c70ea8 100644 (file)
@@ -1440,13 +1440,6 @@ process_dir2_data(
                } else if (INT_GET(dep->inumber, ARCH_CONVERT) == mp->m_sb.sb_gquotino) {
                        clearino = 1;
                        clearreason = _("group quota");
-               } else if (INT_GET(dep->inumber, ARCH_CONVERT) == old_orphanage_ino) {
-                       /*
-                        * Do nothing, silently ignore it, entry has already
-                        * been marked TBD since old_orphanage_ino is set
-                        * non-zero.
-                        */
-                       clearino = 0;
                } else if ((irec_p = find_inode_rec(
                                XFS_INO_TO_AGNO(mp, INT_GET(dep->inumber,
                                        ARCH_CONVERT)),
index 5982377c13765f30f9e6c2e1abe0638402ef9c09..d0db09a3e546446fc2587a4cf62165d8cb34134e 100644 (file)
@@ -182,9 +182,6 @@ EXTERN __uint64_t   sb_ifree;       /* free inodes */
 EXTERN __uint64_t      sb_fdblocks;    /* free data blocks */
 EXTERN __uint64_t      sb_frextents;   /* free realtime extents */
 
-EXTERN xfs_ino_t       orphanage_ino;
-EXTERN xfs_ino_t       old_orphanage_ino;
-
 /* superblock geometry info */
 
 EXTERN xfs_extlen_t    sb_inoalignmt;
index 374e3202a25e82e6f889a0822ce2c20b287a9746..e860deb82a2803da5301002044887d0e3f8738eb 100644 (file)
@@ -63,7 +63,6 @@ phase1(xfs_mount_t *mp)
        need_rbmino = 0;
        need_rsumino = 0;
        lost_quotas = 0;
-       old_orphanage_ino = (xfs_ino_t) 0;
 
        /*
         * get AG 0 into ag header buf
index eb7a61fde1baf147100a43833f2190e0c35bcad1..a69beef89588c088a3d74b3bb4f85762e85ee040 100644 (file)
 #include "progress.h"
 
 
-/* ARGSUSED */
-int
-lf_block_delete_orphanage(xfs_mount_t          *mp,
-                       xfs_ino_t               ino,
-                       xfs_dir_leafblock_t     *leaf,
-                       int                     *dirty,
-                       xfs_buf_t               *rootino_bp,
-                       int                     *rbuf_dirty)
-{
-       xfs_dir_leaf_entry_t    *entry;
-       xfs_dinode_t            *dino;
-       xfs_buf_t               *bp;
-       ino_tree_node_t         *irec;
-       xfs_ino_t               lino;
-       xfs_dir_leaf_name_t     *namest;
-       xfs_agino_t             agino;
-       xfs_agnumber_t          agno;
-       xfs_agino_t             root_agino;
-       xfs_agnumber_t          root_agno;
-       int                     i;
-       int                     ino_offset;
-       int                     ino_dirty;
-       int                     use_rbuf;
-       int                     len;
-       char                    fname[MAXNAMELEN + 1];
-       int                     res;
-
-       entry = &leaf->entries[0];
-       *dirty = 0;
-       use_rbuf = 0;
-       res = 0;
-       root_agno = XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino);
-       root_agino = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino);
-
-       for (i = 0; i < INT_GET(leaf->hdr.count, ARCH_CONVERT); entry++, i++) {
-               namest = XFS_DIR_LEAF_NAMESTRUCT(leaf,
-                       INT_GET(entry->nameidx, ARCH_CONVERT));
-               XFS_DIR_SF_GET_DIRINO(&namest->inumber, &lino);
-               bcopy(namest->name, fname, entry->namelen);
-               fname[entry->namelen] = '\0';
-
-               if (fname[0] != '/' && !strcmp(fname, ORPHANAGE))  {
-                       agino = XFS_INO_TO_AGINO(mp, lino);
-                       agno = XFS_INO_TO_AGNO(mp, lino);
-
-                       old_orphanage_ino = lino;
-
-                       irec = find_inode_rec(agno, agino);
-
-                       /*
-                        * if the orphange inode is in the tree,
-                        * get it, clear it, and mark it free.
-                        * the inodes in the orphanage will get
-                        * reattached to the new orphanage.
-                        */
-                       if (irec != NULL)  {
-                               ino_offset = agino - irec->ino_startnum;
-
-                               /*
-                                * check if we have to use the root inode
-                                * buffer or read one in ourselves.  Note
-                                * that the root inode is always the first
-                                * inode of the chunk that it's in so there
-                                * are two possible cases where lost+found
-                                * might be in the same buffer as the root
-                                * inode.  One case is a large block
-                                * filesystem where the two inodes are
-                                * in different inode chunks but wind
-                                * up in the same block (multiple chunks
-                                * per block) and the second case (one or
-                                * more blocks per chunk) is where the two
-                                * inodes are in the same chunk. Note that
-                                * inodes are allocated on disk in units
-                                * of MAX(XFS_INODES_PER_CHUNK,sb_inopblock).
-                                */
-                               if (XFS_INO_TO_FSB(mp, mp->m_sb.sb_rootino)
-                                               == XFS_INO_TO_FSB(mp, lino) ||
-                                   (agno == root_agno &&
-                                    agino < root_agino + XFS_INODES_PER_CHUNK)) {
-                                       use_rbuf = 1;
-                                       bp = rootino_bp;
-                                       dino = XFS_MAKE_IPTR(mp, bp, agino -
-                                               XFS_INO_TO_AGINO(mp,
-                                                       mp->m_sb.sb_rootino));
-                               } else {
-                                       len = (int)XFS_FSB_TO_BB(mp,
-                                               MAX(1, XFS_INODES_PER_CHUNK/
-                                                       inodes_per_block));
-                                       bp = libxfs_readbuf(mp->m_dev,
-                                               XFS_AGB_TO_DADDR(mp, agno,
-                                                       XFS_AGINO_TO_AGBNO(mp,
-                                                               irec->ino_startnum)),
-                                               len, 0);
-                                       if (!bp)
-                                               do_error(
-                                       _("couldn't read %s inode %llu\n"),
-                                                       ORPHANAGE, lino);
-
-                                       /*
-                                        * get the agbno containing the first
-                                        * inode in the chunk.  In multi-block
-                                        * chunks, this gets us the offset
-                                        * relative to the beginning of a
-                                        * properly aligned buffer.  In
-                                        * multi-chunk blocks, this gets us
-                                        * the correct block number.  Then
-                                        * turn the block number back into
-                                        * an agino and calculate the offset
-                                        * from there to feed to make the iptr.
-                                        * the last term in effect rounds down
-                                        * to the first agino in the buffer.
-                                        */
-                                       dino = XFS_MAKE_IPTR(mp, bp,
-                                               agino - XFS_OFFBNO_TO_AGINO(mp,
-                                                       XFS_AGINO_TO_AGBNO(mp,
-                                                       irec->ino_startnum),
-                                                       0));
-                               }
-
-                               do_warn(
-                       _("        - clearing existing \"%s\" inode\n"),
-                                       ORPHANAGE);
-
-                               ino_dirty = clear_dinode(mp, dino, lino);
-
-                               if (!use_rbuf)  {
-                                       ASSERT(ino_dirty == 0 ||
-                                               (ino_dirty && !no_modify));
-
-                                       if (ino_dirty && !no_modify)
-                                               libxfs_writebuf(bp, 0);
-                                       else
-                                               libxfs_putbuf(bp);
-                               } else  {
-                                       if (ino_dirty)
-                                               *rbuf_dirty = 1;
-                               }
-
-                               if (inode_isadir(irec, ino_offset))
-                                       clear_inode_isadir(irec, ino_offset);
-
-                               set_inode_free(irec, ino_offset);
-                       }
-
-                       /*
-                        * regardless of whether the inode num is good or
-                        * bad, mark the entry to be junked so the
-                        * createname in phase 6 will succeed.
-                        */
-                       namest->name[0] = '/';
-                       *dirty = 1;
-                       do_warn(
-                       _("        - marking entry \"%s\" to be deleted\n"),
-                               fname);
-                       res++;
-               }
-       }
-
-       return(res);
-}
-
-int
-longform_delete_orphanage(xfs_mount_t  *mp,
-                       xfs_ino_t       ino,
-                       xfs_dinode_t    *dino,
-                       xfs_buf_t       *rootino_bp,
-                       int             *rbuf_dirty)
-{
-       xfs_dir_leafblock_t     *leaf;
-       xfs_buf_t               *bp;
-       xfs_dfsbno_t            fsbno;
-       xfs_dablk_t             da_bno;
-       int                     dirty;
-       int                     res;
-
-       da_bno = 0;
-       *rbuf_dirty = 0;
-
-       if ((fsbno = get_first_dblock_fsbno(mp, ino, dino)) == NULLDFSBNO)
-               do_error(
-       _("couldn't map first leaf block of directory inode %llu\n"), ino);
-
-       /*
-        * cycle through the entire directory looking to delete
-        * every "lost+found" entry.  make sure to catch duplicate
-        * entries.
-        *
-        * We could probably speed this up by doing a smarter lookup
-        * to get us to the first block that contains the hashvalue
-        * of "lost+found" but what the heck.  that would require a
-        * double lookup for each level.  and how big can '/' get???
-        * It's probably not worth it.
-        */
-       res = 0;
-
-       do {
-               if (fsbno == NULLDFSBNO)
-                       break;
-               bp = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, fsbno),
-                                       XFS_FSB_TO_BB(mp, 1), 0);
-               if (!bp)
-                       do_error(_("can't read block %u (fsbno %llu) for "
-                                  "directory inode %llu\n"),
-                               da_bno, fsbno, ino);
-
-               leaf = (xfs_dir_leafblock_t *)XFS_BUF_PTR(bp);
-
-               if (INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) !=
-                   XFS_DIR_LEAF_MAGIC)
-                       do_error(_("bad magic # (0x%x) for directory "
-                               "leaf block (bno %u fsbno %llu)\n"),
-                               INT_GET(leaf->hdr.info.magic, ARCH_CONVERT),
-                               da_bno, fsbno);
-
-               da_bno = INT_GET(leaf->hdr.info.forw, ARCH_CONVERT);
-
-               res += lf_block_delete_orphanage(mp, ino, leaf, &dirty,
-                                       rootino_bp, rbuf_dirty);
-
-               ASSERT(dirty == 0 || (dirty && !no_modify));
-
-               if (dirty && !no_modify)
-                       libxfs_writebuf(bp, 0);
-               else
-                       libxfs_putbuf(bp);
-
-               if (da_bno != 0)
-                       fsbno = get_bmapi(mp, dino, ino, da_bno, XFS_DATA_FORK);
-
-       } while (da_bno != 0);
-
-       return(res);
-}
-
-/*
- * returns 1 if a deletion happened, 0 otherwise.
- */
-/* ARGSUSED */
-int
-shortform_delete_orphanage(xfs_mount_t *mp,
-                       xfs_ino_t       ino,
-                       xfs_dinode_t    *root_dino,
-                       xfs_buf_t       *rootino_bp,
-                       int             *ino_dirty)
-{
-       xfs_dir_shortform_t     *sf;
-       xfs_dinode_t            *dino;
-       xfs_dir_sf_entry_t      *sf_entry, *next_sfe, *tmp_sfe;
-       xfs_buf_t               *bp;
-       xfs_ino_t               lino;
-       xfs_agino_t             agino;
-       xfs_agino_t             root_agino;
-       int                     max_size;
-       xfs_agnumber_t          agno;
-       xfs_agnumber_t          root_agno;
-       int                     ino_dir_size;
-       ino_tree_node_t         *irec;
-       int                     ino_offset;
-       int                     i;
-       int                     dirty;
-       int                     tmp_len;
-       int                     tmp_elen;
-       int                     len;
-       int                     use_rbuf;
-       char                    fname[MAXNAMELEN + 1];
-       int                     res;
-
-       sf = &root_dino->di_u.di_dirsf;
-       *ino_dirty = 0;
-       res = 0;
-       irec = NULL;
-       ino_dir_size = INT_GET(root_dino->di_core.di_size, ARCH_CONVERT);
-       max_size = XFS_DFORK_DSIZE(root_dino, mp);
-       use_rbuf = 0;
-       root_agno = XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino);
-       root_agino = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino);
-
-       /*
-        * run through entries looking for "lost+found".
-        */
-       sf_entry = next_sfe = &sf->list[0];
-       for (i = 0; i < INT_GET(sf->hdr.count, ARCH_CONVERT) && ino_dir_size >
-                       (__psint_t)next_sfe - (__psint_t)sf; i++)  {
-               tmp_sfe = NULL;
-               sf_entry = next_sfe;
-               XFS_DIR_SF_GET_DIRINO(&sf_entry->inumber, &lino);
-               bcopy(sf_entry->name, fname, sf_entry->namelen);
-               fname[sf_entry->namelen] = '\0';
-
-               if (!strcmp(ORPHANAGE, fname))  {
-                       agno = XFS_INO_TO_AGNO(mp, lino);
-                       agino = XFS_INO_TO_AGINO(mp, lino);
-
-                       irec = find_inode_rec(agno, agino);
-
-                       /*
-                        * if the orphange inode is in the tree,
-                        * get it, clear it, and mark it free.
-                        * the inodes in the orphanage will get
-                        * reattached to the new orphanage.
-                        */
-                       if (irec != NULL) {
-                               do_warn(
-                       _("        - clearing existing \"%s\" inode\n"),
-                                       ORPHANAGE);
-
-                               ino_offset = agino - irec->ino_startnum;
-
-                               /*
-                                * check if we have to use the root inode
-                                * buffer or read one in ourselves.  Note
-                                * that the root inode is always the first
-                                * inode of the chunk that it's in so there
-                                * are two possible cases where lost+found
-                                * might be in the same buffer as the root
-                                * inode.  One case is a large block
-                                * filesystem where the two inodes are
-                                * in different inode chunks but wind
-                                * up in the same block (multiple chunks
-                                * per block) and the second case (one or
-                                * more blocks per chunk) is where the two
-                                * inodes are in the same chunk. Note that
-                                * inodes are allocated on disk in units
-                                * of MAX(XFS_INODES_PER_CHUNK,sb_inopblock).
-                                */
-                               if (XFS_INO_TO_FSB(mp, mp->m_sb.sb_rootino)
-                                               == XFS_INO_TO_FSB(mp, lino) ||
-                                   (agno == root_agno &&
-                                    agino < root_agino + XFS_INODES_PER_CHUNK)) {
-                                       use_rbuf = 1;
-                                       bp = rootino_bp;
-
-                                       dino = XFS_MAKE_IPTR(mp, bp, agino -
-                                               XFS_INO_TO_AGINO(mp,
-                                                       mp->m_sb.sb_rootino));
-                               } else {
-                                       len = (int)XFS_FSB_TO_BB(mp,
-                                               MAX(1, XFS_INODES_PER_CHUNK/
-                                                       inodes_per_block));
-                                       bp = libxfs_readbuf(mp->m_dev,
-                                               XFS_AGB_TO_DADDR(mp, agno,
-                                                       XFS_AGINO_TO_AGBNO(mp,
-                                                               irec->ino_startnum)),
-                                               len, 0);
-                                       if (!bp)
-                                               do_error(
-                                       _("could not read %s inode %llu\n"),
-                                                       ORPHANAGE, lino);
-
-                                       /*
-                                        * get the agbno containing the first
-                                        * inode in the chunk.  In multi-block
-                                        * chunks, this gets us the offset
-                                        * relative to the beginning of a
-                                        * properly aligned buffer.  In
-                                        * multi-chunk blocks, this gets us
-                                        * the correct block number.  Then
-                                        * turn the block number back into
-                                        * an agino and calculate the offset
-                                        * from there to feed to make the iptr.
-                                        * the last term in effect rounds down
-                                        * to the first agino in the buffer.
-                                        */
-                                       dino = XFS_MAKE_IPTR(mp, bp,
-                                               agino - XFS_OFFBNO_TO_AGINO(mp,
-                                                       XFS_AGINO_TO_AGBNO(mp,
-                                                       irec->ino_startnum),
-                                                       0));
-                               }
-
-                               dirty = clear_dinode(mp, dino, lino);
-
-                               ASSERT(dirty == 0 || (dirty && !no_modify));
-
-                               /*
-                                * if we read the lost+found inode in to
-                                * it, get rid of it here.  if the lost+found
-                                * inode is in the root inode buffer, the
-                                * buffer will be marked dirty anyway since
-                                * the lost+found entry in the root inode is
-                                * also being deleted which makes the root
-                                * inode buffer automatically dirty.
-                                */
-                               if (!use_rbuf)  {
-                                       dino = NULL;
-                                       if (dirty && !no_modify)
-                                               libxfs_writebuf(bp, 0);
-                                       else
-                                               libxfs_putbuf(bp);
-                               }
-
-                               if (inode_isadir(irec, ino_offset))
-                                       clear_inode_isadir(irec, ino_offset);
-
-                               set_inode_free(irec, ino_offset);
-                       }
-
-                       do_warn(_("        - deleting existing \"%s\" entry\n"),
-                               ORPHANAGE);
-
-                       /*
-                        * note -- exactly the same deletion code as in
-                        * process_shortform_dir()
-                        */
-                       tmp_elen = XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry);
-                       INT_MOD(root_dino->di_core.di_size, ARCH_CONVERT,
-                               -(tmp_elen));
-
-                       tmp_sfe = (xfs_dir_sf_entry_t *)
-                               ((__psint_t) sf_entry + tmp_elen);
-                       tmp_len = max_size - ((__psint_t) tmp_sfe
-                                       - (__psint_t) sf);
-
-                       memmove(sf_entry, tmp_sfe, tmp_len);
-
-                       INT_MOD(sf->hdr.count, ARCH_CONVERT, -1);
-
-                       bzero((void *) ((__psint_t) sf_entry + tmp_len),
-                               tmp_elen);
-
-                       /*
-                        * set the tmp value to the current
-                        * pointer so we'll process the entry
-                        * we just moved up
-                        */
-                       tmp_sfe = sf_entry;
-
-                       /*
-                        * WARNING:  drop the index i by one
-                        * so it matches the decremented count for
-                        * accurate comparisons in the loop test.
-                        * mark root inode as dirty to make deletion
-                        * permanent.
-                        */
-                       i--;
-
-                       *ino_dirty = 1;
-                       res++;
-
-               }
-               next_sfe = (tmp_sfe == NULL)
-                       ? (xfs_dir_sf_entry_t *) ((__psint_t) sf_entry +
-                               XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry))
-                       : tmp_sfe;
-       }
-
-       return(res);
-}
-
-/* ARGSUSED */
-int
-lf2_block_delete_orphanage(xfs_mount_t         *mp,
-                       xfs_ino_t               ino,
-                       xfs_dir2_data_t         *data,
-                       int                     *dirty,
-                       xfs_buf_t               *rootino_bp,
-                       int                     *rbuf_dirty)
-{
-       xfs_dinode_t            *dino;
-       xfs_buf_t               *bp;
-       ino_tree_node_t         *irec;
-       xfs_ino_t               lino;
-       xfs_agino_t             agino;
-       xfs_agnumber_t          agno;
-       xfs_agino_t             root_agino;
-       xfs_agnumber_t          root_agno;
-       int                     ino_offset;
-       int                     ino_dirty;
-       int                     use_rbuf;
-       int                     len;
-       char                    fname[MAXNAMELEN + 1];
-       int                     res;
-       char                    *ptr;
-       char                    *endptr;
-       xfs_dir2_block_tail_t   *btp;
-       xfs_dir2_data_entry_t   *dep;
-       xfs_dir2_data_unused_t  *dup;
-
-       ptr = (char *)data->u;
-       if (INT_GET(data->hdr.magic, ARCH_CONVERT) == XFS_DIR2_BLOCK_MAGIC) {
-               btp = XFS_DIR2_BLOCK_TAIL_P(mp, (xfs_dir2_block_t *)data);
-               endptr = (char *)XFS_DIR2_BLOCK_LEAF_P(btp);
-       } else
-               endptr = (char *)data + mp->m_dirblksize;
-       *dirty = 0;
-       use_rbuf = 0;
-       res = 0;
-       root_agno = XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino);
-       root_agino = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino);
-
-       while (ptr < endptr) {
-               dup = (xfs_dir2_data_unused_t *)ptr;
-               if (INT_GET(dup->freetag, ARCH_CONVERT) ==
-                   XFS_DIR2_DATA_FREE_TAG) {
-                       if (ptr + INT_GET(dup->length, ARCH_CONVERT) > endptr ||
-                               INT_GET(dup->length, ARCH_CONVERT) == 0 ||
-                               (INT_GET(dup->length, ARCH_CONVERT) &
-                                               (XFS_DIR2_DATA_ALIGN - 1)))
-                               break;
-                       ptr += INT_GET(dup->length, ARCH_CONVERT);
-                       continue;
-               }
-               dep = (xfs_dir2_data_entry_t *)ptr;
-               lino = INT_GET(dep->inumber, ARCH_CONVERT);
-               bcopy(dep->name, fname, dep->namelen);
-               fname[dep->namelen] = '\0';
-
-               if (fname[0] != '/' && !strcmp(fname, ORPHANAGE))  {
-                       agino = XFS_INO_TO_AGINO(mp, lino);
-                       agno = XFS_INO_TO_AGNO(mp, lino);
-
-                       old_orphanage_ino = lino;
-
-                       irec = find_inode_rec(agno, agino);
-
-                       /*
-                        * if the orphange inode is in the tree,
-                        * get it, clear it, and mark it free.
-                        * the inodes in the orphanage will get
-                        * reattached to the new orphanage.
-                        */
-                       if (irec != NULL)  {
-                               ino_offset = agino - irec->ino_startnum;
-
-                               /*
-                                * check if we have to use the root inode
-                                * buffer or read one in ourselves.  Note
-                                * that the root inode is always the first
-                                * inode of the chunk that it's in so there
-                                * are two possible cases where lost+found
-                                * might be in the same buffer as the root
-                                * inode.  One case is a large block
-                                * filesystem where the two inodes are
-                                * in different inode chunks but wind
-                                * up in the same block (multiple chunks
-                                * per block) and the second case (one or
-                                * more blocks per chunk) is where the two
-                                * inodes are in the same chunk. Note that
-                                * inodes are allocated on disk in units
-                                * of MAX(XFS_INODES_PER_CHUNK,sb_inopblock).
-                                */
-                               if (XFS_INO_TO_FSB(mp, mp->m_sb.sb_rootino)
-                                               == XFS_INO_TO_FSB(mp, lino) ||
-                                   (agno == root_agno &&
-                                    agino < root_agino + XFS_INODES_PER_CHUNK)) {
-                                       use_rbuf = 1;
-                                       bp = rootino_bp;
-                                       dino = XFS_MAKE_IPTR(mp, bp, agino -
-                                               XFS_INO_TO_AGINO(mp,
-                                                       mp->m_sb.sb_rootino));
-                               } else  {
-                                       len = (int)XFS_FSB_TO_BB(mp,
-                                               MAX(1, XFS_INODES_PER_CHUNK/
-                                                       inodes_per_block));
-                                       bp = libxfs_readbuf(mp->m_dev,
-                                               XFS_AGB_TO_DADDR(mp, agno,
-                                                       XFS_AGINO_TO_AGBNO(mp,
-                                                               irec->ino_startnum)),
-                                               len, 0);
-                                       if (!bp)
-                                               do_error(
-                                       _("couldn't read %s inode %llu\n"),
-                                                       ORPHANAGE, lino);
-
-                                       /*
-                                        * get the agbno containing the first
-                                        * inode in the chunk.  In multi-block
-                                        * chunks, this gets us the offset
-                                        * relative to the beginning of a
-                                        * properly aligned buffer.  In
-                                        * multi-chunk blocks, this gets us
-                                        * the correct block number.  Then
-                                        * turn the block number back into
-                                        * an agino and calculate the offset
-                                        * from there to feed to make the iptr.
-                                        * the last term in effect rounds down
-                                        * to the first agino in the buffer.
-                                        */
-                                       dino = XFS_MAKE_IPTR(mp, bp,
-                                               agino - XFS_OFFBNO_TO_AGINO(mp,
-                                                       XFS_AGINO_TO_AGBNO(mp,
-                                                       irec->ino_startnum),
-                                                       0));
-                               }
-
-                               do_warn(
-                               _("        - clearing existing \"%s\" inode\n"),
-                                       ORPHANAGE);
-
-                               ino_dirty = clear_dinode(mp, dino, lino);
-
-                               if (!use_rbuf) {
-                                       ASSERT(ino_dirty == 0 ||
-                                               (ino_dirty && !no_modify));
-
-                                       if (ino_dirty && !no_modify)
-                                               libxfs_writebuf(bp, 0);
-                                       else
-                                               libxfs_putbuf(bp);
-                               } else {
-                                       if (ino_dirty)
-                                               *rbuf_dirty = 1;
-                               }
-
-                               if (inode_isadir(irec, ino_offset))
-                                       clear_inode_isadir(irec, ino_offset);
-
-                               set_inode_free(irec, ino_offset);
-
-                       }
-
-                       /*
-                        * regardless of whether the inode num is good or
-                        * bad, mark the entry to be junked so the
-                        * createname in phase 6 will succeed.
-                        */
-                       dep->name[0] = '/';
-                       *dirty = 1;
-                       do_warn(
-                       _("        - marking entry \"%s\" to be deleted\n"),
-                               fname);
-                       res++;
-               }
-               ptr += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
-       }
-
-       return(res);
-}
-
-int
-longform2_delete_orphanage(xfs_mount_t *mp,
-                       xfs_ino_t       ino,
-                       xfs_dinode_t    *dino,
-                       xfs_buf_t       *rootino_bp,
-                       int             *rbuf_dirty)
-{
-       xfs_dir2_data_t         *data;
-       xfs_dabuf_t             *bp;
-       xfs_dfsbno_t            fsbno;
-       xfs_dablk_t             da_bno;
-       int                     dirty;
-       int                     res;
-       bmap_ext_t              *bmp;
-       int                     i;
-
-       da_bno = 0;
-       *rbuf_dirty = 0;
-       fsbno = NULLDFSBNO;
-       bmp = malloc(mp->m_dirblkfsbs * sizeof(*bmp));
-       if (!bmp)
-               do_error(
-       _("malloc failed (%u bytes) in longform2_delete_orphanage, ino %llu\n"),
-                       mp->m_dirblkfsbs * sizeof(*bmp), ino);
-
-       /*
-        * cycle through the entire directory looking to delete
-        * every "lost+found" entry.  make sure to catch duplicate
-        * entries.
-        *
-        * We could probably speed this up by doing a smarter lookup
-        * to get us to the first block that contains the hashvalue
-        * of "lost+found" but what the heck.  that would require a
-        * double lookup for each level.  and how big can '/' get???
-        * It's probably not worth it.
-        */
-       res = 0;
-
-       for (da_bno = 0;
-            da_bno < XFS_B_TO_FSB(mp, INT_GET(dino->di_core.di_size, ARCH_CONVERT));
-            da_bno += mp->m_dirblkfsbs) {
-               for (i = 0; i < mp->m_dirblkfsbs; i++) {
-                       fsbno = get_bmapi(mp, dino, ino, da_bno + i,
-                                         XFS_DATA_FORK);
-                       if (fsbno == NULLDFSBNO)
-                               break;
-                       bmp[i].startoff = da_bno + i;
-                       bmp[i].startblock = fsbno;
-                       bmp[i].blockcount = 1;
-                       bmp[i].flag = 0;
-               }
-               if (fsbno == NULLDFSBNO)
-                       continue;
-               bp = da_read_buf(mp, mp->m_dirblkfsbs, bmp);
-               if (bp == NULL)
-                       do_error(
-       _("can't read block %u (fsbno %llu) for directory inode %llu\n"),
-                               da_bno, bmp[0].startblock, ino);
-
-               data = (xfs_dir2_data_t *)bp->data;
-
-               if (INT_GET(data->hdr.magic, ARCH_CONVERT) !=
-                                       XFS_DIR2_DATA_MAGIC &&
-                   INT_GET(data->hdr.magic, ARCH_CONVERT) !=
-                                       XFS_DIR2_BLOCK_MAGIC)
-                       do_error(
-       _("bad magic # (0x%x) for directory data block (bno %u fsbno %llu)\n"),
-                               INT_GET(data->hdr.magic, ARCH_CONVERT),
-                               da_bno, bmp[0].startblock);
-
-               res += lf2_block_delete_orphanage(mp, ino, data, &dirty,
-                                       rootino_bp, rbuf_dirty);
-
-               ASSERT(dirty == 0 || (dirty && !no_modify));
-
-               if (dirty && !no_modify)
-                       da_bwrite(mp, bp);
-               else
-                       da_brelse(bp);
-       }
-       free(bmp);
-
-       return(res);
-}
-
-/*
- * returns 1 if a deletion happened, 0 otherwise.
- */
-/* ARGSUSED */
-int
-shortform2_delete_orphanage(xfs_mount_t        *mp,
-                       xfs_ino_t       ino,
-                       xfs_dinode_t    *root_dino,
-                       xfs_buf_t       *rootino_bp,
-                       int             *ino_dirty)
-{
-       xfs_dir2_sf_t           *sf;
-       xfs_dinode_t            *dino;
-       xfs_dir2_sf_entry_t     *sf_entry, *next_sfe, *tmp_sfe;
-       xfs_buf_t               *bp;
-       xfs_ino_t               lino;
-       xfs_agino_t             agino;
-       xfs_agino_t             root_agino;
-       int                     max_size;
-       xfs_agnumber_t          agno;
-       xfs_agnumber_t          root_agno;
-       int                     ino_dir_size;
-       ino_tree_node_t         *irec;
-       int                     ino_offset;
-       int                     i;
-       int                     dirty;
-       int                     tmp_len;
-       int                     tmp_elen;
-       int                     len;
-       int                     use_rbuf;
-       char                    fname[MAXNAMELEN + 1];
-       int                     res;
-
-       sf = &root_dino->di_u.di_dir2sf;
-       *ino_dirty = 0;
-       irec = NULL;
-       ino_dir_size = INT_GET(root_dino->di_core.di_size, ARCH_CONVERT);
-       max_size = XFS_DFORK_DSIZE(root_dino, mp);
-       use_rbuf = 0;
-       res = 0;
-       root_agno = XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino);
-       root_agino = XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino);
-
-       /*
-        * run through entries looking for "lost+found".
-        */
-       sf_entry = next_sfe = XFS_DIR2_SF_FIRSTENTRY(sf);
-       for (i = 0; i < INT_GET(sf->hdr.count, ARCH_CONVERT) && ino_dir_size >
-                       (__psint_t)next_sfe - (__psint_t)sf; i++)  {
-               tmp_sfe = NULL;
-               sf_entry = next_sfe;
-               lino = XFS_DIR2_SF_GET_INUMBER(sf,
-                       XFS_DIR2_SF_INUMBERP(sf_entry));
-               bcopy(sf_entry->name, fname, sf_entry->namelen);
-               fname[sf_entry->namelen] = '\0';
-
-               if (!strcmp(ORPHANAGE, fname))  {
-                       agno = XFS_INO_TO_AGNO(mp, lino);
-                       agino = XFS_INO_TO_AGINO(mp, lino);
-
-                       irec = find_inode_rec(agno, agino);
-
-                       /*
-                        * if the orphange inode is in the tree,
-                        * get it, clear it, and mark it free.
-                        * the inodes in the orphanage will get
-                        * reattached to the new orphanage.
-                        */
-                       if (irec != NULL)  {
-                               do_warn(
-                               _("        - clearing existing \"%s\" inode\n"),
-                                       ORPHANAGE);
-
-                               ino_offset = agino - irec->ino_startnum;
-
-                               /*
-                                * check if we have to use the root inode
-                                * buffer or read one in ourselves.  Note
-                                * that the root inode is always the first
-                                * inode of the chunk that it's in so there
-                                * are two possible cases where lost+found
-                                * might be in the same buffer as the root
-                                * inode.  One case is a large block
-                                * filesystem where the two inodes are
-                                * in different inode chunks but wind
-                                * up in the same block (multiple chunks
-                                * per block) and the second case (one or
-                                * more blocks per chunk) is where the two
-                                * inodes are in the same chunk. Note that
-                                * inodes are allocated on disk in units
-                                * of MAX(XFS_INODES_PER_CHUNK,sb_inopblock).
-                                */
-                               if (XFS_INO_TO_FSB(mp, mp->m_sb.sb_rootino)
-                                               == XFS_INO_TO_FSB(mp, lino) ||
-                                   (agno == root_agno &&
-                                    agino < root_agino + XFS_INODES_PER_CHUNK)) {
-                                       use_rbuf = 1;
-                                       bp = rootino_bp;
-
-                                       dino = XFS_MAKE_IPTR(mp, bp, agino -
-                                               XFS_INO_TO_AGINO(mp,
-                                                       mp->m_sb.sb_rootino));
-                               } else  {
-                                       len = (int)XFS_FSB_TO_BB(mp,
-                                               MAX(1, XFS_INODES_PER_CHUNK/
-                                                       inodes_per_block));
-                                       bp = libxfs_readbuf(mp->m_dev,
-                                               XFS_AGB_TO_DADDR(mp, agno,
-                                                       XFS_AGINO_TO_AGBNO(mp,
-                                                               irec->ino_startnum)),
-                                               len, 0);
-                                       if (!bp)
-                                               do_error(
-                                       _("could not read %s inode %llu\n"),
-                                                       ORPHANAGE, lino);
-
-                                       /*
-                                        * get the agbno containing the first
-                                        * inode in the chunk.  In multi-block
-                                        * chunks, this gets us the offset
-                                        * relative to the beginning of a
-                                        * properly aligned buffer.  In
-                                        * multi-chunk blocks, this gets us
-                                        * the correct block number.  Then
-                                        * turn the block number back into
-                                        * an agino and calculate the offset
-                                        * from there to feed to make the iptr.
-                                        * the last term in effect rounds down
-                                        * to the first agino in the buffer.
-                                        */
-                                       dino = XFS_MAKE_IPTR(mp, bp,
-                                               agino - XFS_OFFBNO_TO_AGINO(mp,
-                                                       XFS_AGINO_TO_AGBNO(mp,
-                                                       irec->ino_startnum),
-                                                       0));
-                               }
-
-                               dirty = clear_dinode(mp, dino, lino);
-
-                               ASSERT(dirty == 0 || (dirty && !no_modify));
-
-                               /*
-                                * if we read the lost+found inode in to
-                                * it, get rid of it here.  if the lost+found
-                                * inode is in the root inode buffer, the
-                                * buffer will be marked dirty anyway since
-                                * the lost+found entry in the root inode is
-                                * also being deleted which makes the root
-                                * inode buffer automatically dirty.
-                                */
-                               if (!use_rbuf)  {
-                                       dino = NULL;
-                                       if (dirty && !no_modify)
-                                               libxfs_writebuf(bp, 0);
-                                       else
-                                               libxfs_putbuf(bp);
-                               }
-
-
-                               if (inode_isadir(irec, ino_offset))
-                                       clear_inode_isadir(irec, ino_offset);
-
-                               set_inode_free(irec, ino_offset);
-                       }
-
-                       do_warn(_("        - deleting existing \"%s\" entry\n"),
-                               ORPHANAGE);
-
-                       /*
-                        * note -- exactly the same deletion code as in
-                        * process_shortform_dir()
-                        */
-                       tmp_elen = XFS_DIR2_SF_ENTSIZE_BYENTRY(sf, sf_entry);
-                       INT_MOD(root_dino->di_core.di_size, ARCH_CONVERT,
-                               -(tmp_elen));
-
-                       tmp_sfe = (xfs_dir2_sf_entry_t *)
-                               ((__psint_t) sf_entry + tmp_elen);
-                       tmp_len = max_size - ((__psint_t) tmp_sfe
-                                       - (__psint_t) sf);
-
-                       memmove(sf_entry, tmp_sfe, tmp_len);
-
-                       INT_MOD(sf->hdr.count, ARCH_CONVERT, -1);
-                       if (lino > XFS_DIR2_MAX_SHORT_INUM)
-                               sf->hdr.i8count--;
-
-                       bzero((void *) ((__psint_t) sf_entry + tmp_len),
-                               tmp_elen);
-
-                       /*
-                        * set the tmp value to the current
-                        * pointer so we'll process the entry
-                        * we just moved up
-                        */
-                       tmp_sfe = sf_entry;
-
-                       /*
-                        * WARNING:  drop the index i by one
-                        * so it matches the decremented count for
-                        * accurate comparisons in the loop test.
-                        * mark root inode as dirty to make deletion
-                        * permanent.
-                        */
-                       i--;
-
-                       *ino_dirty = 1;
-
-                       res++;
-               }
-               next_sfe = (tmp_sfe == NULL)
-                       ? (xfs_dir2_sf_entry_t *) ((__psint_t) sf_entry +
-                               XFS_DIR2_SF_ENTSIZE_BYENTRY(sf, sf_entry))
-                       : tmp_sfe;
-       }
-
-       return(res);
-}
-
-void
-delete_orphanage(xfs_mount_t *mp)
-{
-       xfs_ino_t ino;
-       xfs_dinode_t *dino;
-       xfs_buf_t *dbp;
-       int dirty, res, len;
-
-       ASSERT(!no_modify);
-
-       dbp = NULL;
-       dirty = res = 0;
-       ino = mp->m_sb.sb_rootino;
-
-       /*
-        * we know the root is in use or we wouldn't be here
-        */
-       len = (int)XFS_FSB_TO_BB(mp,
-                       MAX(1, XFS_INODES_PER_CHUNK/inodes_per_block));
-       dbp = libxfs_readbuf(mp->m_dev,
-                       XFS_FSB_TO_DADDR(mp, XFS_INO_TO_FSB(mp, ino)), len, 0);
-       if (!dbp)
-               do_error(_("could not read buffer for root inode %llu "
-                          "(daddr %lld, size %d)\n"), ino,
-                       XFS_FSB_TO_DADDR(mp, XFS_INO_TO_FSB(mp, ino)),
-                       XFS_FSB_TO_BB(mp, 1));
-
-       /*
-        * we also know that the root inode is always the first inode
-        * allocated in the system, therefore it'll be at the beginning
-        * of the root inode chunk
-        */
-       dino = XFS_MAKE_IPTR(mp, dbp, 0);
-
-       switch (dino->di_core.di_format)  {
-       case XFS_DINODE_FMT_EXTENTS:
-       case XFS_DINODE_FMT_BTREE:
-               if (XFS_SB_VERSION_HASDIRV2(&mp->m_sb))
-                       res = longform2_delete_orphanage(mp, ino, dino, dbp,
-                               &dirty);
-               else
-                       res = longform_delete_orphanage(mp, ino, dino, dbp,
-                               &dirty);
-               break;
-       case XFS_DINODE_FMT_LOCAL:
-               if (XFS_SB_VERSION_HASDIRV2(&mp->m_sb))
-                       res = shortform2_delete_orphanage(mp, ino, dino, dbp,
-                               &dirty);
-               else
-                       res = shortform_delete_orphanage(mp, ino, dino, dbp,
-                               &dirty);
-               ASSERT((res == 0 && dirty == 0) || (res > 0 && dirty == 1));
-               break;
-       default:
-               break;
-       }
-
-       if (res)  {
-               switch (dino->di_core.di_version)  {
-               case XFS_DINODE_VERSION_1:
-                       INT_MOD(dino->di_core.di_onlink, ARCH_CONVERT, -res);
-                       INT_SET(dino->di_core.di_nlink, ARCH_CONVERT,
-                               INT_GET(dino->di_core.di_onlink, ARCH_CONVERT));
-                       break;
-               case XFS_DINODE_VERSION_2:
-                       INT_MOD(dino->di_core.di_nlink, ARCH_CONVERT, -res);
-                       break;
-               default:
-                       do_error(_("unknown version #%d in root inode\n"),
-                                       dino->di_core.di_version);
-               }
-
-               dirty = 1;
-       }
-
-       if (dirty)
-               libxfs_writebuf(dbp, 0);
-       else
-               libxfs_putbuf(dbp);
-}
-
 /*
  * null out quota inode fields in sb if they point to non-existent inodes.
  * this isn't as redundant as it looks since it's possible that the sb field
@@ -1180,16 +166,6 @@ phase4(xfs_mount_t *mp)
                        do_warn(_("root inode lost\n"));
        }
 
-       /*
-        * have to delete lost+found first so that blocks used
-        * by lost+found don't show up as used
-        */
-       if (!no_modify)  {
-               do_log(_("        - clear lost+found (if it exists) ...\n"));
-               if (!need_root_inode)
-                       delete_orphanage(mp);
-       }
-
        for (i = 0; i < mp->m_sb.sb_agcount; i++)  {
                ag_end = (i < mp->m_sb.sb_agcount - 1) ? mp->m_sb.sb_agblocks :
                        mp->m_sb.sb_dblocks -
index 743c455b87c7f17de774dff5bb261d191cf84a1f..1bba95b5f358fe64c0db3870fc95a822fa835221 100644 (file)
 #include "progress.h"
 #include "versions.h"
 
-static struct cred zerocr;
-static struct fsxattr zerofsx;
-static int orphanage_entered;
+static struct cred             zerocr;
+static struct fsxattr          zerofsx;
+static xfs_ino_t               orphanage_ino;
+static xfs_inode_t             *orphanage_ip;
 
 /*
  * Data structures and routines to keep track of directory entries
@@ -808,6 +809,24 @@ mk_orphanage(xfs_mount_t *mp)
        const int       mode = 0755;
        int             nres;
 
+       /*
+        * check for an existing lost+found first, if it exists, return
+        * it's inode. Otherwise, we can create it. Bad lost+found inodes
+        * would have been cleared in phase3 and phase4.
+        */
+
+       if ((i = libxfs_iget(mp, NULL, mp->m_sb.sb_rootino, 0, &pip, 0)))
+               do_error(_("%d - couldn't iget root inode to obtain %s\n"),
+                       i, ORPHANAGE);
+
+       if (dir_lookup(mp, NULL, pip, ORPHANAGE, strlen(ORPHANAGE),
+                       &ino) == 0)
+               return ino;
+
+       /*
+        * could not be found, create it
+        */
+
        tp = libxfs_trans_alloc(mp, 0);
        XFS_BMAP_INIT(&flist, &first);
 
@@ -820,9 +839,9 @@ mk_orphanage(xfs_mount_t *mp)
         * use iget/ijoin instead of trans_iget because the ialloc
         * wrapper can commit the transaction and start a new one
         */
-       if ((i = libxfs_iget(mp, NULL, mp->m_sb.sb_rootino, 0, &pip, 0)))
+/*     if ((i = libxfs_iget(mp, NULL, mp->m_sb.sb_rootino, 0, &pip, 0)))
                do_error(_("%d - couldn't iget root inode to make %s\n"),
-                       i, ORPHANAGE);
+                       i, ORPHANAGE);*/
 
        error = libxfs_inode_alloc(&tp, pip, mode|S_IFDIR,
                                        1, 0, &zerocr, &zerofsx, &ip);
@@ -843,18 +862,19 @@ mk_orphanage(xfs_mount_t *mp)
         */
        if ((error = dir_createname(mp, tp, pip, ORPHANAGE,
                        strlen(ORPHANAGE), ip->i_ino, &first, &flist, nres))) {
-               do_warn(
-               _("can't make %s, createname error %d, will try later\n"),
+               do_error(
+               _("can't make %s, createname error %d\n"),
                        ORPHANAGE, error);
-               orphanage_entered = 0;
-       } else
-               orphanage_entered = 1;
+       }
 
        /*
         * bump up the link count in the root directory to account
         * for .. in the new directory
         */
        pip->i_d.di_nlink++;
+       add_inode_ref(find_inode_rec(XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino),
+                               XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino)), 0);
+
 
        libxfs_trans_log_inode(tp, pip, XFS_ILOG_CORE);
        dir_init(mp, tp, ip, pip);
@@ -870,36 +890,45 @@ mk_orphanage(xfs_mount_t *mp)
 
        libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC, 0);
 
-       /* need libxfs_iput here? - nathans TODO - possible memory leak? */
-
        return(ino);
 }
 
 /*
- * move a file to the orphange.  the orphanage is guaranteed
- * at this point to only have file in it whose name == file inode #
+ * move a file to the orphange.
  */
-void
-mv_orphanage(xfs_mount_t       *mp,
-               xfs_ino_t       dir_ino,        /* orphange inode # */
-               xfs_ino_t       ino,            /* inode # to be moved */
-               int             isa_dir)        /* 1 if inode is a directory */
+static void
+mv_orphanage(
+       xfs_mount_t             *mp,
+       xfs_ino_t               ino,            /* inode # to be moved */
+       int                     isa_dir)        /* 1 if inode is a directory */
 {
-       xfs_ino_t       entry_ino_num;
-       xfs_inode_t     *dir_ino_p;
-       xfs_inode_t     *ino_p;
-       xfs_trans_t     *tp;
-       xfs_fsblock_t   first;
-       xfs_bmap_free_t flist;
-       int             err;
-       int             committed;
-       char            fname[MAXPATHLEN + 1];
-       int             nres;
+       xfs_ino_t               entry_ino_num;
+       xfs_inode_t             *ino_p;
+       xfs_trans_t             *tp;
+       xfs_fsblock_t           first;
+       xfs_bmap_free_t         flist;
+       int                     err;
+       int                     committed;
+       char                    fname[MAXPATHLEN + 1];
+       int                     fnamelen;
+       int                     nres;
+       int                     incr;
+       ino_tree_node_t         *irec;
+       int                     ino_offset = 0;
 
-       snprintf(fname, sizeof(fname), "%llu", (unsigned long long)ino);
+       fnamelen = snprintf(fname, sizeof(fname), "%llu",
+                       (unsigned long long)ino);
 
-       if ((err = libxfs_iget(mp, NULL, dir_ino, 0, &dir_ino_p, 0)))
-               do_error(_("%d - couldn't iget orphanage inode\n"), err);
+       ASSERT(orphanage_ip != NULL);
+       /*
+        * Make sure the filename is unique in the lost+found
+        */
+       incr = 0;
+       while (dir_lookup(mp, NULL, orphanage_ip, fname, fnamelen,
+                       &entry_ino_num) == 0) {
+               fnamelen = snprintf(fname, sizeof(fname), "%llu.%d",
+                               (unsigned long long)ino, ++incr);
+       }
 
        tp = libxfs_trans_alloc(mp, 0);
 
@@ -907,10 +936,15 @@ mv_orphanage(xfs_mount_t  *mp,
                do_error(_("%d - couldn't iget disconnected inode\n"), err);
 
        if (isa_dir)  {
-               nres = XFS_DIRENTER_SPACE_RES(mp, strlen(fname)) +
+               irec = find_inode_rec(XFS_INO_TO_AGNO(mp, orphanage_ino),
+                               XFS_INO_TO_AGINO(mp, orphanage_ino));
+               if (irec)
+                       ino_offset = XFS_INO_TO_AGINO(mp, orphanage_ino) -
+                                       irec->ino_startnum;
+               nres = XFS_DIRENTER_SPACE_RES(mp, fnamelen) +
                       XFS_DIRENTER_SPACE_RES(mp, 2);
-               if ((err = dir_lookup(mp, tp, ino_p, "..", 2,
-                               &entry_ino_num))) {
+               err = dir_lookup(mp, tp, ino_p, "..", 2, &entry_ino_num);
+               if (err) {
                        ASSERT(err == ENOENT);
 
                        if ((err = libxfs_trans_reserve(tp, nres,
@@ -921,22 +955,25 @@ mv_orphanage(xfs_mount_t  *mp,
        _("space reservation failed (%d), filesystem may be out of space\n"),
                                        err);
 
-                       libxfs_trans_ijoin(tp, dir_ino_p, 0);
+                       libxfs_trans_ijoin(tp, orphanage_ip, 0);
                        libxfs_trans_ijoin(tp, ino_p, 0);
 
                        XFS_BMAP_INIT(&flist, &first);
-                       if ((err = dir_createname(mp, tp, dir_ino_p, fname,
-                                               strlen(fname), ino, &first,
+                       if ((err = dir_createname(mp, tp, orphanage_ip, fname,
+                                               fnamelen, ino, &first,
                                                &flist, nres)))
                                do_error(
        _("name create failed in %s (%d), filesystem may be out of space\n"),
                                        ORPHANAGE, err);
 
-                       dir_ino_p->i_d.di_nlink++;
-                       libxfs_trans_log_inode(tp, dir_ino_p, XFS_ILOG_CORE);
+                       if (irec)
+                               add_inode_ref(irec, ino_offset);
+                       else
+                               orphanage_ip->i_d.di_nlink++;
+                       libxfs_trans_log_inode(tp, orphanage_ip, XFS_ILOG_CORE);
 
                        if ((err = dir_createname(mp, tp, ino_p, "..", 2,
-                                               dir_ino, &first, &flist, nres)))
+                                               orphanage_ino, &first, &flist, nres)))
                                do_error(
        _("creation of .. entry failed (%d), filesystem may be out of space\n"),
                                        err);
@@ -960,28 +997,31 @@ mv_orphanage(xfs_mount_t  *mp,
        _("space reservation failed (%d), filesystem may be out of space\n"),
                                        err);
 
-                       libxfs_trans_ijoin(tp, dir_ino_p, 0);
+                       libxfs_trans_ijoin(tp, orphanage_ip, 0);
                        libxfs_trans_ijoin(tp, ino_p, 0);
 
                        XFS_BMAP_INIT(&flist, &first);
 
-                       if ((err = dir_createname(mp, tp, dir_ino_p, fname,
-                                               strlen(fname), ino, &first,
+                       if ((err = dir_createname(mp, tp, orphanage_ip, fname,
+                                               fnamelen, ino, &first,
                                                &flist, nres)))
                                do_error(
        _("name create failed in %s (%d), filesystem may be out of space\n"),
                                        ORPHANAGE, err);
 
-                       dir_ino_p->i_d.di_nlink++;
-                       libxfs_trans_log_inode(tp, dir_ino_p, XFS_ILOG_CORE);
+                       if (irec)
+                               add_inode_ref(irec, ino_offset);
+                       else
+                               orphanage_ip->i_d.di_nlink++;
+                       libxfs_trans_log_inode(tp, orphanage_ip, XFS_ILOG_CORE);
 
                        /*
                         * don't replace .. value if it already points
                         * to us.  that'll pop a libxfs/kernel ASSERT.
                         */
-                       if (entry_ino_num != dir_ino)  {
+                       if (entry_ino_num != orphanage_ino)  {
                                if ((err = dir_replace(mp, tp, ino_p, "..",
-                                                       2, dir_ino, &first,
+                                                       2, orphanage_ino, &first,
                                                        &flist, nres)))
                                        do_error(
        _("name replace op failed (%d), filesystem may be out of space\n"),
@@ -997,6 +1037,7 @@ mv_orphanage(xfs_mount_t   *mp,
                        libxfs_trans_commit(tp,
                                XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC, 0);
                }
+
        } else  {
                /*
                 * use the remove log reservation as that's
@@ -1004,19 +1045,19 @@ mv_orphanage(xfs_mount_t        *mp,
                 * links, we're not doing the inode allocation
                 * also accounted for in the create
                 */
-               nres = XFS_DIRENTER_SPACE_RES(mp, strlen(fname));
+               nres = XFS_DIRENTER_SPACE_RES(mp, fnamelen);
                if ((err = libxfs_trans_reserve(tp, nres, XFS_REMOVE_LOG_RES(mp), 0,
                                XFS_TRANS_PERM_LOG_RES, XFS_REMOVE_LOG_COUNT)))
                        do_error(
        _("space reservation failed (%d), filesystem may be out of space\n"),
                                err);
 
-               libxfs_trans_ijoin(tp, dir_ino_p, 0);
+               libxfs_trans_ijoin(tp, orphanage_ip, 0);
                libxfs_trans_ijoin(tp, ino_p, 0);
 
                XFS_BMAP_INIT(&flist, &first);
-               if ((err = dir_createname(mp, tp, dir_ino_p, fname,
-                               strlen(fname), ino, &first, &flist, nres)))
+               if ((err = dir_createname(mp, tp, orphanage_ip, fname,
+                               fnamelen, ino, &first, &flist, nres)))
                        do_error(
        _("name create failed in %s (%d), filesystem may be out of space\n"),
                                ORPHANAGE, err);
@@ -1365,6 +1406,24 @@ _("couldn't remove bogus entry \"%s\" in\n\tdirectory inode %llu, errno = %d\n")
        return(1);
 }
 
+static int
+entry_junked(
+       const char      *msg,
+       const char      *iname,
+       xfs_ino_t       ino1,
+       xfs_ino_t       ino2)
+{
+       do_warn(msg, iname, ino1, ino2);
+       if (!no_modify) {
+               if (verbose)
+                       do_warn(_(", marking entry to be junked\n"));
+               else
+                       do_warn("\n");
+       } else
+               do_warn(_(", would junk entry\n"));
+       return !no_modify;
+}
+
 /*
  * process a leaf block, also checks for .. entry
  * and corrects it to match what we think .. should be
@@ -1442,9 +1501,9 @@ lf_block_dir_entry_check(xfs_mount_t              *mp,
                 * take care of it then.
                 */
                if (entry->namelen == 2 && namest->name[0] == '.' &&
-                               namest->name[1] == '.')  {
+                               namest->name[1] == '.')
                        continue;
-               }
+
                ASSERT(no_modify || !verify_inum(mp, lino));
 
                /*
@@ -1463,17 +1522,6 @@ lf_block_dir_entry_check(xfs_mount_t             *mp,
                        continue;
                }
 
-               /*
-                * special case the "lost+found" entry if pointing
-                * to where we think lost+found should be.  if that's
-                * the case, that's the one we created in phase 6.
-                * just skip it.  no need to process it and it's ..
-                * link is already accounted for.
-                */
-
-               if (lino == orphanage_ino && strcmp(fname, ORPHANAGE) == 0)
-                       continue;
-
                /*
                 * skip entries with bogus inumbers if we're in no modify mode
                 */
@@ -1488,18 +1536,12 @@ lf_block_dir_entry_check(xfs_mount_t            *mp,
 
                if (irec == NULL)  {
                        nbad++;
-                       do_warn(
-       _("entry \"%s\" in dir inode %llu points to non-existent inode, "),
-                               fname, ino);
-
-                       if (!no_modify)  {
+                       if (entry_junked(_("entry \"%s\" in dir inode %llu "
+                                       "points to non-existent inode %llu"),
+                                       fname, ino, lino)) {
                                namest->name[0] = '/';
                                *dirty = 1;
-                               do_warn(_("marking entry to be junked\n"));
-                       } else  {
-                               do_warn(_("would junk entry\n"));
                        }
-
                        continue;
                }
 
@@ -1511,53 +1553,53 @@ lf_block_dir_entry_check(xfs_mount_t            *mp,
                 * really is free.
                 */
                if (is_inode_free(irec, ino_offset))  {
-                       /*
-                        * don't complain if this entry points to the old
-                        * and now-free lost+found inode
-                        */
-                       if (verbose || no_modify || lino != old_orphanage_ino)
-                               do_warn(
-               _("entry \"%s\" in dir inode %llu points to free inode %llu"),
-                                       fname, ino, lino);
                        nbad++;
-
-                       if (!no_modify)  {
-                               if (verbose || lino != old_orphanage_ino)
-                                       do_warn(
-                                       _(", marking entry to be junked\n"));
-
-                               else
-                                       do_warn("\n");
+                       if (entry_junked(_("entry \"%s\" in dir inode %llu "
+                                       "points to free inode %llu"),
+                                       fname, ino, lino)) {
                                namest->name[0] = '/';
                                *dirty = 1;
-                       } else  {
-                               do_warn(_(", would junk entry\n"));
                        }
-
                        continue;
                }
-
+               /*
+                * check if this inode is lost+found dir in the root
+                */
+               if (ino == mp->m_sb.sb_rootino && strcmp(fname, ORPHANAGE) == 0) {
+                       /* root inode, "lost+found", if it's not a directory,
+                        * trash it, otherwise, assign it */
+                       if (!inode_isadir(irec, ino_offset)) {
+                               nbad++;
+                               if (entry_junked(_("%s (ino %llu) in root "
+                                               "(%llu) is not a directory"),
+                                               ORPHANAGE, lino, ino)) {
+                                       namest->name[0] = '/';
+                                       *dirty = 1;
+                               }
+                               continue;
+                       }
+                       /*
+                        * if this is a dup, it will be picked up below,
+                        * otherwise, mark it as the orphanage for later.
+                        */
+                       if (!orphanage_ino)
+                               orphanage_ino = lino;
+               }
                /*
                 * check for duplicate names in directory.
                 */
                if (!dir_hash_add(hashtab, (da_bno << mp->m_sb.sb_blocklog) +
-                                               entry->nameidx,
-                               lino, entry->namelen, namest->name)) {
-                       do_warn(
-               _("entry \"%s\" (ino %llu) in dir %llu is a duplicate name"),
-                               fname, lino, ino);
+                               entry->nameidx, lino, entry->namelen,
+                               namest->name)) {
                        nbad++;
-                       if (!no_modify) {
-                               if (verbose)
-                                       do_warn(
-                                       _(", marking entry to be junked\n"));
-                               else
-                                       do_warn("\n");
+                       if (entry_junked(_("entry \"%s\" (ino %llu) in dir "
+                                       "%llu is a duplicate name"),
+                                       fname, lino, ino)) {
                                namest->name[0] = '/';
                                *dirty = 1;
-                       } else {
-                               do_warn(_(", would junk entry\n"));
                        }
+                       if (lino == orphanage_ino)
+                               orphanage_ino = 0;
                        continue;
                }
                /*
@@ -1598,13 +1640,14 @@ _("entry \"%s\" in dir ino %llu not consistent with .. value (%llu) in ino %llu,
                }
 
                if (junkit)  {
+                       if (lino == orphanage_ino)
+                               orphanage_ino = 0;
                        junkit = 0;
                        nbad++;
-
                        if (!no_modify)  {
                                namest->name[0] = '/';
                                *dirty = 1;
-                               if (verbose || lino != old_orphanage_ino)
+                               if (verbose)
                                        do_warn(
                                        _("\twill clear entry \"%s\"\n"),
                                                fname);
@@ -2155,22 +2198,7 @@ longform_dir2_entry_check_data(
                ptr += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
                inum = INT_GET(dep->inumber, ARCH_CONVERT);
                lastfree = 0;
-               if (!dir_hash_add(hashtab, addr, inum, dep->namelen,
-                               dep->name)) {
-                       do_warn(
-               _("entry \"%s\" (ino %llu) in dir %llu is a duplicate name"),
-                               fname, inum, ip->i_ino);
-                       if (!no_modify) {
-                               if (verbose)
-                                       do_warn(
-                                       _(", marking entry to be junked\n"));
-                               else
-                                       do_warn("\n");
-                       } else {
-                               do_warn(_(", would junk entry\n"));
-                       }
-                       dep->name[0] = '/';
-               }
+
                /*
                 * skip bogus entries (leading '/').  they'll be deleted
                 * later.  must still log it, else we leak references to
@@ -2182,10 +2210,81 @@ longform_dir2_entry_check_data(
                                libxfs_dir2_data_log_entry(tp, bp, dep);
                        continue;
                }
-               junkit = 0;
                bcopy(dep->name, fname, dep->namelen);
                fname[dep->namelen] = '\0';
                ASSERT(inum != NULLFSINO);
+
+               irec = find_inode_rec(XFS_INO_TO_AGNO(mp, inum),
+                                       XFS_INO_TO_AGINO(mp, inum));
+               if (irec == NULL)  {
+                       nbad++;
+                       if (entry_junked(_("entry \"%s\" in directory inode "
+                                       "%llu points to non-existent inode %llu"),
+                                       fname, ip->i_ino, inum)) {
+                               dep->name[0] = '/';
+                               libxfs_dir2_data_log_entry(tp, bp, dep);
+                       }
+                       continue;
+               }
+               ino_offset = XFS_INO_TO_AGINO(mp, inum) - irec->ino_startnum;
+
+               /*
+                * if it's a free inode, blow out the entry.
+                * by now, any inode that we think is free
+                * really is free.
+                */
+               if (is_inode_free(irec, ino_offset))  {
+                       nbad++;
+                       if (entry_junked(_("entry \"%s\" in directory inode "
+                                       "%llu points to free inode %llu"),
+                                       fname, ip->i_ino, inum)) {
+                               dep->name[0] = '/';
+                               libxfs_dir2_data_log_entry(tp, bp, dep);
+                       }
+                       continue;
+               }
+
+               /*
+                * check if this inode is lost+found dir in the root
+                */
+               if (inum == mp->m_sb.sb_rootino && strcmp(fname, ORPHANAGE) == 0) {
+                       /*
+                        * if it's not a directory, trash it
+                        */
+                       if (!inode_isadir(irec, ino_offset)) {
+                               nbad++;
+                               if (entry_junked(_("%s (ino %llu) in root "
+                                               "(%llu) is not a directory"),
+                                               ORPHANAGE, inum, ip->i_ino)) {
+                                       dep->name[0] = '/';
+                                       libxfs_dir2_data_log_entry(tp, bp, dep);
+                               }
+                               continue;
+                       }
+                       /*
+                        * if this is a dup, it will be picked up below,
+                        * otherwise, mark it as the orphanage for later.
+                        */
+                       if (!orphanage_ino)
+                               orphanage_ino = inum;
+               }
+               /*
+                * check for duplicate names in directory.
+                */
+               if (!dir_hash_add(hashtab, addr, inum, dep->namelen,
+                               dep->name)) {
+                       nbad++;
+                       if (entry_junked(_("entry \"%s\" (ino %llu) in dir "
+                                       "%llu is a duplicate name"),
+                                       fname, inum, ip->i_ino)) {
+                               dep->name[0] = '/';
+                               libxfs_dir2_data_log_entry(tp, bp, dep);
+                       }
+                       if (inum == orphanage_ino)
+                               orphanage_ino = 0;
+                       continue;
+               }
+
                /*
                 * skip the '..' entry since it's checked when the
                 * directory is reached by something else.  if it never
@@ -2211,68 +2310,11 @@ longform_dir2_entry_check_data(
                        *need_dot = 0;
                        continue;
                }
-               /*
-                * special case the "lost+found" entry if pointing
-                * to where we think lost+found should be.  if that's
-                * the case, that's the one we created in phase 6.
-                * just skip it.  no need to process it and it's ..
-                * link is already accounted for.
-                */
-               if (inum == orphanage_ino && strcmp(fname, ORPHANAGE) == 0)
-                       continue;
                /*
                 * skip entries with bogus inumbers if we're in no modify mode
                 */
                if (no_modify && verify_inum(mp, inum))
                        continue;
-               /*
-                * ok, now handle the rest of the cases besides '.' and '..'
-                */
-               irec = find_inode_rec(XFS_INO_TO_AGNO(mp, inum),
-                                       XFS_INO_TO_AGINO(mp, inum));
-               if (irec == NULL)  {
-                       nbad++;
-                       do_warn(_("entry \"%s\" in directory inode %llu points "
-                                 "to non-existent inode, "),
-                               fname, ip->i_ino);
-                       if (!no_modify)  {
-                               dep->name[0] = '/';
-                               libxfs_dir2_data_log_entry(tp, bp, dep);
-                               do_warn(_("marking entry to be junked\n"));
-                       } else  {
-                               do_warn(_("would junk entry\n"));
-                       }
-                       continue;
-               }
-               ino_offset = XFS_INO_TO_AGINO(mp, inum) - irec->ino_startnum;
-               /*
-                * if it's a free inode, blow out the entry.
-                * by now, any inode that we think is free
-                * really is free.
-                */
-               if (is_inode_free(irec, ino_offset))  {
-                       /*
-                        * don't complain if this entry points to the old
-                        * and now-free lost+found inode
-                        */
-                       if (verbose || no_modify || inum != old_orphanage_ino)
-                               do_warn(
-       _("entry \"%s\" in directory inode %llu points to free inode %llu"),
-                                       fname, ip->i_ino, inum);
-                       nbad++;
-                       if (!no_modify)  {
-                               if (verbose || inum != old_orphanage_ino)
-                                       do_warn(
-                                       _(", marking entry to be junked\n"));
-                               else
-                                       do_warn("\n");
-                               dep->name[0] = '/';
-                               libxfs_dir2_data_log_entry(tp, bp, dep);
-                       } else  {
-                               do_warn(_(", would junk entry\n"));
-                       }
-                       continue;
-               }
                /*
                 * check easy case first, regular inode, just bump
                 * the link count and continue
@@ -2283,6 +2325,7 @@ longform_dir2_entry_check_data(
                }
                parent = get_inode_parent(irec, ino_offset);
                ASSERT(parent != 0);
+               junkit = 0;
                /*
                 * bump up the link counts in parent and child
                 * directory but if the link doesn't agree with
@@ -2293,7 +2336,7 @@ longform_dir2_entry_check_data(
                if (is_inode_reached(irec, ino_offset))  {
                        junkit = 1;
                        do_warn(
-_("entry \"%s\" in dir %llu points to an already connected directory inode %llu,\n"),
+_("entry \"%s\" in dir %llu points to an already connected directory inode %llu\n"),
                                fname, ip->i_ino, inum);
                } else if (parent == ip->i_ino)  {
                        add_inode_reached(irec, ino_offset);
@@ -2303,16 +2346,18 @@ _("entry \"%s\" in dir %llu points to an already connected directory inode %llu,
                } else  {
                        junkit = 1;
                        do_warn(
-_("entry \"%s\" in dir inode %llu inconsistent with .. value (%llu) in ino %llu,\n"),
+_("entry \"%s\" in dir inode %llu inconsistent with .. value (%llu) in ino %llu\n"),
                                fname, ip->i_ino, parent, inum);
                }
                if (junkit)  {
+                       if (inum == orphanage_ino)
+                               orphanage_ino = 0;
                        junkit = 0;
                        nbad++;
                        if (!no_modify)  {
                                dep->name[0] = '/';
                                libxfs_dir2_data_log_entry(tp, bp, dep);
-                               if (verbose || inum != old_orphanage_ino)
+                               if (verbose)
                                        do_warn(
                                        _("\twill clear entry \"%s\"\n"),
                                                fname);
@@ -2767,36 +2812,14 @@ shortform_dir_entry_check(xfs_mount_t   *mp,
                ASSERT(no_modify || lino != NULLFSINO);
                ASSERT(no_modify || !verify_inum(mp, lino));
 
-               /*
-                * special case the "lost+found" entry if it's pointing
-                * to where we think lost+found should be.  if that's
-                * the case, that's the one we created in phase 6.
-                * just skip it.  no need to process it and its ..
-                * link is already accounted for.  Also skip entries
-                * with bogus inode numbers if we're in no modify mode.
-                */
-
-               if ((lino == orphanage_ino && strcmp(fname, ORPHANAGE) == 0)
-                               || (no_modify && verify_inum(mp, lino))) {
-                       next_sfe = (xfs_dir_sf_entry_t *)
-                               ((__psint_t) sf_entry +
-                               XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry));
-                       continue;
-               }
-
                irec = find_inode_rec(XFS_INO_TO_AGNO(mp, lino),
                                        XFS_INO_TO_AGINO(mp, lino));
-
-               if (irec == NULL && no_modify)  {
-                       do_warn(
-_("entry \"%s\" in shortform dir %llu references non-existent ino %llu\n"),
+               if (irec == NULL) {
+                       do_warn(_("entry \"%s\" in shortform dir %llu "
+                               "references non-existent ino %llu"),
                                fname, ino, lino);
-                       do_warn(_("would junk entry\n"));
-                       continue;
+                       goto do_junkit;
                }
-
-               ASSERT(irec != NULL);
-
                ino_offset = XFS_INO_TO_AGINO(mp, lino) - irec->ino_startnum;
 
                /*
@@ -2804,42 +2827,41 @@ _("entry \"%s\" in shortform dir %llu references non-existent ino %llu\n"),
                 * by now, any inode that we think is free
                 * really is free.
                 */
-               if (is_inode_free(irec, ino_offset))  {
+               if (!is_inode_free(irec, ino_offset))  {
+                       do_warn(_("entry \"%s\" in shortform dir inode %llu "
+                               "points to free inode %llu"), fname, ino, lino);
+                       goto do_junkit;
+               }
+               /*
+                * check if this inode is lost+found dir in the root
+                */
+               if (ino == mp->m_sb.sb_rootino && strcmp(fname, ORPHANAGE) == 0) {
                        /*
-                        * don't complain if this entry points to the old
-                        * and now-free lost+found inode
+                        * if it's not a directory, trash it
                         */
-                       if (verbose || no_modify || lino != old_orphanage_ino)
-                               do_warn(
-_("entry \"%s\" in shortform dir inode %llu points to free inode %llu\n"),
-                                       fname, ino, lino);
-
-                       if (!no_modify)  {
-                               junkit = 1;
-                       } else  {
-                               do_warn(_("would junk entry \"%s\"\n"),
-                                       fname);
+                       if (!inode_isadir(irec, ino_offset)) {
+                               do_warn(_("%s (ino %llu) in root (%llu) is not "
+                                       "a directory"), ORPHANAGE, lino, ino);
+                               goto do_junkit;
                        }
-               } else if (!dir_hash_add(hashtab,
-                               (xfs_dir2_dataptr_t)(sf_entry - &sf->list[0]),
-                               lino, sf_entry->namelen, sf_entry->name)) {
                        /*
-                        * check for duplicate names in directory.
+                        * if this is a dup, it will be picked up below,
+                        * otherwise, mark it as the orphanage for later.
                         */
-                       do_warn(
-               _("entry \"%s\" (ino %llu) in dir %llu is a duplicate name"),
-                               fname, lino, ino);
-                       if (!no_modify) {
-                               junkit = 1;
-                               if (verbose)
-                                       do_warn(
-                                       _(", marking entry to be junked\n"));
-                               else
-                                       do_warn("\n");
-                       } else {
-                               do_warn(_(", would junk entry\n"));
-                       }
-               } else if (!inode_isadir(irec, ino_offset))  {
+                       if (!orphanage_ino)
+                               orphanage_ino = lino;
+               }
+               /*
+                * check for duplicate names in directory.
+                */
+               if (!dir_hash_add(hashtab,
+                               (xfs_dir2_dataptr_t)(sf_entry - &sf->list[0]),
+                               lino, sf_entry->namelen, sf_entry->name)) {
+                       do_warn(_("entry \"%s\" (ino %llu) in dir %llu is a "
+                               "duplicate name"), fname, lino, ino);
+                       goto do_junkit;
+               }
+               if (!inode_isadir(irec, ino_offset))  {
                        /*
                         * check easy case first, regular inode, just bump
                         * the link count and continue
@@ -2860,8 +2882,8 @@ _("entry \"%s\" in shortform dir inode %llu points to free inode %llu\n"),
                         */
                        if (is_inode_reached(irec, ino_offset))  {
                                junkit = 1;
-                               do_warn(
-_("entry \"%s\" in dir %llu references already connected dir ino %llu,\n"),
+                               do_warn(_("entry \"%s\" in dir %llu references "
+                                       "already connected dir ino %llu,\n"),
                                        fname, ino, lino);
                        } else if (parent == ino)  {
                                add_inode_reached(irec, ino_offset);
@@ -2872,13 +2894,16 @@ _("entry \"%s\" in dir %llu references already connected dir ino %llu,\n"),
                                        push_dir(stack, lino);
                        } else  {
                                junkit = 1;
-                               do_warn(
-_("entry \"%s\" in dir %llu not consistent with .. value (%llu) in dir ino %llu,\n"),
+                               do_warn(_("entry \"%s\" in dir %llu not "
+                                       "consistent with .. value (%llu) in "
+                                       "dir ino %llu"),
                                        fname, ino, parent, lino);
                        }
                }
-
                if (junkit)  {
+do_junkit:
+                       if (lino == orphanage_ino)
+                               orphanage_ino = 0;
                        if (!no_modify)  {
                                tmp_elen = XFS_DIR_SF_ENTSIZE_BYENTRY(sf_entry);
                                tmp_sfe = (xfs_dir_sf_entry_t *)
@@ -2910,12 +2935,12 @@ _("entry \"%s\" in dir %llu not consistent with .. value (%llu) in dir ino %llu,
 
                                *ino_dirty = 1;
 
-                               if (verbose || lino != old_orphanage_ino)
-                                       do_warn(
-                       _("junking entry \"%s\" in directory inode %llu\n"),
-                                               fname, lino);
+                               if (verbose)
+                                       do_warn(_("junking entry\n"));
+                               else
+                                       do_warn("\n");
                        } else  {
-                               do_warn(_("would junk entry \"%s\"\n"), fname);
+                               do_warn(_("would junk entry\n"), fname);
                        }
                }
 
@@ -3173,23 +3198,6 @@ shortform_dir2_entry_check(xfs_mount_t   *mp,
                ASSERT(no_modify || (lino != NULLFSINO && lino != 0));
                ASSERT(no_modify || !verify_inum(mp, lino));
 
-               /*
-                * special case the "lost+found" entry if it's pointing
-                * to where we think lost+found should be.  if that's
-                * the case, that's the one we created in phase 6.
-                * just skip it.  no need to process it and its ..
-                * link is already accounted for.
-                */
-
-               if (lino == orphanage_ino && strcmp(fname, ORPHANAGE) == 0) {
-                       if (lino > XFS_DIR2_MAX_SHORT_INUM)
-                               i8++;
-                       next_sfep = (xfs_dir2_sf_entry_t *)
-                               ((__psint_t) sfep +
-                               XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp, sfep));
-                       continue;
-               }
-
                /*
                 * Also skip entries with bogus inode numbers if we're
                 * in no modify mode.
@@ -3205,16 +3213,13 @@ shortform_dir2_entry_check(xfs_mount_t  *mp,
                irec = find_inode_rec(XFS_INO_TO_AGNO(mp, lino),
                                        XFS_INO_TO_AGINO(mp, lino));
 
-               if (irec == NULL && no_modify)  {
+               if (irec == NULL)  {
                        do_warn(_("entry \"%s\" in shortform directory %llu "
-                                 "references non-existent inode %llu\n"),
+                                 "references non-existent inode %llu"),
                                fname, ino, lino);
-                       do_warn(_("would junk entry\n"));
-                       continue;
+                       goto do_junkit;
                }
 
-               ASSERT(irec != NULL);
-
                ino_offset = XFS_INO_TO_AGINO(mp, lino) - irec->ino_startnum;
 
                /*
@@ -3223,42 +3228,41 @@ shortform_dir2_entry_check(xfs_mount_t  *mp,
                 * really is free.
                 */
                if (is_inode_free(irec, ino_offset))  {
+                       do_warn(_("entry \"%s\" in shortform directory "
+                                 "inode %llu points to free inode %llu"),
+                               fname, ino, lino);
+                       goto do_junkit;
+               }
+               /*
+                * check if this inode is lost+found dir in the root
+                */
+               if (ino == mp->m_sb.sb_rootino && strcmp(fname, ORPHANAGE) == 0) {
                        /*
-                        * don't complain if this entry points to the old
-                        * and now-free lost+found inode
+                        * if it's not a directory, trash it
                         */
-                       if (verbose || no_modify || lino != old_orphanage_ino)
-                               do_warn(_("entry \"%s\" in shortform directory "
-                                         "inode %llu points to free inode "
-                                         "%llu\n"),
-                                       fname, ino, lino);
-
-                       if (!no_modify)  {
-                               junkit = 1;
-                       } else  {
-                               do_warn(_("would junk entry \"%s\"\n"),
-                                       fname);
+                       if (!inode_isadir(irec, ino_offset)) {
+                               do_warn(_("%s (ino %llu) in root (%llu) is not "
+                                       "a directory"), ORPHANAGE, lino, ino);
+                               goto do_junkit;
                        }
-               } else if (!dir_hash_add(hashtab, (xfs_dir2_dataptr_t)
-                                       (sfep - XFS_DIR2_SF_FIRSTENTRY(sfp)),
-                               lino, sfep->namelen, sfep->name)) {
                        /*
-                        * check for duplicate names in directory.
+                        * if this is a dup, it will be picked up below,
+                        * otherwise, mark it as the orphanage for later.
                         */
-                       do_warn(
-               _("entry \"%s\" (ino %llu) in dir %llu is a duplicate name"),
-                               fname, lino, ino);
-                       if (!no_modify) {
-                               junkit = 1;
-                               if (verbose)
-                                       do_warn(
-                                       _(", marking entry to be junked\n"));
-                               else
-                                       do_warn("\n");
-                       } else {
-                               do_warn(_(", would junk entry\n"));
-                       }
-               } else if (!inode_isadir(irec, ino_offset))  {
+                       if (!orphanage_ino)
+                               orphanage_ino = lino;
+               }
+               /*
+                * check for duplicate names in directory.
+                */
+               if (!dir_hash_add(hashtab, (xfs_dir2_dataptr_t)
+                                       (sfep - XFS_DIR2_SF_FIRSTENTRY(sfp)),
+                               lino, sfep->namelen, sfep->name)) {
+                       do_warn(_("entry \"%s\" (ino %llu) in dir %llu is a "
+                               "duplicate name"), fname, lino, ino);
+                       goto do_junkit;
+               }
+               if (!inode_isadir(irec, ino_offset))  {
                        /*
                         * check easy case first, regular inode, just bump
                         * the link count
@@ -3295,6 +3299,9 @@ shortform_dir2_entry_check(xfs_mount_t    *mp,
                }
 
                if (junkit)  {
+do_junkit:
+                       if (lino == orphanage_ino)
+                               orphanage_ino = 0;
                        if (!no_modify)  {
                                tmp_elen = XFS_DIR2_SF_ENTSIZE_BYENTRY(sfp, sfep);
                                tmp_sfep = (xfs_dir2_sf_entry_t *)
@@ -3326,12 +3333,12 @@ shortform_dir2_entry_check(xfs_mount_t  *mp,
 
                                *ino_dirty = 1;
 
-                               if (verbose || lino != old_orphanage_ino)
-                                       do_warn(_("junking entry \"%s\" in "
-                                                 "directory inode %llu\n"),
-                                               fname, lino);
+                               if (verbose)
+                                       do_warn(_("junking entry\n"));
+                               else
+                                       do_warn("\n");
                        } else  {
-                               do_warn(_("would junk entry \"%s\"\n"), fname);
+                               do_warn(_("would junk entry\n"));
                        }
                } else if (lino > XFS_DIR2_MAX_SHORT_INUM)
                        i8++;
@@ -3465,25 +3472,6 @@ process_dirstack(xfs_mount_t *mp, dir_stack_t *stack)
                         * guaranteed by phase 3 and/or below.
                         */
                        add_inode_reached(irec, ino_offset);
-                       /*
-                        * account for link for the orphanage
-                        * "lost+found".  if we're running in
-                        * modify mode and it already existed,
-                        * we deleted it so it's '..' reference
-                        * never got counted.  so add it here if
-                        * we're going to create lost+found.
-                        *
-                        * if we're running in no_modify mode,
-                        * we never deleted lost+found and we're
-                        * not going to create it so do nothing.
-                        *
-                        * either way, the counts will match when
-                        * we look at the root inode's nlinks
-                        * field and compare that to our incore
-                        * count in phase 7.
-                        */
-                       if (!no_modify)
-                               add_inode_ref(irec, ino_offset);
                }
 
                add_inode_refchecked(ino, irec, ino_offset);
@@ -3562,36 +3550,6 @@ process_dirstack(xfs_mount_t *mp, dir_stack_t *stack)
 
                hashval = 0;
 
-               if (!no_modify && !orphanage_entered &&
-                   ino == mp->m_sb.sb_rootino) {
-                       do_warn(_("re-entering %s into root directory\n"),
-                               ORPHANAGE);
-                       tp = libxfs_trans_alloc(mp, 0);
-                       nres = XFS_MKDIR_SPACE_RES(mp, strlen(ORPHANAGE));
-                       error = libxfs_trans_reserve(tp, nres,
-                                       XFS_MKDIR_LOG_RES(mp), 0,
-                                       XFS_TRANS_PERM_LOG_RES,
-                                       XFS_MKDIR_LOG_COUNT);
-                       if (error)
-                               res_failed(error);
-                       libxfs_trans_ijoin(tp, ip, 0);
-                       libxfs_trans_ihold(tp, ip);
-                       XFS_BMAP_INIT(&flist, &first);
-                       if ((error = dir_createname(mp, tp, ip, ORPHANAGE,
-                                               strlen(ORPHANAGE),
-                                               orphanage_ino, &first, &flist,
-                                               nres)))
-                               do_error(_("can't make %s entry in root inode "
-                                          "%llu, createname error %d\n"),
-                                       ORPHANAGE, ino, error);
-                       libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-                       error = libxfs_bmap_finish(&tp, &flist, first, &committed);
-                       ASSERT(error == 0);
-                       libxfs_trans_commit(tp,
-                               XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_SYNC, 0);
-                       orphanage_entered = 1;
-               }
-
                /*
                 * if we have to create a .. for /, do it now *before*
                 * we delete the bogus entries, otherwise the directory
@@ -3822,6 +3780,51 @@ mark_standalone_inodes(xfs_mount_t *mp)
        }
 }
 
+static void
+check_for_orphaned_inodes(
+       xfs_mount_t             *mp,
+       ino_tree_node_t         *irec)
+{
+       int                     i;
+       int                     err;
+       xfs_ino_t               ino;
+
+       for (i = 0; i < XFS_INODES_PER_CHUNK; i++)  {
+               ASSERT(is_inode_confirmed(irec, i));
+               if (is_inode_free(irec, i))
+                       continue;
+
+               if (!is_inode_reached(irec, i)) {
+                       ASSERT(inode_isadir(irec, i) ||
+                               num_inode_references(irec, i) == 0);
+                       ino = XFS_AGINO_TO_INO(mp, i, i + irec->ino_startnum);
+                       if (inode_isadir(irec, i))
+                               do_warn(_("disconnected dir inode %llu, "), ino);
+                       else
+                               do_warn(_("disconnected inode %llu, "), ino);
+                       if (!no_modify)  {
+                               if (!orphanage_ino)
+                                       orphanage_ino = mk_orphanage(mp);
+                               if (!orphanage_ip) {
+                                       err = libxfs_iget(mp, NULL, orphanage_ino, 0, &orphanage_ip, 0);
+                                       if (err)
+                                               do_error(_("%d - couldn't iget orphanage inode\n"), err);
+                               }
+                               do_warn(_("moving to %s\n"), ORPHANAGE);
+                               mv_orphanage(mp, ino, inode_isadir(irec, i));
+                       } else  {
+                               do_warn(_("would move to %s\n"), ORPHANAGE);
+                       }
+                       /*
+                        * for read-only case, even though the inode isn't
+                        * really reachable, set the flag (and bump our link
+                        * count) anyway to fool phase 7
+                        */
+                       add_inode_reached(irec, i);
+               }
+       }
+}
+
 static void
 traverse_function(xfs_mount_t *mp, xfs_agnumber_t agno)
 {
@@ -3877,9 +3880,11 @@ phase6(xfs_mount_t *mp)
        dir_stack_t             stack;
        int                     i;
        int                     j;
+       xfs_ino_t               orphanage_ino;
 
        bzero(&zerocr, sizeof(struct cred));
        bzero(&zerofsx, sizeof(struct fsxattr));
+       orphanage_ino = 0;
 
        do_log(_("Phase 6 - check inode connectivity...\n"));
 
@@ -3943,15 +3948,6 @@ _("        - resetting contents of realtime bitmap and summary inodes\n"));
                }
        }
 
-       /*
-        * make orphanage (it's guaranteed to not exist now)
-        */
-       if (!no_modify)  {
-               do_log(_("        - ensuring existence of %s directory\n"),
-                       ORPHANAGE);
-               orphanage_ino = mk_orphanage(mp);
-       }
-
        dir_stack_init(&stack);
 
        mark_standalone_inodes(mp);
@@ -4031,59 +4027,16 @@ _("        - skipping filesystem traversal from / ... \n"));
        }
 
        do_log(_("        - traversals finished ... \n"));
-
-       /* flush all dirty data before doing lost+found search */
-       libxfs_bcache_flush();
-
-       do_log(_("        - moving disconnected inodes to lost+found ... \n"));
+       do_log(_("        - moving disconnected inodes to %s ... \n"),
+               ORPHANAGE);
 
        /*
         * move all disconnected inodes to the orphanage
         */
        for (i = 0; i < glob_agcount; i++)  {
                irec = findfirst_inode_rec(i);
-
-               if (irec == NULL)
-                       continue;
-
                while (irec != NULL)  {
-                       for (j = 0; j < XFS_INODES_PER_CHUNK; j++)  {
-                               ASSERT(is_inode_confirmed(irec, j));
-                               if (is_inode_free(irec, j))
-                                       continue;
-                               if (!is_inode_reached(irec, j)) {
-                                       ASSERT(inode_isadir(irec, j) ||
-                                               num_inode_references(irec, j)
-                                               == 0);
-                                       ino = XFS_AGINO_TO_INO(mp, i,
-                                               j + irec->ino_startnum);
-                                       if (inode_isadir(irec, j))
-                                               do_warn(
-                                       _("disconnected dir inode %llu, "),
-                                                       ino);
-                                       else
-                                               do_warn(
-                                       _("disconnected inode %llu, "),
-                                                       ino);
-                                       if (!no_modify)  {
-                                               do_warn(_("moving to %s\n"),
-                                                       ORPHANAGE);
-                                               mv_orphanage(mp, orphanage_ino,
-                                                       ino,
-                                                       inode_isadir(irec, j));
-                                       } else  {
-                                               do_warn(_("would move to %s\n"),
-                                                       ORPHANAGE);
-                                       }
-                                       /*
-                                        * for read-only case, even though
-                                        * the inode isn't really reachable,
-                                        * set the flag (and bump our link
-                                        * count) anyway to fool phase 7
-                                        */
-                                       add_inode_reached(irec, j);
-                               }
-                       }
+                       check_for_orphaned_inodes(mp, irec);
                        irec = next_ino_rec(irec);
                }
        }
index c66533270c1a92b6211a45ac858c8d3f8eab9bf3..ee89a374f2d59b5e0df1eae7d68b9cbd81ecb77c 100644 (file)
@@ -96,11 +96,8 @@ update_inode_nlinks(
 
        /*
         * compare and set links for all inodes
-        * but the lost+found inode.  we keep
-        * that correct as we go.
         */
-       if (ino != orphanage_ino)
-               set_nlinks(&ip->i_d, ino, nlinks, &dirty);
+       set_nlinks(&ip->i_d, ino, nlinks, &dirty);
 
        if (!dirty)  {
                libxfs_trans_iput(tp, ip, 0);