This is a note to let you know that I've just added the patch titled gfs2: Clean up {lookup,fillup}_metapath to the 4.15-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: gfs2-clean-up-lookup-fillup-_metapath.patch and it can be found in the queue-4.15 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From e8b43fe0c1e035a135be7ca3791d465fcb1b501e Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher <agruenba@xxxxxxxxxx> Date: Fri, 8 Dec 2017 17:01:57 +0100 Subject: gfs2: Clean up {lookup,fillup}_metapath From: Andreas Gruenbacher <agruenba@xxxxxxxxxx> commit e8b43fe0c1e035a135be7ca3791d465fcb1b501e upstream. Split out the entire lookup loop from lookup_metapath and fillup_metapath. Make both functions return the actual height in mp->mp_aheight, and return 0 on success. Handle lookup errors properly in trunc_dealloc. Signed-off-by: Andreas Gruenbacher <agruenba@xxxxxxxxxx> Signed-off-by: Bob Peterson <rpeterso@xxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- fs/gfs2/bmap.c | 74 +++++++++++++++++++++++---------------------------------- 1 file changed, 30 insertions(+), 44 deletions(-) --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -305,21 +305,22 @@ static void gfs2_metapath_ra(struct gfs2 } } -/** - * lookup_mp_height - helper function for lookup_metapath - * @ip: the inode - * @mp: the metapath - * @h: the height which needs looking up - */ -static int lookup_mp_height(struct gfs2_inode *ip, struct metapath *mp, int h) +static int __fillup_metapath(struct gfs2_inode *ip, struct metapath *mp, + unsigned int x, unsigned int h) { - __be64 *ptr = metapointer(h, mp); - u64 dblock = be64_to_cpu(*ptr); - - if (!dblock) - return h + 1; + for (; x < h; x++) { + __be64 *ptr = metapointer(x, mp); + u64 dblock = be64_to_cpu(*ptr); + int ret; - return gfs2_meta_indirect_buffer(ip, h + 1, dblock, &mp->mp_bh[h + 1]); + if (!dblock) + break; + ret = gfs2_meta_indirect_buffer(ip, x + 1, dblock, &mp->mp_bh[x + 1]); + if (ret) + return ret; + } + mp->mp_aheight = x + 1; + return 0; } /** @@ -336,25 +337,12 @@ static int lookup_mp_height(struct gfs2_ * at which it found the unallocated block. Blocks which are found are * added to the mp->mp_bh[] list. * - * Returns: error or height of metadata tree + * Returns: error */ static int lookup_metapath(struct gfs2_inode *ip, struct metapath *mp) { - unsigned int end_of_metadata = ip->i_height - 1; - unsigned int x; - int ret; - - for (x = 0; x < end_of_metadata; x++) { - ret = lookup_mp_height(ip, mp, x); - if (ret) - goto out; - } - - ret = ip->i_height; -out: - mp->mp_aheight = ret; - return ret; + return __fillup_metapath(ip, mp, 0, ip->i_height - 1); } /** @@ -365,25 +353,21 @@ out: * * Similar to lookup_metapath, but does lookups for a range of heights * - * Returns: error or height of metadata tree + * Returns: error */ static int fillup_metapath(struct gfs2_inode *ip, struct metapath *mp, int h) { - unsigned int start_h = h - 1; - int ret; + unsigned int x = 0; if (h) { /* find the first buffer we need to look up. */ - while (start_h > 0 && mp->mp_bh[start_h] == NULL) - start_h--; - for (; start_h < h; start_h++) { - ret = lookup_mp_height(ip, mp, start_h); - if (ret) - return ret; + for (x = h - 1; x > 0; x--) { + if (mp->mp_bh[x]) + break; } } - return ip->i_height; + return __fillup_metapath(ip, mp, x, h); } static inline void release_metapath(struct metapath *mp) @@ -790,7 +774,7 @@ int gfs2_iomap_begin(struct inode *inode goto do_alloc; ret = lookup_metapath(ip, &mp); - if (ret < 0) + if (ret) goto out_release; if (mp.mp_aheight != ip->i_height) @@ -1339,7 +1323,9 @@ static int trunc_dealloc(struct gfs2_ino mp.mp_bh[0] = dibh; ret = lookup_metapath(ip, &mp); - if (ret == ip->i_height) + if (ret) + goto out_metapath; + if (mp.mp_aheight == ip->i_height) state = DEALLOC_MP_FULL; /* We have a complete metapath */ else state = DEALLOC_FILL_MP; /* deal with partial metapath */ @@ -1435,16 +1421,16 @@ static int trunc_dealloc(struct gfs2_ino case DEALLOC_FILL_MP: /* Fill the buffers out to the current height. */ ret = fillup_metapath(ip, &mp, mp_h); - if (ret < 0) + if (ret) goto out; /* If buffers found for the entire strip height */ - if ((ret == ip->i_height) && (mp_h == strip_h)) { + if (mp.mp_aheight - 1 == strip_h) { state = DEALLOC_MP_FULL; break; } - if (ret < ip->i_height) /* We have a partial height */ - mp_h = ret - 1; + if (mp.mp_aheight < ip->i_height) /* We have a partial height */ + mp_h = mp.mp_aheight - 1; /* If we find a non-null block pointer, crawl a bit higher up in the metapath and try again, otherwise Patches currently in stable-queue which might be from agruenba@xxxxxxxxxx are queue-4.15/gfs2-clean-up-lookup-fillup-_metapath.patch queue-4.15/gfs2-fixes-to-implement-iomap-for-block_map-2.patch