summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Morton <akpm@osdl.org>2004-05-09 23:55:16 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-05-09 23:55:16 -0700
commite736428d8be55699f3d9626f5196402a3702575b (patch)
tree47417350208b665029ca60afb29f3f470238e395
parent774882ea14069557c58def6000c2b390261fb746 (diff)
[PATCH] Fix ext3 bogus ENOSPC
With strange workloads which do a lot of quick truncation on small filesystems it is possible to get into a situation where there are free blocks on the disk, but they are not allocatable at this time due to their having been freed up in the current JBD transaction. Applications get unexpected ENOSPC errors. We can fix that with this patch, originally by Andreas Dilger which forces a single commit+retry when an ENOSPC is encountered.
-rw-r--r--fs/ext3/inode.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index b76259edea9b..b0456fd965bd 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -1081,15 +1081,28 @@ static int ext3_prepare_write(struct file *file, struct page *page,
struct inode *inode = page->mapping->host;
int ret, needed_blocks = ext3_writepage_trans_blocks(inode);
handle_t *handle;
+ int tried_commit = 0;
+retry:
handle = ext3_journal_start(inode, needed_blocks);
if (IS_ERR(handle)) {
ret = PTR_ERR(handle);
goto out;
}
ret = block_prepare_write(page, from, to, ext3_get_block);
- if (ret != 0)
- goto prepare_write_failed;
+ if (ret) {
+ if (ret != -ENOSPC || tried_commit)
+ goto prepare_write_failed;
+ /*
+ * It could be that there _is_ free space, but it's all tied up
+ * in uncommitted bitmaps. So force a commit here, which makes
+ * those blocks allocatable and try again.
+ */
+ tried_commit = 1;
+ handle->h_sync = 1;
+ ext3_journal_stop(handle);
+ goto retry;
+ }
if (ext3_should_journal_data(inode)) {
ret = walk_page_buffers(handle, page_buffers(page),