mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 21:38:32 +08:00
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:
parent
cfa8694382
commit
3d5d472cf5
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user