fs/affs/file.c: unlock/release page on error

When affs_bread_ino() fails, correctly unlock the page and release the
page cache with proper error value.  All write_end() should
unlock/release the page that was locked by write_beg().

Signed-off-by: Taesoo Kim <tsgatesv@gmail.com>
Cc: Fabian Frederick <fabf@skynet.be>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Jan Kara <jack@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Taesoo Kim 2015-03-25 15:55:29 -07:00 committed by Linus Torvalds
parent cfa8694382
commit 3d5d472cf5

View File

@ -699,8 +699,10 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
boff = tmp % bsize; boff = tmp % bsize;
if (boff) { if (boff) {
bh = affs_bread_ino(inode, bidx, 0); bh = affs_bread_ino(inode, bidx, 0);
if (IS_ERR(bh)) if (IS_ERR(bh)) {
return PTR_ERR(bh); written = PTR_ERR(bh);
goto err_first_bh;
}
tmp = min(bsize - boff, to - from); tmp = min(bsize - boff, to - from);
BUG_ON(boff + tmp > bsize || tmp > bsize); BUG_ON(boff + tmp > bsize || tmp > bsize);
memcpy(AFFS_DATA(bh) + boff, data + from, tmp); memcpy(AFFS_DATA(bh) + boff, data + from, tmp);
@ -712,14 +714,16 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
bidx++; bidx++;
} else if (bidx) { } else if (bidx) {
bh = affs_bread_ino(inode, bidx - 1, 0); bh = affs_bread_ino(inode, bidx - 1, 0);
if (IS_ERR(bh)) if (IS_ERR(bh)) {
return PTR_ERR(bh); written = PTR_ERR(bh);
goto err_first_bh;
}
} }
while (from + bsize <= to) { while (from + bsize <= to) {
prev_bh = bh; prev_bh = bh;
bh = affs_getemptyblk_ino(inode, bidx); bh = affs_getemptyblk_ino(inode, bidx);
if (IS_ERR(bh)) if (IS_ERR(bh))
goto out; goto err_bh;
memcpy(AFFS_DATA(bh), data + from, bsize); memcpy(AFFS_DATA(bh), data + from, bsize);
if (buffer_new(bh)) { if (buffer_new(bh)) {
AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA); AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);
@ -751,7 +755,7 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
prev_bh = bh; prev_bh = bh;
bh = affs_bread_ino(inode, bidx, 1); bh = affs_bread_ino(inode, bidx, 1);
if (IS_ERR(bh)) if (IS_ERR(bh))
goto out; goto err_bh;
tmp = min(bsize, to - from); tmp = min(bsize, to - from);
BUG_ON(tmp > bsize); BUG_ON(tmp > bsize);
memcpy(AFFS_DATA(bh), data + from, tmp); memcpy(AFFS_DATA(bh), data + from, tmp);
@ -790,12 +794,13 @@ done:
if (tmp > inode->i_size) if (tmp > inode->i_size)
inode->i_size = AFFS_I(inode)->mmu_private = tmp; inode->i_size = AFFS_I(inode)->mmu_private = tmp;
err_first_bh:
unlock_page(page); unlock_page(page);
page_cache_release(page); page_cache_release(page);
return written; return written;
out: err_bh:
bh = prev_bh; bh = prev_bh;
if (!written) if (!written)
written = PTR_ERR(bh); written = PTR_ERR(bh);