Loading fs/xfs/libxfs/xfs_alloc.c +37 −5 Original line number Original line Diff line number Diff line Loading @@ -149,13 +149,27 @@ xfs_alloc_compute_aligned( { { xfs_agblock_t bno; xfs_agblock_t bno; xfs_extlen_t len; xfs_extlen_t len; xfs_extlen_t diff; /* Trim busy sections out of found extent */ /* Trim busy sections out of found extent */ xfs_extent_busy_trim(args, foundbno, foundlen, &bno, &len); xfs_extent_busy_trim(args, foundbno, foundlen, &bno, &len); /* * If we have a largish extent that happens to start before min_agbno, * see if we can shift it into range... */ if (bno < args->min_agbno && bno + len > args->min_agbno) { diff = args->min_agbno - bno; if (len > diff) { bno += diff; len -= diff; } } if (args->alignment > 1 && len >= args->minlen) { if (args->alignment > 1 && len >= args->minlen) { xfs_agblock_t aligned_bno = roundup(bno, args->alignment); xfs_agblock_t aligned_bno = roundup(bno, args->alignment); xfs_extlen_t diff = aligned_bno - bno; diff = aligned_bno - bno; *resbno = aligned_bno; *resbno = aligned_bno; *reslen = diff >= len ? 0 : len - diff; *reslen = diff >= len ? 0 : len - diff; Loading Loading @@ -795,9 +809,13 @@ xfs_alloc_find_best_extent( * The good extent is closer than this one. * The good extent is closer than this one. */ */ if (!dir) { if (!dir) { if (*sbnoa > args->max_agbno) goto out_use_good; if (*sbnoa >= args->agbno + gdiff) if (*sbnoa >= args->agbno + gdiff) goto out_use_good; goto out_use_good; } else { } else { if (*sbnoa < args->min_agbno) goto out_use_good; if (*sbnoa <= args->agbno - gdiff) if (*sbnoa <= args->agbno - gdiff) goto out_use_good; goto out_use_good; } } Loading Loading @@ -884,6 +902,17 @@ xfs_alloc_ag_vextent_near( dofirst = prandom_u32() & 1; dofirst = prandom_u32() & 1; #endif #endif /* handle unitialized agbno range so caller doesn't have to */ if (!args->min_agbno && !args->max_agbno) args->max_agbno = args->mp->m_sb.sb_agblocks - 1; ASSERT(args->min_agbno <= args->max_agbno); /* clamp agbno to the range if it's outside */ if (args->agbno < args->min_agbno) args->agbno = args->min_agbno; if (args->agbno > args->max_agbno) args->agbno = args->max_agbno; restart: restart: bno_cur_lt = NULL; bno_cur_lt = NULL; bno_cur_gt = NULL; bno_cur_gt = NULL; Loading Loading @@ -976,6 +1005,8 @@ xfs_alloc_ag_vextent_near( <bnoa, <lena); <bnoa, <lena); if (ltlena < args->minlen) if (ltlena < args->minlen) continue; continue; if (ltbnoa < args->min_agbno || ltbnoa > args->max_agbno) continue; args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); xfs_alloc_fix_len(args); xfs_alloc_fix_len(args); ASSERT(args->len >= args->minlen); ASSERT(args->len >= args->minlen); Loading Loading @@ -1096,11 +1127,11 @@ xfs_alloc_ag_vextent_near( XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); xfs_alloc_compute_aligned(args, ltbno, ltlen, xfs_alloc_compute_aligned(args, ltbno, ltlen, <bnoa, <lena); <bnoa, <lena); if (ltlena >= args->minlen) if (ltlena >= args->minlen && ltbnoa >= args->min_agbno) break; break; if ((error = xfs_btree_decrement(bno_cur_lt, 0, &i))) if ((error = xfs_btree_decrement(bno_cur_lt, 0, &i))) goto error0; goto error0; if (!i) { if (!i || ltbnoa < args->min_agbno) { xfs_btree_del_cursor(bno_cur_lt, xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_NOERROR); XFS_BTREE_NOERROR); bno_cur_lt = NULL; bno_cur_lt = NULL; Loading @@ -1112,11 +1143,11 @@ xfs_alloc_ag_vextent_near( XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); xfs_alloc_compute_aligned(args, gtbno, gtlen, xfs_alloc_compute_aligned(args, gtbno, gtlen, >bnoa, >lena); >bnoa, >lena); if (gtlena >= args->minlen) if (gtlena >= args->minlen && gtbnoa <= args->max_agbno) break; break; if ((error = xfs_btree_increment(bno_cur_gt, 0, &i))) if ((error = xfs_btree_increment(bno_cur_gt, 0, &i))) goto error0; goto error0; if (!i) { if (!i || gtbnoa > args->max_agbno) { xfs_btree_del_cursor(bno_cur_gt, xfs_btree_del_cursor(bno_cur_gt, XFS_BTREE_NOERROR); XFS_BTREE_NOERROR); bno_cur_gt = NULL; bno_cur_gt = NULL; Loading Loading @@ -1216,6 +1247,7 @@ xfs_alloc_ag_vextent_near( ASSERT(ltnew >= ltbno); ASSERT(ltnew >= ltbno); ASSERT(ltnew + rlen <= ltbnoa + ltlena); ASSERT(ltnew + rlen <= ltbnoa + ltlena); ASSERT(ltnew + rlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); ASSERT(ltnew + rlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); ASSERT(ltnew >= args->min_agbno && ltnew <= args->max_agbno); args->agbno = ltnew; args->agbno = ltnew; if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur_lt, ltbno, ltlen, if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur_lt, ltbno, ltlen, Loading fs/xfs/libxfs/xfs_alloc.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -112,6 +112,8 @@ typedef struct xfs_alloc_arg { xfs_extlen_t total; /* total blocks needed in xaction */ xfs_extlen_t total; /* total blocks needed in xaction */ xfs_extlen_t alignment; /* align answer to multiple of this */ xfs_extlen_t alignment; /* align answer to multiple of this */ xfs_extlen_t minalignslop; /* slop for minlen+alignment calcs */ xfs_extlen_t minalignslop; /* slop for minlen+alignment calcs */ xfs_agblock_t min_agbno; /* set an agbno range for NEAR allocs */ xfs_agblock_t max_agbno; /* ... */ xfs_extlen_t len; /* output: actual size of extent */ xfs_extlen_t len; /* output: actual size of extent */ xfs_alloctype_t type; /* allocation type XFS_ALLOCTYPE_... */ xfs_alloctype_t type; /* allocation type XFS_ALLOCTYPE_... */ xfs_alloctype_t otype; /* original allocation type */ xfs_alloctype_t otype; /* original allocation type */ Loading fs/xfs/libxfs/xfs_format.h +42 −6 Original line number Original line Diff line number Diff line Loading @@ -170,7 +170,7 @@ typedef struct xfs_sb { __uint32_t sb_features_log_incompat; __uint32_t sb_features_log_incompat; __uint32_t sb_crc; /* superblock crc */ __uint32_t sb_crc; /* superblock crc */ __uint32_t sb_pad; xfs_extlen_t sb_spino_align; /* sparse inode chunk alignment */ xfs_ino_t sb_pquotino; /* project quota inode */ xfs_ino_t sb_pquotino; /* project quota inode */ xfs_lsn_t sb_lsn; /* last write sequence */ xfs_lsn_t sb_lsn; /* last write sequence */ Loading Loading @@ -256,7 +256,7 @@ typedef struct xfs_dsb { __be32 sb_features_log_incompat; __be32 sb_features_log_incompat; __le32 sb_crc; /* superblock crc */ __le32 sb_crc; /* superblock crc */ __be32 sb_pad; __be32 sb_spino_align; /* sparse inode chunk alignment */ __be64 sb_pquotino; /* project quota inode */ __be64 sb_pquotino; /* project quota inode */ __be64 sb_lsn; /* last write sequence */ __be64 sb_lsn; /* last write sequence */ Loading Loading @@ -457,8 +457,10 @@ xfs_sb_has_ro_compat_feature( } } #define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */ #define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */ #define XFS_SB_FEAT_INCOMPAT_SPINODES (1 << 1) /* sparse inode chunks */ #define XFS_SB_FEAT_INCOMPAT_ALL \ #define XFS_SB_FEAT_INCOMPAT_ALL \ (XFS_SB_FEAT_INCOMPAT_FTYPE) (XFS_SB_FEAT_INCOMPAT_FTYPE| \ XFS_SB_FEAT_INCOMPAT_SPINODES) #define XFS_SB_FEAT_INCOMPAT_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_ALL #define XFS_SB_FEAT_INCOMPAT_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_ALL static inline bool static inline bool Loading Loading @@ -506,6 +508,12 @@ static inline int xfs_sb_version_hasfinobt(xfs_sb_t *sbp) (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_FINOBT); (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_FINOBT); } } static inline bool xfs_sb_version_hassparseinodes(struct xfs_sb *sbp) { return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 && xfs_sb_has_incompat_feature(sbp, XFS_SB_FEAT_INCOMPAT_SPINODES); } /* /* * end of superblock version macros * end of superblock version macros */ */ Loading Loading @@ -1216,26 +1224,54 @@ typedef __uint64_t xfs_inofree_t; #define XFS_INOBT_ALL_FREE ((xfs_inofree_t)-1) #define XFS_INOBT_ALL_FREE ((xfs_inofree_t)-1) #define XFS_INOBT_MASK(i) ((xfs_inofree_t)1 << (i)) #define XFS_INOBT_MASK(i) ((xfs_inofree_t)1 << (i)) #define XFS_INOBT_HOLEMASK_FULL 0 /* holemask for full chunk */ #define XFS_INOBT_HOLEMASK_BITS (NBBY * sizeof(__uint16_t)) #define XFS_INODES_PER_HOLEMASK_BIT \ (XFS_INODES_PER_CHUNK / (NBBY * sizeof(__uint16_t))) static inline xfs_inofree_t xfs_inobt_maskn(int i, int n) static inline xfs_inofree_t xfs_inobt_maskn(int i, int n) { { return ((n >= XFS_INODES_PER_CHUNK ? 0 : XFS_INOBT_MASK(n)) - 1) << i; return ((n >= XFS_INODES_PER_CHUNK ? 0 : XFS_INOBT_MASK(n)) - 1) << i; } } /* /* * Data record structure * The on-disk inode record structure has two formats. The original "full" * format uses a 4-byte freecount. The "sparse" format uses a 1-byte freecount * and replaces the 3 high-order freecount bytes wth the holemask and inode * count. * * The holemask of the sparse record format allows an inode chunk to have holes * that refer to blocks not owned by the inode record. This facilitates inode * allocation in the event of severe free space fragmentation. */ */ typedef struct xfs_inobt_rec { typedef struct xfs_inobt_rec { __be32 ir_startino; /* starting inode number */ __be32 ir_startino; /* starting inode number */ __be32 ir_freecount; /* count of free inodes (set bits) */ union { struct { __be32 ir_freecount; /* count of free inodes */ } f; struct { __be16 ir_holemask;/* hole mask for sparse chunks */ __u8 ir_count; /* total inode count */ __u8 ir_freecount; /* count of free inodes */ } sp; } ir_u; __be64 ir_free; /* free inode mask */ __be64 ir_free; /* free inode mask */ } xfs_inobt_rec_t; } xfs_inobt_rec_t; typedef struct xfs_inobt_rec_incore { typedef struct xfs_inobt_rec_incore { xfs_agino_t ir_startino; /* starting inode number */ xfs_agino_t ir_startino; /* starting inode number */ __int32_t ir_freecount; /* count of free inodes (set bits) */ __uint16_t ir_holemask; /* hole mask for sparse chunks */ __uint8_t ir_count; /* total inode count */ __uint8_t ir_freecount; /* count of free inodes (set bits) */ xfs_inofree_t ir_free; /* free inode mask */ xfs_inofree_t ir_free; /* free inode mask */ } xfs_inobt_rec_incore_t; } xfs_inobt_rec_incore_t; static inline bool xfs_inobt_issparse(uint16_t holemask) { /* non-zero holemask represents a sparse rec. */ return holemask; } /* /* * Key structure * Key structure Loading fs/xfs/libxfs/xfs_fs.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -239,6 +239,7 @@ typedef struct xfs_fsop_resblks { #define XFS_FSOP_GEOM_FLAGS_V5SB 0x8000 /* version 5 superblock */ #define XFS_FSOP_GEOM_FLAGS_V5SB 0x8000 /* version 5 superblock */ #define XFS_FSOP_GEOM_FLAGS_FTYPE 0x10000 /* inode directory types */ #define XFS_FSOP_GEOM_FLAGS_FTYPE 0x10000 /* inode directory types */ #define XFS_FSOP_GEOM_FLAGS_FINOBT 0x20000 /* free inode btree */ #define XFS_FSOP_GEOM_FLAGS_FINOBT 0x20000 /* free inode btree */ #define XFS_FSOP_GEOM_FLAGS_SPINODES 0x40000 /* sparse inode chunks */ /* /* * Minimum and maximum sizes need for growth checks. * Minimum and maximum sizes need for growth checks. Loading Loading
fs/xfs/libxfs/xfs_alloc.c +37 −5 Original line number Original line Diff line number Diff line Loading @@ -149,13 +149,27 @@ xfs_alloc_compute_aligned( { { xfs_agblock_t bno; xfs_agblock_t bno; xfs_extlen_t len; xfs_extlen_t len; xfs_extlen_t diff; /* Trim busy sections out of found extent */ /* Trim busy sections out of found extent */ xfs_extent_busy_trim(args, foundbno, foundlen, &bno, &len); xfs_extent_busy_trim(args, foundbno, foundlen, &bno, &len); /* * If we have a largish extent that happens to start before min_agbno, * see if we can shift it into range... */ if (bno < args->min_agbno && bno + len > args->min_agbno) { diff = args->min_agbno - bno; if (len > diff) { bno += diff; len -= diff; } } if (args->alignment > 1 && len >= args->minlen) { if (args->alignment > 1 && len >= args->minlen) { xfs_agblock_t aligned_bno = roundup(bno, args->alignment); xfs_agblock_t aligned_bno = roundup(bno, args->alignment); xfs_extlen_t diff = aligned_bno - bno; diff = aligned_bno - bno; *resbno = aligned_bno; *resbno = aligned_bno; *reslen = diff >= len ? 0 : len - diff; *reslen = diff >= len ? 0 : len - diff; Loading Loading @@ -795,9 +809,13 @@ xfs_alloc_find_best_extent( * The good extent is closer than this one. * The good extent is closer than this one. */ */ if (!dir) { if (!dir) { if (*sbnoa > args->max_agbno) goto out_use_good; if (*sbnoa >= args->agbno + gdiff) if (*sbnoa >= args->agbno + gdiff) goto out_use_good; goto out_use_good; } else { } else { if (*sbnoa < args->min_agbno) goto out_use_good; if (*sbnoa <= args->agbno - gdiff) if (*sbnoa <= args->agbno - gdiff) goto out_use_good; goto out_use_good; } } Loading Loading @@ -884,6 +902,17 @@ xfs_alloc_ag_vextent_near( dofirst = prandom_u32() & 1; dofirst = prandom_u32() & 1; #endif #endif /* handle unitialized agbno range so caller doesn't have to */ if (!args->min_agbno && !args->max_agbno) args->max_agbno = args->mp->m_sb.sb_agblocks - 1; ASSERT(args->min_agbno <= args->max_agbno); /* clamp agbno to the range if it's outside */ if (args->agbno < args->min_agbno) args->agbno = args->min_agbno; if (args->agbno > args->max_agbno) args->agbno = args->max_agbno; restart: restart: bno_cur_lt = NULL; bno_cur_lt = NULL; bno_cur_gt = NULL; bno_cur_gt = NULL; Loading Loading @@ -976,6 +1005,8 @@ xfs_alloc_ag_vextent_near( <bnoa, <lena); <bnoa, <lena); if (ltlena < args->minlen) if (ltlena < args->minlen) continue; continue; if (ltbnoa < args->min_agbno || ltbnoa > args->max_agbno) continue; args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); xfs_alloc_fix_len(args); xfs_alloc_fix_len(args); ASSERT(args->len >= args->minlen); ASSERT(args->len >= args->minlen); Loading Loading @@ -1096,11 +1127,11 @@ xfs_alloc_ag_vextent_near( XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); xfs_alloc_compute_aligned(args, ltbno, ltlen, xfs_alloc_compute_aligned(args, ltbno, ltlen, <bnoa, <lena); <bnoa, <lena); if (ltlena >= args->minlen) if (ltlena >= args->minlen && ltbnoa >= args->min_agbno) break; break; if ((error = xfs_btree_decrement(bno_cur_lt, 0, &i))) if ((error = xfs_btree_decrement(bno_cur_lt, 0, &i))) goto error0; goto error0; if (!i) { if (!i || ltbnoa < args->min_agbno) { xfs_btree_del_cursor(bno_cur_lt, xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_NOERROR); XFS_BTREE_NOERROR); bno_cur_lt = NULL; bno_cur_lt = NULL; Loading @@ -1112,11 +1143,11 @@ xfs_alloc_ag_vextent_near( XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); xfs_alloc_compute_aligned(args, gtbno, gtlen, xfs_alloc_compute_aligned(args, gtbno, gtlen, >bnoa, >lena); >bnoa, >lena); if (gtlena >= args->minlen) if (gtlena >= args->minlen && gtbnoa <= args->max_agbno) break; break; if ((error = xfs_btree_increment(bno_cur_gt, 0, &i))) if ((error = xfs_btree_increment(bno_cur_gt, 0, &i))) goto error0; goto error0; if (!i) { if (!i || gtbnoa > args->max_agbno) { xfs_btree_del_cursor(bno_cur_gt, xfs_btree_del_cursor(bno_cur_gt, XFS_BTREE_NOERROR); XFS_BTREE_NOERROR); bno_cur_gt = NULL; bno_cur_gt = NULL; Loading Loading @@ -1216,6 +1247,7 @@ xfs_alloc_ag_vextent_near( ASSERT(ltnew >= ltbno); ASSERT(ltnew >= ltbno); ASSERT(ltnew + rlen <= ltbnoa + ltlena); ASSERT(ltnew + rlen <= ltbnoa + ltlena); ASSERT(ltnew + rlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); ASSERT(ltnew + rlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); ASSERT(ltnew >= args->min_agbno && ltnew <= args->max_agbno); args->agbno = ltnew; args->agbno = ltnew; if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur_lt, ltbno, ltlen, if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur_lt, ltbno, ltlen, Loading
fs/xfs/libxfs/xfs_alloc.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -112,6 +112,8 @@ typedef struct xfs_alloc_arg { xfs_extlen_t total; /* total blocks needed in xaction */ xfs_extlen_t total; /* total blocks needed in xaction */ xfs_extlen_t alignment; /* align answer to multiple of this */ xfs_extlen_t alignment; /* align answer to multiple of this */ xfs_extlen_t minalignslop; /* slop for minlen+alignment calcs */ xfs_extlen_t minalignslop; /* slop for minlen+alignment calcs */ xfs_agblock_t min_agbno; /* set an agbno range for NEAR allocs */ xfs_agblock_t max_agbno; /* ... */ xfs_extlen_t len; /* output: actual size of extent */ xfs_extlen_t len; /* output: actual size of extent */ xfs_alloctype_t type; /* allocation type XFS_ALLOCTYPE_... */ xfs_alloctype_t type; /* allocation type XFS_ALLOCTYPE_... */ xfs_alloctype_t otype; /* original allocation type */ xfs_alloctype_t otype; /* original allocation type */ Loading
fs/xfs/libxfs/xfs_format.h +42 −6 Original line number Original line Diff line number Diff line Loading @@ -170,7 +170,7 @@ typedef struct xfs_sb { __uint32_t sb_features_log_incompat; __uint32_t sb_features_log_incompat; __uint32_t sb_crc; /* superblock crc */ __uint32_t sb_crc; /* superblock crc */ __uint32_t sb_pad; xfs_extlen_t sb_spino_align; /* sparse inode chunk alignment */ xfs_ino_t sb_pquotino; /* project quota inode */ xfs_ino_t sb_pquotino; /* project quota inode */ xfs_lsn_t sb_lsn; /* last write sequence */ xfs_lsn_t sb_lsn; /* last write sequence */ Loading Loading @@ -256,7 +256,7 @@ typedef struct xfs_dsb { __be32 sb_features_log_incompat; __be32 sb_features_log_incompat; __le32 sb_crc; /* superblock crc */ __le32 sb_crc; /* superblock crc */ __be32 sb_pad; __be32 sb_spino_align; /* sparse inode chunk alignment */ __be64 sb_pquotino; /* project quota inode */ __be64 sb_pquotino; /* project quota inode */ __be64 sb_lsn; /* last write sequence */ __be64 sb_lsn; /* last write sequence */ Loading Loading @@ -457,8 +457,10 @@ xfs_sb_has_ro_compat_feature( } } #define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */ #define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */ #define XFS_SB_FEAT_INCOMPAT_SPINODES (1 << 1) /* sparse inode chunks */ #define XFS_SB_FEAT_INCOMPAT_ALL \ #define XFS_SB_FEAT_INCOMPAT_ALL \ (XFS_SB_FEAT_INCOMPAT_FTYPE) (XFS_SB_FEAT_INCOMPAT_FTYPE| \ XFS_SB_FEAT_INCOMPAT_SPINODES) #define XFS_SB_FEAT_INCOMPAT_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_ALL #define XFS_SB_FEAT_INCOMPAT_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_ALL static inline bool static inline bool Loading Loading @@ -506,6 +508,12 @@ static inline int xfs_sb_version_hasfinobt(xfs_sb_t *sbp) (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_FINOBT); (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_FINOBT); } } static inline bool xfs_sb_version_hassparseinodes(struct xfs_sb *sbp) { return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 && xfs_sb_has_incompat_feature(sbp, XFS_SB_FEAT_INCOMPAT_SPINODES); } /* /* * end of superblock version macros * end of superblock version macros */ */ Loading Loading @@ -1216,26 +1224,54 @@ typedef __uint64_t xfs_inofree_t; #define XFS_INOBT_ALL_FREE ((xfs_inofree_t)-1) #define XFS_INOBT_ALL_FREE ((xfs_inofree_t)-1) #define XFS_INOBT_MASK(i) ((xfs_inofree_t)1 << (i)) #define XFS_INOBT_MASK(i) ((xfs_inofree_t)1 << (i)) #define XFS_INOBT_HOLEMASK_FULL 0 /* holemask for full chunk */ #define XFS_INOBT_HOLEMASK_BITS (NBBY * sizeof(__uint16_t)) #define XFS_INODES_PER_HOLEMASK_BIT \ (XFS_INODES_PER_CHUNK / (NBBY * sizeof(__uint16_t))) static inline xfs_inofree_t xfs_inobt_maskn(int i, int n) static inline xfs_inofree_t xfs_inobt_maskn(int i, int n) { { return ((n >= XFS_INODES_PER_CHUNK ? 0 : XFS_INOBT_MASK(n)) - 1) << i; return ((n >= XFS_INODES_PER_CHUNK ? 0 : XFS_INOBT_MASK(n)) - 1) << i; } } /* /* * Data record structure * The on-disk inode record structure has two formats. The original "full" * format uses a 4-byte freecount. The "sparse" format uses a 1-byte freecount * and replaces the 3 high-order freecount bytes wth the holemask and inode * count. * * The holemask of the sparse record format allows an inode chunk to have holes * that refer to blocks not owned by the inode record. This facilitates inode * allocation in the event of severe free space fragmentation. */ */ typedef struct xfs_inobt_rec { typedef struct xfs_inobt_rec { __be32 ir_startino; /* starting inode number */ __be32 ir_startino; /* starting inode number */ __be32 ir_freecount; /* count of free inodes (set bits) */ union { struct { __be32 ir_freecount; /* count of free inodes */ } f; struct { __be16 ir_holemask;/* hole mask for sparse chunks */ __u8 ir_count; /* total inode count */ __u8 ir_freecount; /* count of free inodes */ } sp; } ir_u; __be64 ir_free; /* free inode mask */ __be64 ir_free; /* free inode mask */ } xfs_inobt_rec_t; } xfs_inobt_rec_t; typedef struct xfs_inobt_rec_incore { typedef struct xfs_inobt_rec_incore { xfs_agino_t ir_startino; /* starting inode number */ xfs_agino_t ir_startino; /* starting inode number */ __int32_t ir_freecount; /* count of free inodes (set bits) */ __uint16_t ir_holemask; /* hole mask for sparse chunks */ __uint8_t ir_count; /* total inode count */ __uint8_t ir_freecount; /* count of free inodes (set bits) */ xfs_inofree_t ir_free; /* free inode mask */ xfs_inofree_t ir_free; /* free inode mask */ } xfs_inobt_rec_incore_t; } xfs_inobt_rec_incore_t; static inline bool xfs_inobt_issparse(uint16_t holemask) { /* non-zero holemask represents a sparse rec. */ return holemask; } /* /* * Key structure * Key structure Loading
fs/xfs/libxfs/xfs_fs.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -239,6 +239,7 @@ typedef struct xfs_fsop_resblks { #define XFS_FSOP_GEOM_FLAGS_V5SB 0x8000 /* version 5 superblock */ #define XFS_FSOP_GEOM_FLAGS_V5SB 0x8000 /* version 5 superblock */ #define XFS_FSOP_GEOM_FLAGS_FTYPE 0x10000 /* inode directory types */ #define XFS_FSOP_GEOM_FLAGS_FTYPE 0x10000 /* inode directory types */ #define XFS_FSOP_GEOM_FLAGS_FINOBT 0x20000 /* free inode btree */ #define XFS_FSOP_GEOM_FLAGS_FINOBT 0x20000 /* free inode btree */ #define XFS_FSOP_GEOM_FLAGS_SPINODES 0x40000 /* sparse inode chunks */ /* /* * Minimum and maximum sizes need for growth checks. * Minimum and maximum sizes need for growth checks. Loading