diff options
author | Taesoo Kim <tsgatesv@gmail.com> | 2015-03-25 18:55:29 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-03-25 19:20:31 -0400 |
commit | 3d5d472cf55d1be091e8a145f80602bf435ece85 (patch) | |
tree | b7dabd4ff6599771ec9dc19beacb60ebf23bb352 /fs | |
parent | cfa869438282be84ad4110bba5027ef1fbbe71e4 (diff) |
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>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/affs/file.c | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/fs/affs/file.c b/fs/affs/file.c index d2468bf95669..a91795e01a7f 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c | |||
@@ -699,8 +699,10 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping, | |||
699 | boff = tmp % bsize; | 699 | boff = tmp % bsize; |
700 | if (boff) { | 700 | if (boff) { |
701 | bh = affs_bread_ino(inode, bidx, 0); | 701 | bh = affs_bread_ino(inode, bidx, 0); |
702 | if (IS_ERR(bh)) | 702 | if (IS_ERR(bh)) { |
703 | return PTR_ERR(bh); | 703 | written = PTR_ERR(bh); |
704 | goto err_first_bh; | ||
705 | } | ||
704 | tmp = min(bsize - boff, to - from); | 706 | tmp = min(bsize - boff, to - from); |
705 | BUG_ON(boff + tmp > bsize || tmp > bsize); | 707 | BUG_ON(boff + tmp > bsize || tmp > bsize); |
706 | memcpy(AFFS_DATA(bh) + boff, data + from, tmp); | 708 | 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, | |||
712 | bidx++; | 714 | bidx++; |
713 | } else if (bidx) { | 715 | } else if (bidx) { |
714 | bh = affs_bread_ino(inode, bidx - 1, 0); | 716 | bh = affs_bread_ino(inode, bidx - 1, 0); |
715 | if (IS_ERR(bh)) | 717 | if (IS_ERR(bh)) { |
716 | return PTR_ERR(bh); | 718 | written = PTR_ERR(bh); |
719 | goto err_first_bh; | ||
720 | } | ||
717 | } | 721 | } |
718 | while (from + bsize <= to) { | 722 | while (from + bsize <= to) { |
719 | prev_bh = bh; | 723 | prev_bh = bh; |
720 | bh = affs_getemptyblk_ino(inode, bidx); | 724 | bh = affs_getemptyblk_ino(inode, bidx); |
721 | if (IS_ERR(bh)) | 725 | if (IS_ERR(bh)) |
722 | goto out; | 726 | goto err_bh; |
723 | memcpy(AFFS_DATA(bh), data + from, bsize); | 727 | memcpy(AFFS_DATA(bh), data + from, bsize); |
724 | if (buffer_new(bh)) { | 728 | if (buffer_new(bh)) { |
725 | AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA); | 729 | 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, | |||
751 | prev_bh = bh; | 755 | prev_bh = bh; |
752 | bh = affs_bread_ino(inode, bidx, 1); | 756 | bh = affs_bread_ino(inode, bidx, 1); |
753 | if (IS_ERR(bh)) | 757 | if (IS_ERR(bh)) |
754 | goto out; | 758 | goto err_bh; |
755 | tmp = min(bsize, to - from); | 759 | tmp = min(bsize, to - from); |
756 | BUG_ON(tmp > bsize); | 760 | BUG_ON(tmp > bsize); |
757 | memcpy(AFFS_DATA(bh), data + from, tmp); | 761 | memcpy(AFFS_DATA(bh), data + from, tmp); |
@@ -790,12 +794,13 @@ done: | |||
790 | if (tmp > inode->i_size) | 794 | if (tmp > inode->i_size) |
791 | inode->i_size = AFFS_I(inode)->mmu_private = tmp; | 795 | inode->i_size = AFFS_I(inode)->mmu_private = tmp; |
792 | 796 | ||
797 | err_first_bh: | ||
793 | unlock_page(page); | 798 | unlock_page(page); |
794 | page_cache_release(page); | 799 | page_cache_release(page); |
795 | 800 | ||
796 | return written; | 801 | return written; |
797 | 802 | ||
798 | out: | 803 | err_bh: |
799 | bh = prev_bh; | 804 | bh = prev_bh; |
800 | if (!written) | 805 | if (!written) |
801 | written = PTR_ERR(bh); | 806 | written = PTR_ERR(bh); |