X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Focfs2%2Fsuballoc.c;fp=fs%2Focfs2%2Fsuballoc.c;h=c46c164aefbb23d6f12626df7c3ff4ff6c0268ba;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hp=9d91e66f51a9fa4606a6f864e2bc7531e10c1a75;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c;p=linux-2.6.git diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 9d91e66f5..c46c164ae 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -70,6 +70,12 @@ static int ocfs2_block_group_search(struct inode *inode, 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, @@ -79,6 +85,11 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, 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, @@ -132,64 +143,6 @@ static u32 ocfs2_bits_per_group(struct ocfs2_chain_list *cl) 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, @@ -204,9 +157,8 @@ static int ocfs2_block_group_fill(struct ocfs2_journal_handle *handle, mlog_entry_void(); if (((unsigned long long) bg_bh->b_blocknr) != group_blkno) { - ocfs2_error(alloc_inode->i_sb, "group block (%llu) != " - "b_blocknr (%llu)", - (unsigned long long)group_blkno, + ocfs2_error(alloc_inode->i_sb, "group block (%"MLFu64") " + "!= b_blocknr (%llu)", group_blkno, (unsigned long long) bg_bh->b_blocknr); status = -EIO; goto bail; @@ -328,8 +280,8 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb, /* 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); + mlog(0, "new descriptor, record %u, at block %"MLFu64"\n", + alloc_rec, bg_blkno); bg_bh = sb_getblk(osb->sb, bg_blkno); if (!bg_bh) { @@ -430,8 +382,8 @@ static int ocfs2_reserve_suballoc_bits(struct ocfs2_super *osb, goto bail; } if (!(fe->i_flags & cpu_to_le32(OCFS2_CHAIN_FL))) { - ocfs2_error(alloc_inode->i_sb, "Invalid chain allocator %llu", - (unsigned long long)le64_to_cpu(fe->i_blkno)); + ocfs2_error(alloc_inode->i_sb, "Invalid chain allocator " + "# %"MLFu64, le64_to_cpu(fe->i_blkno)); status = -EIO; goto bail; } @@ -710,7 +662,6 @@ static int ocfs2_test_bg_bit_allocatable(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) { @@ -727,8 +678,10 @@ static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb, 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)) { @@ -876,10 +829,9 @@ static int ocfs2_relink_block_group(struct ocfs2_journal_handle *handle, goto out; } - mlog(0, "Suballoc %llu, chain %u, move group %llu to top, prev = %llu\n", - (unsigned long long)fe->i_blkno, chain, - (unsigned long long)bg->bg_blkno, - (unsigned long long)prev_bg->bg_blkno); + mlog(0, "In suballoc %"MLFu64", chain %u, move group %"MLFu64" to " + "top, prev = %"MLFu64"\n", + fe->i_blkno, chain, bg->bg_blkno, prev_bg->bg_blkno); fe_ptr = le64_to_cpu(fe->id2.i_chain.cl_recs[chain].c_blkno); bg_ptr = le64_to_cpu(bg->bg_next_group); @@ -957,35 +909,14 @@ static int ocfs2_cluster_group_search(struct inode *inode, { 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; @@ -1018,109 +949,17 @@ static int ocfs2_block_group_search(struct inode *inode, 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; @@ -1135,9 +974,8 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, struct ocfs2_group_desc *bg; chain = ac->ac_chain; - mlog(0, "trying to alloc %u bits from chain %u, inode %llu\n", - bits_wanted, chain, - (unsigned long long)OCFS2_I(alloc_inode)->ip_blkno); + mlog(0, "trying to alloc %u bits from chain %u, inode %"MLFu64"\n", + bits_wanted, chain, OCFS2_I(alloc_inode)->ip_blkno); status = ocfs2_read_block(OCFS2_SB(alloc_inode->i_sb), le64_to_cpu(cl->cl_recs[chain].c_blkno), @@ -1147,9 +985,9 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, 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; } @@ -1177,9 +1015,9 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, 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; } } @@ -1189,8 +1027,8 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, goto bail; } - mlog(0, "alloc succeeds: we give %u bits from block group %llu\n", - tmp_bits, (unsigned long long)bg->bg_blkno); + mlog(0, "alloc succeeds: we give %u bits from block group %"MLFu64"\n", + tmp_bits, bg->bg_blkno); *num_bits = tmp_bits; @@ -1254,11 +1092,10 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, goto bail; } - mlog(0, "Allocated %u bits from suballocator %llu\n", *num_bits, - (unsigned long long)fe->i_blkno); + mlog(0, "Allocated %u bits from suballocator %"MLFu64"\n", + *num_bits, 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); @@ -1280,8 +1117,6 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, { 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; @@ -1299,37 +1134,15 @@ 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 " - "bits but only %u total.", - (unsigned long long)le64_to_cpu(fe->i_blkno), + ocfs2_error(osb->sb, "Chain allocator dinode %"MLFu64" has %u" + "used bits but only %u total.", + le64_to_cpu(fe->i_blkno), le32_to_cpu(fe->id1.bitmap1.i_used), le32_to_cpu(fe->id1.bitmap1.i_total)); status = -EIO; 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); @@ -1337,9 +1150,9 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, 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; @@ -1361,8 +1174,8 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, 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) { @@ -1370,19 +1183,8 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, 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; } @@ -1536,7 +1338,7 @@ int ocfs2_claim_clusters(struct ocfs2_super *osb, { 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(); @@ -1677,9 +1479,10 @@ static int ocfs2_free_suballoc_bits(struct ocfs2_journal_handle *handle, } BUG_ON((count + start_bit) > ocfs2_bits_per_group(cl)); - mlog(0, "%llu: freeing %u bits from group %llu, starting at %u\n", - (unsigned long long)OCFS2_I(alloc_inode)->ip_blkno, count, - (unsigned long long)bg_blkno, start_bit); + mlog(0, "suballocator %"MLFu64": freeing %u bits from group %"MLFu64 + ", starting at %u\n", + OCFS2_I(alloc_inode)->ip_blkno, count, bg_blkno, + start_bit); status = ocfs2_read_block(osb, bg_blkno, &group_bh, OCFS2_BH_CACHED, alloc_inode); @@ -1689,9 +1492,9 @@ static int ocfs2_free_suballoc_bits(struct ocfs2_journal_handle *handle, } 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)); @@ -1789,10 +1592,10 @@ int ocfs2_free_clusters(struct ocfs2_journal_handle *handle, ocfs2_block_to_cluster_group(bitmap_inode, start_blk, &bg_blkno, &bg_start_bit); - mlog(0, "want to free %u clusters starting at block %llu\n", - num_clusters, (unsigned long long)start_blk); - mlog(0, "bg_blkno = %llu, bg_start_bit = %u\n", - (unsigned long long)bg_blkno, bg_start_bit); + mlog(0, "want to free %u clusters starting at block %"MLFu64"\n", + num_clusters, start_blk); + mlog(0, "bg_blkno = %"MLFu64", bg_start_bit = %u\n", + bg_blkno, bg_start_bit); status = ocfs2_free_suballoc_bits(handle, bitmap_inode, bitmap_bh, bg_start_bit, bg_blkno, @@ -1813,22 +1616,18 @@ static inline void ocfs2_debug_bg(struct ocfs2_group_desc *bg) printk("bg_free_bits_count: %u\n", bg->bg_free_bits_count); printk("bg_chain: %u\n", bg->bg_chain); printk("bg_generation: %u\n", le32_to_cpu(bg->bg_generation)); - printk("bg_next_group: %llu\n", - (unsigned long long)bg->bg_next_group); - printk("bg_parent_dinode: %llu\n", - (unsigned long long)bg->bg_parent_dinode); - printk("bg_blkno: %llu\n", - (unsigned long long)bg->bg_blkno); + printk("bg_next_group: %"MLFu64"\n", bg->bg_next_group); + printk("bg_parent_dinode: %"MLFu64"\n", bg->bg_parent_dinode); + printk("bg_blkno: %"MLFu64"\n", bg->bg_blkno); } static inline void ocfs2_debug_suballoc_inode(struct ocfs2_dinode *fe) { int i; - printk("Suballoc Inode %llu:\n", (unsigned long long)fe->i_blkno); + printk("Suballoc Inode %"MLFu64":\n", fe->i_blkno); printk("i_signature: %s\n", fe->i_signature); - printk("i_size: %llu\n", - (unsigned long long)fe->i_size); + printk("i_size: %"MLFu64"\n", fe->i_size); printk("i_clusters: %u\n", fe->i_clusters); printk("i_generation: %u\n", le32_to_cpu(fe->i_generation)); @@ -1846,7 +1645,7 @@ static inline void ocfs2_debug_suballoc_inode(struct ocfs2_dinode *fe) fe->id2.i_chain.cl_recs[i].c_free); printk("fe->id2.i_chain.cl_recs[%d].c_total: %u\n", i, fe->id2.i_chain.cl_recs[i].c_total); - printk("fe->id2.i_chain.cl_recs[%d].c_blkno: %llu\n", i, - (unsigned long long)fe->id2.i_chain.cl_recs[i].c_blkno); + printk("fe->id2.i_chain.cl_recs[%d].c_blkno: %"MLFu64"\n", i, + fe->id2.i_chain.cl_recs[i].c_blkno); } }