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 0d7c5540ad66..1fbb0e20131b 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -1630,6 +1630,43 @@ static int ocfs2_zero_tail(struct inode *inode, struct buffer_head *di_bh, | |||
1630 | return ret; | 1630 | return ret; |
1631 | } | 1631 | } |
1632 | 1632 | ||
1633 | /* | ||
1634 | * Try to flush truncate logs if we can free enough clusters from it. | ||
1635 | * As for return value, "< 0" means error, "0" no space and "1" means | ||
1636 | * we have freed enough spaces and let the caller try to allocate again. | ||
1637 | */ | ||
1638 | static int ocfs2_try_to_free_truncate_log(struct ocfs2_super *osb, | ||
1639 | unsigned int needed) | ||
1640 | { | ||
1641 | tid_t target; | ||
1642 | int ret = 0; | ||
1643 | unsigned int truncated_clusters; | ||
1644 | |||
1645 | mutex_lock(&osb->osb_tl_inode->i_mutex); | ||
1646 | truncated_clusters = osb->truncated_clusters; | ||
1647 | mutex_unlock(&osb->osb_tl_inode->i_mutex); | ||
1648 | |||
1649 | /* | ||
1650 | * Check whether we can succeed in allocating if we free | ||
1651 | * the truncate log. | ||
1652 | */ | ||
1653 | if (truncated_clusters < needed) | ||
1654 | goto out; | ||
1655 | |||
1656 | ret = ocfs2_flush_truncate_log(osb); | ||
1657 | if (ret) { | ||
1658 | mlog_errno(ret); | ||
1659 | goto out; | ||
1660 | } | ||
1661 | |||
1662 | if (jbd2_journal_start_commit(osb->journal->j_journal, &target)) { | ||
1663 | jbd2_log_wait_commit(osb->journal->j_journal, target); | ||
1664 | ret = 1; | ||
1665 | } | ||
1666 | out: | ||
1667 | return ret; | ||
1668 | } | ||
1669 | |||
1633 | int ocfs2_write_begin_nolock(struct file *filp, | 1670 | int ocfs2_write_begin_nolock(struct file *filp, |
1634 | struct address_space *mapping, | 1671 | struct address_space *mapping, |
1635 | loff_t pos, unsigned len, unsigned flags, | 1672 | loff_t pos, unsigned len, unsigned flags, |
@@ -1637,7 +1674,7 @@ int ocfs2_write_begin_nolock(struct file *filp, | |||
1637 | struct buffer_head *di_bh, struct page *mmap_page) | 1674 | struct buffer_head *di_bh, struct page *mmap_page) |
1638 | { | 1675 | { |
1639 | int ret, cluster_of_pages, credits = OCFS2_INODE_UPDATE_CREDITS; | 1676 | int ret, cluster_of_pages, credits = OCFS2_INODE_UPDATE_CREDITS; |
1640 | unsigned int clusters_to_alloc, extents_to_split; | 1677 | unsigned int clusters_to_alloc, extents_to_split, clusters_need = 0; |
1641 | struct ocfs2_write_ctxt *wc; | 1678 | struct ocfs2_write_ctxt *wc; |
1642 | struct inode *inode = mapping->host; | 1679 | struct inode *inode = mapping->host; |
1643 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 1680 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
@@ -1646,7 +1683,9 @@ int ocfs2_write_begin_nolock(struct file *filp, | |||
1646 | struct ocfs2_alloc_context *meta_ac = NULL; | 1683 | struct ocfs2_alloc_context *meta_ac = NULL; |
1647 | handle_t *handle; | 1684 | handle_t *handle; |
1648 | struct ocfs2_extent_tree et; | 1685 | struct ocfs2_extent_tree et; |
1686 | int try_free = 1, ret1; | ||
1649 | 1687 | ||
1688 | try_again: | ||
1650 | ret = ocfs2_alloc_write_ctxt(&wc, osb, pos, len, di_bh); | 1689 | ret = ocfs2_alloc_write_ctxt(&wc, osb, pos, len, di_bh); |
1651 | if (ret) { | 1690 | if (ret) { |
1652 | mlog_errno(ret); | 1691 | mlog_errno(ret); |
@@ -1681,6 +1720,7 @@ int ocfs2_write_begin_nolock(struct file *filp, | |||
1681 | mlog_errno(ret); | 1720 | mlog_errno(ret); |
1682 | goto out; | 1721 | goto out; |
1683 | } else if (ret == 1) { | 1722 | } else if (ret == 1) { |
1723 | clusters_need = wc->w_clen; | ||
1684 | ret = ocfs2_refcount_cow(inode, filp, di_bh, | 1724 | ret = ocfs2_refcount_cow(inode, filp, di_bh, |
1685 | wc->w_cpos, wc->w_clen, UINT_MAX); | 1725 | wc->w_cpos, wc->w_clen, UINT_MAX); |
1686 | if (ret) { | 1726 | if (ret) { |
@@ -1695,6 +1735,7 @@ int ocfs2_write_begin_nolock(struct file *filp, | |||
1695 | mlog_errno(ret); | 1735 | mlog_errno(ret); |
1696 | goto out; | 1736 | goto out; |
1697 | } | 1737 | } |
1738 | clusters_need += clusters_to_alloc; | ||
1698 | 1739 | ||
1699 | di = (struct ocfs2_dinode *)wc->w_di_bh->b_data; | 1740 | di = (struct ocfs2_dinode *)wc->w_di_bh->b_data; |
1700 | 1741 | ||
@@ -1817,6 +1858,22 @@ out: | |||
1817 | ocfs2_free_alloc_context(data_ac); | 1858 | ocfs2_free_alloc_context(data_ac); |
1818 | if (meta_ac) | 1859 | if (meta_ac) |
1819 | ocfs2_free_alloc_context(meta_ac); | 1860 | ocfs2_free_alloc_context(meta_ac); |
1861 | |||
1862 | if (ret == -ENOSPC && try_free) { | ||
1863 | /* | ||
1864 | * Try to free some truncate log so that we can have enough | ||
1865 | * clusters to allocate. | ||
1866 | */ | ||
1867 | try_free = 0; | ||
1868 | |||
1869 | ret1 = ocfs2_try_to_free_truncate_log(osb, clusters_need); | ||
1870 | if (ret1 == 1) | ||
1871 | goto try_again; | ||
1872 | |||
1873 | if (ret1 < 0) | ||
1874 | mlog_errno(ret1); | ||
1875 | } | ||
1876 | |||
1820 | return ret; | 1877 | return ret; |
1821 | } | 1878 | } |
1822 | 1879 | ||