summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2015-06-16 18:06:40 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2015-07-06 17:39:21 -0400
commit3b7a3a05e8b006a73c406230b3d2d3da920779d9 (patch)
tree84f527922d2d9d596c51e1f638b35bb6b31ca00f
parentd622f167b8435c856376edec130053fb56bf83e4 (diff)
downloadlinux-stable-3b7a3a05e8b006a73c406230b3d2d3da920779d9.tar.gz
linux-stable-3b7a3a05e8b006a73c406230b3d2d3da920779d9.tar.bz2
linux-stable-3b7a3a05e8b006a73c406230b3d2d3da920779d9.zip
ufs: free excessive blocks upon ->write_begin() failure/short copy
Broken in "[PATCH] ufs: truncate should allocate block for last byte"; all way back in 2006. ufs_setattr() hadn't been the only user of vmtruncate() and eliminating ->truncate() method required corrections in a bunch of places. Eventually those places had migrated into ->write_begin() failure exit and ->write_end() after short copy... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/ufs/inode.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index 282b0ced6272..a4fc3adfdc4c 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -530,8 +530,10 @@ static void ufs_write_failed(struct address_space *mapping, loff_t to)
{
struct inode *inode = mapping->host;
- if (to > inode->i_size)
+ if (to > inode->i_size) {
truncate_pagecache(inode, inode->i_size);
+ ufs_truncate_blocks(inode);
+ }
}
static int ufs_write_begin(struct file *file, struct address_space *mapping,
@@ -548,6 +550,18 @@ static int ufs_write_begin(struct file *file, struct address_space *mapping,
return ret;
}
+static int ufs_write_end(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *page, void *fsdata)
+{
+ int ret;
+
+ ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
+ if (ret < len)
+ ufs_write_failed(mapping, pos + len);
+ return ret;
+}
+
static sector_t ufs_bmap(struct address_space *mapping, sector_t block)
{
return generic_block_bmap(mapping,block,ufs_getfrag_block);
@@ -557,7 +571,7 @@ const struct address_space_operations ufs_aops = {
.readpage = ufs_readpage,
.writepage = ufs_writepage,
.write_begin = ufs_write_begin,
- .write_end = generic_write_end,
+ .write_end = ufs_write_end,
.bmap = ufs_bmap
};