diff options
Diffstat (limited to 'fs/ocfs2/aops.c')
-rw-r--r-- | fs/ocfs2/aops.c | 59 |
1 files changed, 58 insertions, 1 deletions
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index f1e962cb3b73..d55a10e2f300 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -1627,6 +1627,43 @@ static int ocfs2_zero_tail(struct inode *inode, struct buffer_head *di_bh, | |||
1627 | return ret; | 1627 | return ret; |
1628 | } | 1628 | } |
1629 | 1629 | ||
1630 | /* | ||
1631 | * Try to flush truncate logs if we can free enough clusters from it. | ||
1632 | * As for return value, "< 0" means error, "0" no space and "1" means | ||
1633 | * we have freed enough spaces and let the caller try to allocate again. | ||
1634 | */ | ||
1635 | static int ocfs2_try_to_free_truncate_log(struct ocfs2_super *osb, | ||
1636 | unsigned int needed) | ||
1637 | { | ||
1638 | tid_t target; | ||
1639 | int ret = 0; | ||
1640 | unsigned int truncated_clusters; | ||
1641 | |||
1642 | mutex_lock(&osb->osb_tl_inode->i_mutex); | ||
1643 | truncated_clusters = osb->truncated_clusters; | ||
1644 | mutex_unlock(&osb->osb_tl_inode->i_mutex); | ||
1645 | |||
1646 | /* | ||
1647 | * Check whether we can succeed in allocating if we free | ||
1648 | * the truncate log. | ||
1649 | */ | ||
1650 | if (truncated_clusters < needed) | ||
1651 | goto out; | ||
1652 | |||
1653 | ret = ocfs2_flush_truncate_log(osb); | ||
1654 | if (ret) { | ||
1655 | mlog_errno(ret); | ||
1656 | goto out; | ||
1657 | } | ||
1658 | |||
1659 | if (jbd2_journal_start_commit(osb->journal->j_journal, &target)) { | ||
1660 | jbd2_log_wait_commit(osb->journal->j_journal, target); | ||
1661 | ret = 1; | ||
1662 | } | ||
1663 | out: | ||
1664 | return ret; | ||
1665 | } | ||
1666 | |||
1630 | int ocfs2_write_begin_nolock(struct file *filp, | 1667 | int ocfs2_write_begin_nolock(struct file *filp, |
1631 | struct address_space *mapping, | 1668 | struct address_space *mapping, |
1632 | loff_t pos, unsigned len, unsigned flags, | 1669 | loff_t pos, unsigned len, unsigned flags, |
@@ -1634,7 +1671,7 @@ int ocfs2_write_begin_nolock(struct file *filp, | |||
1634 | struct buffer_head *di_bh, struct page *mmap_page) | 1671 | struct buffer_head *di_bh, struct page *mmap_page) |
1635 | { | 1672 | { |
1636 | int ret, cluster_of_pages, credits = OCFS2_INODE_UPDATE_CREDITS; | 1673 | int ret, cluster_of_pages, credits = OCFS2_INODE_UPDATE_CREDITS; |
1637 | unsigned int clusters_to_alloc, extents_to_split; | 1674 | unsigned int clusters_to_alloc, extents_to_split, clusters_need = 0; |
1638 | struct ocfs2_write_ctxt *wc; | 1675 | struct ocfs2_write_ctxt *wc; |
1639 | struct inode *inode = mapping->host; | 1676 | struct inode *inode = mapping->host; |
1640 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 1677 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
@@ -1643,7 +1680,9 @@ int ocfs2_write_begin_nolock(struct file *filp, | |||
1643 | struct ocfs2_alloc_context *meta_ac = NULL; | 1680 | struct ocfs2_alloc_context *meta_ac = NULL; |
1644 | handle_t *handle; | 1681 | handle_t *handle; |
1645 | struct ocfs2_extent_tree et; | 1682 | struct ocfs2_extent_tree et; |
1683 | int try_free = 1, ret1; | ||
1646 | 1684 | ||
1685 | try_again: | ||
1647 | ret = ocfs2_alloc_write_ctxt(&wc, osb, pos, len, di_bh); | 1686 | ret = ocfs2_alloc_write_ctxt(&wc, osb, pos, len, di_bh); |
1648 | if (ret) { | 1687 | if (ret) { |
1649 | mlog_errno(ret); | 1688 | mlog_errno(ret); |
@@ -1678,6 +1717,7 @@ int ocfs2_write_begin_nolock(struct file *filp, | |||
1678 | mlog_errno(ret); | 1717 | mlog_errno(ret); |
1679 | goto out; | 1718 | goto out; |
1680 | } else if (ret == 1) { | 1719 | } else if (ret == 1) { |
1720 | clusters_need = wc->w_clen; | ||
1681 | ret = ocfs2_refcount_cow(inode, filp, di_bh, | 1721 | ret = ocfs2_refcount_cow(inode, filp, di_bh, |
1682 | wc->w_cpos, wc->w_clen, UINT_MAX); | 1722 | wc->w_cpos, wc->w_clen, UINT_MAX); |
1683 | if (ret) { | 1723 | if (ret) { |
@@ -1692,6 +1732,7 @@ int ocfs2_write_begin_nolock(struct file *filp, | |||
1692 | mlog_errno(ret); | 1732 | mlog_errno(ret); |
1693 | goto out; | 1733 | goto out; |
1694 | } | 1734 | } |
1735 | clusters_need += clusters_to_alloc; | ||
1695 | 1736 | ||
1696 | di = (struct ocfs2_dinode *)wc->w_di_bh->b_data; | 1737 | di = (struct ocfs2_dinode *)wc->w_di_bh->b_data; |
1697 | 1738 | ||
@@ -1814,6 +1855,22 @@ out: | |||
1814 | ocfs2_free_alloc_context(data_ac); | 1855 | ocfs2_free_alloc_context(data_ac); |
1815 | if (meta_ac) | 1856 | if (meta_ac) |
1816 | ocfs2_free_alloc_context(meta_ac); | 1857 | ocfs2_free_alloc_context(meta_ac); |
1858 | |||
1859 | if (ret == -ENOSPC && try_free) { | ||
1860 | /* | ||
1861 | * Try to free some truncate log so that we can have enough | ||
1862 | * clusters to allocate. | ||
1863 | */ | ||
1864 | try_free = 0; | ||
1865 | |||
1866 | ret1 = ocfs2_try_to_free_truncate_log(osb, clusters_need); | ||
1867 | if (ret1 == 1) | ||
1868 | goto try_again; | ||
1869 | |||
1870 | if (ret1 < 0) | ||
1871 | mlog_errno(ret1); | ||
1872 | } | ||
1873 | |||
1817 | return ret; | 1874 | return ret; |
1818 | } | 1875 | } |
1819 | 1876 | ||