| From c0bb334fa20ad338a0560d6d4daa3d96fd43685c Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 20 Apr 2020 19:42:04 +0200 |
| Subject: gfs2: Another gfs2_walk_metadata fix |
| |
| From: Andreas Gruenbacher <agruenba@redhat.com> |
| |
| [ Upstream commit 566a2ab3c9005f62e784bd39022d58d34ef4365c ] |
| |
| Make sure we don't walk past the end of the metadata in gfs2_walk_metadata: the |
| inode holds fewer pointers than indirect blocks. |
| |
| Slightly clean up gfs2_iomap_get. |
| |
| Fixes: a27a0c9b6a20 ("gfs2: gfs2_walk_metadata fix") |
| Cc: stable@vger.kernel.org # v5.3+ |
| Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> |
| Signed-off-by: Bob Peterson <rpeterso@redhat.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| fs/gfs2/bmap.c | 16 +++++++++------- |
| 1 file changed, 9 insertions(+), 7 deletions(-) |
| |
| diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c |
| index 08f6fbb3655e2..31ed264356253 100644 |
| --- a/fs/gfs2/bmap.c |
| +++ b/fs/gfs2/bmap.c |
| @@ -528,10 +528,12 @@ static int gfs2_walk_metadata(struct inode *inode, struct metapath *mp, |
| |
| /* Advance in metadata tree. */ |
| (mp->mp_list[hgt])++; |
| - if (mp->mp_list[hgt] >= sdp->sd_inptrs) { |
| - if (!hgt) |
| + if (hgt) { |
| + if (mp->mp_list[hgt] >= sdp->sd_inptrs) |
| + goto lower_metapath; |
| + } else { |
| + if (mp->mp_list[hgt] >= sdp->sd_diptrs) |
| break; |
| - goto lower_metapath; |
| } |
| |
| fill_up_metapath: |
| @@ -876,10 +878,9 @@ static int gfs2_iomap_get(struct inode *inode, loff_t pos, loff_t length, |
| ret = -ENOENT; |
| goto unlock; |
| } else { |
| - /* report a hole */ |
| iomap->offset = pos; |
| iomap->length = length; |
| - goto do_alloc; |
| + goto hole_found; |
| } |
| } |
| iomap->length = size; |
| @@ -933,8 +934,6 @@ static int gfs2_iomap_get(struct inode *inode, loff_t pos, loff_t length, |
| return ret; |
| |
| do_alloc: |
| - iomap->addr = IOMAP_NULL_ADDR; |
| - iomap->type = IOMAP_HOLE; |
| if (flags & IOMAP_REPORT) { |
| if (pos >= size) |
| ret = -ENOENT; |
| @@ -956,6 +955,9 @@ static int gfs2_iomap_get(struct inode *inode, loff_t pos, loff_t length, |
| if (pos < size && height == ip->i_height) |
| ret = gfs2_hole_size(inode, lblock, len, mp, iomap); |
| } |
| +hole_found: |
| + iomap->addr = IOMAP_NULL_ADDR; |
| + iomap->type = IOMAP_HOLE; |
| goto out; |
| } |
| |
| -- |
| 2.20.1 |
| |