|
@@ -1459,7 +1459,7 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
|
|
|
struct page **pagep, void **fsdata)
|
|
|
{
|
|
|
struct inode *inode = mapping->host;
|
|
|
- int ret, needed_blocks = ext4_writepage_trans_blocks(inode);
|
|
|
+ int ret, needed_blocks;
|
|
|
handle_t *handle;
|
|
|
int retries = 0;
|
|
|
struct page *page;
|
|
@@ -1470,6 +1470,11 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
|
|
|
"dev %s ino %lu pos %llu len %u flags %u",
|
|
|
inode->i_sb->s_id, inode->i_ino,
|
|
|
(unsigned long long) pos, len, flags);
|
|
|
+ /*
|
|
|
+ * Reserve one block more for addition to orphan list in case
|
|
|
+ * we allocate blocks but write fails for some reason
|
|
|
+ */
|
|
|
+ needed_blocks = ext4_writepage_trans_blocks(inode) + 1;
|
|
|
index = pos >> PAGE_CACHE_SHIFT;
|
|
|
from = pos & (PAGE_CACHE_SIZE - 1);
|
|
|
to = from + len;
|
|
@@ -1503,15 +1508,30 @@ retry:
|
|
|
|
|
|
if (ret) {
|
|
|
unlock_page(page);
|
|
|
- ext4_journal_stop(handle);
|
|
|
page_cache_release(page);
|
|
|
/*
|
|
|
* block_write_begin may have instantiated a few blocks
|
|
|
* outside i_size. Trim these off again. Don't need
|
|
|
* i_size_read because we hold i_mutex.
|
|
|
+ *
|
|
|
+ * Add inode to orphan list in case we crash before
|
|
|
+ * truncate finishes
|
|
|
*/
|
|
|
if (pos + len > inode->i_size)
|
|
|
+ ext4_orphan_add(handle, inode);
|
|
|
+
|
|
|
+ ext4_journal_stop(handle);
|
|
|
+ if (pos + len > inode->i_size) {
|
|
|
vmtruncate(inode, inode->i_size);
|
|
|
+ /*
|
|
|
+ * If vmtruncate failed early the inode might
|
|
|
+ * still be on the orphan list; we need to
|
|
|
+ * make sure the inode is removed from the
|
|
|
+ * orphan list in that case.
|
|
|
+ */
|
|
|
+ if (inode->i_nlink)
|
|
|
+ ext4_orphan_del(NULL, inode);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
|