Skip to content

Commit

Permalink
Merge branch 'xfs-sparse-inode' into for-next
Browse files Browse the repository at this point in the history
  • Loading branch information
Dave Chinner committed Jun 1, 2015
2 parents e01c025 + 22ce1e1 commit b9a350a
Show file tree
Hide file tree
Showing 16 changed files with 829 additions and 86 deletions.
42 changes: 37 additions & 5 deletions fs/xfs/libxfs/xfs_alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,13 +149,27 @@ xfs_alloc_compute_aligned(
{
xfs_agblock_t bno;
xfs_extlen_t len;
xfs_extlen_t diff;

/* Trim busy sections out of found extent */
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) {
xfs_agblock_t aligned_bno = roundup(bno, args->alignment);
xfs_extlen_t diff = aligned_bno - bno;

diff = aligned_bno - bno;

*resbno = aligned_bno;
*reslen = diff >= len ? 0 : len - diff;
Expand Down Expand Up @@ -795,9 +809,13 @@ xfs_alloc_find_best_extent(
* The good extent is closer than this one.
*/
if (!dir) {
if (*sbnoa > args->max_agbno)
goto out_use_good;
if (*sbnoa >= args->agbno + gdiff)
goto out_use_good;
} else {
if (*sbnoa < args->min_agbno)
goto out_use_good;
if (*sbnoa <= args->agbno - gdiff)
goto out_use_good;
}
Expand Down Expand Up @@ -884,6 +902,17 @@ xfs_alloc_ag_vextent_near(
dofirst = prandom_u32() & 1;
#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:
bno_cur_lt = NULL;
bno_cur_gt = NULL;
Expand Down Expand Up @@ -976,6 +1005,8 @@ xfs_alloc_ag_vextent_near(
&ltbnoa, &ltlena);
if (ltlena < args->minlen)
continue;
if (ltbnoa < args->min_agbno || ltbnoa > args->max_agbno)
continue;
args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen);
xfs_alloc_fix_len(args);
ASSERT(args->len >= args->minlen);
Expand Down Expand Up @@ -1096,11 +1127,11 @@ xfs_alloc_ag_vextent_near(
XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0);
xfs_alloc_compute_aligned(args, ltbno, ltlen,
&ltbnoa, &ltlena);
if (ltlena >= args->minlen)
if (ltlena >= args->minlen && ltbnoa >= args->min_agbno)
break;
if ((error = xfs_btree_decrement(bno_cur_lt, 0, &i)))
goto error0;
if (!i) {
if (!i || ltbnoa < args->min_agbno) {
xfs_btree_del_cursor(bno_cur_lt,
XFS_BTREE_NOERROR);
bno_cur_lt = NULL;
Expand All @@ -1112,11 +1143,11 @@ xfs_alloc_ag_vextent_near(
XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0);
xfs_alloc_compute_aligned(args, gtbno, gtlen,
&gtbnoa, &gtlena);
if (gtlena >= args->minlen)
if (gtlena >= args->minlen && gtbnoa <= args->max_agbno)
break;
if ((error = xfs_btree_increment(bno_cur_gt, 0, &i)))
goto error0;
if (!i) {
if (!i || gtbnoa > args->max_agbno) {
xfs_btree_del_cursor(bno_cur_gt,
XFS_BTREE_NOERROR);
bno_cur_gt = NULL;
Expand Down Expand Up @@ -1216,6 +1247,7 @@ xfs_alloc_ag_vextent_near(
ASSERT(ltnew >= ltbno);
ASSERT(ltnew + rlen <= ltbnoa + ltlena);
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;

if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur_lt, ltbno, ltlen,
Expand Down
2 changes: 2 additions & 0 deletions fs/xfs/libxfs/xfs_alloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ typedef struct xfs_alloc_arg {
xfs_extlen_t total; /* total blocks needed in xaction */
xfs_extlen_t alignment; /* align answer to multiple of this */
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_alloctype_t type; /* allocation type XFS_ALLOCTYPE_... */
xfs_alloctype_t otype; /* original allocation type */
Expand Down
48 changes: 42 additions & 6 deletions fs/xfs/libxfs/xfs_format.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ typedef struct xfs_sb {
__uint32_t sb_features_log_incompat;

__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_lsn_t sb_lsn; /* last write sequence */
Expand Down Expand Up @@ -256,7 +256,7 @@ typedef struct xfs_dsb {
__be32 sb_features_log_incompat;

__le32 sb_crc; /* superblock crc */
__be32 sb_pad;
__be32 sb_spino_align; /* sparse inode chunk alignment */

__be64 sb_pquotino; /* project quota inode */
__be64 sb_lsn; /* last write sequence */
Expand Down Expand Up @@ -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_SPINODES (1 << 1) /* sparse inode chunks */
#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
static inline bool
Expand Down Expand Up @@ -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);
}

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
*/
Expand Down Expand Up @@ -1216,26 +1224,54 @@ typedef __uint64_t xfs_inofree_t;
#define XFS_INOBT_ALL_FREE ((xfs_inofree_t)-1)
#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)
{
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 {
__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 */
} xfs_inobt_rec_t;

typedef struct xfs_inobt_rec_incore {
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_inobt_rec_incore_t;

static inline bool xfs_inobt_issparse(uint16_t holemask)
{
/* non-zero holemask represents a sparse rec. */
return holemask;
}

/*
* Key structure
Expand Down
1 change: 1 addition & 0 deletions fs/xfs/libxfs/xfs_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ typedef struct xfs_fsop_resblks {
#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_FINOBT 0x20000 /* free inode btree */
#define XFS_FSOP_GEOM_FLAGS_SPINODES 0x40000 /* sparse inode chunks */

/*
* Minimum and maximum sizes need for growth checks.
Expand Down
Loading

0 comments on commit b9a350a

Please sign in to comment.