From 61eaadcd52924b8015ee57b9abd3844c5f9e03a8 Mon Sep 17 00:00:00 2001 From: Bob Peterson Date: Mon, 3 Jul 2017 11:37:02 -0500 Subject: GFS2: Prevent double brelse in gfs2_meta_indirect_buffer Before this patch, problems reading in indirect buffers would send an IO error back to the caller, and release the buffer_head with brelse() in function gfs2_meta_indirect_buffer, however, it would still return the address of the buffer_head it released. After the error was discovered, function gfs2_block_map would call function release_metapath to free all buffers. That checked: if (mp->mp_bh[i] == NULL) but since the value was set after the error, it was non-zero, so brelse was called a second time. This resulted in the following error: kernel: WARNING: at fs/buffer.c:1224 __brelse+0x3a/0x40() (Tainted: G W -- ------------ ) kernel: Hardware name: RHEV Hypervisor kernel: VFS: brelse: Trying to free free buffer This patch changes gfs2_meta_indirect_buffer so it only sets the buffer_head pointer in cases where it isn't released. Signed-off-by: Bob Peterson Acked-by: Steven Whitehouse --- fs/gfs2/meta_io.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs/gfs2/meta_io.c') diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index fabe1614f879..4da7745c890a 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c @@ -419,8 +419,9 @@ int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num, if (ret == 0 && gfs2_metatype_check(sdp, bh, mtype)) { brelse(bh); ret = -EIO; + } else { + *bhp = bh; } - *bhp = bh; return ret; } -- cgit v1.2.3 From e477b24b507998bc6568316a2e034025960d2404 Mon Sep 17 00:00:00 2001 From: Coly Li Date: Fri, 21 Jul 2017 07:48:22 -0500 Subject: gfs2: add flag REQ_PRIO for metadata I/O When gfs2 does metadata I/O, only REQ_META is used as a metadata hint of the bio. But flag REQ_META is just a hint for block trace, not for block layer code to handle a bio as metadata request. For some of metadata I/Os of gfs2, A REQ_PRIO flag on the metadata bio would be very informative to block layer code. For example, if bcache is used as a I/O cache for gfs2, it will be possible for bcache code to get the hint and cache the pre-fetched metadata blocks on cache device. This behavior may be helpful to improve metadata I/O performance if the following requests hit the cache. Here are the locations in gfs2 code where a REQ_PRIO flag should be added, - All places where REQ_READAHEAD is used, gfs2 code uses this flag for metadata read ahead. - In gfs2_meta_rq() where the first metadata block is read in. - In gfs2_write_buf_to_page(), read in quota metadata blocks to have them up to date. These metadata blocks are probably to be accessed again in future, adding a REQ_PRIO flag may have bcache to keep such metadata in fast cache device. For system without a cache layer, REQ_PRIO can still provide hint to block layer to handle metadata requests more properly. Signed-off-by: Coly Li Signed-off-by: Bob Peterson --- fs/gfs2/meta_io.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'fs/gfs2/meta_io.c') diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 4da7745c890a..61ef6c9be816 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c @@ -453,7 +453,7 @@ struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen) if (buffer_uptodate(first_bh)) goto out; if (!buffer_locked(first_bh)) - ll_rw_block(REQ_OP_READ, REQ_META, 1, &first_bh); + ll_rw_block(REQ_OP_READ, REQ_META | REQ_PRIO, 1, &first_bh); dblock++; extlen--; @@ -462,7 +462,9 @@ struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen) bh = gfs2_getbuf(gl, dblock, CREATE); if (!buffer_uptodate(bh) && !buffer_locked(bh)) - ll_rw_block(REQ_OP_READ, REQ_RAHEAD | REQ_META, 1, &bh); + ll_rw_block(REQ_OP_READ, + REQ_RAHEAD | REQ_META | REQ_PRIO, + 1, &bh); brelse(bh); dblock++; extlen--; -- cgit v1.2.3