aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/aops.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-01-11 14:28:34 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-11 14:28:34 -0500
commit498f7f505dc79934c878c7667840c50c64f232fc (patch)
tree67eca6dcb6fe76ec3d2bdef5e3102591fe957776 /fs/ocfs2/aops.c
parent0969d11e201b82d30a158ccdb3aca67a7b845613 (diff)
parentd6351db2073315ddebac72cc1935e912f60f86e0 (diff)
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2
* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2: (22 commits) MAINTAINERS: Update Joel Becker's email address ocfs2: Remove unused truncate function from alloc.c ocfs2/cluster: dereferencing before checking in nst_seq_show() ocfs2: fix build for OCFS2_FS_STATS not enabled ocfs2/cluster: Show o2net timing statistics ocfs2/cluster: Track process message timing stats for each socket ocfs2/cluster: Track send message timing stats for each socket ocfs2/cluster: Use ktime instead of timeval in struct o2net_sock_container ocfs2/cluster: Replace timeval with ktime in struct o2net_send_tracking ocfs2: Add DEBUG_FS dependency ocfs2/dlm: Hard code the values for enums ocfs2/dlm: Minor cleanup ocfs2/dlm: Cleanup dlmdebug.c ocfs2: Release buffer_head in case of error in ocfs2_double_lock. ocfs2/cluster: Pin the local node when o2hb thread starts ocfs2/cluster: Show pin state for each o2hb region ocfs2/cluster: Pin/unpin o2hb regions ocfs2/cluster: Remove dropped region from o2hb quorum region bitmap ocfs2/cluster: Pin the remote node item in configfs ocfs2/dlm: make existing convertion precedent over new lock ...
Diffstat (limited to 'fs/ocfs2/aops.c')
-rw-r--r--fs/ocfs2/aops.c59
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 */
1638static 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 }
1666out:
1667 return ret;
1668}
1669
1633int ocfs2_write_begin_nolock(struct file *filp, 1670int 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
1688try_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