summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Piggin <nickpiggin@yahoo.com.au>2007-10-19 17:16:53 +1000
committerDavid Woodhouse <dwmw2@infradead.org>2007-10-22 10:24:44 +0100
commit2a754b51aacb122cec25c849e3cf7f5503cc3ec6 (patch)
tree679a7b65a8a031904d2098d4133de07045ee0ca6
parentc21f900cb8817009930e672d22a5b91e5b706351 (diff)
downloadlinux-2a754b51aacb122cec25c849e3cf7f5503cc3ec6.tar.gz
linux-2a754b51aacb122cec25c849e3cf7f5503cc3ec6.tar.bz2
linux-2a754b51aacb122cec25c849e3cf7f5503cc3ec6.zip
[JFFS2] Fix return value from jffs2_write_end()
jffs2_write_end() is sometimes passing back a "written" length greater than the length we passed into it, leading to a BUG at mm/filemap.c:1749 when used with unionfs. It happens because we actually write more than was requested, to reduce log fragmentation. These "longer" writes are fine, but they shouldn't get propagated back to the vm/vfs. Signed-off-by: Nick Piggin <npiggin@suse.de> Signed-off-by: David Woodhouse <dwmw2@infradead.org>
-rw-r--r--fs/jffs2/file.c11
1 files changed, 4 insertions, 7 deletions
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 023a17539dd4..f9c5dd6f4b64 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -255,7 +255,7 @@ static int jffs2_write_end(struct file *filp, struct address_space *mapping,
_whole_ page. This helps to reduce the number of
nodes in files which have many short writes, like
syslog files. */
- start = aligned_start = 0;
+ aligned_start = 0;
}
ri = jffs2_alloc_raw_inode();
@@ -291,14 +291,11 @@ static int jffs2_write_end(struct file *filp, struct address_space *mapping,
}
/* Adjust writtenlen for the padding we did, so we don't confuse our caller */
- if (writtenlen < (start&3))
- writtenlen = 0;
- else
- writtenlen -= (start&3);
+ writtenlen -= min(writtenlen, (start - aligned_start));
if (writtenlen) {
- if (inode->i_size < (pg->index << PAGE_CACHE_SHIFT) + start + writtenlen) {
- inode->i_size = (pg->index << PAGE_CACHE_SHIFT) + start + writtenlen;
+ if (inode->i_size < pos + writtenlen) {
+ inode->i_size = pos + writtenlen;
inode->i_blocks = (inode->i_size + 511) >> 9;
inode->i_ctime = inode->i_mtime = ITIME(je32_to_cpu(ri->ctime));