diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-02-14 13:14:59 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-02-14 13:14:59 -0500 |
| commit | 6556677a80400ca5744340d8ff6fbed22621293e (patch) | |
| tree | bca737a2d803b775016daf8996548d1cedc9e020 | |
| parent | 694a20dae6efc3803740971fa9f7c86b8c8d4685 (diff) | |
| parent | 49edd5bf429c405b3a7f75503845d9f66a47dd4b (diff) | |
Merge tag 'gfs2-4.16.rc1.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2
Pull gfs2 fix from Bob Peterson:
"Fix regressions in the gfs2 iomap for block_map implementation we
recently discovered in commit 3974320ca6"
* tag 'gfs2-4.16.rc1.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2:
gfs2: Fixes to "Implement iomap for block_map"
| -rw-r--r-- | fs/gfs2/bmap.c | 43 |
1 files changed, 23 insertions, 20 deletions
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 86863792f36a..86d6a4435c87 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c | |||
| @@ -716,7 +716,7 @@ int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length, | |||
| 716 | __be64 *ptr; | 716 | __be64 *ptr; |
| 717 | sector_t lblock; | 717 | sector_t lblock; |
| 718 | sector_t lend; | 718 | sector_t lend; |
| 719 | int ret; | 719 | int ret = 0; |
| 720 | int eob; | 720 | int eob; |
| 721 | unsigned int len; | 721 | unsigned int len; |
| 722 | struct buffer_head *bh; | 722 | struct buffer_head *bh; |
| @@ -728,12 +728,14 @@ int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length, | |||
| 728 | goto out; | 728 | goto out; |
| 729 | } | 729 | } |
| 730 | 730 | ||
| 731 | if ((flags & IOMAP_REPORT) && gfs2_is_stuffed(ip)) { | 731 | if (gfs2_is_stuffed(ip)) { |
| 732 | gfs2_stuffed_iomap(inode, iomap); | 732 | if (flags & IOMAP_REPORT) { |
| 733 | if (pos >= iomap->length) | 733 | gfs2_stuffed_iomap(inode, iomap); |
| 734 | return -ENOENT; | 734 | if (pos >= iomap->length) |
| 735 | ret = 0; | 735 | ret = -ENOENT; |
| 736 | goto out; | 736 | goto out; |
| 737 | } | ||
| 738 | BUG_ON(!(flags & IOMAP_WRITE)); | ||
| 737 | } | 739 | } |
| 738 | 740 | ||
| 739 | lblock = pos >> inode->i_blkbits; | 741 | lblock = pos >> inode->i_blkbits; |
| @@ -744,7 +746,7 @@ int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length, | |||
| 744 | iomap->type = IOMAP_HOLE; | 746 | iomap->type = IOMAP_HOLE; |
| 745 | iomap->length = (u64)(lend - lblock) << inode->i_blkbits; | 747 | iomap->length = (u64)(lend - lblock) << inode->i_blkbits; |
| 746 | iomap->flags = IOMAP_F_MERGED; | 748 | iomap->flags = IOMAP_F_MERGED; |
| 747 | bmap_lock(ip, 0); | 749 | bmap_lock(ip, flags & IOMAP_WRITE); |
| 748 | 750 | ||
| 749 | /* | 751 | /* |
| 750 | * Directory data blocks have a struct gfs2_meta_header header, so the | 752 | * Directory data blocks have a struct gfs2_meta_header header, so the |
| @@ -787,27 +789,28 @@ int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length, | |||
| 787 | iomap->flags |= IOMAP_F_BOUNDARY; | 789 | iomap->flags |= IOMAP_F_BOUNDARY; |
| 788 | iomap->length = (u64)len << inode->i_blkbits; | 790 | iomap->length = (u64)len << inode->i_blkbits; |
| 789 | 791 | ||
| 790 | ret = 0; | ||
| 791 | |||
| 792 | out_release: | 792 | out_release: |
| 793 | release_metapath(&mp); | 793 | release_metapath(&mp); |
| 794 | bmap_unlock(ip, 0); | 794 | bmap_unlock(ip, flags & IOMAP_WRITE); |
| 795 | out: | 795 | out: |
| 796 | trace_gfs2_iomap_end(ip, iomap, ret); | 796 | trace_gfs2_iomap_end(ip, iomap, ret); |
| 797 | return ret; | 797 | return ret; |
| 798 | 798 | ||
| 799 | do_alloc: | 799 | do_alloc: |
| 800 | if (!(flags & IOMAP_WRITE)) { | 800 | if (flags & IOMAP_WRITE) { |
| 801 | if (pos >= i_size_read(inode)) { | 801 | ret = gfs2_iomap_alloc(inode, iomap, flags, &mp); |
| 802 | } else if (flags & IOMAP_REPORT) { | ||
| 803 | loff_t size = i_size_read(inode); | ||
| 804 | if (pos >= size) | ||
| 802 | ret = -ENOENT; | 805 | ret = -ENOENT; |
| 803 | goto out_release; | 806 | else if (height <= ip->i_height) |
| 804 | } | 807 | iomap->length = hole_size(inode, lblock, &mp); |
| 805 | ret = 0; | 808 | else |
| 806 | iomap->length = hole_size(inode, lblock, &mp); | 809 | iomap->length = size - pos; |
| 807 | goto out_release; | 810 | } else { |
| 811 | if (height <= ip->i_height) | ||
| 812 | iomap->length = hole_size(inode, lblock, &mp); | ||
| 808 | } | 813 | } |
| 809 | |||
| 810 | ret = gfs2_iomap_alloc(inode, iomap, flags, &mp); | ||
| 811 | goto out_release; | 814 | goto out_release; |
| 812 | } | 815 | } |
| 813 | 816 | ||
