aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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