]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
Fix up prefetched v1 inode nlink check and repair in xfs_repair
authorBarry Naujok <bnaujok@sgi.com>
Thu, 19 Oct 2006 03:57:49 +0000 (03:57 +0000)
committerBarry Naujok <bnaujok@sgi.com>
Thu, 19 Oct 2006 03:57:49 +0000 (03:57 +0000)
Merge of master-melb:xfs-cmds:27235a by kenmcd.

  pv:957164
  Fix up prefetched v1 inode nlink check and repair in xfs_repair

repair/phase7.c

index 1ab8c9aae02799186c005b315d6532d51129e445..4aaa12c64196d6569874474273338cc1cea37414 100644 (file)
@@ -65,7 +65,8 @@ phase7_alt_function(xfs_mount_t *mp, xfs_agnumber_t agno)
 {
        register ino_tree_node_t *irec;
        int                     j;
-       int                     dirty;
+       int                     chunk_dirty;
+       int                     inode_dirty;
        xfs_ino_t               ino;
        __uint32_t              nrefs;
        xfs_agblock_t           agbno;
@@ -113,7 +114,7 @@ phase7_alt_function(xfs_mount_t *mp, xfs_agnumber_t agno)
                        irec = next_ino_rec(irec);
                        continue;       /* while */
                }
-               dirty = 0;
+               chunk_dirty = 0;
                for (j = 0; j < XFS_INODES_PER_CHUNK; j++)  {
                        assert(is_inode_confirmed(irec, j));
 
@@ -131,10 +132,21 @@ phase7_alt_function(xfs_mount_t *mp, xfs_agnumber_t agno)
 
                        dip = (xfs_dinode_t *)(XFS_BUF_PTR(bp) +
                                        (j << mp->m_sb.sb_inodelog));
+                       
+                       inode_dirty = 0;
 
                        /* Swap the fields we care about to native format */
-                       dip->di_core.di_magic = INT_GET(dip->di_core.di_magic, ARCH_CONVERT);
-                       dip->di_core.di_nlink = INT_GET(dip->di_core.di_nlink, ARCH_CONVERT);
+                       dip->di_core.di_magic = INT_GET(dip->di_core.di_magic, 
+                                                       ARCH_CONVERT);
+                       dip->di_core.di_onlink = INT_GET(dip->di_core.di_onlink, 
+                                                       ARCH_CONVERT);
+                       if (INT_GET(dip->di_core.di_version, ARCH_CONVERT) ==
+                                       XFS_DINODE_VERSION_1) 
+                               dip->di_core.di_nlink = dip->di_core.di_onlink;
+                       else 
+                               dip->di_core.di_nlink = 
+                                               INT_GET(dip->di_core.di_nlink, 
+                                                       ARCH_CONVERT);
 
                        if (dip->di_core.di_magic != XFS_DINODE_MAGIC) {
                                if (!no_modify) {
@@ -156,16 +168,46 @@ phase7_alt_function(xfs_mount_t *mp, xfs_agnumber_t agno)
                        if (dip->di_core.di_nlink != nrefs) {
                                if (ino != orphanage_ino) {
                                        set_nlinks(&dip->di_core, ino,
-                                                       nrefs, &dirty);
+                                                       nrefs, &inode_dirty);
                                }
                        }
 
                        /* Swap the fields back */
-                       dip->di_core.di_magic = INT_GET(dip->di_core.di_magic, ARCH_CONVERT);
-                       dip->di_core.di_nlink = INT_GET(dip->di_core.di_nlink, ARCH_CONVERT);
+                       dip->di_core.di_magic = INT_GET(dip->di_core.di_magic, 
+                                       ARCH_CONVERT);
+                       if (inode_dirty && INT_GET(dip->di_core.di_version, 
+                                       ARCH_CONVERT) == XFS_DINODE_VERSION_1) {
+                               if (!XFS_SB_VERSION_HASNLINK(&mp->m_sb)) {
+                                       ASSERT(dip->di_core.di_nlink <= 
+                                                       XFS_MAXLINK_1);
+                                       dip->di_core.di_nlink = 
+                                               INT_GET(dip->di_core.di_nlink, 
+                                                       ARCH_CONVERT);
+                                       dip->di_core.di_onlink = 
+                                               dip->di_core.di_nlink;
+                               } else {
+                                       /* superblock support v2 nlinks */
+                                       INT_SET(dip->di_core.di_version, 
+                                               ARCH_CONVERT, XFS_DINODE_VERSION_2);
+                                       dip->di_core.di_nlink = 
+                                               INT_GET(dip->di_core.di_nlink, 
+                                                       ARCH_CONVERT);
+                                       dip->di_core.di_onlink = 0;
+                                       memset(&(dip->di_core.di_pad[0]), 0,
+                                               sizeof(dip->di_core.di_pad));
+                               }       
+                       } else {
+                               dip->di_core.di_nlink = 
+                                               INT_GET(dip->di_core.di_nlink, 
+                                                       ARCH_CONVERT);
+                               dip->di_core.di_onlink = 
+                                               INT_GET(dip->di_core.di_onlink, 
+                                                       ARCH_CONVERT);
+                       }
+                       chunk_dirty |= inode_dirty;
                }
 
-               if (dirty)
+               if (chunk_dirty)
                        libxfs_writebuf(bp, 0);
                else
                        libxfs_putbuf(bp);