Commit 8b06bc59 authored by Joel Becker's avatar Joel Becker Committed by Tao Ma

ocfs2: Grow discontig block groups in one transaction.

Rather than extending the transaction every time we add an extent to a
discontiguous block group, we grab enough credits to fill the extent
list up front.  This means we can free the bits in the same transaction
if we end up not getting enough space.
Signed-off-by: default avatarJoel Becker <joel.becker@oracle.com>
parent 2b6cb576
...@@ -561,6 +561,18 @@ static inline int ocfs2_calc_group_alloc_credits(struct super_block *sb, ...@@ -561,6 +561,18 @@ static inline int ocfs2_calc_group_alloc_credits(struct super_block *sb,
return blocks; return blocks;
} }
/*
* Allocating a discontiguous block group requires the credits from
* ocfs2_calc_group_alloc_credits() as well as enough credits to fill
* the group descriptor's extent list. The caller already has started
* the transaction with ocfs2_calc_group_alloc_credits(). They extend
* it with these credits.
*/
static inline int ocfs2_calc_bg_discontig_credits(struct super_block *sb)
{
return ocfs2_extent_recs_per_gd(sb);
}
static inline int ocfs2_calc_tree_trunc_credits(struct super_block *sb, static inline int ocfs2_calc_tree_trunc_credits(struct super_block *sb,
unsigned int clusters_to_del, unsigned int clusters_to_del,
struct ocfs2_dinode *fe, struct ocfs2_dinode *fe,
......
...@@ -523,12 +523,6 @@ static int ocfs2_block_group_grow_discontig(handle_t *handle, ...@@ -523,12 +523,6 @@ static int ocfs2_block_group_grow_discontig(handle_t *handle,
while ((needed > 0) && (le16_to_cpu(el->l_next_free_rec) < while ((needed > 0) && (le16_to_cpu(el->l_next_free_rec) <
le16_to_cpu(el->l_count))) { le16_to_cpu(el->l_count))) {
status = ocfs2_extend_trans(handle, OCFS2_SUBALLOC_ALLOC);
if (status) {
mlog_errno(status);
goto bail;
}
if (min_bits > needed) if (min_bits > needed)
min_bits = needed; min_bits = needed;
status = ocfs2_block_group_claim_bits(osb, handle, ac, status = ocfs2_block_group_claim_bits(osb, handle, ac,
...@@ -556,11 +550,12 @@ static int ocfs2_block_group_grow_discontig(handle_t *handle, ...@@ -556,11 +550,12 @@ static int ocfs2_block_group_grow_discontig(handle_t *handle,
return status; return status;
} }
static void ocfs2_bg_alloc_cleanup(struct inode *alloc_inode, static void ocfs2_bg_alloc_cleanup(handle_t *handle,
struct buffer_head *bg_bh, struct ocfs2_alloc_context *cluster_ac,
struct ocfs2_cached_dealloc_ctxt *dealloc) struct inode *alloc_inode,
struct buffer_head *bg_bh)
{ {
int i; int i, ret;
struct ocfs2_group_desc *bg; struct ocfs2_group_desc *bg;
struct ocfs2_extent_list *el; struct ocfs2_extent_list *el;
struct ocfs2_extent_rec *rec; struct ocfs2_extent_rec *rec;
...@@ -572,9 +567,13 @@ static void ocfs2_bg_alloc_cleanup(struct inode *alloc_inode, ...@@ -572,9 +567,13 @@ static void ocfs2_bg_alloc_cleanup(struct inode *alloc_inode,
el = &bg->bg_list; el = &bg->bg_list;
for (i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) { for (i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) {
rec = &el->l_recs[i]; rec = &el->l_recs[i];
ocfs2_cache_cluster_dealloc(dealloc, ret = ocfs2_free_clusters(handle, cluster_ac->ac_inode,
le64_to_cpu(rec->e_blkno), cluster_ac->ac_bh,
le32_to_cpu(rec->e_leaf_clusters)); le64_to_cpu(rec->e_blkno),
le32_to_cpu(rec->e_leaf_clusters));
if (ret)
mlog_errno(ret);
/* Try all the clusters to free */
} }
ocfs2_remove_from_cache(INODE_CACHE(alloc_inode), bg_bh); ocfs2_remove_from_cache(INODE_CACHE(alloc_inode), bg_bh);
...@@ -585,8 +584,7 @@ static struct buffer_head * ...@@ -585,8 +584,7 @@ static struct buffer_head *
ocfs2_block_group_alloc_discontig(handle_t *handle, ocfs2_block_group_alloc_discontig(handle_t *handle,
struct inode *alloc_inode, struct inode *alloc_inode,
struct ocfs2_alloc_context *ac, struct ocfs2_alloc_context *ac,
struct ocfs2_chain_list *cl, struct ocfs2_chain_list *cl)
struct ocfs2_cached_dealloc_ctxt *dealloc)
{ {
int status; int status;
u32 bit_off, num_bits; u32 bit_off, num_bits;
...@@ -601,6 +599,13 @@ ocfs2_block_group_alloc_discontig(handle_t *handle, ...@@ -601,6 +599,13 @@ ocfs2_block_group_alloc_discontig(handle_t *handle,
goto bail; goto bail;
} }
status = ocfs2_extend_trans(handle,
ocfs2_calc_bg_discontig_credits(osb->sb));
if (status) {
mlog_errno(status);
goto bail;
}
/* Claim the first region */ /* Claim the first region */
status = ocfs2_block_group_claim_bits(osb, handle, ac, min_bits, status = ocfs2_block_group_claim_bits(osb, handle, ac, min_bits,
&bit_off, &num_bits); &bit_off, &num_bits);
...@@ -638,7 +643,7 @@ ocfs2_block_group_alloc_discontig(handle_t *handle, ...@@ -638,7 +643,7 @@ ocfs2_block_group_alloc_discontig(handle_t *handle,
bail: bail:
if (status) if (status)
ocfs2_bg_alloc_cleanup(alloc_inode, bg_bh, dealloc); ocfs2_bg_alloc_cleanup(handle, ac, alloc_inode, bg_bh);
return status ? ERR_PTR(status) : bg_bh; return status ? ERR_PTR(status) : bg_bh;
} }
...@@ -660,14 +665,11 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb, ...@@ -660,14 +665,11 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
u64 bg_blkno; u64 bg_blkno;
struct buffer_head *bg_bh = NULL; struct buffer_head *bg_bh = NULL;
struct ocfs2_group_desc *bg; struct ocfs2_group_desc *bg;
struct ocfs2_cached_dealloc_ctxt dealloc;
BUG_ON(ocfs2_is_cluster_bitmap(alloc_inode)); BUG_ON(ocfs2_is_cluster_bitmap(alloc_inode));
mlog_entry_void(); mlog_entry_void();
ocfs2_init_dealloc_ctxt(&dealloc);
cl = &fe->id2.i_chain; cl = &fe->id2.i_chain;
status = ocfs2_reserve_clusters_with_limit(osb, status = ocfs2_reserve_clusters_with_limit(osb,
le16_to_cpu(cl->cl_cpg), le16_to_cpu(cl->cl_cpg),
...@@ -699,8 +701,7 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb, ...@@ -699,8 +701,7 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
if (IS_ERR(bg_bh) && (PTR_ERR(bg_bh) == -ENOSPC)) if (IS_ERR(bg_bh) && (PTR_ERR(bg_bh) == -ENOSPC))
bg_bh = ocfs2_block_group_alloc_discontig(handle, bg_bh = ocfs2_block_group_alloc_discontig(handle,
alloc_inode, alloc_inode,
ac, cl, ac, cl);
&dealloc);
if (IS_ERR(bg_bh)) { if (IS_ERR(bg_bh)) {
status = PTR_ERR(bg_bh); status = PTR_ERR(bg_bh);
bg_bh = NULL; bg_bh = NULL;
...@@ -750,11 +751,6 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb, ...@@ -750,11 +751,6 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
if (handle) if (handle)
ocfs2_commit_trans(osb, handle); ocfs2_commit_trans(osb, handle);
if (ocfs2_dealloc_has_cluster(&dealloc)) {
ocfs2_schedule_truncate_log_flush(osb, 1);
ocfs2_run_deallocs(osb, &dealloc);
}
if (ac) if (ac)
ocfs2_free_alloc_context(ac); ocfs2_free_alloc_context(ac);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment