diff options
author | Nick Piggin <nickpiggin@yahoo.com.au> | 2007-10-19 03:16:53 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2007-10-22 05:24:44 -0400 |
commit | 2a754b51aacb122cec25c849e3cf7f5503cc3ec6 (patch) | |
tree | 679a7b65a8a031904d2098d4133de07045ee0ca6 /fs | |
parent | c21f900cb8817009930e672d22a5b91e5b706351 (diff) |
[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>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/jffs2/file.c | 11 |
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, | |||
255 | _whole_ page. This helps to reduce the number of | 255 | _whole_ page. This helps to reduce the number of |
256 | nodes in files which have many short writes, like | 256 | nodes in files which have many short writes, like |
257 | syslog files. */ | 257 | syslog files. */ |
258 | start = aligned_start = 0; | 258 | aligned_start = 0; |
259 | } | 259 | } |
260 | 260 | ||
261 | ri = jffs2_alloc_raw_inode(); | 261 | ri = jffs2_alloc_raw_inode(); |
@@ -291,14 +291,11 @@ static int jffs2_write_end(struct file *filp, struct address_space *mapping, | |||
291 | } | 291 | } |
292 | 292 | ||
293 | /* Adjust writtenlen for the padding we did, so we don't confuse our caller */ | 293 | /* Adjust writtenlen for the padding we did, so we don't confuse our caller */ |
294 | if (writtenlen < (start&3)) | 294 | writtenlen -= min(writtenlen, (start - aligned_start)); |
295 | writtenlen = 0; | ||
296 | else | ||
297 | writtenlen -= (start&3); | ||
298 | 295 | ||
299 | if (writtenlen) { | 296 | if (writtenlen) { |
300 | if (inode->i_size < (pg->index << PAGE_CACHE_SHIFT) + start + writtenlen) { | 297 | if (inode->i_size < pos + writtenlen) { |
301 | inode->i_size = (pg->index << PAGE_CACHE_SHIFT) + start + writtenlen; | 298 | inode->i_size = pos + writtenlen; |
302 | inode->i_blocks = (inode->i_size + 511) >> 9; | 299 | inode->i_blocks = (inode->i_size + 511) >> 9; |
303 | 300 | ||
304 | inode->i_ctime = inode->i_mtime = ITIME(je32_to_cpu(ri->ctime)); | 301 | inode->i_ctime = inode->i_mtime = ITIME(je32_to_cpu(ri->ctime)); |