|
@@ -2538,6 +2538,12 @@ static int reiserfs_writepage(struct page *page, struct writeback_control *wbc)
|
|
|
return reiserfs_write_full_page(page, wbc);
|
|
|
}
|
|
|
|
|
|
+static void reiserfs_truncate_failed_write(struct inode *inode)
|
|
|
+{
|
|
|
+ truncate_inode_pages(inode->i_mapping, inode->i_size);
|
|
|
+ reiserfs_truncate_file(inode, 0);
|
|
|
+}
|
|
|
+
|
|
|
static int reiserfs_write_begin(struct file *file,
|
|
|
struct address_space *mapping,
|
|
|
loff_t pos, unsigned len, unsigned flags,
|
|
@@ -2604,6 +2610,8 @@ static int reiserfs_write_begin(struct file *file,
|
|
|
if (ret) {
|
|
|
unlock_page(page);
|
|
|
page_cache_release(page);
|
|
|
+ /* Truncate allocated blocks */
|
|
|
+ reiserfs_truncate_failed_write(inode);
|
|
|
}
|
|
|
return ret;
|
|
|
}
|
|
@@ -2701,9 +2709,7 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
|
|
|
** transaction tracking stuff when the size changes. So, we have
|
|
|
** to do the i_size updates here.
|
|
|
*/
|
|
|
- pos += copied;
|
|
|
-
|
|
|
- if (pos > inode->i_size) {
|
|
|
+ if (pos + copied > inode->i_size) {
|
|
|
struct reiserfs_transaction_handle myth;
|
|
|
lock_depth = reiserfs_write_lock_once(inode->i_sb);
|
|
|
locked = true;
|
|
@@ -2721,7 +2727,7 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
|
|
|
goto journal_error;
|
|
|
|
|
|
reiserfs_update_inode_transaction(inode);
|
|
|
- inode->i_size = pos;
|
|
|
+ inode->i_size = pos + copied;
|
|
|
/*
|
|
|
* this will just nest into our transaction. It's important
|
|
|
* to use mark_inode_dirty so the inode gets pushed around on the
|
|
@@ -2751,6 +2757,10 @@ static int reiserfs_write_end(struct file *file, struct address_space *mapping,
|
|
|
reiserfs_write_unlock_once(inode->i_sb, lock_depth);
|
|
|
unlock_page(page);
|
|
|
page_cache_release(page);
|
|
|
+
|
|
|
+ if (pos + len > inode->i_size)
|
|
|
+ reiserfs_truncate_failed_write(inode);
|
|
|
+
|
|
|
return ret == 0 ? copied : ret;
|
|
|
|
|
|
journal_error:
|