diff options
| author | Andrew Morton <akpm@osdl.org> | 2004-05-09 23:55:16 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-05-09 23:55:16 -0700 |
| commit | e736428d8be55699f3d9626f5196402a3702575b (patch) | |
| tree | 47417350208b665029ca60afb29f3f470238e395 | |
| parent | 774882ea14069557c58def6000c2b390261fb746 (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.c | 17 |
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), |
