From ec20cec7a351584ca6c70ead012e73d61f9a8e04 Mon Sep 17 00:00:00 2001 From: Joel Becker Date: Fri, 19 Mar 2010 14:13:52 -0700 Subject: ocfs2: Make ocfs2_journal_dirty() void. jbd[2]_journal_dirty_metadata() only returns 0. It's been returning 0 since before the kernel moved to git. There is no point in checking this error. ocfs2_journal_dirty() has been faithfully returning the status since the beginning. All over ocfs2, we have blocks of code checking this can't fail status. In the past few years, we've tried to avoid adding these checks, because they are pointless. But anyone who looks at our code assumes they are needed. Finally, ocfs2_journal_dirty() is made a void function. All error checking is removed from other files. We'll BUG_ON() the status of jbd2_journal_dirty_metadata() just in case they change it someday. They won't. Signed-off-by: Joel Becker --- fs/ocfs2/suballoc.c | 64 +++++++++-------------------------------------------- 1 file changed, 10 insertions(+), 54 deletions(-) (limited to 'fs/ocfs2/suballoc.c') diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 19ba00f28547..d4babfba4f04 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -369,9 +369,7 @@ static int ocfs2_block_group_fill(handle_t *handle, ocfs2_set_bit(0, (unsigned long *)bg->bg_bitmap); bg->bg_free_bits_count = cpu_to_le16(le16_to_cpu(bg->bg_bits) - 1); - status = ocfs2_journal_dirty(handle, bg_bh); - if (status < 0) - mlog_errno(status); + ocfs2_journal_dirty(handle, bg_bh); /* There is no need to zero out or otherwise initialize the * other blocks in a group - All valid FS metadata in a block @@ -506,11 +504,7 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb, le32_add_cpu(&fe->id1.bitmap1.i_total, le16_to_cpu(bg->bg_bits)); le32_add_cpu(&fe->i_clusters, le16_to_cpu(cl->cl_cpg)); - status = ocfs2_journal_dirty(handle, bh); - if (status < 0) { - mlog_errno(status); - goto bail; - } + ocfs2_journal_dirty(handle, bh); spin_lock(&OCFS2_I(alloc_inode)->ip_lock); OCFS2_I(alloc_inode)->ip_clusters = le32_to_cpu(fe->i_clusters); @@ -1129,16 +1123,10 @@ static inline int ocfs2_block_group_set_bits(handle_t *handle, } le16_add_cpu(&bg->bg_free_bits_count, -num_bits); - while(num_bits--) ocfs2_set_bit(bit_off++, bitmap); - status = ocfs2_journal_dirty(handle, - group_bh); - if (status < 0) { - mlog_errno(status); - goto bail; - } + ocfs2_journal_dirty(handle, group_bh); bail: mlog_exit(status); @@ -1202,12 +1190,7 @@ static int ocfs2_relink_block_group(handle_t *handle, } prev_bg->bg_next_group = bg->bg_next_group; - - status = ocfs2_journal_dirty(handle, prev_bg_bh); - if (status < 0) { - mlog_errno(status); - goto out_rollback; - } + ocfs2_journal_dirty(handle, prev_bg_bh); status = ocfs2_journal_access_gd(handle, INODE_CACHE(alloc_inode), bg_bh, OCFS2_JOURNAL_ACCESS_WRITE); @@ -1217,12 +1200,7 @@ static int ocfs2_relink_block_group(handle_t *handle, } bg->bg_next_group = fe->id2.i_chain.cl_recs[chain].c_blkno; - - status = ocfs2_journal_dirty(handle, bg_bh); - if (status < 0) { - mlog_errno(status); - goto out_rollback; - } + ocfs2_journal_dirty(handle, bg_bh); status = ocfs2_journal_access_di(handle, INODE_CACHE(alloc_inode), fe_bh, OCFS2_JOURNAL_ACCESS_WRITE); @@ -1232,14 +1210,8 @@ static int ocfs2_relink_block_group(handle_t *handle, } fe->id2.i_chain.cl_recs[chain].c_blkno = bg->bg_blkno; + ocfs2_journal_dirty(handle, fe_bh); - status = ocfs2_journal_dirty(handle, fe_bh); - if (status < 0) { - mlog_errno(status); - goto out_rollback; - } - - status = 0; out_rollback: if (status < 0) { fe->id2.i_chain.cl_recs[chain].c_blkno = cpu_to_le64(fe_ptr); @@ -1386,10 +1358,7 @@ static int ocfs2_alloc_dinode_update_counts(struct inode *inode, tmp_used = le32_to_cpu(di->id1.bitmap1.i_used); di->id1.bitmap1.i_used = cpu_to_le32(num_bits + tmp_used); le32_add_cpu(&cl->cl_recs[chain].c_free, -num_bits); - - ret = ocfs2_journal_dirty(handle, di_bh); - if (ret < 0) - mlog_errno(ret); + ocfs2_journal_dirty(handle, di_bh); out: return ret; @@ -1560,13 +1529,7 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, tmp_used = le32_to_cpu(fe->id1.bitmap1.i_used); fe->id1.bitmap1.i_used = cpu_to_le32(*num_bits + tmp_used); le32_add_cpu(&cl->cl_recs[chain].c_free, -(*num_bits)); - - status = ocfs2_journal_dirty(handle, - ac->ac_bh); - if (status < 0) { - mlog_errno(status); - goto bail; - } + ocfs2_journal_dirty(handle, ac->ac_bh); status = ocfs2_block_group_set_bits(handle, alloc_inode, @@ -2023,9 +1986,7 @@ static int ocfs2_block_group_clear_bits(handle_t *handle, if (undo_fn) jbd_unlock_bh_state(group_bh); - status = ocfs2_journal_dirty(handle, group_bh); - if (status < 0) - mlog_errno(status); + ocfs2_journal_dirty(handle, group_bh); bail: return status; } @@ -2092,12 +2053,7 @@ static int _ocfs2_free_suballoc_bits(handle_t *handle, count); tmp_used = le32_to_cpu(fe->id1.bitmap1.i_used); fe->id1.bitmap1.i_used = cpu_to_le32(tmp_used - count); - - status = ocfs2_journal_dirty(handle, alloc_bh); - if (status < 0) { - mlog_errno(status); - goto bail; - } + ocfs2_journal_dirty(handle, alloc_bh); bail: brelse(group_bh); -- cgit v1.2.2 From e3b4a97dbe9741a3227c3ed857a0632532fcd386 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Mon, 7 Dec 2009 13:16:07 -0800 Subject: ocfs2: use allocation reservations for directory data Use the reservations system for unindexed dir tree allocations. We don't bother with the indexed tree as reads from it are mostly random anyway. Directory reservations are marked seperately, to allow the reservations code a chance to optimize their window sizes. This patch allocates only 8 bits for directory windows as they generally are not expected to grow as quickly as file data. Future improvements to dir window sizing can trivially be made. Signed-off-by: Mark Fasheh --- fs/ocfs2/suballoc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs/ocfs2/suballoc.c') diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index d4babfba4f04..f20bcbf64ce0 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -130,6 +130,7 @@ void ocfs2_free_ac_resource(struct ocfs2_alloc_context *ac) } brelse(ac->ac_bh); ac->ac_bh = NULL; + ac->ac_resv = NULL; } void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac) -- cgit v1.2.2 From 33d5d380d667ad264675cfdb297dfc3c5b6542cc Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Wed, 24 Feb 2010 13:34:09 -0800 Subject: ocfs2: allocate btree internal block groups from the global bitmap Otherwise, the need for a very large contiguous allocation tends to wreak havoc on many inode allocation reservations on the local alloc, thus ruining any chances for contiguousness. Signed-off-by: Mark Fasheh --- fs/ocfs2/suballoc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'fs/ocfs2/suballoc.c') diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index f20bcbf64ce0..df95707c8b10 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -755,7 +755,7 @@ int ocfs2_reserve_new_metadata_blocks(struct ocfs2_super *osb, status = ocfs2_reserve_suballoc_bits(osb, (*ac), EXTENT_ALLOC_SYSTEM_INODE, (u32)osb->slot_num, NULL, - ALLOC_NEW_GROUP); + ALLOC_GROUPS_FROM_GLOBAL|ALLOC_NEW_GROUP); if (status >= 0) { @@ -1871,6 +1871,8 @@ int __ocfs2_claim_clusters(struct ocfs2_super *osb, && ac->ac_which != OCFS2_AC_USE_MAIN); if (ac->ac_which == OCFS2_AC_USE_LOCAL) { + WARN_ON(min_clusters > 1); + status = ocfs2_claim_local_alloc_bits(osb, handle, ac, -- cgit v1.2.2 From a57c8fd2ad238258cc983049008aea5f985804b2 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Tue, 16 Mar 2010 21:01:00 -0700 Subject: ocfs2: remove ocfs2_local_alloc_in_range() Inodes are always allocated from the global bitmap now so we don't need this any more. Also, the existing implementation bounces reservations around needlessly. Signed-off-by: Mark Fasheh --- fs/ocfs2/suballoc.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'fs/ocfs2/suballoc.c') diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index df95707c8b10..667d622b3659 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -941,11 +941,7 @@ static int ocfs2_reserve_clusters_with_limit(struct ocfs2_super *osb, status = ocfs2_reserve_local_alloc_bits(osb, bits_wanted, *ac); - if (status == -EFBIG) { - /* The local alloc window is outside ac_max_block. - * use the main bitmap. */ - status = -ENOSPC; - } else if ((status < 0) && (status != -ENOSPC)) { + if ((status < 0) && (status != -ENOSPC)) { mlog_errno(status); goto bail; } -- cgit v1.2.2 From 4cbe4249d6586d5d88ef271e07302407a14c8443 Mon Sep 17 00:00:00 2001 From: Joel Becker Date: Tue, 13 Apr 2010 14:26:12 +0800 Subject: ocfs2: Define data structures for discontiguous block groups. Defines the OCFS2_FEATURE_INCOMPAT_DISCONTIG_BG feature bit and modifies struct ocfs2_group_desc for the feature. Signed-off-by: Joel Becker Signed-off-by: Tao Ma --- fs/ocfs2/suballoc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/ocfs2/suballoc.c') diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 667d622b3659..1070f79fa068 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -360,7 +360,7 @@ static int ocfs2_block_group_fill(handle_t *handle, memset(bg, 0, sb->s_blocksize); strcpy(bg->bg_signature, OCFS2_GROUP_DESC_SIGNATURE); bg->bg_generation = cpu_to_le32(OCFS2_SB(sb)->fs_generation); - bg->bg_size = cpu_to_le16(ocfs2_group_bitmap_size(sb)); + bg->bg_size = cpu_to_le16(ocfs2_group_bitmap_size(sb, 1)); bg->bg_bits = cpu_to_le16(ocfs2_bits_per_group(cl)); bg->bg_chain = cpu_to_le16(my_chain); bg->bg_next_group = cl->cl_recs[my_chain].c_blkno; -- cgit v1.2.2 From 798db35f4649eac2778381c390ed7d12de9ec767 Mon Sep 17 00:00:00 2001 From: Joel Becker Date: Tue, 13 Apr 2010 14:26:32 +0800 Subject: ocfs2: Allocate discontiguous block groups. If we cannot get a contiguous region for a block group, allocate a discontiguous one when the filesystem supports it. Signed-off-by: Joel Becker Signed-off-by: Tao Ma --- fs/ocfs2/suballoc.c | 304 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 264 insertions(+), 40 deletions(-) (limited to 'fs/ocfs2/suballoc.c') diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 1070f79fa068..2f753954a7a8 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -60,6 +60,7 @@ static int ocfs2_block_group_fill(handle_t *handle, struct inode *alloc_inode, struct buffer_head *bg_bh, u64 group_blkno, + unsigned int group_clusters, u16 my_chain, struct ocfs2_chain_list *cl); static int ocfs2_block_group_alloc(struct ocfs2_super *osb, @@ -326,14 +327,36 @@ out: return rc; } +static void ocfs2_bg_discontig_add_extent(struct ocfs2_super *osb, + struct ocfs2_group_desc *bg, + struct ocfs2_chain_list *cl, + u64 p_blkno, u32 clusters) +{ + struct ocfs2_extent_list *el = &bg->bg_list; + struct ocfs2_extent_rec *rec; + + BUG_ON(!ocfs2_supports_discontig_bh(osb)); + if (!el->l_next_free_rec) + el->l_count = cpu_to_le16(ocfs2_extent_recs_per_gd(osb->sb)); + rec = &el->l_recs[le16_to_cpu(el->l_next_free_rec)]; + rec->e_blkno = p_blkno; + rec->e_cpos = cpu_to_le32(le16_to_cpu(bg->bg_bits) / + le16_to_cpu(cl->cl_bpc)); + rec->e_leaf_clusters = cpu_to_le32(clusters); + le16_add_cpu(&bg->bg_bits, clusters * le16_to_cpu(cl->cl_bpc)); + le16_add_cpu(&el->l_next_free_rec, 1); +} + static int ocfs2_block_group_fill(handle_t *handle, struct inode *alloc_inode, struct buffer_head *bg_bh, u64 group_blkno, + unsigned int group_clusters, u16 my_chain, struct ocfs2_chain_list *cl) { int status = 0; + struct ocfs2_super *osb = OCFS2_SB(alloc_inode->i_sb); struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data; struct super_block * sb = alloc_inode->i_sb; @@ -361,11 +384,16 @@ static int ocfs2_block_group_fill(handle_t *handle, strcpy(bg->bg_signature, OCFS2_GROUP_DESC_SIGNATURE); bg->bg_generation = cpu_to_le32(OCFS2_SB(sb)->fs_generation); bg->bg_size = cpu_to_le16(ocfs2_group_bitmap_size(sb, 1)); - bg->bg_bits = cpu_to_le16(ocfs2_bits_per_group(cl)); bg->bg_chain = cpu_to_le16(my_chain); bg->bg_next_group = cl->cl_recs[my_chain].c_blkno; bg->bg_parent_dinode = cpu_to_le64(OCFS2_I(alloc_inode)->ip_blkno); bg->bg_blkno = cpu_to_le64(group_blkno); + if (group_clusters == le16_to_cpu(cl->cl_cpg)) + bg->bg_bits = cpu_to_le16(ocfs2_bits_per_group(cl)); + else + ocfs2_bg_discontig_add_extent(osb, bg, cl, bg->bg_blkno, + group_clusters); + /* set the 1st bit in the bitmap to account for the descriptor block */ ocfs2_set_bit(0, (unsigned long *)bg->bg_bitmap); bg->bg_free_bits_count = cpu_to_le16(le16_to_cpu(bg->bg_bits) - 1); @@ -396,6 +424,218 @@ static inline u16 ocfs2_find_smallest_chain(struct ocfs2_chain_list *cl) return best; } +static struct buffer_head * +ocfs2_block_group_alloc_contig(struct ocfs2_super *osb, handle_t *handle, + struct inode *alloc_inode, + struct ocfs2_alloc_context *ac, + struct ocfs2_chain_list *cl) +{ + int status; + u32 bit_off, num_bits; + u64 bg_blkno; + struct buffer_head *bg_bh; + unsigned int alloc_rec = ocfs2_find_smallest_chain(cl); + + status = ocfs2_claim_clusters(osb, handle, ac, + le16_to_cpu(cl->cl_cpg), &bit_off, + &num_bits); + if (status < 0) { + if (status != -ENOSPC) + mlog_errno(status); + goto bail; + } + + /* setup the group */ + bg_blkno = ocfs2_clusters_to_blocks(osb->sb, bit_off); + mlog(0, "new descriptor, record %u, at block %llu\n", + alloc_rec, (unsigned long long)bg_blkno); + + bg_bh = sb_getblk(osb->sb, bg_blkno); + if (!bg_bh) { + status = -EIO; + mlog_errno(status); + goto bail; + } + ocfs2_set_new_buffer_uptodate(INODE_CACHE(alloc_inode), bg_bh); + + status = ocfs2_block_group_fill(handle, alloc_inode, bg_bh, + bg_blkno, num_bits, alloc_rec, cl); + if (status < 0) { + brelse(bg_bh); + mlog_errno(status); + } + +bail: + return status ? ERR_PTR(status) : bg_bh; +} + +static int ocfs2_block_group_claim_bits(struct ocfs2_super *osb, + handle_t *handle, + struct ocfs2_alloc_context *ac, + unsigned int min_bits, + u32 *bit_off, u32 *num_bits) +{ + int status; + + while (min_bits) { + status = ocfs2_claim_clusters(osb, handle, ac, min_bits, + bit_off, num_bits); + if (status != -ENOSPC) + break; + + min_bits >>= 1; + } + + return status; +} + +static int ocfs2_block_group_grow_discontig(handle_t *handle, + struct inode *alloc_inode, + struct buffer_head *bg_bh, + struct ocfs2_alloc_context *ac, + struct ocfs2_chain_list *cl, + unsigned int min_bits) +{ + int status; + struct ocfs2_super *osb = OCFS2_SB(alloc_inode->i_sb); + struct ocfs2_group_desc *bg = + (struct ocfs2_group_desc *)bg_bh->b_data; + unsigned int needed = + ocfs2_bits_per_group(cl) - le16_to_cpu(bg->bg_bits); + u32 p_cpos, clusters; + u64 p_blkno; + struct ocfs2_extent_list *el = &bg->bg_list; + + status = ocfs2_journal_access_gd(handle, + INODE_CACHE(alloc_inode), + bg_bh, + OCFS2_JOURNAL_ACCESS_CREATE); + if (status < 0) { + mlog_errno(status); + goto bail; + } + + while ((needed > 0) && (le16_to_cpu(el->l_next_free_rec) < + 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) + min_bits = needed; + status = ocfs2_block_group_claim_bits(osb, handle, ac, + min_bits, &p_cpos, + &clusters); + if (status < 0) { + if (status != -ENOSPC) + mlog_errno(status); + goto bail; + } + p_blkno = ocfs2_clusters_to_blocks(osb->sb, p_cpos); + ocfs2_bg_discontig_add_extent(osb, bg, cl, p_blkno, + clusters); + + min_bits = clusters; + needed = ocfs2_bits_per_group(cl) - le16_to_cpu(bg->bg_bits); + } + + if (needed > 0) { + } + + ocfs2_journal_dirty(handle, bg_bh); + +bail: + return status; +} + +static void ocfs2_bg_alloc_cleanup(struct inode *alloc_inode, + struct buffer_head *bg_bh, + struct ocfs2_cached_dealloc_ctxt *dealloc) +{ + int i; + struct ocfs2_group_desc *bg; + struct ocfs2_extent_list *el; + struct ocfs2_extent_rec *rec; + + if (!bg_bh) + return; + + bg = (struct ocfs2_group_desc *)bg_bh->b_data; + el = &bg->bg_list; + for (i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) { + rec = &el->l_recs[i]; + ocfs2_cache_cluster_dealloc(dealloc, + le64_to_cpu(rec->e_blkno), + le32_to_cpu(rec->e_leaf_clusters)); + } + + ocfs2_remove_from_cache(INODE_CACHE(alloc_inode), bg_bh); + brelse(bg_bh); +} + +static struct buffer_head * +ocfs2_block_group_alloc_discontig(handle_t *handle, + struct inode *alloc_inode, + struct ocfs2_alloc_context *ac, + struct ocfs2_chain_list *cl, + struct ocfs2_cached_dealloc_ctxt *dealloc) +{ + int status; + u32 bit_off, num_bits; + u64 bg_blkno; + unsigned int min_bits = le16_to_cpu(cl->cl_cpg) >> 1; + struct buffer_head *bg_bh = NULL; + unsigned int alloc_rec = ocfs2_find_smallest_chain(cl); + struct ocfs2_super *osb = OCFS2_SB(alloc_inode->i_sb); + + if (!ocfs2_supports_discontig_bh(osb)) { + status = -ENOSPC; + goto bail; + } + + /* Claim the first region */ + status = ocfs2_block_group_claim_bits(osb, handle, ac, min_bits, + &bit_off, &num_bits); + if (status < 0) { + if (status != -ENOSPC) + mlog_errno(status); + goto bail; + } + min_bits = num_bits; + + /* setup the group */ + bg_blkno = ocfs2_clusters_to_blocks(osb->sb, bit_off); + mlog(0, "new descriptor, record %u, at block %llu\n", + alloc_rec, (unsigned long long)bg_blkno); + + bg_bh = sb_getblk(osb->sb, bg_blkno); + if (!bg_bh) { + status = -EIO; + mlog_errno(status); + goto bail; + } + ocfs2_set_new_buffer_uptodate(INODE_CACHE(alloc_inode), bg_bh); + + status = ocfs2_block_group_fill(handle, alloc_inode, bg_bh, + bg_blkno, num_bits, alloc_rec, cl); + if (status < 0) { + mlog_errno(status); + goto bail; + } + + status = ocfs2_block_group_grow_discontig(handle, alloc_inode, + bg_bh, ac, cl, min_bits); + if (status) + mlog_errno(status); + +bail: + if (status) + ocfs2_bg_alloc_cleanup(alloc_inode, bg_bh, dealloc); + return status ? ERR_PTR(status) : bg_bh; +} + /* * We expect the block group allocator to already be locked. */ @@ -411,16 +651,17 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb, struct ocfs2_chain_list *cl; struct ocfs2_alloc_context *ac = NULL; handle_t *handle = NULL; - u32 bit_off, num_bits; - u16 alloc_rec; u64 bg_blkno; struct buffer_head *bg_bh = NULL; struct ocfs2_group_desc *bg; + struct ocfs2_cached_dealloc_ctxt dealloc; BUG_ON(ocfs2_is_cluster_bitmap(alloc_inode)); mlog_entry_void(); + ocfs2_init_dealloc_ctxt(&dealloc); + cl = &fe->id2.i_chain; status = ocfs2_reserve_clusters_with_limit(osb, le16_to_cpu(cl->cl_cpg), @@ -446,44 +687,21 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb, (unsigned long long)*last_alloc_group); ac->ac_last_group = *last_alloc_group; } - status = ocfs2_claim_clusters(osb, - handle, - ac, - le16_to_cpu(cl->cl_cpg), - &bit_off, - &num_bits); - if (status < 0) { + + bg_bh = ocfs2_block_group_alloc_contig(osb, handle, alloc_inode, + ac, cl); + if (IS_ERR(bg_bh) && (PTR_ERR(bg_bh) == -ENOSPC)) + bg_bh = ocfs2_block_group_alloc_discontig(handle, + alloc_inode, + ac, cl, + &dealloc); + if (IS_ERR(bg_bh)) { + status = PTR_ERR(bg_bh); + bg_bh = NULL; if (status != -ENOSPC) mlog_errno(status); goto bail; } - - alloc_rec = ocfs2_find_smallest_chain(cl); - - /* setup the group */ - bg_blkno = ocfs2_clusters_to_blocks(osb->sb, bit_off); - mlog(0, "new descriptor, record %u, at block %llu\n", - alloc_rec, (unsigned long long)bg_blkno); - - bg_bh = sb_getblk(osb->sb, bg_blkno); - if (!bg_bh) { - status = -EIO; - mlog_errno(status); - goto bail; - } - ocfs2_set_new_buffer_uptodate(INODE_CACHE(alloc_inode), bg_bh); - - status = ocfs2_block_group_fill(handle, - alloc_inode, - bg_bh, - bg_blkno, - alloc_rec, - cl); - if (status < 0) { - mlog_errno(status); - goto bail; - } - bg = (struct ocfs2_group_desc *) bg_bh->b_data; status = ocfs2_journal_access_di(handle, INODE_CACHE(alloc_inode), @@ -493,10 +711,11 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb, goto bail; } - le32_add_cpu(&cl->cl_recs[alloc_rec].c_free, + le32_add_cpu(&cl->cl_recs[bg->bg_chain].c_free, le16_to_cpu(bg->bg_free_bits_count)); - le32_add_cpu(&cl->cl_recs[alloc_rec].c_total, le16_to_cpu(bg->bg_bits)); - cl->cl_recs[alloc_rec].c_blkno = cpu_to_le64(bg_blkno); + le32_add_cpu(&cl->cl_recs[bg->bg_chain].c_total, + le16_to_cpu(bg->bg_bits)); + cl->cl_recs[bg->bg_chain].c_blkno = cpu_to_le64(bg_blkno); if (le16_to_cpu(cl->cl_next_free_rec) < le16_to_cpu(cl->cl_count)) le16_add_cpu(&cl->cl_next_free_rec, 1); @@ -525,6 +744,11 @@ bail: if (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) ocfs2_free_alloc_context(ac); -- cgit v1.2.2 From 7d1fe093bf04124dcc50c5dde1765bd098464bfa Mon Sep 17 00:00:00 2001 From: Joel Becker Date: Tue, 13 Apr 2010 14:30:19 +0800 Subject: ocfs2: Pass suballocation results back via a structure. We're going to be adding more info to a suballocator allocation. Rather than growing every function in the chain, let's pass a result structure around. Signed-off-by: Joel Becker Signed-off-by: Tao Ma --- fs/ocfs2/suballoc.c | 165 ++++++++++++++++++++++------------------------------ 1 file changed, 69 insertions(+), 96 deletions(-) (limited to 'fs/ocfs2/suballoc.c') diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 2f753954a7a8..3d823cffc620 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -53,6 +53,12 @@ #define OCFS2_MAX_TO_STEAL 1024 +struct ocfs2_suballoc_result { + u64 sr_bg_blkno; /* The bg we allocated from */ + unsigned int sr_bit_offset; /* The bit in the bg */ + unsigned int sr_bits; /* How many bits we claimed */ +}; + static inline void ocfs2_debug_bg(struct ocfs2_group_desc *bg); static inline void ocfs2_debug_suballoc_inode(struct ocfs2_dinode *fe); static inline u16 ocfs2_find_victim_chain(struct ocfs2_chain_list *cl); @@ -74,20 +80,18 @@ static int ocfs2_cluster_group_search(struct inode *inode, struct buffer_head *group_bh, u32 bits_wanted, u32 min_bits, u64 max_block, - u16 *bit_off, u16 *bits_found); + struct ocfs2_suballoc_result *res); static int ocfs2_block_group_search(struct inode *inode, struct buffer_head *group_bh, u32 bits_wanted, u32 min_bits, u64 max_block, - u16 *bit_off, u16 *bits_found); + struct ocfs2_suballoc_result *res); static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, struct ocfs2_alloc_context *ac, handle_t *handle, u32 bits_wanted, u32 min_bits, - u16 *bit_off, - unsigned int *num_bits, - u64 *bg_blkno); + struct ocfs2_suballoc_result *res); static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh, int nr); static inline int ocfs2_block_group_set_bits(handle_t *handle, @@ -1248,8 +1252,7 @@ static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb, struct buffer_head *bg_bh, unsigned int bits_wanted, unsigned int total_bits, - u16 *bit_off, - u16 *bits_found) + struct ocfs2_suballoc_result *res) { void *bitmap; u16 best_offset, best_size; @@ -1293,14 +1296,9 @@ static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb, } } - /* XXX: I think the first clause is equivalent to the second - * - jlbec */ - if (found == bits_wanted) { - *bit_off = start - found; - *bits_found = found; - } else if (best_size) { - *bit_off = best_offset; - *bits_found = best_size; + if (best_size) { + res->sr_bit_offset = best_offset; + res->sr_bits = best_size; } else { status = -ENOSPC; /* No error log here -- see the comment above @@ -1456,14 +1454,13 @@ static int ocfs2_cluster_group_search(struct inode *inode, struct buffer_head *group_bh, u32 bits_wanted, u32 min_bits, u64 max_block, - u16 *bit_off, u16 *bits_found) + struct ocfs2_suballoc_result *res) { int search = -ENOSPC; int ret; u64 blkoff; struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *) group_bh->b_data; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - u16 tmp_off, tmp_found; unsigned int max_bits, gd_cluster_off; BUG_ON(!ocfs2_is_cluster_bitmap(inode)); @@ -1490,15 +1487,15 @@ static int ocfs2_cluster_group_search(struct inode *inode, ret = ocfs2_block_group_find_clear_bits(OCFS2_SB(inode->i_sb), group_bh, bits_wanted, - max_bits, - &tmp_off, &tmp_found); + max_bits, res); if (ret) return ret; if (max_block) { blkoff = ocfs2_clusters_to_blocks(inode->i_sb, gd_cluster_off + - tmp_off + tmp_found); + res->sr_bit_offset + + res->sr_bits); mlog(0, "Checking %llu against %llu\n", (unsigned long long)blkoff, (unsigned long long)max_block); @@ -1510,16 +1507,14 @@ static int ocfs2_cluster_group_search(struct inode *inode, * return success, but we still want to return * -ENOSPC unless it found the minimum number * of bits. */ - if (min_bits <= tmp_found) { - *bit_off = tmp_off; - *bits_found = tmp_found; + if (min_bits <= res->sr_bits) search = 0; /* success */ - } else if (tmp_found) { + else if (res->sr_bits) { /* * Don't show bits which we'll be returning * for allocation to the local alloc bitmap. */ - ocfs2_local_alloc_seen_free_bits(osb, tmp_found); + ocfs2_local_alloc_seen_free_bits(osb, res->sr_bits); } } @@ -1530,7 +1525,7 @@ static int ocfs2_block_group_search(struct inode *inode, struct buffer_head *group_bh, u32 bits_wanted, u32 min_bits, u64 max_block, - u16 *bit_off, u16 *bits_found) + struct ocfs2_suballoc_result *res) { int ret = -ENOSPC; u64 blkoff; @@ -1543,10 +1538,10 @@ static int ocfs2_block_group_search(struct inode *inode, ret = ocfs2_block_group_find_clear_bits(OCFS2_SB(inode->i_sb), group_bh, bits_wanted, le16_to_cpu(bg->bg_bits), - bit_off, bits_found); + res); if (!ret && max_block) { - blkoff = le64_to_cpu(bg->bg_blkno) + *bit_off + - *bits_found; + blkoff = le64_to_cpu(bg->bg_blkno) + + res->sr_bit_offset + res->sr_bits; mlog(0, "Checking %llu against %llu\n", (unsigned long long)blkoff, (unsigned long long)max_block); @@ -1589,20 +1584,17 @@ static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac, handle_t *handle, u32 bits_wanted, u32 min_bits, - u16 *bit_off, - unsigned int *num_bits, - u64 gd_blkno, + struct ocfs2_suballoc_result *res, u16 *bits_left) { int ret; - u16 found; struct buffer_head *group_bh = NULL; struct ocfs2_group_desc *gd; struct ocfs2_dinode *di = (struct ocfs2_dinode *)ac->ac_bh->b_data; struct inode *alloc_inode = ac->ac_inode; - ret = ocfs2_read_group_descriptor(alloc_inode, di, gd_blkno, - &group_bh); + ret = ocfs2_read_group_descriptor(alloc_inode, di, + res->sr_bg_blkno, &group_bh); if (ret < 0) { mlog_errno(ret); return ret; @@ -1610,17 +1602,15 @@ static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac, gd = (struct ocfs2_group_desc *) group_bh->b_data; ret = ac->ac_group_search(alloc_inode, group_bh, bits_wanted, min_bits, - ac->ac_max_block, bit_off, &found); + ac->ac_max_block, res); if (ret < 0) { if (ret != -ENOSPC) mlog_errno(ret); goto out; } - *num_bits = found; - ret = ocfs2_alloc_dinode_update_counts(alloc_inode, handle, ac->ac_bh, - *num_bits, + res->sr_bits, le16_to_cpu(gd->bg_chain)); if (ret < 0) { mlog_errno(ret); @@ -1628,7 +1618,7 @@ static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac, } ret = ocfs2_block_group_set_bits(handle, alloc_inode, gd, group_bh, - *bit_off, *num_bits); + res->sr_bit_offset, res->sr_bits); if (ret < 0) mlog_errno(ret); @@ -1644,13 +1634,11 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, handle_t *handle, u32 bits_wanted, u32 min_bits, - u16 *bit_off, - unsigned int *num_bits, - u64 *bg_blkno, + struct ocfs2_suballoc_result *res, u16 *bits_left) { int status; - u16 chain, tmp_bits; + u16 chain; u32 tmp_used; u64 next_group; struct inode *alloc_inode = ac->ac_inode; @@ -1679,8 +1667,8 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, * the 1st group with any empty bits. */ while ((status = ac->ac_group_search(alloc_inode, group_bh, bits_wanted, min_bits, - ac->ac_max_block, bit_off, - &tmp_bits)) == -ENOSPC) { + ac->ac_max_block, + res)) == -ENOSPC) { if (!bg->bg_next_group) break; @@ -1705,11 +1693,11 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, } mlog(0, "alloc succeeds: we give %u bits from block group %llu\n", - tmp_bits, (unsigned long long)le64_to_cpu(bg->bg_blkno)); + res->sr_bits, (unsigned long long)le64_to_cpu(bg->bg_blkno)); - *num_bits = tmp_bits; + res->sr_bg_blkno = le64_to_cpu(bg->bg_blkno); - BUG_ON(*num_bits == 0); + BUG_ON(res->sr_bits == 0); /* * Keep track of previous block descriptor read. When @@ -1726,7 +1714,7 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, */ if (ac->ac_allow_chain_relink && (prev_group_bh) && - (ocfs2_block_group_reasonably_empty(bg, *num_bits))) { + (ocfs2_block_group_reasonably_empty(bg, res->sr_bits))) { status = ocfs2_relink_block_group(handle, alloc_inode, ac->ac_bh, group_bh, prev_group_bh, chain); @@ -1748,25 +1736,24 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, } tmp_used = le32_to_cpu(fe->id1.bitmap1.i_used); - fe->id1.bitmap1.i_used = cpu_to_le32(*num_bits + tmp_used); - le32_add_cpu(&cl->cl_recs[chain].c_free, -(*num_bits)); + fe->id1.bitmap1.i_used = cpu_to_le32(res->sr_bits + tmp_used); + le32_add_cpu(&cl->cl_recs[chain].c_free, -res->sr_bits); ocfs2_journal_dirty(handle, ac->ac_bh); status = ocfs2_block_group_set_bits(handle, alloc_inode, bg, group_bh, - *bit_off, - *num_bits); + res->sr_bit_offset, + res->sr_bits); if (status < 0) { mlog_errno(status); goto bail; } - mlog(0, "Allocated %u bits from suballocator %llu\n", *num_bits, + mlog(0, "Allocated %u bits from suballocator %llu\n", res->sr_bits, (unsigned long long)le64_to_cpu(fe->i_blkno)); - *bg_blkno = le64_to_cpu(bg->bg_blkno); *bits_left = le16_to_cpu(bg->bg_free_bits_count); bail: brelse(group_bh); @@ -1782,14 +1769,11 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, handle_t *handle, u32 bits_wanted, u32 min_bits, - u16 *bit_off, - unsigned int *num_bits, - u64 *bg_blkno) + struct ocfs2_suballoc_result *res) { int status; u16 victim, i; u16 bits_left = 0; - u64 hint_blkno = ac->ac_last_group; struct ocfs2_chain_list *cl; struct ocfs2_dinode *fe; @@ -1816,22 +1800,16 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, goto bail; } - if (hint_blkno) { + res->sr_bg_blkno = ac->ac_last_group; + if (res->sr_bg_blkno) { /* Attempt to short-circuit the usual search mechanism * by jumping straight to the most recently used * allocation group. This helps us mantain some * contiguousness across allocations. */ status = ocfs2_search_one_group(ac, handle, bits_wanted, - min_bits, bit_off, num_bits, - hint_blkno, &bits_left); - if (!status) { - /* Be careful to update *bg_blkno here as the - * caller is expecting it to be filled in, and - * ocfs2_search_one_group() won't do that for - * us. */ - *bg_blkno = hint_blkno; + min_bits, res, &bits_left); + if (!status) goto set_hint; - } if (status < 0 && status != -ENOSPC) { mlog_errno(status); goto bail; @@ -1844,8 +1822,8 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, ac->ac_chain = victim; ac->ac_allow_chain_relink = 1; - status = ocfs2_search_chain(ac, handle, bits_wanted, min_bits, bit_off, - num_bits, bg_blkno, &bits_left); + status = ocfs2_search_chain(ac, handle, bits_wanted, min_bits, + res, &bits_left); if (!status) goto set_hint; if (status < 0 && status != -ENOSPC) { @@ -1869,8 +1847,7 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, ac->ac_chain = i; status = ocfs2_search_chain(ac, handle, bits_wanted, min_bits, - bit_off, num_bits, bg_blkno, - &bits_left); + res, &bits_left); if (!status) break; if (status < 0 && status != -ENOSPC) { @@ -1887,7 +1864,7 @@ set_hint: if (bits_left < min_bits) ac->ac_last_group = 0; else - ac->ac_last_group = *bg_blkno; + ac->ac_last_group = res->sr_bg_blkno; } bail: @@ -1904,7 +1881,7 @@ int ocfs2_claim_metadata(struct ocfs2_super *osb, u64 *blkno_start) { int status; - u64 bg_blkno; + struct ocfs2_suballoc_result res; BUG_ON(!ac); BUG_ON(ac->ac_bits_wanted < (ac->ac_bits_given + bits_wanted)); @@ -1915,17 +1892,17 @@ int ocfs2_claim_metadata(struct ocfs2_super *osb, handle, bits_wanted, 1, - suballoc_bit_start, - num_bits, - &bg_blkno); + &res); if (status < 0) { mlog_errno(status); goto bail; } atomic_inc(&osb->alloc_stats.bg_allocs); - *blkno_start = bg_blkno + (u64) *suballoc_bit_start; - ac->ac_bits_given += (*num_bits); + *suballoc_bit_start = res.sr_bit_offset; + *blkno_start = res.sr_bg_blkno + (u64)(res.sr_bit_offset); + ac->ac_bits_given += res.sr_bits; + *num_bits = res.sr_bits; status = 0; bail: mlog_exit(status); @@ -1972,8 +1949,7 @@ int ocfs2_claim_new_inode(struct ocfs2_super *osb, u64 *fe_blkno) { int status; - unsigned int num_bits; - u64 bg_blkno; + struct ocfs2_suballoc_result res; mlog_entry_void(); @@ -1989,18 +1965,17 @@ int ocfs2_claim_new_inode(struct ocfs2_super *osb, handle, 1, 1, - suballoc_bit, - &num_bits, - &bg_blkno); + &res); if (status < 0) { mlog_errno(status); goto bail; } atomic_inc(&osb->alloc_stats.bg_allocs); - BUG_ON(num_bits != 1); + BUG_ON(res.sr_bits != 1); - *fe_blkno = bg_blkno + (u64) (*suballoc_bit); + *suballoc_bit = res.sr_bit_offset; + *fe_blkno = res.sr_bg_blkno + (u64)(res.sr_bit_offset); ac->ac_bits_given++; ocfs2_save_inode_ac_group(dir, ac); status = 0; @@ -2080,8 +2055,7 @@ int __ocfs2_claim_clusters(struct ocfs2_super *osb, { int status; unsigned int bits_wanted = max_clusters; - u64 bg_blkno = 0; - u16 bg_bit_off; + struct ocfs2_suballoc_result res; mlog_entry_void(); @@ -2120,14 +2094,12 @@ int __ocfs2_claim_clusters(struct ocfs2_super *osb, handle, bits_wanted, min_clusters, - &bg_bit_off, - num_clusters, - &bg_blkno); + &res); if (!status) { *cluster_start = ocfs2_desc_bitmap_to_cluster_off(ac->ac_inode, - bg_blkno, - bg_bit_off); + res.sr_bg_blkno, + res.sr_bit_offset); atomic_inc(&osb->alloc_stats.bitmap_data); } } @@ -2137,7 +2109,8 @@ int __ocfs2_claim_clusters(struct ocfs2_super *osb, goto bail; } - ac->ac_bits_given += *num_clusters; + ac->ac_bits_given += res.sr_bits; + *num_clusters = res.sr_bits; bail: mlog_exit(status); -- cgit v1.2.2 From aa8f8e93c898a0319bcd6c79a9a42fe52abac7d7 Mon Sep 17 00:00:00 2001 From: Joel Becker Date: Fri, 26 Mar 2010 10:08:07 +0800 Subject: ocfs2: ocfs2_claim_suballoc_bits() doesn't need an osb argument. It's contained on ac->ac_inode->i_sb anyway. Signed-off-by: Joel Becker --- fs/ocfs2/suballoc.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'fs/ocfs2/suballoc.c') diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 3d823cffc620..602c05eae7c5 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -86,8 +86,7 @@ static int ocfs2_block_group_search(struct inode *inode, u32 bits_wanted, u32 min_bits, u64 max_block, struct ocfs2_suballoc_result *res); -static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, - struct ocfs2_alloc_context *ac, +static int ocfs2_claim_suballoc_bits(struct ocfs2_alloc_context *ac, handle_t *handle, u32 bits_wanted, u32 min_bits, @@ -1764,8 +1763,7 @@ bail: } /* will give out up to bits_wanted contiguous bits. */ -static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, - struct ocfs2_alloc_context *ac, +static int ocfs2_claim_suballoc_bits(struct ocfs2_alloc_context *ac, handle_t *handle, u32 bits_wanted, u32 min_bits, @@ -1791,7 +1789,8 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, if (le32_to_cpu(fe->id1.bitmap1.i_used) >= le32_to_cpu(fe->id1.bitmap1.i_total)) { - ocfs2_error(osb->sb, "Chain allocator dinode %llu has %u used " + ocfs2_error(ac->ac_inode->i_sb, + "Chain allocator dinode %llu has %u used " "bits but only %u total.", (unsigned long long)le64_to_cpu(fe->i_blkno), le32_to_cpu(fe->id1.bitmap1.i_used), @@ -1887,8 +1886,7 @@ int ocfs2_claim_metadata(struct ocfs2_super *osb, BUG_ON(ac->ac_bits_wanted < (ac->ac_bits_given + bits_wanted)); BUG_ON(ac->ac_which != OCFS2_AC_USE_META); - status = ocfs2_claim_suballoc_bits(osb, - ac, + status = ocfs2_claim_suballoc_bits(ac, handle, bits_wanted, 1, @@ -1960,8 +1958,7 @@ int ocfs2_claim_new_inode(struct ocfs2_super *osb, ocfs2_init_inode_ac_group(dir, parent_fe_bh, ac); - status = ocfs2_claim_suballoc_bits(osb, - ac, + status = ocfs2_claim_suballoc_bits(ac, handle, 1, 1, @@ -2089,8 +2086,7 @@ int __ocfs2_claim_clusters(struct ocfs2_super *osb, if (bits_wanted > (osb->bitmap_cpg - 1)) bits_wanted = osb->bitmap_cpg - 1; - status = ocfs2_claim_suballoc_bits(osb, - ac, + status = ocfs2_claim_suballoc_bits(ac, handle, bits_wanted, min_clusters, -- cgit v1.2.2 From 13e434cf0cacd2f03a7f4cd077e3e995ef5ef710 Mon Sep 17 00:00:00 2001 From: Joel Becker Date: Fri, 26 Mar 2010 10:08:27 +0800 Subject: ocfs2: Trim suballocations if they cross discontiguous regions A discontiguous block group can find a range of free bits that straddle more than one region of its space. Callers can't handle that, so we trim the returned bits until they fit within one region. Only cluster allocations ask for min_bits>1. Discontiguous block groups are only for block allocations. So min_bits doesn't matter here. Signed-off-by: Joel Becker --- fs/ocfs2/suballoc.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'fs/ocfs2/suballoc.c') diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 602c05eae7c5..c9661c477869 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -1579,6 +1579,48 @@ out: return ret; } +static int ocfs2_bg_discontig_trim_by_rec(struct ocfs2_suballoc_result *res, + struct ocfs2_extent_rec *rec, + struct ocfs2_chain_list *cl) +{ + unsigned int bpc = le16_to_cpu(cl->cl_bpc); + unsigned int bitoff = le32_to_cpu(rec->e_cpos) * bpc; + unsigned int bitcount = le32_to_cpu(rec->e_leaf_clusters) * bpc; + + if (res->sr_bit_offset < bitoff) + return 0; + if (res->sr_bit_offset >= (bitoff + bitcount)) + return 0; + if ((res->sr_bit_offset + res->sr_bits) > (bitoff + bitcount)) + res->sr_bits = (bitoff + bitcount) - res->sr_bit_offset; + return 1; +} + +static void ocfs2_bg_discontig_trim_result(struct ocfs2_alloc_context *ac, + struct ocfs2_group_desc *bg, + struct ocfs2_suballoc_result *res) +{ + int i; + struct ocfs2_extent_rec *rec; + struct ocfs2_dinode *di = (struct ocfs2_dinode *)ac->ac_bh->b_data; + struct ocfs2_chain_list *cl = &di->id2.i_chain; + + if (!ocfs2_supports_discontig_bh(OCFS2_SB(ac->ac_inode->i_sb))) + return; + + if (ocfs2_is_cluster_bitmap(ac->ac_inode)) + return; + + if (!bg->bg_list.l_next_free_rec) + return; + + for (i = 0; i < le16_to_cpu(bg->bg_list.l_next_free_rec); i++) { + rec = &bg->bg_list.l_recs[i]; + if (ocfs2_bg_discontig_trim_by_rec(res, rec, cl)) + break; + } +} + static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac, handle_t *handle, u32 bits_wanted, @@ -1608,6 +1650,9 @@ static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac, goto out; } + if (!ret) + ocfs2_bg_discontig_trim_result(ac, gd, res); + ret = ocfs2_alloc_dinode_update_counts(alloc_inode, handle, ac->ac_bh, res->sr_bits, le16_to_cpu(gd->bg_chain)); @@ -1697,6 +1742,9 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, res->sr_bg_blkno = le64_to_cpu(bg->bg_blkno); BUG_ON(res->sr_bits == 0); + if (!status) + ocfs2_bg_discontig_trim_result(ac, bg, res); + /* * Keep track of previous block descriptor read. When -- cgit v1.2.2 From 1ed9b777f77929ae961d6f9cdf828a07200ba71c Mon Sep 17 00:00:00 2001 From: Joel Becker Date: Thu, 6 May 2010 13:59:06 +0800 Subject: ocfs2: ocfs2_claim_*() don't need an ocfs2_super argument. They all take an ocfs2_alloc_context, which has the allocation inode. Signed-off-by: Joel Becker Signed-off-by: Tao Ma --- fs/ocfs2/suballoc.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'fs/ocfs2/suballoc.c') diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index c9661c477869..3f6201777784 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -439,7 +439,7 @@ ocfs2_block_group_alloc_contig(struct ocfs2_super *osb, handle_t *handle, struct buffer_head *bg_bh; unsigned int alloc_rec = ocfs2_find_smallest_chain(cl); - status = ocfs2_claim_clusters(osb, handle, ac, + status = ocfs2_claim_clusters(handle, ac, le16_to_cpu(cl->cl_cpg), &bit_off, &num_bits); if (status < 0) { @@ -481,7 +481,7 @@ static int ocfs2_block_group_claim_bits(struct ocfs2_super *osb, int status; while (min_bits) { - status = ocfs2_claim_clusters(osb, handle, ac, min_bits, + status = ocfs2_claim_clusters(handle, ac, min_bits, bit_off, num_bits); if (status != -ENOSPC) break; @@ -1919,8 +1919,7 @@ bail: return status; } -int ocfs2_claim_metadata(struct ocfs2_super *osb, - handle_t *handle, +int ocfs2_claim_metadata(handle_t *handle, struct ocfs2_alloc_context *ac, u32 bits_wanted, u16 *suballoc_bit_start, @@ -1943,7 +1942,7 @@ int ocfs2_claim_metadata(struct ocfs2_super *osb, mlog_errno(status); goto bail; } - atomic_inc(&osb->alloc_stats.bg_allocs); + atomic_inc(&OCFS2_SB(ac->ac_inode->i_sb)->alloc_stats.bg_allocs); *suballoc_bit_start = res.sr_bit_offset; *blkno_start = res.sr_bg_blkno + (u64)(res.sr_bit_offset); @@ -1986,8 +1985,7 @@ static inline void ocfs2_save_inode_ac_group(struct inode *dir, OCFS2_I(dir)->ip_last_used_slot = ac->ac_alloc_slot; } -int ocfs2_claim_new_inode(struct ocfs2_super *osb, - handle_t *handle, +int ocfs2_claim_new_inode(handle_t *handle, struct inode *dir, struct buffer_head *parent_fe_bh, struct ocfs2_alloc_context *ac, @@ -2015,7 +2013,7 @@ int ocfs2_claim_new_inode(struct ocfs2_super *osb, mlog_errno(status); goto bail; } - atomic_inc(&osb->alloc_stats.bg_allocs); + atomic_inc(&OCFS2_SB(ac->ac_inode->i_sb)->alloc_stats.bg_allocs); BUG_ON(res.sr_bits != 1); @@ -2090,8 +2088,7 @@ static inline void ocfs2_block_to_cluster_group(struct inode *inode, * contig. allocation, set to '1' to indicate we can deal with extents * of any size. */ -int __ocfs2_claim_clusters(struct ocfs2_super *osb, - handle_t *handle, +int __ocfs2_claim_clusters(handle_t *handle, struct ocfs2_alloc_context *ac, u32 min_clusters, u32 max_clusters, @@ -2101,6 +2098,7 @@ int __ocfs2_claim_clusters(struct ocfs2_super *osb, int status; unsigned int bits_wanted = max_clusters; struct ocfs2_suballoc_result res; + struct ocfs2_super *osb = OCFS2_SB(ac->ac_inode->i_sb); mlog_entry_void(); @@ -2161,8 +2159,7 @@ bail: return status; } -int ocfs2_claim_clusters(struct ocfs2_super *osb, - handle_t *handle, +int ocfs2_claim_clusters(handle_t *handle, struct ocfs2_alloc_context *ac, u32 min_clusters, u32 *cluster_start, @@ -2170,7 +2167,7 @@ int ocfs2_claim_clusters(struct ocfs2_super *osb, { unsigned int bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given; - return __ocfs2_claim_clusters(osb, handle, ac, min_clusters, + return __ocfs2_claim_clusters(handle, ac, min_clusters, bits_wanted, cluster_start, num_clusters); } -- cgit v1.2.2 From ba2066351b630f0205ebf725f5c81a2a07a77cd7 Mon Sep 17 00:00:00 2001 From: Joel Becker Date: Fri, 26 Mar 2010 10:08:59 +0800 Subject: ocfs2: Return allocated metadata blknos on the ocfs2_suballoc_result. Rather than calculating the resulting block number, return it on the ocfs2_suballoc_result structure. This way we can calculate block numbers for discontiguous block groups. Cluster groups keep doing it the old way. Signed-off-by: Joel Becker --- fs/ocfs2/suballoc.c | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) (limited to 'fs/ocfs2/suballoc.c') diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 3f6201777784..9c2e669a74fa 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -55,6 +55,7 @@ struct ocfs2_suballoc_result { u64 sr_bg_blkno; /* The bg we allocated from */ + u64 sr_blkno; /* The first allocated block */ unsigned int sr_bit_offset; /* The bit in the bg */ unsigned int sr_bits; /* How many bits we claimed */ }; @@ -1579,9 +1580,9 @@ out: return ret; } -static int ocfs2_bg_discontig_trim_by_rec(struct ocfs2_suballoc_result *res, - struct ocfs2_extent_rec *rec, - struct ocfs2_chain_list *cl) +static int ocfs2_bg_discontig_fix_by_rec(struct ocfs2_suballoc_result *res, + struct ocfs2_extent_rec *rec, + struct ocfs2_chain_list *cl) { unsigned int bpc = le16_to_cpu(cl->cl_bpc); unsigned int bitoff = le32_to_cpu(rec->e_cpos) * bpc; @@ -1591,32 +1592,35 @@ static int ocfs2_bg_discontig_trim_by_rec(struct ocfs2_suballoc_result *res, return 0; if (res->sr_bit_offset >= (bitoff + bitcount)) return 0; + res->sr_blkno = le64_to_cpu(rec->e_blkno) + + (res->sr_bit_offset - bitoff); if ((res->sr_bit_offset + res->sr_bits) > (bitoff + bitcount)) res->sr_bits = (bitoff + bitcount) - res->sr_bit_offset; return 1; } -static void ocfs2_bg_discontig_trim_result(struct ocfs2_alloc_context *ac, - struct ocfs2_group_desc *bg, - struct ocfs2_suballoc_result *res) +static void ocfs2_bg_discontig_fix_result(struct ocfs2_alloc_context *ac, + struct ocfs2_group_desc *bg, + struct ocfs2_suballoc_result *res) { int i; struct ocfs2_extent_rec *rec; struct ocfs2_dinode *di = (struct ocfs2_dinode *)ac->ac_bh->b_data; struct ocfs2_chain_list *cl = &di->id2.i_chain; - if (!ocfs2_supports_discontig_bh(OCFS2_SB(ac->ac_inode->i_sb))) - return; - - if (ocfs2_is_cluster_bitmap(ac->ac_inode)) + if (ocfs2_is_cluster_bitmap(ac->ac_inode)) { + res->sr_blkno = 0; return; + } - if (!bg->bg_list.l_next_free_rec) + res->sr_blkno = res->sr_bg_blkno + res->sr_bit_offset; + if (!ocfs2_supports_discontig_bh(OCFS2_SB(ac->ac_inode->i_sb)) || + !bg->bg_list.l_next_free_rec) return; for (i = 0; i < le16_to_cpu(bg->bg_list.l_next_free_rec); i++) { rec = &bg->bg_list.l_recs[i]; - if (ocfs2_bg_discontig_trim_by_rec(res, rec, cl)) + if (ocfs2_bg_discontig_fix_by_rec(res, rec, cl)) break; } } @@ -1651,7 +1655,7 @@ static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac, } if (!ret) - ocfs2_bg_discontig_trim_result(ac, gd, res); + ocfs2_bg_discontig_fix_result(ac, gd, res); ret = ocfs2_alloc_dinode_update_counts(alloc_inode, handle, ac->ac_bh, res->sr_bits, @@ -1743,7 +1747,7 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, BUG_ON(res->sr_bits == 0); if (!status) - ocfs2_bg_discontig_trim_result(ac, bg, res); + ocfs2_bg_discontig_fix_result(ac, bg, res); /* @@ -1927,7 +1931,7 @@ int ocfs2_claim_metadata(handle_t *handle, u64 *blkno_start) { int status; - struct ocfs2_suballoc_result res; + struct ocfs2_suballoc_result res = { .sr_blkno = 0, }; BUG_ON(!ac); BUG_ON(ac->ac_bits_wanted < (ac->ac_bits_given + bits_wanted)); @@ -1945,7 +1949,7 @@ int ocfs2_claim_metadata(handle_t *handle, atomic_inc(&OCFS2_SB(ac->ac_inode->i_sb)->alloc_stats.bg_allocs); *suballoc_bit_start = res.sr_bit_offset; - *blkno_start = res.sr_bg_blkno + (u64)(res.sr_bit_offset); + *blkno_start = res.sr_blkno; ac->ac_bits_given += res.sr_bits; *num_bits = res.sr_bits; status = 0; @@ -1993,7 +1997,7 @@ int ocfs2_claim_new_inode(handle_t *handle, u64 *fe_blkno) { int status; - struct ocfs2_suballoc_result res; + struct ocfs2_suballoc_result res = { .sr_blkno = 0, }; mlog_entry_void(); @@ -2018,7 +2022,7 @@ int ocfs2_claim_new_inode(handle_t *handle, BUG_ON(res.sr_bits != 1); *suballoc_bit = res.sr_bit_offset; - *fe_blkno = res.sr_bg_blkno + (u64)(res.sr_bit_offset); + *fe_blkno = res.sr_blkno; ac->ac_bits_given++; ocfs2_save_inode_ac_group(dir, ac); status = 0; @@ -2097,7 +2101,7 @@ int __ocfs2_claim_clusters(handle_t *handle, { int status; unsigned int bits_wanted = max_clusters; - struct ocfs2_suballoc_result res; + struct ocfs2_suballoc_result res = { .sr_blkno = 0, }; struct ocfs2_super *osb = OCFS2_SB(ac->ac_inode->i_sb); mlog_entry_void(); @@ -2138,6 +2142,7 @@ int __ocfs2_claim_clusters(handle_t *handle, min_clusters, &res); if (!status) { + BUG_ON(res.sr_blkno); /* cluster alloc can't set */ *cluster_start = ocfs2_desc_bitmap_to_cluster_off(ac->ac_inode, res.sr_bg_blkno, -- cgit v1.2.2 From 2b6cb576aa80611f1f6a3c88708d1e68a8d97985 Mon Sep 17 00:00:00 2001 From: Joel Becker Date: Fri, 26 Mar 2010 10:09:15 +0800 Subject: ocfs2: Set suballoc_loc on allocated metadata. Get the suballoc_loc from ocfs2_claim_new_inode() or ocfs2_claim_metadata(). Store it on the appropriate field of the block we just allocated. Signed-off-by: Joel Becker --- fs/ocfs2/suballoc.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'fs/ocfs2/suballoc.c') diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 9c2e669a74fa..7809f41bcbfc 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -54,7 +54,9 @@ #define OCFS2_MAX_TO_STEAL 1024 struct ocfs2_suballoc_result { - u64 sr_bg_blkno; /* The bg we allocated from */ + u64 sr_bg_blkno; /* The bg we allocated from. Set + to 0 when a block group is + contiguous. */ u64 sr_blkno; /* The first allocated block */ unsigned int sr_bit_offset; /* The bit in the bg */ unsigned int sr_bits; /* How many bits we claimed */ @@ -1604,6 +1606,7 @@ static void ocfs2_bg_discontig_fix_result(struct ocfs2_alloc_context *ac, struct ocfs2_suballoc_result *res) { int i; + u64 bg_blkno = res->sr_bg_blkno; /* Save off */ struct ocfs2_extent_rec *rec; struct ocfs2_dinode *di = (struct ocfs2_dinode *)ac->ac_bh->b_data; struct ocfs2_chain_list *cl = &di->id2.i_chain; @@ -1614,14 +1617,17 @@ static void ocfs2_bg_discontig_fix_result(struct ocfs2_alloc_context *ac, } res->sr_blkno = res->sr_bg_blkno + res->sr_bit_offset; + res->sr_bg_blkno = 0; /* Clear it for contig block groups */ if (!ocfs2_supports_discontig_bh(OCFS2_SB(ac->ac_inode->i_sb)) || !bg->bg_list.l_next_free_rec) return; for (i = 0; i < le16_to_cpu(bg->bg_list.l_next_free_rec); i++) { rec = &bg->bg_list.l_recs[i]; - if (ocfs2_bg_discontig_fix_by_rec(res, rec, cl)) + if (ocfs2_bg_discontig_fix_by_rec(res, rec, cl)) { + res->sr_bg_blkno = bg_blkno; /* Restore */ break; + } } } @@ -1926,6 +1932,7 @@ bail: int ocfs2_claim_metadata(handle_t *handle, struct ocfs2_alloc_context *ac, u32 bits_wanted, + u64 *suballoc_loc, u16 *suballoc_bit_start, unsigned int *num_bits, u64 *blkno_start) @@ -1948,6 +1955,7 @@ int ocfs2_claim_metadata(handle_t *handle, } atomic_inc(&OCFS2_SB(ac->ac_inode->i_sb)->alloc_stats.bg_allocs); + *suballoc_loc = res.sr_bg_blkno; *suballoc_bit_start = res.sr_bit_offset; *blkno_start = res.sr_blkno; ac->ac_bits_given += res.sr_bits; @@ -1993,11 +2001,12 @@ int ocfs2_claim_new_inode(handle_t *handle, struct inode *dir, struct buffer_head *parent_fe_bh, struct ocfs2_alloc_context *ac, + u64 *suballoc_loc, u16 *suballoc_bit, u64 *fe_blkno) { int status; - struct ocfs2_suballoc_result res = { .sr_blkno = 0, }; + struct ocfs2_suballoc_result res; mlog_entry_void(); @@ -2021,6 +2030,7 @@ int ocfs2_claim_new_inode(handle_t *handle, BUG_ON(res.sr_bits != 1); + *suballoc_loc = res.sr_bg_blkno; *suballoc_bit = res.sr_bit_offset; *fe_blkno = res.sr_blkno; ac->ac_bits_given++; -- cgit v1.2.2 From 8b06bc592ebc5a31e8d0b9c2ab17c6e78dde1f86 Mon Sep 17 00:00:00 2001 From: Joel Becker Date: Fri, 26 Mar 2010 10:09:29 +0800 Subject: 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: Joel Becker --- fs/ocfs2/suballoc.c | 48 ++++++++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 26 deletions(-) (limited to 'fs/ocfs2/suballoc.c') diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 7809f41bcbfc..e5403acdb3f5 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -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) < 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) min_bits = needed; status = ocfs2_block_group_claim_bits(osb, handle, ac, @@ -556,11 +550,12 @@ bail: return status; } -static void ocfs2_bg_alloc_cleanup(struct inode *alloc_inode, - struct buffer_head *bg_bh, - struct ocfs2_cached_dealloc_ctxt *dealloc) +static void ocfs2_bg_alloc_cleanup(handle_t *handle, + struct ocfs2_alloc_context *cluster_ac, + struct inode *alloc_inode, + struct buffer_head *bg_bh) { - int i; + int i, ret; struct ocfs2_group_desc *bg; struct ocfs2_extent_list *el; struct ocfs2_extent_rec *rec; @@ -572,9 +567,13 @@ static void ocfs2_bg_alloc_cleanup(struct inode *alloc_inode, el = &bg->bg_list; for (i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) { rec = &el->l_recs[i]; - ocfs2_cache_cluster_dealloc(dealloc, - le64_to_cpu(rec->e_blkno), - le32_to_cpu(rec->e_leaf_clusters)); + ret = ocfs2_free_clusters(handle, cluster_ac->ac_inode, + cluster_ac->ac_bh, + 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); @@ -585,8 +584,7 @@ static struct buffer_head * ocfs2_block_group_alloc_discontig(handle_t *handle, struct inode *alloc_inode, struct ocfs2_alloc_context *ac, - struct ocfs2_chain_list *cl, - struct ocfs2_cached_dealloc_ctxt *dealloc) + struct ocfs2_chain_list *cl) { int status; u32 bit_off, num_bits; @@ -601,6 +599,13 @@ ocfs2_block_group_alloc_discontig(handle_t *handle, 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 */ status = ocfs2_block_group_claim_bits(osb, handle, ac, min_bits, &bit_off, &num_bits); @@ -638,7 +643,7 @@ ocfs2_block_group_alloc_discontig(handle_t *handle, bail: 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; } @@ -660,14 +665,11 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb, u64 bg_blkno; struct buffer_head *bg_bh = NULL; struct ocfs2_group_desc *bg; - struct ocfs2_cached_dealloc_ctxt dealloc; BUG_ON(ocfs2_is_cluster_bitmap(alloc_inode)); mlog_entry_void(); - ocfs2_init_dealloc_ctxt(&dealloc); - cl = &fe->id2.i_chain; status = ocfs2_reserve_clusters_with_limit(osb, le16_to_cpu(cl->cl_cpg), @@ -699,8 +701,7 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb, if (IS_ERR(bg_bh) && (PTR_ERR(bg_bh) == -ENOSPC)) bg_bh = ocfs2_block_group_alloc_discontig(handle, alloc_inode, - ac, cl, - &dealloc); + ac, cl); if (IS_ERR(bg_bh)) { status = PTR_ERR(bg_bh); bg_bh = NULL; @@ -750,11 +751,6 @@ bail: if (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) ocfs2_free_alloc_context(ac); -- cgit v1.2.2 From 95ec0adf0b56d6a3f0ca1ec87173311898486b2e Mon Sep 17 00:00:00 2001 From: Joel Becker Date: Fri, 26 Mar 2010 10:10:08 +0800 Subject: ocfs2: Don't relink cluster groups when allocating discontig block groups We don't have enough credits, and the filesystem is in a full state anyway. Signed-off-by: Joel Becker --- fs/ocfs2/suballoc.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'fs/ocfs2/suballoc.c') diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index e5403acdb3f5..5852a46647a2 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -606,6 +606,14 @@ ocfs2_block_group_alloc_discontig(handle_t *handle, goto bail; } + /* + * We're going to be grabbing from multiple cluster groups. + * We don't have enough credits to relink them all, and the + * cluster groups will be staying in cache for the duration of + * this operation. + */ + ac->ac_allow_chain_relink = 0; + /* Claim the first region */ status = ocfs2_block_group_claim_bits(osb, handle, ac, min_bits, &bit_off, &num_bits); -- cgit v1.2.2 From 4711954eaa8d30f653fda238cecf919f1ae40d6f Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Thu, 22 Apr 2010 14:09:15 +0800 Subject: ocfs2: Some tiny bug fixes for discontiguous block allocation. The fixes include: 1. some endian problems. 2. we should use bit/bpc in ocfs2_block_group_grow_discontig to allocate clusters. 3. set num_clusters properly in __ocfs2_claim_clusters. 4. change name from ocfs2_supports_discontig_bh to ocfs2_supports_discontig_bg. Signed-off-by: Tao Ma --- fs/ocfs2/suballoc.c | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) (limited to 'fs/ocfs2/suballoc.c') diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 5852a46647a2..b7491e2481ca 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -341,15 +341,17 @@ static void ocfs2_bg_discontig_add_extent(struct ocfs2_super *osb, struct ocfs2_extent_list *el = &bg->bg_list; struct ocfs2_extent_rec *rec; - BUG_ON(!ocfs2_supports_discontig_bh(osb)); + BUG_ON(!ocfs2_supports_discontig_bg(osb)); if (!el->l_next_free_rec) el->l_count = cpu_to_le16(ocfs2_extent_recs_per_gd(osb->sb)); rec = &el->l_recs[le16_to_cpu(el->l_next_free_rec)]; - rec->e_blkno = p_blkno; + rec->e_blkno = cpu_to_le64(p_blkno); rec->e_cpos = cpu_to_le32(le16_to_cpu(bg->bg_bits) / le16_to_cpu(cl->cl_bpc)); rec->e_leaf_clusters = cpu_to_le32(clusters); le16_add_cpu(&bg->bg_bits, clusters * le16_to_cpu(cl->cl_bpc)); + le16_add_cpu(&bg->bg_free_bits_count, + clusters * le16_to_cpu(cl->cl_bpc)); le16_add_cpu(&el->l_next_free_rec, 1); } @@ -397,7 +399,7 @@ static int ocfs2_block_group_fill(handle_t *handle, if (group_clusters == le16_to_cpu(cl->cl_cpg)) bg->bg_bits = cpu_to_le16(ocfs2_bits_per_group(cl)); else - ocfs2_bg_discontig_add_extent(osb, bg, cl, bg->bg_blkno, + ocfs2_bg_discontig_add_extent(osb, bg, cl, group_blkno, group_clusters); /* set the 1st bit in the bitmap to account for the descriptor block */ @@ -506,8 +508,8 @@ static int ocfs2_block_group_grow_discontig(handle_t *handle, struct ocfs2_super *osb = OCFS2_SB(alloc_inode->i_sb); struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *)bg_bh->b_data; - unsigned int needed = - ocfs2_bits_per_group(cl) - le16_to_cpu(bg->bg_bits); + unsigned int needed = le16_to_cpu(cl->cl_cpg) - + le16_to_cpu(bg->bg_bits) / le16_to_cpu(cl->cl_bpc); u32 p_cpos, clusters; u64 p_blkno; struct ocfs2_extent_list *el = &bg->bg_list; @@ -538,10 +540,17 @@ static int ocfs2_block_group_grow_discontig(handle_t *handle, clusters); min_bits = clusters; - needed = ocfs2_bits_per_group(cl) - le16_to_cpu(bg->bg_bits); + needed = le16_to_cpu(cl->cl_cpg) - + le16_to_cpu(bg->bg_bits) / le16_to_cpu(cl->cl_bpc); } if (needed > 0) { + /* + * We have used up all the extent rec but can't fill up + * the cpg. So bail out. + */ + status = -ENOSPC; + goto bail; } ocfs2_journal_dirty(handle, bg_bh); @@ -594,7 +603,7 @@ ocfs2_block_group_alloc_discontig(handle_t *handle, unsigned int alloc_rec = ocfs2_find_smallest_chain(cl); struct ocfs2_super *osb = OCFS2_SB(alloc_inode->i_sb); - if (!ocfs2_supports_discontig_bh(osb)) { + if (!ocfs2_supports_discontig_bg(osb)) { status = -ENOSPC; goto bail; } @@ -670,7 +679,7 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb, struct ocfs2_chain_list *cl; struct ocfs2_alloc_context *ac = NULL; handle_t *handle = NULL; - u64 bg_blkno; + u16 alloc_rec; struct buffer_head *bg_bh = NULL; struct ocfs2_group_desc *bg; @@ -726,11 +735,12 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb, goto bail; } - le32_add_cpu(&cl->cl_recs[bg->bg_chain].c_free, + alloc_rec = le16_to_cpu(bg->bg_chain); + le32_add_cpu(&cl->cl_recs[alloc_rec].c_free, le16_to_cpu(bg->bg_free_bits_count)); - le32_add_cpu(&cl->cl_recs[bg->bg_chain].c_total, + le32_add_cpu(&cl->cl_recs[alloc_rec].c_total, le16_to_cpu(bg->bg_bits)); - cl->cl_recs[bg->bg_chain].c_blkno = cpu_to_le64(bg_blkno); + cl->cl_recs[alloc_rec].c_blkno = cpu_to_le64(bg->bg_blkno); if (le16_to_cpu(cl->cl_next_free_rec) < le16_to_cpu(cl->cl_count)) le16_add_cpu(&cl->cl_next_free_rec, 1); @@ -1622,7 +1632,7 @@ static void ocfs2_bg_discontig_fix_result(struct ocfs2_alloc_context *ac, res->sr_blkno = res->sr_bg_blkno + res->sr_bit_offset; res->sr_bg_blkno = 0; /* Clear it for contig block groups */ - if (!ocfs2_supports_discontig_bh(OCFS2_SB(ac->ac_inode->i_sb)) || + if (!ocfs2_supports_discontig_bg(OCFS2_SB(ac->ac_inode->i_sb)) || !bg->bg_list.l_next_free_rec) return; @@ -2162,6 +2172,7 @@ int __ocfs2_claim_clusters(handle_t *handle, res.sr_bg_blkno, res.sr_bit_offset); atomic_inc(&osb->alloc_stats.bitmap_data); + *num_clusters = res.sr_bits; } } if (status < 0) { @@ -2170,8 +2181,7 @@ int __ocfs2_claim_clusters(handle_t *handle, goto bail; } - ac->ac_bits_given += res.sr_bits; - *num_clusters = res.sr_bits; + ac->ac_bits_given += *num_clusters; bail: mlog_exit(status); -- cgit v1.2.2 From 8571882c21e5073b2f96147ec4ff9b7042339e1b Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Tue, 13 Apr 2010 14:38:06 +0800 Subject: ocfs2: ocfs2_group_bitmap_size has to handle old volume. ocfs2_group_bitmap_size has to handle the case when the volume don't have discontiguous block group support. So pass the feature_incompat in and check it. Signed-off-by: Tao Ma --- fs/ocfs2/suballoc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs/ocfs2/suballoc.c') diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index b7491e2481ca..6f39da4a9a10 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -391,7 +391,8 @@ static int ocfs2_block_group_fill(handle_t *handle, memset(bg, 0, sb->s_blocksize); strcpy(bg->bg_signature, OCFS2_GROUP_DESC_SIGNATURE); bg->bg_generation = cpu_to_le32(OCFS2_SB(sb)->fs_generation); - bg->bg_size = cpu_to_le16(ocfs2_group_bitmap_size(sb, 1)); + bg->bg_size = cpu_to_le16(ocfs2_group_bitmap_size(sb, 1, + osb->s_feature_incompat)); bg->bg_chain = cpu_to_le16(my_chain); bg->bg_next_group = cl->cl_recs[my_chain].c_blkno; bg->bg_parent_dinode = cpu_to_le64(OCFS2_I(alloc_inode)->ip_blkno); -- cgit v1.2.2 From 74380c479ad83addeff8a172ab95f59557b5b0c3 Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Mon, 22 Mar 2010 14:20:18 +0800 Subject: ocfs2: Free block to the right block group. In case the block we are going to free is allocated from a discontiguous block group, we have to use suballoc_loc to be the right group. Signed-off-by: Tao Ma --- fs/ocfs2/suballoc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs/ocfs2/suballoc.c') diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 6f39da4a9a10..0c08353fddac 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -2349,6 +2349,8 @@ int ocfs2_free_dinode(handle_t *handle, u16 bit = le16_to_cpu(di->i_suballoc_bit); u64 bg_blkno = ocfs2_which_suballoc_group(blk, bit); + if (di->i_suballoc_loc) + bg_blkno = le64_to_cpu(di->i_suballoc_loc); return ocfs2_free_suballoc_bits(handle, inode_alloc_inode, inode_alloc_bh, bit, bg_blkno, 1); } -- cgit v1.2.2 From abf1b3cb5b20fbad27ca9c7497235eeb4dd3f4fd Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Tue, 27 Apr 2010 08:30:36 +0800 Subject: ocfs2: Set ac_last_group properly with discontig group. ac_last_group is used to record the last block group we used during allocation. But the initialization process only calls ocfs2_which_suballoc_group and fails to use suballoc_loc properly. So let us do it. Another function ocfs2_test_suballoc_bit also needs fix. I have searched all the callers of ocfs2_which_suballoc_group, and all the callers notices suballoc_loc now. Signed-off-by: Tao Ma --- fs/ocfs2/suballoc.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'fs/ocfs2/suballoc.c') diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 0c08353fddac..a327c80721ee 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -1982,10 +1982,10 @@ bail: } static void ocfs2_init_inode_ac_group(struct inode *dir, - struct buffer_head *parent_fe_bh, + struct buffer_head *parent_di_bh, struct ocfs2_alloc_context *ac) { - struct ocfs2_dinode *fe = (struct ocfs2_dinode *)parent_fe_bh->b_data; + struct ocfs2_dinode *di = (struct ocfs2_dinode *)parent_di_bh->b_data; /* * Try to allocate inodes from some specific group. * @@ -1999,10 +1999,14 @@ static void ocfs2_init_inode_ac_group(struct inode *dir, if (OCFS2_I(dir)->ip_last_used_group && OCFS2_I(dir)->ip_last_used_slot == ac->ac_alloc_slot) ac->ac_last_group = OCFS2_I(dir)->ip_last_used_group; - else if (le16_to_cpu(fe->i_suballoc_slot) == ac->ac_alloc_slot) - ac->ac_last_group = ocfs2_which_suballoc_group( - le64_to_cpu(fe->i_blkno), - le16_to_cpu(fe->i_suballoc_bit)); + else if (le16_to_cpu(di->i_suballoc_slot) == ac->ac_alloc_slot) { + if (di->i_suballoc_loc) + ac->ac_last_group = le64_to_cpu(di->i_suballoc_loc); + else + ac->ac_last_group = ocfs2_which_suballoc_group( + le64_to_cpu(di->i_blkno), + le16_to_cpu(di->i_suballoc_bit)); + } } static inline void ocfs2_save_inode_ac_group(struct inode *dir, @@ -2620,7 +2624,7 @@ static int ocfs2_test_suballoc_bit(struct ocfs2_super *osb, struct buffer_head *alloc_bh, u64 blkno, u16 bit, int *res) { - struct ocfs2_dinode *alloc_fe; + struct ocfs2_dinode *alloc_di; struct ocfs2_group_desc *group; struct buffer_head *group_bh = NULL; u64 bg_blkno; @@ -2629,17 +2633,20 @@ static int ocfs2_test_suballoc_bit(struct ocfs2_super *osb, mlog_entry("blkno: %llu bit: %u\n", (unsigned long long)blkno, (unsigned int)bit); - alloc_fe = (struct ocfs2_dinode *)alloc_bh->b_data; - if ((bit + 1) > ocfs2_bits_per_group(&alloc_fe->id2.i_chain)) { + alloc_di = (struct ocfs2_dinode *)alloc_bh->b_data; + if ((bit + 1) > ocfs2_bits_per_group(&alloc_di->id2.i_chain)) { mlog(ML_ERROR, "suballoc bit %u out of range of %u\n", (unsigned int)bit, - ocfs2_bits_per_group(&alloc_fe->id2.i_chain)); + ocfs2_bits_per_group(&alloc_di->id2.i_chain)); status = -EINVAL; goto bail; } - bg_blkno = ocfs2_which_suballoc_group(blkno, bit); - status = ocfs2_read_group_descriptor(suballoc, alloc_fe, bg_blkno, + if (alloc_di->i_suballoc_loc) + bg_blkno = le64_to_cpu(alloc_di->i_suballoc_loc); + else + bg_blkno = ocfs2_which_suballoc_group(blkno, bit); + status = ocfs2_read_group_descriptor(suballoc, alloc_di, bg_blkno, &group_bh); if (status < 0) { mlog(ML_ERROR, "read group %llu failed %d\n", -- cgit v1.2.2 From 18d3a98f3c1b0e27ce026afa4d1ef042f2903726 Mon Sep 17 00:00:00 2001 From: Joel Becker Date: Tue, 18 May 2010 16:47:55 -0700 Subject: ocfs2: Silence a gcc warning. ocfs2_block_group_claim_bits() is never called with min_bits=0, but we shouldn't leave status undefined if it ever is. Signed-off-by: Joel Becker --- fs/ocfs2/suballoc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/ocfs2/suballoc.c') diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index a327c80721ee..f4c2a9eb8c4d 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -484,7 +484,7 @@ static int ocfs2_block_group_claim_bits(struct ocfs2_super *osb, unsigned int min_bits, u32 *bit_off, u32 *num_bits) { - int status; + int status = 0; while (min_bits) { status = ocfs2_claim_clusters(handle, ac, min_bits, -- cgit v1.2.2