|
|
| 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); |