]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
Cache disk nlink values in Phase 3 for Phase 7
authorBarry Naujok <bnaujok@sgi.com>
Mon, 16 Jul 2007 06:09:45 +0000 (06:09 +0000)
committerBarry Naujok <bnaujok@sgi.com>
Mon, 16 Jul 2007 06:09:45 +0000 (06:09 +0000)
Merge of master-melb:xfs-cmds:29142a by kenmcd.

  Minore cleanup

repair/Makefile
repair/dino_chunks.c
repair/globals.h
repair/incore.h
repair/incore_ino.c
repair/phase6.c
repair/phase7.c
repair/xfs_repair.c

index cfa172cd23fff1eb525871fff12dbe2e087cc45b..37caf27513e7cf5e86164edecabbbe39766d20fa 100644 (file)
@@ -15,7 +15,7 @@ CFILES = agheader.c attr_repair.c avl.c avl64.c bmap.c dino_chunks.c \
        dinode.c dir.c dir2.c dir_stack.c globals.c incore.c \
        incore_bmc.c init.c incore_ext.c incore_ino.c phase1.c \
        phase2.c phase3.c phase4.c phase5.c phase6.c phase7.c rt.c sb.c \
-       progress.c prefetch.c scan.c versions.c xfs_repair.c threads.c
+       progress.c prefetch.c scan.c threads.c versions.c xfs_repair.c
 
 LLDLIBS = $(LIBXFS) $(LIBXLOG) $(LIBUUID) $(LIBPTHREAD) $(LIBRT)
 LTDEPENDENCIES = $(LIBXFS) $(LIBXLOG)
index e80e1b8ac6a4d23f29d21abb3e09d943c32b0fe9..2a316b68c4883a30dc67b4fd7bfe79329e619bd2 100644 (file)
@@ -779,6 +779,15 @@ process_inode_chunk(xfs_mount_t *mp, xfs_agnumber_t agno, int num_inos,
                                        do_warn(_("would correct imap\n"));
                        }
                        set_inode_used(ino_rec, irec_offset);
+
+                       /*
+                        * store on-disk nlink count for comparing in phase 7
+                        */
+                       set_inode_disk_nlinks(ino_rec, irec_offset,
+                               dino->di_core.di_version > XFS_DINODE_VERSION_1
+                                       ? be32_to_cpu(dino->di_core.di_nlink)
+                                       : be16_to_cpu(dino->di_core.di_onlink));
+
                } else  {
                        set_inode_free(ino_rec, irec_offset);
                }
index a4727a0b1b365d1403d64693381f4c5517e9946b..53b7859450782ee328c045c265c55ab03f1b403e 100644 (file)
@@ -166,12 +166,12 @@ EXTERN xfs_suminfo_t      *sumcompute;
 
 /* inode tree records have full or partial backptr fields ? */
 
-EXTERN int             full_backptrs;  /*
-                                        * if 1, use backptrs_t component
-                                        * of ino_un union, if 0, use
-                                        * parent_list_t component.  see
-                                        * incore.h for more details
-                                        */
+EXTERN int             full_ino_ex_data;/*
+                                         * if 1, use ino_ex_data_t component
+                                         * of ino_un union, if 0, use
+                                         * parent_list_t component.  see
+                                         * incore.h for more details
+                                         */
 
 #define ORPHANAGE      "lost+found"
 
index 7783a6b69cfacdec6cbe2844da0fb13520282c12..ddc2a89fea8733f25b41cdffbc20f1933959546e 100644 (file)
@@ -328,6 +328,8 @@ void                incore_ext_teardown(xfs_mount_t *mp);
 
 typedef xfs_ino_t parent_entry_t;
 
