struct buffer_head *group_bh,
u32 bits_wanted, u32 min_bits,
u16 *bit_off, u16 *bits_found);
+static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
+ u32 bits_wanted,
+ u32 min_bits,
+ u16 *bit_off,
+ unsigned int *num_bits,
+ u64 *bg_blkno);
static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
struct ocfs2_alloc_context *ac,
u32 bits_wanted,
u64 *bg_blkno);
static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh,
int nr);
+static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb,
+ struct buffer_head *bg_bh,
+ unsigned int bits_wanted,
+ u16 *bit_off,
+ u16 *bits_found);
static inline int ocfs2_block_group_set_bits(struct ocfs2_journal_handle *handle,
struct inode *alloc_inode,
struct ocfs2_group_desc *bg,
return (u32)le16_to_cpu(cl->cl_cpg) * (u32)le16_to_cpu(cl->cl_bpc);
}
-/* somewhat more expensive than our other checks, so use sparingly. */
-static int ocfs2_check_group_descriptor(struct super_block *sb,
- struct ocfs2_dinode *di,
- struct ocfs2_group_desc *gd)
-{
- unsigned int max_bits;
-
- if (!OCFS2_IS_VALID_GROUP_DESC(gd)) {
- OCFS2_RO_ON_INVALID_GROUP_DESC(sb, gd);
- return -EIO;
- }
-
- if (di->i_blkno != gd->bg_parent_dinode) {
- ocfs2_error(sb, "Group descriptor # %llu has bad parent "
- "pointer (%llu, expected %llu)",
- (unsigned long long)le64_to_cpu(gd->bg_blkno),
- (unsigned long long)le64_to_cpu(gd->bg_parent_dinode),
- (unsigned long long)le64_to_cpu(di->i_blkno));
- return -EIO;
- }
-
- max_bits = le16_to_cpu(di->id2.i_chain.cl_cpg) * le16_to_cpu(di->id2.i_chain.cl_bpc);
- if (le16_to_cpu(gd->bg_bits) > max_bits) {
- ocfs2_error(sb, "Group descriptor # %llu has bit count of %u",
- (unsigned long long)le64_to_cpu(gd->bg_blkno),
- le16_to_cpu(gd->bg_bits));
- return -EIO;
- }
-
- if (le16_to_cpu(gd->bg_chain) >=
- le16_to_cpu(di->id2.i_chain.cl_next_free_rec)) {
- ocfs2_error(sb, "Group descriptor # %llu has bad chain %u",
- (unsigned long long)le64_to_cpu(gd->bg_blkno),
- le16_to_cpu(gd->bg_chain));
- return -EIO;
- }
-
- if (le16_to_cpu(gd->bg_free_bits_count) > le16_to_cpu(gd->bg_bits)) {
- ocfs2_error(sb, "Group descriptor # %llu has bit count %u but "
- "claims that %u are free",
- (unsigned long long)le64_to_cpu(gd->bg_blkno),
- le16_to_cpu(gd->bg_bits),
- le16_to_cpu(gd->bg_free_bits_count));
- return -EIO;
- }
-
- if (le16_to_cpu(gd->bg_bits) > (8 * le16_to_cpu(gd->bg_size))) {
- ocfs2_error(sb, "Group descriptor # %llu has bit count %u but "
- "max bitmap bits of %u",
- (unsigned long long)le64_to_cpu(gd->bg_blkno),
- le16_to_cpu(gd->bg_bits),
- 8 * le16_to_cpu(gd->bg_size));
- return -EIO;
- }
-
- return 0;
-}
-
static int ocfs2_block_group_fill(struct ocfs2_journal_handle *handle,
struct inode *alloc_inode,
struct buffer_head *bg_bh,
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)
{
found = start = best_offset = best_size = 0;
bitmap = bg->bg_bitmap;
- while((offset = ocfs2_find_next_zero_bit(bitmap, total_bits, start)) != -1) {
- if (offset == total_bits)
+ while((offset = ocfs2_find_next_zero_bit(bitmap,
+ le16_to_cpu(bg->bg_bits),
+ start)) != -1) {
+ if (offset == le16_to_cpu(bg->bg_bits))
break;
if (!ocfs2_test_bg_bit_allocatable(bg_bh, offset)) {
{
int search = -ENOSPC;
int ret;
- struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *) group_bh->b_data;
+ struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) group_bh->b_data;
u16 tmp_off, tmp_found;
- unsigned int max_bits, gd_cluster_off;
BUG_ON(!ocfs2_is_cluster_bitmap(inode));
- if (gd->bg_free_bits_count) {
- max_bits = le16_to_cpu(gd->bg_bits);
-
- /* Tail groups in cluster bitmaps which aren't cpg
- * aligned are prone to partial extention by a failed
- * fs resize. If the file system resize never got to
- * update the dinode cluster count, then we don't want
- * to trust any clusters past it, regardless of what
- * the group descriptor says. */
- gd_cluster_off = ocfs2_blocks_to_clusters(inode->i_sb,
- le64_to_cpu(gd->bg_blkno));
- if ((gd_cluster_off + max_bits) >
- OCFS2_I(inode)->ip_clusters) {
- max_bits = OCFS2_I(inode)->ip_clusters - gd_cluster_off;
- mlog(0, "Desc %llu, bg_bits %u, clusters %u, use %u\n",
- (unsigned long long)le64_to_cpu(gd->bg_blkno),
- le16_to_cpu(gd->bg_bits),
- OCFS2_I(inode)->ip_clusters, max_bits);
- }
-
+ if (bg->bg_free_bits_count) {
ret = ocfs2_block_group_find_clear_bits(OCFS2_SB(inode->i_sb),
group_bh, bits_wanted,
- max_bits,
&tmp_off, &tmp_found);
if (ret)
return ret;
if (bg->bg_free_bits_count)
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);
return ret;
}
-static int ocfs2_alloc_dinode_update_counts(struct inode *inode,
- struct ocfs2_journal_handle *handle,
- struct buffer_head *di_bh,
- u32 num_bits,
- u16 chain)
-{
- int ret;
- u32 tmp_used;
- struct ocfs2_dinode *di = (struct ocfs2_dinode *) di_bh->b_data;
- struct ocfs2_chain_list *cl = (struct ocfs2_chain_list *) &di->id2.i_chain;
-
- ret = ocfs2_journal_access(handle, inode, di_bh,
- OCFS2_JOURNAL_ACCESS_WRITE);
- if (ret < 0) {
- mlog_errno(ret);
- goto out;
- }
-
- 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);
-
-out:
- return ret;
-}
-
-static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac,
- u32 bits_wanted,
- u32 min_bits,
- u16 *bit_off,
- unsigned int *num_bits,
- u64 gd_blkno,
- u16 *bits_left)
-{
- int ret;
- u16 found;
- struct buffer_head *group_bh = NULL;
- struct ocfs2_group_desc *gd;
- struct inode *alloc_inode = ac->ac_inode;
- struct ocfs2_journal_handle *handle = ac->ac_handle;
-
- ret = ocfs2_read_block(OCFS2_SB(alloc_inode->i_sb), gd_blkno,
- &group_bh, OCFS2_BH_CACHED, alloc_inode);
- if (ret < 0) {
- mlog_errno(ret);
- return ret;
- }
-
- gd = (struct ocfs2_group_desc *) group_bh->b_data;
- if (!OCFS2_IS_VALID_GROUP_DESC(gd)) {
- OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, gd);
- ret = -EIO;
- goto out;
- }
-
- ret = ac->ac_group_search(alloc_inode, group_bh, bits_wanted, min_bits,
- bit_off, &found);
- 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,
- le16_to_cpu(gd->bg_chain));
- if (ret < 0) {
- mlog_errno(ret);
- goto out;
- }
-
- ret = ocfs2_block_group_set_bits(handle, alloc_inode, gd, group_bh,
- *bit_off, *num_bits);
- if (ret < 0)
- mlog_errno(ret);
-
- *bits_left = le16_to_cpu(gd->bg_free_bits_count);
-
-out:
- brelse(group_bh);
-
- return ret;
-}
-
static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
u32 bits_wanted,
u32 min_bits,
u16 *bit_off,
unsigned int *num_bits,
- u64 *bg_blkno,
- u16 *bits_left)
+ u64 *bg_blkno)
{
int status;
u16 chain, tmp_bits;
goto bail;
}
bg = (struct ocfs2_group_desc *) group_bh->b_data;
- status = ocfs2_check_group_descriptor(alloc_inode->i_sb, fe, bg);
- if (status) {
- mlog_errno(status);
+ if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {
+ OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg);
+ status = -EIO;
goto bail;
}
goto bail;
}
bg = (struct ocfs2_group_desc *) group_bh->b_data;
- status = ocfs2_check_group_descriptor(alloc_inode->i_sb, fe, bg);
- if (status) {
- mlog_errno(status);
+ if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {
+ OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg);
+ status = -EIO;
goto bail;
}
}
(unsigned long long)fe->i_blkno);
*bg_blkno = le64_to_cpu(bg->bg_blkno);
- *bits_left = le16_to_cpu(bg->bg_free_bits_count);
bail:
if (group_bh)
brelse(group_bh);
{
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;
goto bail;
}
- if (hint_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, 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;
- goto set_hint;
- }
- if (status < 0 && status != -ENOSPC) {
- mlog_errno(status);
- goto bail;
- }
- }
-
cl = (struct ocfs2_chain_list *) &fe->id2.i_chain;
victim = ocfs2_find_victim_chain(cl);
ac->ac_allow_chain_relink = 1;
status = ocfs2_search_chain(ac, bits_wanted, min_bits, bit_off,
- num_bits, bg_blkno, &bits_left);
+ num_bits, bg_blkno);
if (!status)
- goto set_hint;
+ goto bail;
if (status < 0 && status != -ENOSPC) {
mlog_errno(status);
goto bail;
ac->ac_chain = i;
status = ocfs2_search_chain(ac, bits_wanted, min_bits,
- bit_off, num_bits, bg_blkno,
- &bits_left);
+ bit_off, num_bits,
+ bg_blkno);
if (!status)
break;
if (status < 0 && status != -ENOSPC) {
goto bail;
}
}
-
-set_hint:
- if (status != -ENOSPC) {
- /* If the next search of this group is not likely to
- * yield a suitable extent, then we reset the last
- * group hint so as to not waste a disk read */
- if (bits_left < min_bits)
- ac->ac_last_group = 0;
- else
- ac->ac_last_group = *bg_blkno;
- }
-
bail:
+
mlog_exit(status);
return status;
}
{
int status;
unsigned int bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given;
- u64 bg_blkno = 0;
+ u64 bg_blkno;
u16 bg_bit_off;
mlog_entry_void();
}
group = (struct ocfs2_group_desc *) group_bh->b_data;
- status = ocfs2_check_group_descriptor(alloc_inode->i_sb, fe, group);
- if (status) {
- mlog_errno(status);
+ if (!OCFS2_IS_VALID_GROUP_DESC(group)) {
+ OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, group);
+ status = -EIO;
goto bail;
}
BUG_ON((count + start_bit) > le16_to_cpu(group->bg_bits));