diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ocfs2/suballoc.c | 48 |
1 files changed, 48 insertions, 0 deletions
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: | |||
1579 | return ret; | 1579 | return ret; |
1580 | } | 1580 | } |
1581 | 1581 | ||
1582 | static 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 | |||
1599 | static 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 | |||
1582 | static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac, | 1624 | static 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 |