aboutsummaryrefslogtreecommitdiffstats
path: root/fs/logfs/readwrite.c
diff options
context:
space:
mode:
authorJoern Engel <joern@logfs.org>2010-04-20 15:44:10 -0400
committerJoern Engel <joern@logfs.org>2010-04-20 15:44:10 -0400
commitb6349ac89eacb813f6963f7263da05bc3f483351 (patch)
tree6027a84ee332ea1598d1ac66d9345770da38d5fe /fs/logfs/readwrite.c
parentb8639077abf034824046ed09e779b74c4393031f (diff)
[LogFS] Split large truncated into smaller chunks
Truncate would do an almost limitless amount of work without invoking the garbage collector in between. Split it up into more manageable, though still large, chunks. Signed-off-by: Joern Engel <joern@logfs.org>
Diffstat (limited to 'fs/logfs/readwrite.c')
-rw-r--r--fs/logfs/readwrite.c34
1 files changed, 26 insertions, 8 deletions
diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c
index aca6c56a107..7e3a1e5fd76 100644
--- a/fs/logfs/readwrite.c
+++ b/fs/logfs/readwrite.c
@@ -1837,19 +1837,37 @@ static int __logfs_truncate(struct inode *inode, u64 size)
1837 return logfs_truncate_direct(inode, size); 1837 return logfs_truncate_direct(inode, size);
1838} 1838}
1839 1839
1840int logfs_truncate(struct inode *inode, u64 size) 1840/*
1841 * Truncate, by changing the segment file, can consume a fair amount
1842 * of resources. So back off from time to time and do some GC.
1843 * 8 or 2048 blocks should be well within safety limits even if
1844 * every single block resided in a different segment.
1845 */
1846#define TRUNCATE_STEP (8 * 1024 * 1024)
1847int logfs_truncate(struct inode *inode, u64 target)
1841{ 1848{
1842 struct super_block *sb = inode->i_sb; 1849 struct super_block *sb = inode->i_sb;
1843 int err; 1850 u64 size = i_size_read(inode);
1851 int err = 0;
1844 1852
1845 logfs_get_wblocks(sb, NULL, 1); 1853 size = ALIGN(size, TRUNCATE_STEP);
1846 err = __logfs_truncate(inode, size); 1854 while (size > target) {
1847 if (!err) 1855 if (size > TRUNCATE_STEP)
1848 err = __logfs_write_inode(inode, 0); 1856 size -= TRUNCATE_STEP;
1849 logfs_put_wblocks(sb, NULL, 1); 1857 else
1858 size = 0;
1859 if (size < target)
1860 size = target;
1861
1862 logfs_get_wblocks(sb, NULL, 1);
1863 err = __logfs_truncate(inode, target);
1864 if (!err)
1865 err = __logfs_write_inode(inode, 0);
1866 logfs_put_wblocks(sb, NULL, 1);
1867 }
1850 1868
1851 if (!err) 1869 if (!err)
1852 err = vmtruncate(inode, size); 1870 err = vmtruncate(inode, target);
1853 1871
1854 /* I don't trust error recovery yet. */ 1872 /* I don't trust error recovery yet. */
1855 WARN_ON(err); 1873 WARN_ON(err);