From: Brian Foster <bfoster@redhat.com>
To: xfs@oss.sgi.com
Subject: Re: [PATCH V4] xfs_repair: add support for validating dirent ftype field
Date: Fri, 24 Jan 2014 18:38:17 -0500 [thread overview]
Message-ID: <52E2F969.9050502@redhat.com> (raw)
In-Reply-To: <1390603109-29667-1-git-send-email-david@fromorbit.com>
On 01/24/2014 05:38 PM, Dave Chinner wrote:
> From: Dave Chinner <dchinner@redhat.com>
>
> Add code to track the filetype of an inode from phase 3 when all the
> inodes are scanned throught to phase 6 when the directory structure
> is validated and corrected.
>
> Add code to phase 6 shortform and long form directory entry
> validation to read the ftype from the dirent, lookup the inode
> record and check they are the same. If they aren't and we are in
> no-modify mode, issue a warning such as:
>
> Phase 6 - check inode connectivity...
> - traversing filesystem ...
> would fix ftype mismatch (5/1) in directory/child inode 64/68
> - traversal finished ...
> - moving disconnected inodes to lost+found ...
>
> If we are fixing the problem:
>
> Phase 6 - check inode connectivity...
> - resetting contents of realtime bitmap and summary inodes
> - traversing filesystem ...
> fixing ftype mismatch (5/1) in directory/child inode 64/68
> - traversal finished ...
> - moving disconnected inodes to lost+found ...
>
> Note that this is from a leaf form directory entry that was
> intentionally corrupted with xfs_db like so:
>
> xfs_db> inode 64
> xfs_db> a u3.bmx[0].startblock
> xfs_db> p
> ....
> du[3].inumber = 68
> du[3].namelen = 11
> du[3].name = "syscalltest"
> du[3].filetype = 1
> du[3].tag = 0x70
> ....
> xfs_db> write du[3].filetype 5
> du[3].filetype = 5
> xfs_db> quit
>
> Shortform directory entry repair was tested in a similar fashion.
>
> Further, track the ftype in the directory hash table that is build,
> so if the directory is rebuild from scratch it has the necessary
> ftype information to rebuild the directory correctly. Further, if we
> detect a ftype mismatch, update the entry in the hash so that later
> directory errors that lead to it being rebuilt use the corrected
> ftype field, not the bad one.
>
> Note that this code pulls in some kernel side code that is currently
> in kernel private locations (xfs_mode_to_ftype table), so there'll
> be some kernel/userspace sync work needed to bring these back into
> line.
>
> Signed-off-by: Dave Chinner <dchinner@redhat.com>
>
> Version 4:
> - removed a couple more typedefs
> - fixed no_modify return value from shortform_dir2_junk()
> - cleaned up variable naming, formatting and comments in
> shortform_dir2_junk() to make it more obvious what it is doing.
>
> Version 3:
> - fixed max_size updates
> - fixed comment grammar
>
> Version 2:
> - factored out junking of entry in shortform directory code
> - fixed leak of ftypes array memory
> ---
Looks good. Nice cleanup.
Reviewed-by: Brian Foster <bfoster@redhat.com>
> include/xfs_dir2.h | 3 +
> libxfs/xfs_dir2.c | 16 ++++
> repair/dino_chunks.c | 11 +++
> repair/incore.h | 27 +++++-
> repair/incore_ino.c | 30 ++++++-
> repair/phase6.c | 246 ++++++++++++++++++++++++++++++++++++---------------
> repair/scan.c | 4 +-
> 7 files changed, 258 insertions(+), 79 deletions(-)
>
> diff --git a/include/xfs_dir2.h b/include/xfs_dir2.h
> index 9910401..3900130 100644
> --- a/include/xfs_dir2.h
> +++ b/include/xfs_dir2.h
> @@ -57,6 +57,9 @@ extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp,
> extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp,
> struct xfs_name *name, uint resblks);
>
> +#define S_SHIFT 12
> +extern const unsigned char xfs_mode_to_ftype[];
> +
> /*
> * Direct call from the bmap code, bypassing the generic directory layer.
> */
> diff --git a/libxfs/xfs_dir2.c b/libxfs/xfs_dir2.c
> index 96a3c1d..4c8c836 100644
> --- a/libxfs/xfs_dir2.c
> +++ b/libxfs/xfs_dir2.c
> @@ -20,6 +20,22 @@
>
> struct xfs_name xfs_name_dotdot = { (unsigned char *)"..", 2, XFS_DIR3_FT_DIR };
>
> +/*
> + * @mode, if set, indicates that the type field needs to be set up.
> + * This uses the transformation from file mode to DT_* as defined in linux/fs.h
> + * for file type specification. This will be propagated into the directory
> + * structure if appropriate for the given operation and filesystem config.
> + */
> +const unsigned char xfs_mode_to_ftype[S_IFMT >> S_SHIFT] = {
> + [0] = XFS_DIR3_FT_UNKNOWN,
> + [S_IFREG >> S_SHIFT] = XFS_DIR3_FT_REG_FILE,
> + [S_IFDIR >> S_SHIFT] = XFS_DIR3_FT_DIR,
> + [S_IFCHR >> S_SHIFT] = XFS_DIR3_FT_CHRDEV,
> + [S_IFBLK >> S_SHIFT] = XFS_DIR3_FT_BLKDEV,
> + [S_IFIFO >> S_SHIFT] = XFS_DIR3_FT_FIFO,
> + [S_IFSOCK >> S_SHIFT] = XFS_DIR3_FT_SOCK,
> + [S_IFLNK >> S_SHIFT] = XFS_DIR3_FT_SYMLINK,
> +};
>
> /*
> * ASCII case-insensitive (ie. A-Z) support for directories that was
> diff --git a/repair/dino_chunks.c b/repair/dino_chunks.c
> index d3c2236..65281e4 100644
> --- a/repair/dino_chunks.c
> +++ b/repair/dino_chunks.c
> @@ -788,6 +788,8 @@ process_inode_chunk(
> * we do now, this is where to start.
> */
> if (is_used) {
> + __uint16_t di_mode;
> +
> if (is_inode_free(ino_rec, irec_offset)) {
> if (verbose || no_modify) {
> do_warn(
> @@ -803,6 +805,15 @@ process_inode_chunk(
> set_inode_used(ino_rec, irec_offset);
>
> /*
> + * store the on-disk file type for comparing in
> + * phase 6.
> + */
> + di_mode = be16_to_cpu(dino->di_mode);
> + di_mode = (di_mode & S_IFMT) >> S_SHIFT;
> + set_inode_ftype(ino_rec, irec_offset,
> + xfs_mode_to_ftype[di_mode]);
> +
> + /*
> * store on-disk nlink count for comparing in phase 7
> */
> set_inode_disk_nlinks(ino_rec, irec_offset,
> diff --git a/repair/incore.h b/repair/incore.h
> index 38caa6d..5419884 100644
> --- a/repair/incore.h
> +++ b/repair/incore.h
> @@ -293,6 +293,7 @@ typedef struct ino_tree_node {
> ino_ex_data_t *ex_data; /* phases 6,7 */
> parent_list_t *plist; /* phases 2-5 */
> } ino_un;
> + __uint8_t *ftypes; /* phases 3,6 */
> } ino_tree_node_t;
>
> #define INOS_PER_IREC (sizeof(__uint64_t) * NBBY)
> @@ -359,7 +360,8 @@ ino_tree_node_t *find_uncertain_inode_rec(xfs_agnumber_t agno,
> xfs_agino_t ino);
> void add_inode_uncertain(xfs_mount_t *mp,
> xfs_ino_t ino, int free);
> -void add_aginode_uncertain(xfs_agnumber_t agno,
> +void add_aginode_uncertain(struct xfs_mount *mp,
> + xfs_agnumber_t agno,
> xfs_agino_t agino, int free);
> void get_uncertain_inode_rec(struct xfs_mount *mp,
> xfs_agnumber_t agno,
> @@ -476,6 +478,29 @@ static inline void add_inode_reached(struct ino_tree_node *irec, int offset)
> }
>
> /*
> + * get/set inode filetype. Only used if the superblock feature bit is set
> + * which allocates irec->ftypes.
> + */
> +static inline void
> +set_inode_ftype(struct ino_tree_node *irec,
> + int ino_offset,
> + __uint8_t ftype)
> +{
> + if (irec->ftypes)
> + irec->ftypes[ino_offset] = ftype;
> +}
> +
> +static inline __uint8_t
> +get_inode_ftype(
> + struct ino_tree_node *irec,
> + int ino_offset)
> +{
> + if (!irec->ftypes)
> + return XFS_DIR3_FT_UNKNOWN;
> + return irec->ftypes[ino_offset];
> +}
> +
> +/*
> * set/get inode number of parent -- works for directory inodes only
> */
> void set_inode_parent(ino_tree_node_t *irec, int ino_offset,
> diff --git a/repair/incore_ino.c b/repair/incore_ino.c
> index 735737a..9502648 100644
> --- a/repair/incore_ino.c
> +++ b/repair/incore_ino.c
> @@ -211,6 +211,21 @@ __uint32_t get_inode_disk_nlinks(struct ino_tree_node *irec, int ino_offset)
> return 0;
> }
>
> +static __uint8_t *
> +alloc_ftypes_array(
> + struct xfs_mount *mp)
> +{
> + __uint8_t *ptr;
> +
> + if (!xfs_sb_version_hasftype(&mp->m_sb))
> + return NULL;
> +
> + ptr = calloc(XFS_INODES_PER_CHUNK, sizeof(*ptr));
> + if (!ptr)
> + do_error(_("could not allocate ftypes array\n"));
> + return ptr;
> +}
> +
> /*
> * Next is the uncertain inode list -- a sorted (in ascending order)
> * list of inode records sorted on the starting inode number. There
> @@ -226,6 +241,7 @@ __uint32_t get_inode_disk_nlinks(struct ino_tree_node *irec, int ino_offset)
> */
> static struct ino_tree_node *
> alloc_ino_node(
> + struct xfs_mount *mp,
> xfs_agino_t starting_ino)
> {
> struct ino_tree_node *irec;
> @@ -245,6 +261,7 @@ alloc_ino_node(
> irec->ino_un.ex_data = NULL;
> irec->nlink_size = sizeof(__uint8_t);
> irec->disk_nlinks.un8 = alloc_nlink_array(irec->nlink_size);
> + irec->ftypes = alloc_ftypes_array(mp);
> return irec;
> }
>
> @@ -285,6 +302,7 @@ free_ino_tree_node(
>
> }
>
> + free(irec->ftypes);
> free(irec);
> }
>
> @@ -303,7 +321,11 @@ static ino_tree_node_t **last_rec;
> * free is set to 1 if the inode is thought to be free, 0 if used
> */
> void
> -add_aginode_uncertain(xfs_agnumber_t agno, xfs_agino_t ino, int free)
> +add_aginode_uncertain(
> + struct xfs_mount *mp,
> + xfs_agnumber_t agno,
> + xfs_agino_t ino,
> + int free)
> {
> ino_tree_node_t *ino_rec;
> xfs_agino_t s_ino;
> @@ -334,7 +356,7 @@ add_aginode_uncertain(xfs_agnumber_t agno, xfs_agino_t ino, int free)
> ino_rec = (ino_tree_node_t *)
> avl_findrange(inode_uncertain_tree_ptrs[agno], s_ino);
> if (!ino_rec) {
> - ino_rec = alloc_ino_node(s_ino);
> + ino_rec = alloc_ino_node(mp, s_ino);
>
> if (!avl_insert(inode_uncertain_tree_ptrs[agno],
> &ino_rec->avl_node))
> @@ -360,7 +382,7 @@ add_aginode_uncertain(xfs_agnumber_t agno, xfs_agino_t ino, int free)
> void
> add_inode_uncertain(xfs_mount_t *mp, xfs_ino_t ino, int free)
> {
> - add_aginode_uncertain(XFS_INO_TO_AGNO(mp, ino),
> + add_aginode_uncertain(mp, XFS_INO_TO_AGNO(mp, ino),
> XFS_INO_TO_AGINO(mp, ino), free);
> }
>
> @@ -432,7 +454,7 @@ add_inode(
> {
> struct ino_tree_node *irec;
>
> - irec = alloc_ino_node(agino);
> + irec = alloc_ino_node(mp, agino);
> if (!avl_insert(inode_tree_ptrs[agno], &irec->avl_node))
> do_warn(_("add_inode - duplicate inode range\n"));
> return irec;
> diff --git a/repair/phase6.c b/repair/phase6.c
> index d2d4a44..cdbf4db 100644
> --- a/repair/phase6.c
> +++ b/repair/phase6.c
> @@ -134,7 +134,8 @@ dir_hash_add(
> __uint32_t addr,
> xfs_ino_t inum,
> int namelen,
> - unsigned char *name)
> + unsigned char *name,
> + __uint8_t ftype)
> {
> xfs_dahash_t hash = 0;
> int byaddr;
> @@ -148,6 +149,7 @@ dir_hash_add(
>
> xname.name = name;
> xname.len = namelen;
> + xname.type = ftype;
>
> junk = name[0] == '/';
> byaddr = DIR_HASH_FUNC(hashtab, addr);
> @@ -312,6 +314,23 @@ dir_hash_see(
> return DIR_HASH_CK_NODATA;
> }
>
> +static void
> +dir_hash_update_ftype(
> + dir_hash_tab_t *hashtab,
> + xfs_dir2_dataptr_t addr,
> + __uint8_t ftype)
> +{
> + int i;
> + dir_hash_ent_t *p;
> +
> + i = DIR_HASH_FUNC(hashtab, addr);
> + for (p = hashtab->byaddr[i]; p; p = p->nextbyaddr) {
> + if (p->address != addr)
> + continue;
> + p->name.type = ftype;
> + }
> +}
> +
> /*
> * checks to make sure leafs match a data entry, and that the stale
> * count is valid.
> @@ -1685,11 +1704,12 @@ longform_dir2_entry_check_data(
> if (!orphanage_ino)
> orphanage_ino = inum;
> }
> +
> /*
> * check for duplicate names in directory.
> */
> if (!dir_hash_add(mp, hashtab, addr, inum, dep->namelen,
> - dep->name)) {
> + dep->name, xfs_dir3_dirent_get_ftype(mp, dep))) {
> nbad++;
> if (entry_junked(
> _("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is a duplicate name"),
> @@ -1763,6 +1783,35 @@ longform_dir2_entry_check_data(
> */
> if (no_modify && verify_inum(mp, inum))
> continue;
> +
> + /* validate ftype field if supported */
> + if (xfs_sb_version_hasftype(&mp->m_sb)) {
> + __uint8_t dir_ftype;
> + __uint8_t ino_ftype;
> +
> + dir_ftype = xfs_dir3_dirent_get_ftype(mp, dep);
> + ino_ftype = get_inode_ftype(irec, ino_offset);
> +
> + if (dir_ftype != ino_ftype) {
> + if (no_modify) {
> + do_warn(
> + _("would fix ftype mismatch (%d/%d) in directory/child inode %" PRIu64 "/%" PRIu64 "\n"),
> + dir_ftype, ino_ftype,
> + ip->i_ino, inum);
> + } else {
> + do_warn(
> + _("fixing ftype mismatch (%d/%d) in directory/child inode %" PRIu64 "/%" PRIu64 "\n"),
> + dir_ftype, ino_ftype,
> + ip->i_ino, inum);
> + xfs_dir3_dirent_put_ftype(mp, dep,
> + ino_ftype);
> + libxfs_dir2_data_log_entry(tp, bp, dep);
> + dir_hash_update_ftype(hashtab, addr,
> + ino_ftype);
> + }
> + }
> + }
> +
> /*
> * check easy case first, regular inode, just bump
> * the link count and continue
> @@ -2189,6 +2238,62 @@ out_fix:
> * shortform directory v2 processing routines -- entry verification and
> * bad entry deletion (pruning).
> */
> +static struct xfs_dir2_sf_entry *
> +shortform_dir2_junk(
> + struct xfs_mount *mp,
> + struct xfs_dir2_sf_hdr *sfp,
> + struct xfs_dir2_sf_entry *sfep,
> + xfs_ino_t lino,
> + int *max_size,
> + int *index,
> + int *bytes_deleted,
> + int *ino_dirty)
> +{
> + struct xfs_dir2_sf_entry *next_sfep;
> + int next_len;
> + int next_elen;
> +
> + if (lino == orphanage_ino)
> + orphanage_ino = 0;
> +
> + next_elen = xfs_dir3_sf_entsize(mp, sfp, sfep->namelen);
> + next_sfep = (xfs_dir2_sf_entry_t *)((__psint_t)sfep + next_elen);
> +
> + /*
> + * if we are just checking, simply return the pointer to the next entry
> + * here so that the checking loop can continue.
> + */
> + if (no_modify) {
> + do_warn(_("would junk entry\n"));
> + return next_sfep;
> + }
> +
> + /*
> + * now move all the remaining entries down over the junked entry and
> + * clear the newly unused bytes at the tail of the directory region.
> + */
> + next_len = *max_size - ((__psint_t)next_sfep - (__psint_t)sfp);
> + *max_size -= next_elen;
> + *bytes_deleted += next_elen;
> +
> + memmove(sfep, next_sfep, next_len);
> + memset((void *)((__psint_t)sfep + next_len), 0, next_elen);
> + sfp->count -= 1;
> + *ino_dirty = 1;
> +
> + /*
> + * WARNING: drop the index i by one so it matches the decremented count
> + * for accurate comparisons in the loop test
> + */
> + (*index)--;
> +
> + if (verbose)
> + do_warn(_("junking entry\n"));
> + else
> + do_warn("\n");
> + return sfep;
> +}
> +
> static void
> shortform_dir2_entry_check(xfs_mount_t *mp,
> xfs_ino_t ino,
> @@ -2201,15 +2306,13 @@ shortform_dir2_entry_check(xfs_mount_t *mp,
> xfs_ino_t lino;
> xfs_ino_t parent;
> struct xfs_dir2_sf_hdr *sfp;
> - xfs_dir2_sf_entry_t *sfep, *next_sfep, *tmp_sfep;
> - xfs_ifork_t *ifp;
> - ino_tree_node_t *irec;
> + struct xfs_dir2_sf_entry *sfep;
> + struct xfs_dir2_sf_entry *next_sfep;
> + struct xfs_ifork *ifp;
> + struct ino_tree_node *irec;
> int max_size;
> int ino_offset;
> int i;
> - int junkit;
> - int tmp_len;
> - int tmp_elen;
> int bad_sfnamelen;
> int namelen;
> int bytes_deleted;
> @@ -2266,9 +2369,7 @@ shortform_dir2_entry_check(xfs_mount_t *mp,
> for (i = 0; i < sfp->count && max_size >
> (__psint_t)next_sfep - (__psint_t)sfp;
> sfep = next_sfep, i++) {
> - junkit = 0;
> bad_sfnamelen = 0;
> - tmp_sfep = NULL;
>
> lino = xfs_dir3_sfe_get_ino(mp, sfp, sfep);
>
> @@ -2340,7 +2441,10 @@ shortform_dir2_entry_check(xfs_mount_t *mp,
> do_warn(
> _("entry \"%s\" in shortform directory %" PRIu64 " references non-existent inode %" PRIu64 "\n"),
> fname, ino, lino);
> - goto do_junkit;
> + next_sfep = shortform_dir2_junk(mp, sfp, sfep, lino,
> + &max_size, &i, &bytes_deleted,
> + ino_dirty);
> + continue;
> }
>
> ino_offset = XFS_INO_TO_AGINO(mp, lino) - irec->ino_startnum;
> @@ -2354,7 +2458,10 @@ shortform_dir2_entry_check(xfs_mount_t *mp,
> do_warn(
> _("entry \"%s\" in shortform directory inode %" PRIu64 " points to free inode %" PRIu64 "\n"),
> fname, ino, lino);
> - goto do_junkit;
> + next_sfep = shortform_dir2_junk(mp, sfp, sfep, lino,
> + &max_size, &i, &bytes_deleted,
> + ino_dirty);
> + continue;
> }
> /*
> * check if this inode is lost+found dir in the root
> @@ -2367,7 +2474,10 @@ shortform_dir2_entry_check(xfs_mount_t *mp,
> do_warn(
> _("%s (ino %" PRIu64 ") in root (%" PRIu64 ") is not a directory"),
> ORPHANAGE, lino, ino);
> - goto do_junkit;
> + next_sfep = shortform_dir2_junk(mp, sfp, sfep,
> + lino, &max_size, &i,
> + &bytes_deleted, ino_dirty);
> + continue;
> }
> /*
> * if this is a dup, it will be picked up below,
> @@ -2381,11 +2491,15 @@ shortform_dir2_entry_check(xfs_mount_t *mp,
> */
> if (!dir_hash_add(mp, hashtab, (xfs_dir2_dataptr_t)
> (sfep - xfs_dir2_sf_firstentry(sfp)),
> - lino, sfep->namelen, sfep->name)) {
> + lino, sfep->namelen, sfep->name,
> + xfs_dir3_sfe_get_ftype(mp, sfp, sfep))) {
> do_warn(
> _("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is a duplicate name"),
> fname, lino, ino);
> - goto do_junkit;
> + next_sfep = shortform_dir2_junk(mp, sfp, sfep, lino,
> + &max_size, &i, &bytes_deleted,
> + ino_dirty);
> + continue;
> }
>
> if (!inode_isadir(irec, ino_offset)) {
> @@ -2403,11 +2517,14 @@ _("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is a duplicate name"),
> * the .. in the child, blow out the entry
> */
> if (is_inode_reached(irec, ino_offset)) {
> - junkit = 1;
> do_warn(
> _("entry \"%s\" in directory inode %" PRIu64
> " references already connected inode %" PRIu64 ".\n"),
> fname, ino, lino);
> + next_sfep = shortform_dir2_junk(mp, sfp, sfep,
> + lino, &max_size, &i,
> + &bytes_deleted, ino_dirty);
> + continue;
> } else if (parent == ino) {
> add_inode_reached(irec, ino_offset);
> add_inode_ref(current_irec, current_ino_offset);
> @@ -2423,76 +2540,60 @@ _("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is a duplicate name"),
> add_dotdot_update(XFS_INO_TO_AGNO(mp, lino),
> irec, ino_offset);
> } else {
> - junkit = 1;
> do_warn(
> _("entry \"%s\" in directory inode %" PRIu64
> " not consistent with .. value (%" PRIu64
> ") in inode %" PRIu64 ",\n"),
> fname, ino, parent, lino);
> + next_sfep = shortform_dir2_junk(mp, sfp, sfep,
> + lino, &max_size, &i,
> + &bytes_deleted, ino_dirty);
> + continue;
> }
> }
>
> - if (junkit) {
> -do_junkit:
> - if (lino == orphanage_ino)
> - orphanage_ino = 0;
> - if (!no_modify) {
> - tmp_elen = xfs_dir3_sf_entsize(mp, sfp,
> - sfep->namelen);
> - tmp_sfep = (xfs_dir2_sf_entry_t *)
> - ((__psint_t) sfep + tmp_elen);
> - tmp_len = max_size - ((__psint_t) tmp_sfep
> - - (__psint_t) sfp);
> - max_size -= tmp_elen;
> - bytes_deleted += tmp_elen;
> -
> - memmove(sfep, tmp_sfep, tmp_len);
> -
> - sfp->count -= 1;
> - memset((void *)((__psint_t)sfep + tmp_len), 0,
> - tmp_elen);
> -
> - /*
> - * set the tmp value to the current
> - * pointer so we'll process the entry
> - * we just moved up
> - */
> - tmp_sfep = sfep;
> -
> - /*
> - * WARNING: drop the index i by one
> - * so it matches the decremented count for
> - * accurate comparisons in the loop test
> - */
> - i--;
> + /* validate ftype field if supported */
> + if (xfs_sb_version_hasftype(&mp->m_sb)) {
> + __uint8_t dir_ftype;
> + __uint8_t ino_ftype;
>
> - *ino_dirty = 1;
> + dir_ftype = xfs_dir3_sfe_get_ftype(mp, sfp, sfep);
> + ino_ftype = get_inode_ftype(irec, ino_offset);
>
> - if (verbose)
> - do_warn(_("junking entry\n"));
> - else
> - do_warn("\n");
> - } else {
> - do_warn(_("would junk entry\n"));
> + if (dir_ftype != ino_ftype) {
> + if (no_modify) {
> + do_warn(
> + _("would fix ftype mismatch (%d/%d) in directory/child inode %" PRIu64 "/%" PRIu64 "\n"),
> + dir_ftype, ino_ftype,
> + ino, lino);
> + } else {
> + do_warn(
> + _("fixing ftype mismatch (%d/%d) in directory/child inode %" PRIu64 "/%" PRIu64 "\n"),
> + dir_ftype, ino_ftype,
> + ino, lino);
> + xfs_dir3_sfe_put_ftype(mp, sfp, sfep,
> + ino_ftype);
> + dir_hash_update_ftype(hashtab,
> + (xfs_dir2_dataptr_t)(sfep - xfs_dir2_sf_firstentry(sfp)),
> + ino_ftype);
> + *ino_dirty = 1;
> + }
> }
> - } else if (lino > XFS_DIR2_MAX_SHORT_INUM)
> + }
> +
> + if (lino > XFS_DIR2_MAX_SHORT_INUM)
> i8++;
>
> /*
> - * go onto next entry unless we've just junked an
> - * entry in which the current entry pointer points
> - * to an unprocessed entry. have to take into entries
> - * with bad namelen into account in no modify mode since we
> - * calculate size based on next_sfep.
> + * go onto next entry - we have to take entries with bad namelen
> + * into account in no modify mode since we calculate size based
> + * on next_sfep.
> */
> ASSERT(no_modify || bad_sfnamelen == 0);
> -
> - next_sfep = (tmp_sfep == NULL)
> - ? (xfs_dir2_sf_entry_t *) ((__psint_t) sfep
> - + ((!bad_sfnamelen)
> - ? xfs_dir3_sf_entsize(mp, sfp, sfep->namelen)
> - : xfs_dir3_sf_entsize(mp, sfp, namelen)))
> - : tmp_sfep;
> + next_sfep = (struct xfs_dir2_sf_entry *)((__psint_t)sfep +
> + (bad_sfnamelen
> + ? xfs_dir3_sf_entsize(mp, sfp, namelen)
> + : xfs_dir3_sf_entsize(mp, sfp, sfep->namelen)));
> }
>
> if (sfp->i8count != i8) {
> @@ -2501,6 +2602,8 @@ do_junkit:
> ino);
> } else {
> if (i8 == 0) {
> + struct xfs_dir2_sf_entry *tmp_sfep;
> +
> tmp_sfep = next_sfep;
> process_sf_dir2_fixi8(mp, sfp, &tmp_sfep);
> bytes_deleted +=
> @@ -2518,8 +2621,7 @@ do_junkit:
> /*
> * sync up sizes if required
> */
> - if (*ino_dirty) {
> - ASSERT(bytes_deleted > 0);
> + if (*ino_dirty && bytes_deleted > 0) {
> ASSERT(!no_modify);
> libxfs_idata_realloc(ip, -bytes_deleted, XFS_DATA_FORK);
> ip->i_d.di_size -= bytes_deleted;
> diff --git a/repair/scan.c b/repair/scan.c
> index 49ed194..73b4581 100644
> --- a/repair/scan.c
> +++ b/repair/scan.c
> @@ -866,9 +866,9 @@ _("inode rec for ino %" PRIu64 " (%d/%d) overlaps existing rec (start %d/%d)\n")
> for (j = 0; j < XFS_INODES_PER_CHUNK; j++) {
> if (XFS_INOBT_IS_FREE_DISK(rp, j)) {
> nfree++;
> - add_aginode_uncertain(agno, ino + j, 1);
> + add_aginode_uncertain(mp, agno, ino + j, 1);
> } else {
> - add_aginode_uncertain(agno, ino + j, 0);
> + add_aginode_uncertain(mp, agno, ino + j, 0);
> }
> }
> }
>
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
prev parent reply other threads:[~2014-01-24 23:38 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-01-24 22:38 [PATCH V4] xfs_repair: add support for validating dirent ftype field Dave Chinner
2014-01-24 23:38 ` Brian Foster [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=52E2F969.9050502@redhat.com \
--to=bfoster@redhat.com \
--cc=xfs@oss.sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).