aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoel Becker <joel.becker@oracle.com>2010-03-25 22:08:27 -0400
committerTao Ma <tao.ma@oracle.com>2010-03-25 22:08:27 -0400
commit13e434cf0cacd2f03a7f4cd077e3e995ef5ef710 (patch)
treee13c0131deb1409c4445242cef52c5fda97a170f
parentaa8f8e93c898a0319bcd6c79a9a42fe52abac7d7 (diff)
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 <joel.becker@oracle.com>
-rw-r--r--fs/ocfs2/suballoc.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
index 602c05eae7c..c9661c47786 100644
--- a/fs/ocfs2/suballoc.c
+++ b/fs/ocfs2/suballoc.c
@@ -1579,6 +1579,48 @@ out:
1579 return ret; 1579 return ret;
1580} 1580}
1581 1581
1582static int ocfs2_bg_discontig_trim_by_rec(struct ocfs2_suballoc_result *res,
1583 struct ocfs2_extent_rec *rec,
1584 struct ocfs2_chain_list *cl)
1585{
1586 unsigned int bpc = le16_to_cpu(cl->cl_bpc);
1587 unsigned int bitoff = le32_to_cpu(rec->e_cpos) * bpc;
1588 unsigned int bitcount = le32_to_cpu(rec->e_leaf_clusters) * bpc;
1589
1590 if (res->sr_bit_offset < bitoff)
1591 return 0;
1592 if (res->sr_bit_offset >= (bitoff + bitcount))
1593 return 0;
1594 if ((res->sr_bit_offset + res->sr_bits) > (bitoff + bitcount))
1595 res->sr_bits = (bitoff + bitcount) - res->sr_bit_offset;
1596 return 1;
1597}
1598
1599static void ocfs2_bg_discontig_trim_result(struct ocfs2_alloc_context *ac,
1600 struct ocfs2_group_desc *bg,
1601 struct ocfs2_suballoc_result *res)
1602{
1603 int i;
1604 struct ocfs2_extent_rec *rec;
1605 struct ocfs2_dinode *di = (struct ocfs2_dinode *)ac->ac_bh->b_data;
1606 struct ocfs2_chain_list *cl = &di->id2.i_chain;
1607
1608 if (!ocfs2_supports_discontig_bh(OCFS2_SB(ac->ac_inode->i_sb)))
1609 return;
1610
1611 if (ocfs2_is_cluster_bitmap(ac->ac_inode))
1612 return;
1613
1614 if (!bg->bg_list.l_next_free_rec)
1615 return;
1616
1617 for (i = 0; i < le16_to_cpu(bg->bg_list.l_next_free_rec); i++) {
1618 rec = &bg->bg_list.l_recs[i];
1619 if (ocfs2_bg_discontig_trim_by_rec(res, rec, cl))
1620 break;
1621 }
1622}
1623
1582static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac, 1624static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac,
1583 handle_t *handle, 1625 handle_t *handle,
1584 u32 bits_wanted, 1626 u32 bits_wanted,
@@ -1608,6 +1650,9 @@ static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac,
1608 goto out; 1650 goto out;
1609 } 1651 }
1610 1652
1653 if (!ret)
1654 ocfs2_bg_discontig_trim_result(ac, gd, res);
1655
1611 ret = ocfs2_alloc_dinode_update_counts(alloc_inode, handle, ac->ac_bh, 1656 ret = ocfs2_alloc_dinode_update_counts(alloc_inode, handle, ac->ac_bh,
1612 res->sr_bits, 1657 res->sr_bits,
1613 le16_to_cpu(gd->bg_chain)); 1658 le16_to_cpu(gd->bg_chain));
@@ -1697,6 +1742,9 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
1697 res->sr_bg_blkno = le64_to_cpu(bg->bg_blkno); 1742 res->sr_bg_blkno = le64_to_cpu(bg->bg_blkno);
1698 1743
1699 BUG_ON(res->sr_bits == 0); 1744 BUG_ON(res->sr_bits == 0);
1745 if (!status)
1746 ocfs2_bg_discontig_trim_result(ac, bg, res);
1747
1700 1748
1701 /* 1749 /*
1702 * Keep track of previous block descriptor read. When 1750 * Keep track of previous block descriptor read. When