aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-02-14 13:14:59 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2018-02-14 13:14:59 -0500
commit6556677a80400ca5744340d8ff6fbed22621293e (patch)
treebca737a2d803b775016daf8996548d1cedc9e020
parent694a20dae6efc3803740971fa9f7c86b8c8d4685 (diff)
parent49edd5bf429c405b3a7f75503845d9f66a47dd4b (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.c43
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
792out_release: 792out_release:
793 release_metapath(&mp); 793 release_metapath(&mp);
794 bmap_unlock(ip, 0); 794 bmap_unlock(ip, flags & IOMAP_WRITE);
795out: 795out:
796 trace_gfs2_iomap_end(ip, iomap, ret); 796 trace_gfs2_iomap_end(ip, iomap, ret);
797 return ret; 797 return ret;
798 798
799do_alloc: 799do_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