diff --git a/fs/xfs/xfs_dir2_format.h b/fs/xfs/xfs_dir2_format.h index 7b986d334b33..a3b1bd841a80 100644 --- a/fs/xfs/xfs_dir2_format.h +++ b/fs/xfs/xfs_dir2_format.h @@ -227,16 +227,6 @@ xfs_dir2_sf_nextentry(struct xfs_dir2_sf_hdr *hdr, #define XFS_DIR2_DATA_FIRSTDB(mp) \ xfs_dir2_byte_to_db(mp, XFS_DIR2_DATA_OFFSET) -/* - * Offsets of . and .. in data space (always block 0) - */ -#define XFS_DIR2_DATA_DOT_OFFSET \ - ((xfs_dir2_data_aoff_t)sizeof(struct xfs_dir2_data_hdr)) -#define XFS_DIR2_DATA_DOTDOT_OFFSET \ - (XFS_DIR2_DATA_DOT_OFFSET + xfs_dir2_data_entsize(1)) -#define XFS_DIR2_DATA_FIRST_OFFSET \ - (XFS_DIR2_DATA_DOTDOT_OFFSET + xfs_dir2_data_entsize(2)) - /* * Describe a free area in the data block. * @@ -378,7 +368,20 @@ xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr) /* * Offsets of . and .. in data space (always block 0) + * + * The macros are used for shortform directories as they have no headers to read + * the magic number out of. Shortform directories need to know the size of the + * data block header because the sfe embeds the block offset of the entry into + * it so that it doesn't change when format conversion occurs. Bad Things Happen + * if we don't follow this rule. */ +#define XFS_DIR3_DATA_DOT_OFFSET(mp) \ + xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&(mp)->m_sb)) +#define XFS_DIR3_DATA_DOTDOT_OFFSET(mp) \ + (XFS_DIR3_DATA_DOT_OFFSET(mp) + xfs_dir2_data_entsize(1)) +#define XFS_DIR3_DATA_FIRST_OFFSET(mp) \ + (XFS_DIR3_DATA_DOTDOT_OFFSET(mp) + xfs_dir2_data_entsize(2)) + static inline xfs_dir2_data_aoff_t xfs_dir3_data_dot_offset(struct xfs_dir2_data_hdr *hdr) { diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c index b9756228e9c0..6157424dbf8f 100644 --- a/fs/xfs/xfs_dir2_sf.c +++ b/fs/xfs/xfs_dir2_sf.c @@ -535,7 +535,7 @@ xfs_dir2_sf_addname_hard( * to insert the new entry. * If it's going to end up at the end then oldsfep will point there. */ - for (offset = XFS_DIR2_DATA_FIRST_OFFSET, + for (offset = XFS_DIR3_DATA_FIRST_OFFSET(dp->i_mount), oldsfep = xfs_dir2_sf_firstentry(oldsfp), add_datasize = xfs_dir2_data_entsize(args->namelen), eof = (char *)oldsfep == &buf[old_isize]; @@ -617,7 +617,7 @@ xfs_dir2_sf_addname_pick( sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; size = xfs_dir2_data_entsize(args->namelen); - offset = XFS_DIR2_DATA_FIRST_OFFSET; + offset = XFS_DIR3_DATA_FIRST_OFFSET(mp); sfep = xfs_dir2_sf_firstentry(sfp); holefit = 0; /* @@ -688,7 +688,7 @@ xfs_dir2_sf_check( dp = args->dp; sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; - offset = XFS_DIR2_DATA_FIRST_OFFSET; + offset = XFS_DIR3_DATA_FIRST_OFFSET(dp->i_mount); ino = xfs_dir2_sf_get_parent_ino(sfp); i8count = ino > XFS_DIR2_MAX_SHORT_INUM; @@ -812,9 +812,9 @@ xfs_dir2_sf_getdents( * mp->m_dirdatablk. */ dot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, - XFS_DIR2_DATA_DOT_OFFSET); + XFS_DIR3_DATA_DOT_OFFSET(mp)); dotdot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, - XFS_DIR2_DATA_DOTDOT_OFFSET); + XFS_DIR3_DATA_DOTDOT_OFFSET(mp)); /* * Put . entry unless we're starting past it.