Diff for /xfs-cmds/xfsprogs/repair/phase6.c between versions 1.43 and 1.44

version 1.43, 2008/05/26 04:03:56 version 1.44, 2008/09/05 04:11:43
Line 36  static struct fsxattr   zerofsx; Line 36  static struct fsxattr   zerofsx;
 static xfs_ino_t                orphanage_ino;  static xfs_ino_t                orphanage_ino;
   
 /*  /*
    * Data structures used to keep track of directories where the ".."
    * entries are updated. These must be rebuilt after the initial pass
    */
   typedef struct dotdot_update {
           struct dotdot_update    *next;
           ino_tree_node_t         *irec;
           xfs_agnumber_t          agno;
           int                     ino_offset;
   } dotdot_update_t;
   
   static dotdot_update_t          *dotdot_update_list;
   static int                      dotdot_update;
   
   static void
   add_dotdot_update(
           xfs_agnumber_t          agno,
           ino_tree_node_t         *irec,
           int                     ino_offset)
   {
           dotdot_update_t         *dir = malloc(sizeof(dotdot_update_t));
   
           if (!dir)
                   do_error(_("malloc failed add_dotdot_update (%u bytes)\n"),
                           sizeof(dotdot_update_t));
   
           dir->next = dotdot_update_list;
           dir->irec = irec;
           dir->agno = agno;
           dir->ino_offset = ino_offset;
   
           dotdot_update_list = dir;
   }
   
   /*
  * Data structures and routines to keep track of directory entries   * Data structures and routines to keep track of directory entries
  * and whether their leaf entry has been seen. Also used for name   * and whether their leaf entry has been seen. Also used for name
  * duplicate checking and rebuilding step if required.   * duplicate checking and rebuilding step if required.
Line 2276  longform_dir2_entry_check_data( Line 2310  longform_dir2_entry_check_data(
                 }                  }
   
                 /*                  /*
                    * if just scanning to rebuild a directory due to a ".."
                    * update, just continue
                    */
                   if (dotdot_update)
                           continue;
   
                   /*
                  * skip the '..' entry since it's checked when the                   * skip the '..' entry since it's checked when the
                  * directory is reached by something else.  if it never                   * directory is reached by something else.  if it never
                  * gets reached, it'll be moved to the orphanage and we'll                   * gets reached, it'll be moved to the orphanage and we'll
Line 2364  _("entry \"%s\" in dir %llu points to an Line 2405  _("entry \"%s\" in dir %llu points to an
                         set_inode_parent(irec, ino_offset, ip->i_ino);                          set_inode_parent(irec, ino_offset, ip->i_ino);
                         add_inode_reached(irec, ino_offset);                          add_inode_reached(irec, ino_offset);
                         add_inode_ref(current_irec, current_ino_offset);                          add_inode_ref(current_irec, current_ino_offset);
                           add_dotdot_update(XFS_INO_TO_AGNO(mp, inum), irec,
                                                                   ino_offset);
                 } else  {                  } else  {
                         junkit = 1;                          junkit = 1;
                         do_warn(                          do_warn(
Line 2613  longform_dir2_entry_check(xfs_mount_t *m Line 2656  longform_dir2_entry_check(xfs_mount_t *m
                         dir_hash_tab_t  *hashtab)                          dir_hash_tab_t  *hashtab)
 {  {
         xfs_dir2_block_t        *block;          xfs_dir2_block_t        *block;
         xfs_dir2_leaf_entry_t   *blp;  
         xfs_dabuf_t             **bplist;          xfs_dabuf_t             **bplist;
         xfs_dir2_block_tail_t   *btp;  
         xfs_dablk_t             da_bno;          xfs_dablk_t             da_bno;
         freetab_t               *freetab;          freetab_t               *freetab;
         int                     num_bps;          int                     num_bps;
Line 2678  longform_dir2_entry_check(xfs_mount_t *m Line 2719  longform_dir2_entry_check(xfs_mount_t *m
         }          }
         fixit = (*num_illegal != 0) || dir2_is_badino(ino) || *need_dot;          fixit = (*num_illegal != 0) || dir2_is_badino(ino) || *need_dot;
   
         /* check btree and freespace */          if (!dotdot_update) {
         if (isblock) {                  /* check btree and freespace */
                 block = bplist[0]->data;                  if (isblock) {
                 btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);                          xfs_dir2_block_tail_t   *btp;
                 blp = XFS_DIR2_BLOCK_LEAF_P(btp);                          xfs_dir2_leaf_entry_t   *blp;
                 seeval = dir_hash_see_all(hashtab, blp,  
                                 INT_GET(btp->count, ARCH_CONVERT),                          block = bplist[0]->data;
                                 INT_GET(btp->stale, ARCH_CONVERT));                          btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
                 if (dir_hash_check(hashtab, ip, seeval))                          blp = XFS_DIR2_BLOCK_LEAF_P(btp);
                         fixit |= 1;                          seeval = dir_hash_see_all(hashtab, blp,
         } else if (isleaf) {                                                  be32_to_cpu(btp->count),
                 fixit |= longform_dir2_check_leaf(mp, ip, hashtab, freetab);                                                  be32_to_cpu(btp->stale));
         } else {                          if (dir_hash_check(hashtab, ip, seeval))
                 fixit |= longform_dir2_check_node(mp, ip, hashtab, freetab);                                  fixit |= 1;
                   } else if (isleaf) {
                           fixit |= longform_dir2_check_leaf(mp, ip, hashtab,
                                                                   freetab);
                   } else {
                           fixit |= longform_dir2_check_node(mp, ip, hashtab,
                                                                   freetab);
                   }
         }          }
         if (!no_modify && fixit) {          if (!no_modify && (fixit || dotdot_update)) {
                 dir_hash_dup_names(hashtab);                  dir_hash_dup_names(hashtab);
                 for (i = 0; i < freetab->naents; i++)                  for (i = 0; i < freetab->naents; i++)
                         if (bplist[i])                          if (bplist[i])
Line 3141  shortform_dir2_entry_check(xfs_mount_t * Line 3189  shortform_dir2_entry_check(xfs_mount_t *
         ASSERT(ip->i_d.di_size <= ifp->if_bytes);          ASSERT(ip->i_d.di_size <= ifp->if_bytes);
   
         /*          /*
            * if just rebuild a directory due to a "..", update and return
            */
           if (dotdot_update) {
                   parent = get_inode_parent(current_irec, current_ino_offset);
                   if (no_modify) {
                           do_warn(_("would set .. in sf dir inode %llu to %llu\n"),
                                   ino, parent);
                   } else {
                           do_warn(_("setting .. in sf dir inode %llu to %llu\n"),
                                   ino, parent);
                           XFS_DIR2_SF_PUT_INUMBER(sfp, &parent, &sfp->hdr.parent);
                           *ino_dirty = 1;
                   }
                   return;
           }
   
           /*
          * no '.' entry in shortform dirs, just bump up ref count by 1           * no '.' entry in shortform dirs, just bump up ref count by 1
          * '..' was already (or will be) accounted for and checked when           * '..' was already (or will be) accounted for and checked when
          * the directory is reached or will be taken care of when the           * the directory is reached or will be taken care of when the
Line 3151  shortform_dir2_entry_check(xfs_mount_t * Line 3216  shortform_dir2_entry_check(xfs_mount_t *
         /*          /*
          * Initialise i8 counter -- the parent inode number counts as well.           * Initialise i8 counter -- the parent inode number counts as well.
          */           */
         i8 = (XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent) > XFS_DIR2_MAX_SHORT_INUM);          i8 = (XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent) >
                                                   XFS_DIR2_MAX_SHORT_INUM);
   
         /*          /*
          * now run through entries, stop at first bad entry, don't need           * now run through entries, stop at first bad entry, don't need
Line 3283  shortform_dir2_entry_check(xfs_mount_t * Line 3349  shortform_dir2_entry_check(xfs_mount_t *
                                 "duplicate name"), fname, lino, ino);                                  "duplicate name"), fname, lino, ino);
                         goto do_junkit;                          goto do_junkit;
                 }                  }
   
                 if (!inode_isadir(irec, ino_offset))  {                  if (!inode_isadir(irec, ino_offset))  {
                         /*                          /*
                          * check easy case first, regular inode, just bump                           * check easy case first, regular inode, just bump
Line 3315  shortform_dir2_entry_check(xfs_mount_t * Line 3382  shortform_dir2_entry_check(xfs_mount_t *
                                 set_inode_parent(irec, ino_offset, ino);                                  set_inode_parent(irec, ino_offset, ino);
                                 add_inode_reached(irec, ino_offset);                                  add_inode_reached(irec, ino_offset);
                                 add_inode_ref(current_irec, current_ino_offset);                                  add_inode_ref(current_irec, current_ino_offset);
                                   add_dotdot_update(XFS_INO_TO_AGNO(mp, lino),
                                                           irec, ino_offset);
                         } else  {                          } else  {
                                 junkit = 1;                                  junkit = 1;
                                 do_warn(_("entry \"%s\" in directory inode %llu"                                  do_warn(_("entry \"%s\" in directory inode %llu"
Line 3432  do_junkit: Line 3501  do_junkit:
 static void  static void
 process_dir_inode(  process_dir_inode(
         xfs_mount_t             *mp,          xfs_mount_t             *mp,
         xfs_ino_t               ino,          xfs_agnumber_t          agno,
         ino_tree_node_t         *irec,          ino_tree_node_t         *irec,
         int                     ino_offset)          int                     ino_offset)
 {  {
           xfs_ino_t               ino;
         xfs_bmap_free_t         flist;          xfs_bmap_free_t         flist;
         xfs_fsblock_t           first;          xfs_fsblock_t           first;
         xfs_inode_t             *ip;          xfs_inode_t             *ip;
Line 3445  process_dir_inode( Line 3515  process_dir_inode(
         int                     need_dot, committed;          int                     need_dot, committed;
         int                     dirty, num_illegal, error, nres;          int                     dirty, num_illegal, error, nres;
   
           ino = XFS_AGINO_TO_INO(mp, agno, irec->ino_startnum + ino_offset);
   
         /*          /*
          * open up directory inode, check all entries,           * open up directory inode, check all entries,
          * then call prune_dir_entries to remove all           * then call prune_dir_entries to remove all
          * remaining illegal directory entries.           * remaining illegal directory entries.
          */           */
   
         ASSERT(!is_inode_refchecked(ino, irec, ino_offset));          ASSERT(!is_inode_refchecked(ino, irec, ino_offset) || dotdot_update);
   
         error = libxfs_iget(mp, NULL, ino, 0, &ip, 0);          error = libxfs_iget(mp, NULL, ino, 0, &ip, 0);
         if (error) {          if (error) {
Line 3853  traverse_function( Line 3925  traverse_function(
   
                 for (i = 0; i < XFS_INODES_PER_CHUNK; i++)  {                  for (i = 0; i < XFS_INODES_PER_CHUNK; i++)  {
                         if (inode_isadir(irec, i))                          if (inode_isadir(irec, i))
                                 process_dir_inode(wq->mp,                                  process_dir_inode(wq->mp, agno, irec, i);
                                         XFS_AGINO_TO_INO(wq->mp, agno,  
                                         irec->ino_startnum + i), irec, i);  
                 }                  }
         }          }
         cleanup_inode_prefetch(pf_args);          cleanup_inode_prefetch(pf_args);
 }  }
   
 static void  static void
   update_missing_dotdot_entries(
           xfs_mount_t             *mp)
   {
           dotdot_update_t         *dir;
   
           /*
            * these entries parents were updated, rebuild them again
            * set dotdot_update flag so processing routines do not count links
            */
           dotdot_update = 1;
           while (dotdot_update_list) {
                   dir = dotdot_update_list;
                   dotdot_update_list = dir->next;
                   process_dir_inode(mp, dir->agno, dir->irec, dir->ino_offset);
                   free(dir);
           }
   }
   
   static void
 traverse_ags(  traverse_ags(
         xfs_mount_t             *mp)          xfs_mount_t             *mp)
 {  {
Line 3974  _("        - resetting contents of realt Line 4063  _("        - resetting contents of realt
          */           */
         traverse_ags(mp);          traverse_ags(mp);
   
           /*
            * any directories that had updated ".." entries, rebuild them now
            */
           update_missing_dotdot_entries(mp);
   
         do_log(_("        - traversal finished ...\n"));          do_log(_("        - traversal finished ...\n"));
         do_log(_("        - moving disconnected inodes to %s ...\n"),          do_log(_("        - moving disconnected inodes to %s ...\n"),
                 ORPHANAGE);                  ORPHANAGE);

Removed from v.1.43  
changed lines
  Added in v.1.44


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>