+struct nlink_ops;
+
 typedef struct parent_list  {
        __uint64_t              pmask;
        parent_entry_t          *pentries;
@@ -336,12 +338,12 @@ typedef struct parent_list  {
 #endif
 } parent_list_t;
 
-typedef struct backptrs  {
+typedef struct ino_ex_data  {
        __uint64_t              ino_reached;    /* bit == 1 if reached */
        __uint64_t              ino_processed;  /* reference checked bit mask */
-       __uint32_t              nlinks[XFS_INODES_PER_CHUNK];
        parent_list_t           *parents;
-} backptrs_t;
+       __uint8_t               *counted_nlinks;/* counted nlinks in P6 */
+} ino_ex_data_t;
 
 typedef struct ino_tree_node  {
        avlnode_t               avl_node;
@@ -349,14 +351,26 @@ typedef struct ino_tree_node  {
        xfs_inofree_t           ir_free;        /* inode free bit mask */
        __uint64_t              ino_confirmed;  /* confirmed bitmask */
        __uint64_t              ino_isa_dir;    /* bit == 1 if a directory */
+       struct nlink_ops        *nlinkops;      /* pointer to current nlink ops */
+       __uint8_t               *disk_nlinks;   /* on-disk nlinks, set in P3 */
        union  {
-               backptrs_t      *backptrs;
-               parent_list_t   *plist;
+               ino_ex_data_t   *ex_data;       /* phases 6,7 */
+               parent_list_t   *plist;         /* phases 2-5 */
        } ino_un;
 } ino_tree_node_t;
 
+typedef struct nlink_ops {
+       const int       nlink_size;
+       void            (*disk_nlink_set)(ino_tree_node_t *, int, __uint32_t);
+       __uint32_t      (*disk_nlink_get)(ino_tree_node_t *, int);
+       __uint32_t      (*counted_nlink_get)(ino_tree_node_t *, int);
+       __uint32_t      (*counted_nlink_inc)(ino_tree_node_t *, int);
+       __uint32_t      (*counted_nlink_dec)(ino_tree_node_t *, int);
+} nlink_ops_t;
+
+
 #define INOS_PER_IREC          (sizeof(__uint64_t) * NBBY)
-void                           add_ino_backptrs(xfs_mount_t *mp);
+void           add_ino_ex_data(xfs_mount_t *mp);
 
 /*
  * return an inode record to the free inode record pool
@@ -428,13 +442,13 @@ void                      clear_uncertain_ino_cache(xfs_agnumber_t agno);
 #define        XFS_INOPROC_MASKN(i,n)  ((__uint64_t)((1 << (n)) - 1) << (i))
 
 #define        XFS_INOPROC_IS_PROC(rp, i) \
-       (((rp)->ino_un.backptrs->ino_processed & XFS_INOPROC_MASK((i))) == 0LL \
+       (((rp)->ino_un.ex_data->ino_processed & XFS_INOPROC_MASK((i))) == 0LL \
                ? 0 : 1)
 #define        XFS_INOPROC_SET_PROC(rp, i) \
-       ((rp)->ino_un.backptrs->ino_processed |= XFS_INOPROC_MASK((i)))
+       ((rp)->ino_un.ex_data->ino_processed |= XFS_INOPROC_MASK((i)))
 /*
 #define        XFS_INOPROC_CLR_PROC(rp, i) \
-       ((rp)->ino_un.backptrs->ino_processed &= ~XFS_INOPROC_MASK((i)))
+       ((rp)->ino_un.ex_data->ino_processed &= ~XFS_INOPROC_MASK((i)))
 */
 
 /*
@@ -457,12 +471,12 @@ void                      clear_uncertain_ino_cache(xfs_agnumber_t agno);
 #define        XFS_INO_RCHD_MASK(i)    ((__uint64_t)1 << (i))
 
 #define        XFS_INO_RCHD_IS_RCHD(rp, i) \
-       (((rp)->ino_un.backptrs->ino_reached & XFS_INO_RCHD_MASK((i))) == 0LL \
+       (((rp)->ino_un.ex_data->ino_reached & XFS_INO_RCHD_MASK((i))) == 0LL \
                ? 0 : 1)
 #define        XFS_INO_RCHD_SET_RCHD(rp, i) \
-               ((rp)->ino_un.backptrs->ino_reached |= XFS_INO_RCHD_MASK((i)))
+               ((rp)->ino_un.ex_data->ino_reached |= XFS_INO_RCHD_MASK((i)))
 #define        XFS_INO_RCHD_CLR_RCHD(rp, i) \
-               ((rp)->ino_un.backptrs->ino_reached &= ~XFS_INO_RCHD_MASK((i)))
+               ((rp)->ino_un.ex_data->ino_reached &= ~XFS_INO_RCHD_MASK((i)))
 /*
  * set/clear/test is inode a directory inode
  */
@@ -519,16 +533,16 @@ void                      clear_uncertain_ino_cache(xfs_agnumber_t agno);
 static inline int
 is_inode_reached(ino_tree_node_t *ino_rec, int ino_offset)
 {
-       ASSERT(ino_rec->ino_un.backptrs != NULL);
+       ASSERT(ino_rec->ino_un.ex_data != NULL);
        return(XFS_INO_RCHD_IS_RCHD(ino_rec, ino_offset));
 }
 
 static inline void
 add_inode_reached(ino_tree_node_t *ino_rec, int ino_offset)
 {
-       ASSERT(ino_rec->ino_un.backptrs != NULL);
+       ASSERT(ino_rec->ino_un.ex_data != NULL);
 
-       ino_rec->ino_un.backptrs->nlinks[ino_offset]++;
+       (*ino_rec->nlinkops->counted_nlink_inc)(ino_rec, ino_offset);
        XFS_INO_RCHD_SET_RCHD(ino_rec, ino_offset);
 
        ASSERT(is_inode_reached(ino_rec, ino_offset));
@@ -537,33 +551,46 @@ add_inode_reached(ino_tree_node_t *ino_rec, int ino_offset)
 static inline void
 add_inode_ref(ino_tree_node_t *ino_rec, int ino_offset)
 {
-       ASSERT(ino_rec->ino_un.backptrs != NULL);
+       ASSERT(ino_rec->ino_un.ex_data != NULL);
 
-       ino_rec->ino_un.backptrs->nlinks[ino_offset]++;
+       (*ino_rec->nlinkops->counted_nlink_inc)(ino_rec, ino_offset);
 }
 
 static inline void
 drop_inode_ref(ino_tree_node_t *ino_rec, int ino_offset)
 {
-       ASSERT(ino_rec->ino_un.backptrs != NULL);
-       ASSERT(ino_rec->ino_un.backptrs->nlinks[ino_offset] > 0);
+       ASSERT(ino_rec->ino_un.ex_data != NULL);
 
-       if (--ino_rec->ino_un.backptrs->nlinks[ino_offset] == 0)
+       if ((*ino_rec->nlinkops->counted_nlink_dec)(ino_rec, ino_offset) == 0)
                XFS_INO_RCHD_CLR_RCHD(ino_rec, ino_offset);
 }
 
 static inline int
 is_inode_referenced(ino_tree_node_t *ino_rec, int ino_offset)
 {
-       ASSERT(ino_rec->ino_un.backptrs != NULL);
-       return(ino_rec->ino_un.backptrs->nlinks[ino_offset] > 0);
+       ASSERT(ino_rec->ino_un.ex_data != NULL);
+
+       return (*ino_rec->nlinkops->counted_nlink_get)(ino_rec, ino_offset) > 0;
 }
 
 static inline __uint32_t
 num_inode_references(ino_tree_node_t *ino_rec, int ino_offset)
 {
-       ASSERT(ino_rec->ino_un.backptrs != NULL);
-       return(ino_rec->ino_un.backptrs->nlinks[ino_offset]);
+       ASSERT(ino_rec->ino_un.ex_data != NULL);
+
+       return (*ino_rec->nlinkops->counted_nlink_get)(ino_rec, ino_offset);
+}
+
+static inline void
+set_inode_disk_nlinks(ino_tree_node_t *ino_rec, int ino_offset, __uint32_t nlinks)
+{
+       (*ino_rec->nlinkops->disk_nlink_set)(ino_rec, ino_offset, nlinks);
+}
+
+static inline __uint32_t
+get_inode_disk_nlinks(ino_tree_node_t *ino_rec, int ino_offset)
+{
+       return (*ino_rec->nlinkops->disk_nlink_get)(ino_rec, ino_offset);
 }
 
 /*
@@ -589,9 +616,6 @@ int is_inode_refchecked(xfs_ino_t ino,
  */
 void           set_inode_parent(ino_tree_node_t *irec, int ino_offset,
                                        xfs_ino_t ino);
-#if 0
-void           clear_inode_parent(ino_tree_node_t *irec, int offset);
-#endif
 xfs_ino_t      get_inode_parent(ino_tree_node_t *irec, int ino_offset);
 
 /*
index c08da769dadce87f3c1b8d7823c20e6f9aee8bd4..370c3614b576b03bffd87416806955990755287b 100644 (file)
@@ -50,6 +50,193 @@ typedef struct ino_flist_s  {
 
 static ino_flist_t ino_flist;  /* free list must be initialized before use */
 
+/* memory optimised nlink counting for all inodes */
+
+static void nlink_grow_8_to_16(ino_tree_node_t *irec);
+static void nlink_grow_16_to_32(ino_tree_node_t *irec);
+
+static void
+disk_nlink_32_set(ino_tree_node_t *irec, int ino_offset, __uint32_t nlinks)
+{
+       ((__uint32_t*)irec->disk_nlinks)[ino_offset] = nlinks;
+}
+
+static __uint32_t
+disk_nlink_32_get(ino_tree_node_t *irec, int ino_offset)
+{
+       return ((__uint32_t*)irec->disk_nlinks)[ino_offset];
+}
+
+static __uint32_t
+counted_nlink_32_get(ino_tree_node_t *irec, int ino_offset)
+{
+       return ((__uint32_t*)irec->ino_un.ex_data->counted_nlinks)[ino_offset];
+}
+
+static __uint32_t
+counted_nlink_32_inc(ino_tree_node_t *irec, int ino_offset)
+{
+       return ++(((__uint32_t*)irec->ino_un.ex_data->counted_nlinks)[ino_offset]);
+}
+
+static __uint32_t
+counted_nlink_32_dec(ino_tree_node_t *irec, int ino_offset)
+{
+       __uint32_t *nlinks = (__uint32_t*)irec->ino_un.ex_data->counted_nlinks;
+
+       ASSERT(nlinks[ino_offset] > 0);
+       return --(nlinks[ino_offset]);
+}
+
+
+static void
+disk_nlink_16_set(ino_tree_node_t *irec, int ino_offset, __uint32_t nlinks)
+{
+       if (nlinks >= 0x10000) {
+               nlink_grow_16_to_32(irec);
+               disk_nlink_32_set(irec, ino_offset, nlinks);
+       } else
+               ((__uint16_t*)irec->disk_nlinks)[ino_offset] = nlinks;
+}
+
+static __uint32_t
+disk_nlink_16_get(ino_tree_node_t *irec, int ino_offset)
+{
+       return ((__uint16_t*)irec->disk_nlinks)[ino_offset];
+}
+
+static __uint32_t
+counted_nlink_16_get(ino_tree_node_t *irec, int ino_offset)
+{
+       return ((__uint16_t*)irec->ino_un.ex_data->counted_nlinks)[ino_offset];
+}
+
+static __uint32_t
+counted_nlink_16_inc(ino_tree_node_t *irec, int ino_offset)
+{
+       __uint16_t *nlinks = (__uint16_t*)irec->ino_un.ex_data->counted_nlinks;
+
+       if (nlinks[ino_offset] == 0xffff) {
+               nlink_grow_16_to_32(irec);
+               return counted_nlink_32_inc(irec, ino_offset);
+       }
+       return ++(nlinks[ino_offset]);
+}
+
+static __uint32_t
+counted_nlink_16_dec(ino_tree_node_t *irec, int ino_offset)
+{
+       __uint16_t *nlinks = (__uint16_t*)irec->ino_un.ex_data->counted_nlinks;
+
+       ASSERT(nlinks[ino_offset] > 0);
+       return --(nlinks[ino_offset]);
+}
+
+
+static void
+disk_nlink_8_set(ino_tree_node_t *irec, int ino_offset, __uint32_t nlinks)
+{
+       if (nlinks >= 0x100) {
+               nlink_grow_8_to_16(irec);
+               disk_nlink_16_set(irec, ino_offset, nlinks);
+       } else
+               irec->disk_nlinks[ino_offset] = nlinks;
+}
+
+static __uint32_t
+disk_nlink_8_get(ino_tree_node_t *irec, int ino_offset)
+{
+       return irec->disk_nlinks[ino_offset];
+}
+
+static __uint32_t
+counted_nlink_8_get(ino_tree_node_t *irec, int ino_offset)
+{
+       return irec->ino_un.ex_data->counted_nlinks[ino_offset];
+}
+
+static __uint32_t
+counted_nlink_8_inc(ino_tree_node_t *irec, int ino_offset)
+{
+       if (irec->ino_un.ex_data->counted_nlinks[ino_offset] == 0xff) {
+               nlink_grow_8_to_16(irec);
+               return counted_nlink_16_inc(irec, ino_offset);
+       }
+       return ++(irec->ino_un.ex_data->counted_nlinks[ino_offset]);
+}
+
+static __uint32_t
+counted_nlink_8_dec(ino_tree_node_t *irec, int ino_offset)
+{
+       ASSERT(irec->ino_un.ex_data->counted_nlinks[ino_offset] > 0);
+       return --(irec->ino_un.ex_data->counted_nlinks[ino_offset]);
+}
+
+
+static nlink_ops_t nlinkops[] = {
+       {sizeof(__uint8_t) * XFS_INODES_PER_CHUNK,
+               disk_nlink_8_set, disk_nlink_8_get,
+               counted_nlink_8_get, counted_nlink_8_inc, counted_nlink_8_dec},
+       {sizeof(__uint16_t) * XFS_INODES_PER_CHUNK,
+               disk_nlink_16_set, disk_nlink_16_get,
+               counted_nlink_16_get, counted_nlink_16_inc, counted_nlink_16_dec},
+       {sizeof(__uint32_t) * XFS_INODES_PER_CHUNK,
+               disk_nlink_32_set, disk_nlink_32_get,
+               counted_nlink_32_get, counted_nlink_32_inc, counted_nlink_32_dec},
+};
+
+static void
+nlink_grow_8_to_16(ino_tree_node_t *irec)
+{
+       __uint16_t      *new_nlinks;
+       int             i;
+
+       new_nlinks = malloc(sizeof(__uint16_t) * XFS_INODES_PER_CHUNK);
+       if (new_nlinks == NULL)
+               do_error(_("could not allocate expanded nlink array\n"));
+       for (i = 0; i < XFS_INODES_PER_CHUNK; i++)
+               new_nlinks[i] = irec->disk_nlinks[i];
+       free(irec->disk_nlinks);
+       irec->disk_nlinks = (__uint8_t*)new_nlinks;
+
+       if (full_ino_ex_data) {
+               new_nlinks = malloc(sizeof(__uint16_t) * XFS_INODES_PER_CHUNK);
+               if (new_nlinks == NULL)
+                       do_error(_("could not allocate expanded nlink array\n"));
+               for (i = 0; i < XFS_INODES_PER_CHUNK; i++)
+                       new_nlinks[i] = irec->ino_un.ex_data->counted_nlinks[i];
+               free(irec->ino_un.ex_data->counted_nlinks);
+               irec->ino_un.ex_data->counted_nlinks = (__uint8_t*)new_nlinks;
+       }
+       irec->nlinkops = &nlinkops[1];
+}
+
+static void
+nlink_grow_16_to_32(ino_tree_node_t *irec)
+{
+       __uint32_t      *new_nlinks;
+       int             i;
+
+       new_nlinks = malloc(sizeof(__uint32_t) * XFS_INODES_PER_CHUNK);
+       if (new_nlinks == NULL)
+               do_error(_("could not allocate expanded nlink array\n"));
+       for (i = 0; i < XFS_INODES_PER_CHUNK; i++)
+               new_nlinks[i] = ((__int16_t*)&irec->disk_nlinks)[i];
+       free(irec->disk_nlinks);
+       irec->disk_nlinks = (__uint8_t*)new_nlinks;
+
+       if (full_ino_ex_data) {
+               new_nlinks = malloc(sizeof(__uint32_t) * XFS_INODES_PER_CHUNK);
+               if (new_nlinks == NULL)
+                       do_error(_("could not allocate expanded nlink array\n"));
+               for (i = 0; i < XFS_INODES_PER_CHUNK; i++)
+                       new_nlinks[i] = ((__int16_t*)&irec->ino_un.ex_data->counted_nlinks)[i];
+               free(irec->ino_un.ex_data->counted_nlinks);
+               irec->ino_un.ex_data->counted_nlinks = (__uint8_t*)new_nlinks;
+       }
+       irec->nlinkops = &nlinkops[2];
+}
+
 /*
  * next is the uncertain inode list -- a sorted (in ascending order)
  * list of inode records sorted on the starting inode number.  There
@@ -65,47 +252,52 @@ static ino_flist_t ino_flist;      /* free list must be initialized before use */
  */
 /* ARGSUSED */
 static ino_tree_node_t *
-mk_ino_tree_nodes(xfs_agino_t starting_ino)
+mk_ino_tree_nodes(
+       xfs_agino_t             starting_ino)
 {
-       int i;
-       ino_tree_node_t *new;
-       avlnode_t *node;
+       int                     i;
+       ino_tree_node_t         *ino_rec;
+       avlnode_t               *node;
 
        PREPAIR_RW_WRITE_LOCK(&ino_flist_lock);
        if (ino_flist.cnt == 0)  {
                ASSERT(ino_flist.list == NULL);
 
-               if ((new = malloc(sizeof(ino_tree_node_t[ALLOC_NUM_INOS])))
+               if ((ino_rec = malloc(sizeof(ino_tree_node_t[ALLOC_NUM_INOS])))
                                        == NULL)
                        do_error(_("inode map malloc failed\n"));
 
                for (i = 0; i < ALLOC_NUM_INOS; i++)  {
-                       new->avl_node.avl_nextino =
+                       ino_rec->avl_node.avl_nextino =
                                (avlnode_t *) ino_flist.list;
-                       ino_flist.list = new;
+                       ino_flist.list = ino_rec;
                        ino_flist.cnt++;
-                       new++;
+                       ino_rec++;
                }
        }
 
        ASSERT(ino_flist.list != NULL);
 
-       new = ino_flist.list;
-       ino_flist.list = (ino_tree_node_t *) new->avl_node.avl_nextino;
+       ino_rec = ino_flist.list;
+       ino_flist.list = (ino_tree_node_t *) ino_rec->avl_node.avl_nextino;
        ino_flist.cnt--;
-       node = &new->avl_node;
+       node = &ino_rec->avl_node;
        node->avl_nextino = node->avl_forw = node->avl_back = NULL;
        PREPAIR_RW_UNLOCK(&ino_flist_lock);
 
        /* initialize node */
 
-       new->ino_startnum = 0;
-       new->ino_confirmed = 0;
-       new->ino_isa_dir = 0;
-       new->ir_free = (xfs_inofree_t) - 1;
-       new->ino_un.backptrs = NULL;
+       ino_rec->ino_startnum = 0;
+       ino_rec->ino_confirmed = 0;
+       ino_rec->ino_isa_dir = 0;
+       ino_rec->ir_free = (xfs_inofree_t) - 1;
+       ino_rec->ino_un.ex_data = NULL;
+       ino_rec->nlinkops = &nlinkops[0];
+       ino_rec->disk_nlinks = calloc(1, nlinkops[0].nlink_size);
+       if (ino_rec->disk_nlinks == NULL)
+               do_error(_("could not allocate nlink array\n"));
 
-       return(new);
+       return(ino_rec);
 }
 
 /*
@@ -131,11 +323,15 @@ free_ino_tree_node(ino_tree_node_t *ino_rec)
        ino_flist.list = ino_rec;
        ino_flist.cnt++;
 
-       if (ino_rec->ino_un.backptrs != NULL)  {
-               if (full_backptrs && ino_rec->ino_un.backptrs->parents != NULL)
-                       free(ino_rec->ino_un.backptrs->parents);
-               if (ino_rec->ino_un.plist != NULL)
-                       free(ino_rec->ino_un.plist);
+       free(ino_rec->disk_nlinks);
+
+       if (ino_rec->ino_un.ex_data != NULL)  {
+               if (full_ino_ex_data) {
+                       free(ino_rec->ino_un.ex_data->parents);
+                       free(ino_rec->ino_un.ex_data->counted_nlinks);
+               }
+               free(ino_rec->ino_un.ex_data);
+
        }
        PREPAIR_RW_UNLOCK(&ino_flist_lock);
 
@@ -443,7 +639,7 @@ set_inode_parent(ino_tree_node_t *irec, int offset, xfs_ino_t parent)
        __uint64_t      bitmask;
        parent_entry_t  *tmp;
 
-       ASSERT(full_backptrs == 0);
+       ASSERT(full_ino_ex_data == 0);
 
        if (irec->ino_un.plist == NULL)  {
                irec->ino_un.plist =
@@ -532,8 +728,8 @@ get_inode_parent(ino_tree_node_t *irec, int offset)
        int             i;
        int             target;
 
-       if (full_backptrs)
-               ptbl = irec->ino_un.backptrs->parents;
+       if (full_ino_ex_data)
+               ptbl = irec->ino_un.ex_data->parents;
        else
                ptbl = irec->ino_un.plist;
 
@@ -555,73 +751,38 @@ get_inode_parent(ino_tree_node_t *irec, int offset)
        return(0LL);
 }
 
-backptrs_t *
-get_backptr(void)
+static void
+alloc_ex_data(ino_tree_node_t *irec)
 {
-       backptrs_t *ptr;
+       parent_list_t   *ptbl;
 
-       if ((ptr = malloc(sizeof(backptrs_t))) == NULL)
-               do_error(_("could not malloc back pointer table\n"));
+       ptbl = irec->ino_un.plist;
+       irec->ino_un.ex_data  = (ino_ex_data_t *)calloc(1, sizeof(ino_ex_data_t));
+       if (irec->ino_un.ex_data == NULL)
+               do_error(_("could not malloc inode extra data\n"));
 
-       bzero(ptr, sizeof(backptrs_t));
+       irec->ino_un.ex_data->parents = ptbl;
+       irec->ino_un.ex_data->counted_nlinks = calloc(1, irec->nlinkops->nlink_size);
 
-       return(ptr);
+       if (irec->ino_un.ex_data->counted_nlinks == NULL)
+               do_error(_("could not malloc inode extra data\n"));
 }
 
 void
-add_ino_backptrs(xfs_mount_t *mp)
+add_ino_ex_data(xfs_mount_t *mp)
 {
-#ifdef XR_BCKPTR_DBG
-       xfs_ino_t ino;
-       int j, k;
-#endif /* XR_BCKPTR_DBG */
-       ino_tree_node_t *ino_rec;
-       parent_list_t *tmp;
-       xfs_agnumber_t i;
+       ino_tree_node_t *ino_rec;
+       xfs_agnumber_t  i;
 
        for (i = 0; i < mp->m_sb.sb_agcount; i++)  {
                ino_rec = findfirst_inode_rec(i);
 
                while (ino_rec != NULL)  {
-                       tmp = ino_rec->ino_un.plist;
-                       ino_rec->ino_un.backptrs = get_backptr();
-                       ino_rec->ino_un.backptrs->parents = tmp;
-
-#ifdef XR_BCKPTR_DBG
-                       if (tmp != NULL)  {
-                               k = 0;
-                               for (j = 0; j < XFS_INODES_PER_CHUNK; j++)  {
-                                       ino = XFS_AGINO_TO_INO(mp, i,
-                                               ino_rec->ino_startnum + j);
-                                       if (ino == 25165846)  {
-                                               do_warn("THERE 1 !!!\n");
-                                       }
-                                       if (tmp->pentries[j] != 0)  {
-                                               k++;
-                                               do_warn(
-                                               "inode %llu - parent %llu\n",
-                                                       ino,
-                                                       tmp->pentries[j]);
-                                               if (ino == 25165846)  {
-                                                       do_warn("THERE!!!\n");
-                                               }
-                                       }
-                               }
-
-                               if (k != tmp->cnt)  {
-                                       do_warn(
-                                       "ERROR - count = %d, counted %d\n",
-                                               tmp->cnt, k);
-                               }
-                       }
-#endif /* XR_BCKPTR_DBG */
+                       alloc_ex_data(ino_rec);
                        ino_rec = next_ino_rec(ino_rec);
                }
        }
-
-       full_backptrs = 1;
-
-       return;
+       full_ino_ex_data = 1;
 }
 
 static __psunsigned_t
@@ -680,7 +841,7 @@ incore_ino_init(xfs_mount_t *mp)
 
        bzero(last_rec, sizeof(ino_tree_node_t *) * agcount);
 
-       full_backptrs = 0;
+       full_ino_ex_data = 0;
 
        return;
 }
index 3ad2bc196c4fd270c342f6cf4f632bf3bdd24307..743c455b87c7f17de774dff5bb261d191cf84a1f 100644 (file)
@@ -94,7 +94,7 @@ typedef struct freetab {
 static int
 dir_hash_add(
        dir_hash_tab_t          *hashtab,
-       __uint32_t              addr,   
+       __uint32_t              addr,
        xfs_ino_t               inum,
        int                     namelen,
        uchar_t                 *name)
@@ -105,9 +105,9 @@ dir_hash_add(
        dir_hash_ent_t          *p;
        int                     dup;
        short                   junk;
-       
+
        ASSERT(!hashtab->names_duped);
-       
+
        junk = name[0] == '/';
        byaddr = DIR_HASH_FUNC(hashtab, addr);
        dup = 0;
@@ -116,7 +116,7 @@ dir_hash_add(
                hash = libxfs_da_hashname(name, namelen);
                byhash = DIR_HASH_FUNC(hashtab, hash);
 
-               /* 
+               /*
                 * search hash bucket for existing name.
                 */
                for (p = hashtab->byhash[byhash]; p; p = p->nextbyhash) {
@@ -129,20 +129,20 @@ dir_hash_add(
                        }
                }
        }
-       
+
        if ((p = malloc(sizeof(*p))) == NULL)
                do_error(_("malloc failed in dir_hash_add (%u bytes)\n"),
                        sizeof(*p));
-       
+
        p->nextbyaddr = hashtab->byaddr[byaddr];
        hashtab->byaddr[byaddr] = p;
-       if (hashtab->last) 
+       if (hashtab->last)
                hashtab->last->nextbyorder = p;
        else
                hashtab->first = p;
        p->nextbyorder = NULL;
        hashtab->last = p;
-       
+
        if (!(p->junkit = junk)) {
                p->hashval = hash;
                p->nextbyhash = hashtab->byhash[byhash];
@@ -153,12 +153,12 @@ dir_hash_add(
        p->seen = 0;
        p->namelen = namelen;
        p->name = name;
-       
+
        return !dup;
 }
 
 /*
- * checks to see if any data entries are not in the leaf blocks 
+ * checks to see if any data entries are not in the leaf blocks
  */
 static int
 dir_hash_unseen(
@@ -242,9 +242,9 @@ dir_hash_init(
        if ((hashtab = calloc(DIR_HASH_TAB_SIZE(hsize), 1)) == NULL)
                do_error(_("calloc failed in dir_hash_init\n"));
        hashtab->size = hsize;
-       hashtab->byhash = (dir_hash_ent_t**)((char *)hashtab + 
+       hashtab->byhash = (dir_hash_ent_t**)((char *)hashtab +
                sizeof(dir_hash_tab_t));
-       hashtab->byaddr = (dir_hash_ent_t**)((char *)hashtab + 
+       hashtab->byaddr = (dir_hash_ent_t**)((char *)hashtab +
                sizeof(dir_hash_tab_t) + sizeof(dir_hash_ent_t*) * hsize);
        return hashtab;
 }
@@ -308,10 +308,10 @@ dir_hash_dup_names(dir_hash_tab_t *hashtab)
 {
        uchar_t                 *name;
        dir_hash_ent_t          *p;
-       
+
        if (hashtab->names_duped)
                return;
-       
+
        for (p = hashtab->first; p; p = p->nextbyorder) {
                name = malloc(p->namelen);
                memcpy(name, p->name, p->namelen);
@@ -1539,9 +1539,9 @@ lf_block_dir_entry_check(xfs_mount_t              *mp,
 
                /*
                 * check for duplicate names in directory.
-                */ 
-               if (!dir_hash_add(hashtab, (da_bno << mp->m_sb.sb_blocklog) + 
-                                               entry->nameidx, 
+                */
+               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"),
@@ -1694,8 +1694,8 @@ _("bad magic # (0x%x) for dir ino %llu leaf block (bno %u fsbno %llu)\n"),
                }
 
                if (!skipit)
-                       lf_block_dir_entry_check(mp, ino, leaf, &dirty, 
-                                       num_illegal, need_dot, stack, irec, 
+                       lf_block_dir_entry_check(mp, ino, leaf, &dirty,
+                                       num_illegal, need_dot, stack, irec,
                                        ino_offset, hashtab, da_bno);
 
                da_bno = INT_GET(leaf->hdr.info.forw, ARCH_CONVERT);
@@ -1746,7 +1746,7 @@ _("can't map leaf block %d in dir %llu, xfs_bmapi returns %d, nmap = %d\n"),
  * lost+found on the next run
  */
 
-static void 
+static void
 longform_dir2_rebuild(
        xfs_mount_t     *mp,
        xfs_ino_t       ino,
@@ -1765,17 +1765,17 @@ longform_dir2_rebuild(
        dir_hash_ent_t          *p;
        int                     committed;
        int                     done;
-       
-       /* 
+
+       /*
         * trash directory completely and rebuild from scratch using the
         * name/inode pairs in the hash table
         */
-        
+
        do_warn(_("rebuilding directory inode %llu\n"), ino);
-       
-       /* 
+
+       /*
         * first attempt to locate the parent inode, if it can't be found,
-        * we'll use the lost+found inode 
+        * we'll use the lost+found inode
         */
        byhash = DIR_HASH_FUNC(hashtab, libxfs_da_hashname((uchar_t*)"..", 2));
        parentino = orphanage_ino;
@@ -1787,7 +1787,7 @@ longform_dir2_rebuild(
        }
 
        XFS_BMAP_INIT(&flist, &firstblock);
-               
+
        tp = libxfs_trans_alloc(mp, 0);
        nres = XFS_REMOVE_SPACE_RES(mp);
        error = libxfs_trans_reserve(tp, nres, XFS_REMOVE_LOG_RES(mp), 0,
@@ -1796,12 +1796,12 @@ longform_dir2_rebuild(
                res_failed(error);
        libxfs_trans_ijoin(tp, ip, 0);
        libxfs_trans_ihold(tp, ip);
-       
-       if ((error = libxfs_bmap_last_offset(tp, ip, &lastblock, 
+
+       if ((error = libxfs_bmap_last_offset(tp, ip, &lastblock,
                                                XFS_DATA_FORK)))
-               do_error(_("xfs_bmap_last_offset failed -- error - %d\n"), 
+               do_error(_("xfs_bmap_last_offset failed -- error - %d\n"),
                        error);
-       
+
        /* re-init the directory to shortform */
        if ((error = libxfs_trans_iget(mp, tp, parentino, 0, 0, &pip))) {
                do_warn(
@@ -1816,8 +1816,8 @@ longform_dir2_rebuild(
        }
 
        /* free all data, leaf, node and freespace blocks */
-       
-       if ((error = libxfs_bunmapi(tp, ip, 0, lastblock, 
+
+       if ((error = libxfs_bunmapi(tp, ip, 0, lastblock,
                        XFS_BMAPI_METADATA, 0, &firstblock, &flist,
                        &done))) {
                do_warn(_("xfs_bunmapi failed -- error - %d\n"), error);
@@ -1825,27 +1825,27 @@ longform_dir2_rebuild(
                                        XFS_TRANS_ABORT);
                return;
        }
-               
+
        ASSERT(done);
 
        libxfs_dir2_init(tp, ip, pip);
-       
+
        error = libxfs_bmap_finish(&tp, &flist, firstblock, &committed);
-                               
-       libxfs_trans_commit(tp, 
+
+       libxfs_trans_commit(tp,
                        XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC, 0);
-               
+
        /* go through the hash list and re-add the inodes */
 
        for (p = hashtab->first; p; p = p->nextbyorder) {
-               
-               if (p->name[0] == '/' || (p->name[0] == '.' && (p->namelen == 1 
+
+               if (p->name[0] == '/' || (p->name[0] == '.' && (p->namelen == 1
                                || (p->namelen == 2 && p->name[1] == '.'))))
                        continue;
-               
+
                tp = libxfs_trans_alloc(mp, 0);
                nres = XFS_CREATE_SPACE_RES(mp, p->namelen);
-               if ((error = libxfs_trans_reserve(tp, nres, 
+               if ((error = libxfs_trans_reserve(tp, nres,
                                XFS_CREATE_LOG_RES(mp), 0,
                                XFS_TRANS_PERM_LOG_RES, XFS_CREATE_LOG_COUNT))) {
                        do_warn(
@@ -1859,7 +1859,7 @@ longform_dir2_rebuild(
 
                XFS_BMAP_INIT(&flist, &firstblock);
                if ((error = libxfs_dir2_createname(tp, ip, (uchar_t *)p->name,
-                               p->namelen, p->inum, &firstblock, &flist, 
+                               p->namelen, p->inum, &firstblock, &flist,
                                nres))) {
                        do_warn(
 _("name create failed in ino %llu (%d), filesystem may be out of space\n"),
@@ -1869,7 +1869,7 @@ _("name create failed in ino %llu (%d), filesystem may be out of space\n"),
                        break;
                }
 
-               if ((error = libxfs_bmap_finish(&tp, &flist, firstblock, 
+               if ((error = libxfs_bmap_finish(&tp, &flist, firstblock,
                                &committed))) {
                        do_warn(
        _("bmap finish failed (%d), filesystem may be out of space\n"),
@@ -1879,9 +1879,9 @@ _("name create failed in ino %llu (%d), filesystem may be out of space\n"),
                                                XFS_TRANS_ABORT);
                        break;
                }
-                       
 
-               libxfs_trans_commit(tp, 
+
+               libxfs_trans_commit(tp,
                                XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_SYNC, 0);
        }
 }
@@ -2155,7 +2155,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, 
+               if (!dir_hash_add(hashtab, addr, inum, dep->namelen,
                                dep->name)) {
                        do_warn(
                _("entry \"%s\" (ino %llu) in dir %llu is a duplicate name"),
@@ -2419,12 +2419,12 @@ longform_dir2_check_node(
        xfs_fileoff_t           next_da_bno;
        int                     seeval = 0;
        int                     used;
-       
+
        for (da_bno = mp->m_dirleafblk, next_da_bno = 0;
             next_da_bno != NULLFILEOFF && da_bno < mp->m_dirfreeblk;
             da_bno = (xfs_dablk_t)next_da_bno) {
                next_da_bno = da_bno + mp->m_dirblkfsbs - 1;
-               if (libxfs_bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK)) 
+               if (libxfs_bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK))
                        break;
                if (libxfs_da_read_bufr(NULL, ip, da_bno, -1, &bp,
                                XFS_DATA_FORK)) {
@@ -2461,17 +2461,17 @@ longform_dir2_check_node(
                seeval = dir_hash_see_all(hashtab, leaf->ents, INT_GET(leaf->hdr.count, ARCH_CONVERT),
                        INT_GET(leaf->hdr.stale, ARCH_CONVERT));
                libxfs_da_brelse(NULL, bp);
-               if (seeval != DIR_HASH_CK_OK) 
+               if (seeval != DIR_HASH_CK_OK)
                        return 1;
        }
-       if (dir_hash_check(hashtab, ip, seeval)) 
+       if (dir_hash_check(hashtab, ip, seeval))
                return 1;
-       
+
        for (da_bno = mp->m_dirfreeblk, next_da_bno = 0;
             next_da_bno != NULLFILEOFF;
             da_bno = (xfs_dablk_t)next_da_bno) {
                next_da_bno = da_bno + mp->m_dirblkfsbs - 1;
-               if (libxfs_bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK)) 
+               if (libxfs_bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK))
                        break;
                if (libxfs_da_read_bufr(NULL, ip, da_bno, -1, &bp,
                                XFS_DATA_FORK)) {
@@ -2597,12 +2597,12 @@ longform_dir2_entry_check(xfs_mount_t   *mp,
                        /* more data blocks than expected */
                        num_bps = db + 1;
                        bplist = realloc(bplist, num_bps * sizeof(xfs_dabuf_t*));
-                       if (!bplist) 
+                       if (!bplist)
                                do_error(
                _("realloc failed in longform_dir2_entry_check (%u bytes)\n"),
                                        num_bps * sizeof(xfs_dabuf_t*));
                }
-               if (libxfs_da_read_bufr(NULL, ip, da_bno, -1, &bplist[db], 
+               if (libxfs_da_read_bufr(NULL, ip, da_bno, -1, &bplist[db],
                                XFS_DATA_FORK)) {
                        do_warn(_(
                        "can't read data block %u for directory inode %llu\n"),
@@ -2621,8 +2621,8 @@ longform_dir2_entry_check(xfs_mount_t     *mp,
                block = bplist[0]->data;
                btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
                blp = XFS_DIR2_BLOCK_LEAF_P(btp);
-               seeval = dir_hash_see_all(hashtab, blp, 
-                               INT_GET(btp->count, ARCH_CONVERT), 
+               seeval = dir_hash_see_all(hashtab, blp,
+                               INT_GET(btp->count, ARCH_CONVERT),
                                INT_GET(btp->stale, ARCH_CONVERT));
                if (dir_hash_check(hashtab, ip, seeval))
                        fixit |= 1;
@@ -2633,17 +2633,17 @@ longform_dir2_entry_check(xfs_mount_t   *mp,
        }
        if (!no_modify && fixit) {
                dir_hash_dup_names(hashtab);
-               for (i = 0; i < freetab->naents; i++) 
+               for (i = 0; i < freetab->naents; i++)
                        if (bplist[i])
                                libxfs_da_brelse(NULL, bplist[i]);
                longform_dir2_rebuild(mp, ino, ip, hashtab);
                *num_illegal = 0;
        } else {
-               for (i = 0; i < freetab->naents; i++) 
+               for (i = 0; i < freetab->naents; i++)
                        if (bplist[i])
                                libxfs_da_brelse(NULL, bplist[i]);
        }
-       
+
        free(bplist);
        free(freetab);
 }
@@ -2798,7 +2798,7 @@ _("entry \"%s\" in shortform dir %llu references non-existent ino %llu\n"),
                ASSERT(irec != NULL);
 
                ino_offset = XFS_INO_TO_AGINO(mp, lino) - irec->ino_startnum;
-               
+
                /*
                 * if it's a free inode, blow out the entry.
                 * by now, any inode that we think is free
@@ -2820,12 +2820,12 @@ _("entry \"%s\" in shortform dir inode %llu points to free inode %llu\n"),
                                do_warn(_("would junk entry \"%s\"\n"),
                                        fname);
                        }
-               } else if (!dir_hash_add(hashtab, 
+               } 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.
-                        */ 
+                        */
                        do_warn(
                _("entry \"%s\" (ino %llu) in dir %llu is a duplicate name"),
                                fname, lino, ino);
@@ -3244,7 +3244,7 @@ shortform_dir2_entry_check(xfs_mount_t    *mp,
                                lino, sfep->namelen, sfep->name)) {
                        /*
                         * check for duplicate names in directory.
-                        */ 
+                        */
                        do_warn(
                _("entry \"%s\" (ino %llu) in dir %llu is a duplicate name"),
                                fname, lino, ino);
@@ -3890,7 +3890,7 @@ phase6(xfs_mount_t *mp)
 
        incore_ext_teardown(mp);
 
-       add_ino_backptrs(mp);
+       add_ino_ex_data(mp);
 
        /*
         * verify existence of root directory - if we have to
@@ -4031,10 +4031,10 @@ _("        - 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"));
 
        /*
index b656725e2b73ea4a15f2636e20b5f2c984f03981..c66533270c1a92b6211a45ac858c8d3f8eab9bf3 100644 (file)
 #include "threads.h"
 
 /* dinoc is a pointer to the IN-CORE dinode core */
-void
-set_nlinks(xfs_dinode_core_t   *dinoc,
-               xfs_ino_t       ino,
-               __uint32_t      nrefs,
-               int             *dirty)
+static void
+set_nlinks(
+       xfs_dinode_core_t       *dinoc,
+       xfs_ino_t               ino,
+       __uint32_t              nrefs,
+       int                     *dirty)
 {
-       if (!no_modify)  {
-               if (dinoc->di_nlink != nrefs)  {
-                       *dirty = 1;
-                       do_warn(
-               _("resetting inode %llu nlinks from %d to %d\n"),
-                               ino, dinoc->di_nlink, nrefs);
+       if (dinoc->di_nlink == nrefs)
+               return;
 
-                       if (nrefs > XFS_MAXLINK_1)  {
-                               ASSERT(fs_inode_nlink);
-                               do_warn(
+       if (!no_modify) {
+               *dirty = 1;
+               do_warn(_("resetting inode %llu nlinks from %d to %d\n"),
+                       ino, dinoc->di_nlink, nrefs);
+
+               if (nrefs > XFS_MAXLINK_1)  {
+                       ASSERT(fs_inode_nlink);
+                       do_warn(
 _("nlinks %d will overflow v1 ino, ino %llu will be converted to version 2\n"),
-                                       nrefs, ino);
+                               nrefs, ino);
 
-                       }
-                       dinoc->di_nlink = nrefs;
                }
+               dinoc->di_nlink = nrefs;
        } else  {
-               if (dinoc->di_nlink != nrefs)
+               do_warn(_("would have reset inode %llu nlinks from %d to %d\n"),
+                       ino, dinoc->di_nlink, nrefs);
+       }
+}
+
+static void
+update_inode_nlinks(
+       xfs_mount_t             *mp,
+       xfs_ino_t               ino,
+       __uint32_t              nlinks)
+{
+       xfs_trans_t             *tp;
+       xfs_inode_t             *ip;
+       int                     error;
+       int                     dirty;
+
+       tp = libxfs_trans_alloc(mp, XFS_TRANS_REMOVE);
+
+       error = libxfs_trans_reserve(tp, (no_modify ? 0 : 10),
+                       XFS_REMOVE_LOG_RES(mp), 0, XFS_TRANS_PERM_LOG_RES,
+                       XFS_REMOVE_LOG_COUNT);
+
+       ASSERT(error == 0);
+
+       error = libxfs_trans_iget(mp, tp, ino, 0, 0, &ip);
+
+       if (error)  {
+               if (!no_modify)
+                       do_error(_("couldn't map inode %llu, err = %d\n"),
+                               ino, error);
+               else  {
                        do_warn(
-                       _("would have reset inode %llu nlinks from %d to %d\n"),
-                               ino, dinoc->di_nlink, nrefs);
+       _("couldn't map inode %llu, err = %d, can't compare link counts\n"),
+                               ino, error);
+                       return;
+               }
+       }
+
+       dirty = 0;
+
+       /*
+        * 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);
+
+       if (!dirty)  {
+               libxfs_trans_iput(tp, ip, 0);
+               libxfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES);
+       } else  {
+               libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+               /*
+                * no need to do a bmap finish since
+                * we're not allocating anything
+                */
+               ASSERT(error == 0);
+               error = libxfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES |
+                               XFS_TRANS_SYNC, NULL);
+
+               ASSERT(error == 0);
        }
 }
 
-void
+static void
 phase7_alt_function(xfs_mount_t *mp, xfs_agnumber_t agno)
 {
-       register ino_tree_node_t *irec;
+       ino_tree_node_t         *irec;
        int                     j;
-       int                     chunk_dirty;
-       int                     inode_dirty;
-       xfs_ino_t               ino;
        __uint32_t              nrefs;
-       xfs_agblock_t           agbno;
-       xfs_dinode_t            *dip;
-       ino_tree_node_t         *ino_ra;
-       xfs_buf_t               *bp;
-
-       if (verbose)
-               do_log(_("        - agno = %d\n"), agno);
-
-       ino_ra = prefetch_inode_chunks(mp, agno, NULL);
 
        /*
-        * read on-disk inodes in chunks. then,
-        * look at each on-disk inode 1 at a time.
-        * if the number of links is bad, reset it.
+        * using the nlink values memorised during phase3/4, compare to the
+        * nlink counted in phase 6, and if different, update on-disk.
         */
 
        irec = findfirst_inode_rec(agno);
 
        while (irec != NULL)  {
-
-               if (ino_ra && (irec->ino_startnum >= ino_ra->ino_startnum))
-                       ino_ra = prefetch_inode_chunks(mp, agno, ino_ra);
-
-               agbno = XFS_AGINO_TO_AGBNO(mp, irec->ino_startnum);
-               bp = libxfs_readbuf(mp->m_dev,
-                               XFS_AGB_TO_DADDR(mp, agno, agbno),
-                               XFS_FSB_TO_BB(mp, XFS_IALLOC_BLOCKS(mp)), 0);
-               if (bp == NULL) {
-                       if (!no_modify) {
-                               do_error(
-       _("cannot read inode %llu, disk block %lld, cnt %d\n"),
-                               XFS_AGINO_TO_INO(mp, agno, irec->ino_startnum),
-                               XFS_AGB_TO_DADDR(mp, agno, agbno),
-                               (int)XFS_FSB_TO_BB(mp, XFS_IALLOC_BLOCKS(mp)));
-                               /* NOT REACHED */
-                       }
-                       do_warn(
-       _("cannot read inode %llu, disk block %lld, cnt %d\n"),
-                               XFS_AGINO_TO_INO(mp, agno, irec->ino_startnum),
-                               XFS_AGB_TO_DADDR(mp, agno, agbno),
-                               (int)XFS_FSB_TO_BB(mp, XFS_IALLOC_BLOCKS(mp)));
-
-                       irec = next_ino_rec(irec);
-                       continue;       /* while */
-               }
-               chunk_dirty = 0;
                for (j = 0; j < XFS_INODES_PER_CHUNK; j++)  {
                        assert(is_inode_confirmed(irec, j));
 
@@ -122,110 +141,27 @@ phase7_alt_function(xfs_mount_t *mp, xfs_agnumber_t agno)
                                continue;
 
                        assert(no_modify || is_inode_reached(irec, j));
-                       assert(no_modify ||
-                                       is_inode_referenced(irec, j));
+                       assert(no_modify || is_inode_referenced(irec, j));
 
                        nrefs = num_inode_references(irec, j);
 
-                       ino = XFS_AGINO_TO_INO(mp, agno,
-                               irec->ino_startnum + j);
-
-                       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_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) {
-                                       do_error(
-       _("ino: %llu, bad d_inode magic saw: (0x%x) expecting (0x%x)\n"),
-                               ino, dip->di_core.di_magic, XFS_DINODE_MAGIC);
-                                       /* NOT REACHED */
-                               }
-                               do_warn(
-       _("ino: %llu, bad d_inode magic saw: (0x%x) expecting (0x%x)\n"),
-                               ino, dip->di_core.di_magic, XFS_DINODE_MAGIC);
-                               continue;
-                       }
-                       /*
-                        * compare and set links for all inodes
-                        * but the lost+found inode.  we keep
-                        * that correct as we go.
-                        */
-                       if (dip->di_core.di_nlink != nrefs) {
-                               if (ino != orphanage_ino) {
-                                       set_nlinks(&dip->di_core, ino,
-                                                       nrefs, &inode_dirty);
-                               }
-                       }
-
-                       /* Swap the fields back */
-                       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);
-                                       INT_SET(dip->di_core.di_onlink, 
-                                                       ARCH_CONVERT,
-                                                       dip->di_core.di_nlink);
-                                       dip->di_core.di_nlink = 
-                                               INT_GET(dip->di_core.di_nlink, 
-                                                       ARCH_CONVERT);
-                               } 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 (get_inode_disk_nlinks(irec, j) != nrefs)
+                               update_inode_nlinks(mp, XFS_AGINO_TO_INO(mp,
+                                               agno, irec->ino_startnum + j),
+                                               nrefs);
                }
-
-               if (chunk_dirty)
-                       libxfs_writebuf(bp, 0);
-               else
-                       libxfs_putbuf(bp);
-
                irec = next_ino_rec(irec);
                PROG_RPT_INC(prog_rpt_done[agno], XFS_INODES_PER_CHUNK);
        }
 }
 
-void
+static void
 phase7_alt(xfs_mount_t *mp)
 {
        int             i;
 
        set_progress_msg(no_modify ? PROGRESS_FMT_VRFY_LINK : PROGRESS_FMT_CORR_LINK,
                (__uint64_t) mp->m_sb.sb_icount);
-       libxfs_bcache_purge();
 
        for (i = 0; i < glob_agcount; i++)  {
                queue_work(phase7_alt_function, mp, i);
@@ -238,13 +174,8 @@ void
 phase7(xfs_mount_t *mp)
 {
        ino_tree_node_t         *irec;
-       xfs_inode_t             *ip;
-       xfs_trans_t             *tp;
        int                     i;
        int                     j;
-       int                     error;
-       int                     dirty;
-       xfs_ino_t               ino;
        __uint32_t              nrefs;
 
        if (!no_modify)
@@ -252,25 +183,14 @@ phase7(xfs_mount_t *mp)
        else
                do_log(_("Phase 7 - verify link counts...\n"));
 
-
        if (do_prefetch) {
                phase7_alt(mp);
                return;
        }
 
-       tp = libxfs_trans_alloc(mp, XFS_TRANS_REMOVE);
-
-       error = libxfs_trans_reserve(tp, (no_modify ? 0 : 10),
-                       XFS_REMOVE_LOG_RES(mp), 0, XFS_TRANS_PERM_LOG_RES,
-                       XFS_REMOVE_LOG_COUNT);
-
-       ASSERT(error == 0);
-
        /*
-        * for each ag, look at each inode 1 at a time using the
-        * sim code.  if the number of links is bad, reset it,
-        * log the inode core, commit the transaction, and
-        * allocate a new transaction
+        * for each ag, look at each inode 1 at a time. If the number of
+        * links is bad, reset it, log the inode core, commit the transaction
         */
        for (i = 0; i < glob_agcount; i++)  {
                irec = findfirst_inode_rec(i);
@@ -288,69 +208,13 @@ phase7(xfs_mount_t *mp)
 
                                nrefs = num_inode_references(irec, j);
 
-                               ino = XFS_AGINO_TO_INO(mp, i,
-                                       irec->ino_startnum + j);
-
-                               error = libxfs_trans_iget(mp, tp, ino, 0, 0, &ip);
-
-                               if (error)  {
-                                       if (!no_modify)
-                                               do_error(
-                               _("couldn't map inode %llu, err = %d\n"),
-                                                       ino, error);
-                                       else  {
-                                               do_warn(
-       _("couldn't map inode %llu, err = %d, can't compare link counts\n"),
-                                                       ino, error);
-                                               continue;
-                                       }
-                               }
-
-                               dirty = 0;
-
-                               /*
-                                * 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, nrefs,
-                                                       &dirty);
-
-                               if (!dirty)  {
-                                       libxfs_trans_iput(tp, ip, 0);
-                               } else  {
-                                       libxfs_trans_log_inode(tp, ip,
-                                                       XFS_ILOG_CORE);
-                                       /*
-                                        * no need to do a bmap finish since
-                                        * we're not allocating anything
-                                        */
-                                       ASSERT(error == 0);
-                                       error = libxfs_trans_commit(tp,
-                                               XFS_TRANS_RELEASE_LOG_RES|
-                                               XFS_TRANS_SYNC, NULL);
-
-                                       ASSERT(error == 0);
-
-                                       tp = libxfs_trans_alloc(mp,
-                                                       XFS_TRANS_REMOVE);
-
-                                       error = libxfs_trans_reserve(tp,
-                                               (no_modify ? 0 : 10),
-                                               XFS_REMOVE_LOG_RES(mp),
-                                               0, XFS_TRANS_PERM_LOG_RES,
-                                               XFS_REMOVE_LOG_COUNT);
-                                       ASSERT(error == 0);
-                               }
+                               if (get_inode_disk_nlinks(irec, j) != nrefs)
+                                       update_inode_nlinks(mp,
+                                               XFS_AGINO_TO_INO(mp, i,
+                                                       irec->ino_startnum + j),
+                                               nrefs);
                        }
                        irec = next_ino_rec(irec);
                }
        }
-
-       /*
-        * always have one unfinished transaction coming out
-        * of the loop.  cancel it.
-        */
-       libxfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES);
 }
index c5d82ad84f95bf174c7120b9cbb800b86eca5553..3f4f5cecb88e3feab5e4a92c8d8d81f5ded6dcac 100644 (file)
@@ -169,7 +169,7 @@ process_args(int argc, char **argv)
        isa_file = 0;
        zap_log = 0;
        dumpcore = 0;
-       full_backptrs = 0;
+       full_ino_ex_data = 0;
        delete_attr_ok = 1;
        force_geo = 0;
        assume_xfs = 0;
@@ -277,7 +277,7 @@ process_args(int argc, char **argv)
                case 't':
                        report_interval = (int) strtol(optarg, 0, 0);
                        break;
-                       
+
                case '?':
                        usage();
                }
@@ -563,7 +563,7 @@ main(int argc, char **argv)
 
        /* XXX: nathans - something in phase4 ain't playing by */
        /* the buffer cache rules.. why doesn't IRIX hit this? */
-       libxfs_bcache_purge();
+       libxfs_bcache_flush();
 
        if (no_modify)
                printf(_("No modify flag set, skipping phase 5\n"));
@@ -576,6 +576,8 @@ main(int argc, char **argv)
                phase6(mp);
                timestamp(PHASE_END, 6, NULL);
 
+               libxfs_bcache_flush();
+
                phase7(mp);
                timestamp(PHASE_END, 7, NULL);
        } else  {