diff options
Diffstat (limited to 'fs/ocfs2')
-rw-r--r-- | fs/ocfs2/alloc.c | 3 | ||||
-rw-r--r-- | fs/ocfs2/aops.c | 59 | ||||
-rw-r--r-- | fs/ocfs2/ocfs2.h | 5 |
3 files changed, 66 insertions, 1 deletions
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 592fae5007d1..8ec418dd9e36 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
@@ -5858,6 +5858,7 @@ int ocfs2_truncate_log_append(struct ocfs2_super *osb, | |||
5858 | 5858 | ||
5859 | ocfs2_journal_dirty(handle, tl_bh); | 5859 | ocfs2_journal_dirty(handle, tl_bh); |
5860 | 5860 | ||
5861 | osb->truncated_clusters += num_clusters; | ||
5861 | bail: | 5862 | bail: |
5862 | mlog_exit(status); | 5863 | mlog_exit(status); |
5863 | return status; | 5864 | return status; |
@@ -5929,6 +5930,8 @@ static int ocfs2_replay_truncate_records(struct ocfs2_super *osb, | |||
5929 | i--; | 5930 | i--; |
5930 | } | 5931 | } |
5931 | 5932 | ||
5933 | osb->truncated_clusters = 0; | ||
5934 | |||
5932 | bail: | 5935 | bail: |
5933 | mlog_exit(status); | 5936 | mlog_exit(status); |
5934 | return status; | 5937 | return status; |
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 | ||
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 70dd3b1798f1..51cd6898e7f1 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h | |||
@@ -420,6 +420,11 @@ struct ocfs2_super | |||
420 | struct inode *osb_tl_inode; | 420 | struct inode *osb_tl_inode; |
421 | struct buffer_head *osb_tl_bh; | 421 | struct buffer_head *osb_tl_bh; |
422 | struct delayed_work osb_truncate_log_wq; | 422 | struct delayed_work osb_truncate_log_wq; |
423 | /* | ||
424 | * How many clusters in our truncate log. | ||
425 | * It must be protected by osb_tl_inode->i_mutex. | ||
426 | */ | ||
427 | unsigned int truncated_clusters; | ||
423 | 428 | ||
424 | struct ocfs2_node_map osb_recovering_orphan_dirs; | 429 | struct ocfs2_node_map osb_recovering_orphan_dirs; |
425 | unsigned int *osb_orphan_wipes; | 430 | unsigned int *osb_orphan_wipes; |