@@ -39,15 +39,14 @@ struct xfs_name xfs_name_dotdot = { (unsigned char *)"..", 2, XFS_DIR3_FT_DIR };
* 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,
+const unsigned char xfs_dtype_to_ftype[S_DT_MAX] = {
+ [S_DT(S_IFREG)] = XFS_DIR3_FT_REG_FILE,
+ [S_DT(S_IFDIR)] = XFS_DIR3_FT_DIR,
+ [S_DT(S_IFCHR)] = XFS_DIR3_FT_CHRDEV,
+ [S_DT(S_IFBLK)] = XFS_DIR3_FT_BLKDEV,
+ [S_DT(S_IFIFO)] = XFS_DIR3_FT_FIFO,
+ [S_DT(S_IFSOCK)] = XFS_DIR3_FT_SOCK,
+ [S_DT(S_IFLNK)] = XFS_DIR3_FT_SYMLINK,
};
/*
@@ -35,7 +35,9 @@ extern struct xfs_name xfs_name_dotdot;
* directory filetype conversion tables.
*/
#define S_SHIFT 12
-extern const unsigned char xfs_mode_to_ftype[];
+#define S_DT(mode) (((mode) & S_IFMT) >> S_SHIFT)
+#define S_DT_MAX (S_DT(S_IFMT) + 1)
+extern const unsigned char xfs_dtype_to_ftype[];
/*
* directory operations vector for encode/decode routines
@@ -847,9 +847,8 @@ next_readbuf:
* 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]);
+ xfs_dtype_to_ftype[S_DT(di_mode)]);
/*
* store on-disk nlink count for comparing in phase 7
@@ -1082,7 +1082,7 @@ mv_orphanage(
if ((err = -libxfs_iget(mp, NULL, ino, 0, &ino_p)))
do_error(_("%d - couldn't iget disconnected inode\n"), err);
- xname.type = xfs_mode_to_ftype[(VFS_I(ino_p)->i_mode & S_IFMT)>>S_SHIFT];
+ xname.type = xfs_dtype_to_ftype[S_DT(VFS_I(ino_p)->i_mode)];
if (isa_dir) {
irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, orphanage_ino),
Fix the size of the xfs_mode_to_ftype conversion table, which was too small to handle a malformed on-disk value of mode=S_IFMT. Use a convenience macros S_DT(mode) to convert from mode to dirent file type and change the name of the table to xfs_dtype_to_ftype to correctly describe its index values. Signed-off-by: Amir Goldstein <amir73il@gmail.com> --- libxfs/xfs_dir2.c | 17 ++++++++--------- libxfs/xfs_dir2.h | 4 +++- repair/dino_chunks.c | 3 +-- repair/phase6.c | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) Darrick, This is the matcing patch to the kernel fix patch. I used S_DT(S_IF*) values in this patch instead of DT_* values to avoid complicating the build. Assuming you want the kernel libxfs to stay in sync with this code feel free to copy&paste the table chunk into the kernel patch I sent you or I can re-send the kernel patch if you like. Tested that xfs_repair detects and fixes wrong file type values. Amir.