* [Cluster-devel] [RHEL7 fs 0/3] gfs2: Fixes to "Implement iomap for block_map"
@ 2018-02-06 18:31 Andreas Gruenbacher
2018-02-06 18:31 ` [Cluster-devel] [RHEL7 fs 1/3] iomap: warn on zero-length mappings Andreas Gruenbacher
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Andreas Gruenbacher @ 2018-02-06 18:31 UTC (permalink / raw)
To: cluster-devel.redhat.com
There are several regressions in commit "[fs] gfs2: Implement iomap for
block_map", which are fixed in mainline commit "Fixes to "Implement
iomap for block_map"".
Because mainline commit "Fixes to "Implement iomap for block_map""
depends on commit "gfs2: Clean up {lookup,fillup}_metapath", backport
that as well.
The regressions trigger a WARN_ON(iomap.length == 0) in iomap_apply in
mainline. This WARN_ON hasn't been backported to RHEL7 yet, so in order
to have a reasonable reproducer, backport that patch as well.
Andreas Gruenbacher (2):
gfs2: Clean up {lookup,fillup}_metapath
gfs2: Fixes to "Implement iomap for block_map"
Darrick J. Wong (1):
iomap: warn on zero-length mappings
fs/gfs2/bmap.c | 117 ++++++++++++++++++++++++++-------------------------------
fs/iomap.c | 2 +
2 files changed, 55 insertions(+), 64 deletions(-)
--
2.14.3
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Cluster-devel] [RHEL7 fs 1/3] iomap: warn on zero-length mappings
2018-02-06 18:31 [Cluster-devel] [RHEL7 fs 0/3] gfs2: Fixes to "Implement iomap for block_map" Andreas Gruenbacher
@ 2018-02-06 18:31 ` Andreas Gruenbacher
2018-02-06 18:31 ` [Cluster-devel] [RHEL7 fs 2/3] gfs2: Clean up {lookup, fillup}_metapath Andreas Gruenbacher
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Andreas Gruenbacher @ 2018-02-06 18:31 UTC (permalink / raw)
To: cluster-devel.redhat.com
From: "Darrick J. Wong" <darrick.wong@oracle.com>
Bugzilla: 1542594
Upstream status: v4.15
Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=15221703
Tested: locally
commit 0c6dda7a1cbd587e48bcef1999875e29549c2b41
Author: Darrick J. Wong <darrick.wong@oracle.com>
Date: Fri Jan 26 11:11:20 2018 -0800
iomap: warn on zero-length mappings
Don't let the iomap callback get away with feeding us a garbage zero
length mapping -- there was a bug in xfs that resulted in those leaking
out to hilarious effect.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
---
fs/iomap.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/fs/iomap.c b/fs/iomap.c
index ca77b55ca134..4b8dc781bbd3 100644
--- a/fs/iomap.c
+++ b/fs/iomap.c
@@ -63,6 +63,8 @@ iomap_apply(struct inode *inode, loff_t pos, loff_t length, unsigned flags,
return ret;
if (WARN_ON(iomap.offset > pos))
return -EIO;
+ if (WARN_ON(iomap.length == 0))
+ return -EIO;
/*
* Cut down the length to the one actually provided by the filesystem,
--
2.14.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [Cluster-devel] [RHEL7 fs 2/3] gfs2: Clean up {lookup, fillup}_metapath
2018-02-06 18:31 [Cluster-devel] [RHEL7 fs 0/3] gfs2: Fixes to "Implement iomap for block_map" Andreas Gruenbacher
2018-02-06 18:31 ` [Cluster-devel] [RHEL7 fs 1/3] iomap: warn on zero-length mappings Andreas Gruenbacher
@ 2018-02-06 18:31 ` Andreas Gruenbacher
2018-02-06 18:31 ` [Cluster-devel] [RHEL7 fs 3/3] gfs2: Fixes to "Implement iomap for block_map" Andreas Gruenbacher
2018-02-06 18:41 ` [Cluster-devel] [RHEL7 fs 0/3] " Andreas Gruenbacher
3 siblings, 0 replies; 5+ messages in thread
From: Andreas Gruenbacher @ 2018-02-06 18:31 UTC (permalink / raw)
To: cluster-devel.redhat.com
Bugzilla: 1542594
Upstream status: v4.15
Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=15221703
Tested: locally
commit e8b43fe0c1e035a135be7ca3791d465fcb1b501e
Author: Andreas Gruenbacher <agruenba@redhat.com>
Date: Fri Dec 8 17:01:57 2017 +0100
gfs2: Clean up {lookup,fillup}_metapath
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@redhat.com>
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
fs/gfs2/bmap.c | 74 ++++++++++++++++++++++++----------------------------------
1 file changed, 30 insertions(+), 44 deletions(-)
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 8569bf37ad7f..55fc3c05103c 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -303,21 +303,22 @@ static void gfs2_metapath_ra(struct gfs2_glock *gl,
}
}
-/**
- * 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);
+ for (; x < h; x++) {
+ __be64 *ptr = metapointer(x, mp);
+ u64 dblock = be64_to_cpu(*ptr);
+ int ret;
- if (!dblock)
- return h + 1;
-
- 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;
}
/**
@@ -334,25 +335,12 @@ static int lookup_mp_height(struct gfs2_inode *ip, struct metapath *mp, int h)
* 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);
}
/**
@@ -363,25 +351,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)
@@ -786,7 +770,7 @@ int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
goto do_alloc;
ret = lookup_metapath(ip, &mp);
- if (ret < 0)
+ if (ret)
goto out_release;
if (mp.mp_aheight != ip->i_height)
@@ -1334,7 +1318,9 @@ static int trunc_dealloc(struct gfs2_inode *ip, u64 newsize)
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 */
@@ -1430,16 +1416,16 @@ static int trunc_dealloc(struct gfs2_inode *ip, u64 newsize)
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
--
2.14.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [Cluster-devel] [RHEL7 fs 3/3] gfs2: Fixes to "Implement iomap for block_map"
2018-02-06 18:31 [Cluster-devel] [RHEL7 fs 0/3] gfs2: Fixes to "Implement iomap for block_map" Andreas Gruenbacher
2018-02-06 18:31 ` [Cluster-devel] [RHEL7 fs 1/3] iomap: warn on zero-length mappings Andreas Gruenbacher
2018-02-06 18:31 ` [Cluster-devel] [RHEL7 fs 2/3] gfs2: Clean up {lookup, fillup}_metapath Andreas Gruenbacher
@ 2018-02-06 18:31 ` Andreas Gruenbacher
2018-02-06 18:41 ` [Cluster-devel] [RHEL7 fs 0/3] " Andreas Gruenbacher
3 siblings, 0 replies; 5+ messages in thread
From: Andreas Gruenbacher @ 2018-02-06 18:31 UTC (permalink / raw)
To: cluster-devel.redhat.com
Bugzilla: 1542594
Upstream status: https://git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2.git/log/?h=for-linus
Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=15221703
Tested: locally
commit 6644a0e9aaa430e40ce175f079751b2694adbe26
Author: Andreas Gruenbacher <agruenba@redhat.com>
Date: Tue Feb 6 07:20:55 2018 -0700
gfs2: Fixes to "Implement iomap for block_map"
It turns out that commit 3974320ca6 "Implement iomap for block_map"
introduced a few bugs that trigger occasional failures with xfstest
generic/476:
In gfs2_iomap_begin, we jump to do_alloc when we determine that we are
beyond the end of the allocated metadata (height > ip->i_height).
There, we can end up calling hole_size with a metapath that doesn't
match the current metadata tree, which deosn't make sense. After
untangling the code at do_alloc, fix this by checking if the block we
are looking for is within the range of allocated metadata.
In addition, add a BUG() in case gfs2_iomap_begin is accidentally called
for reading stuffed files: this is handled separately. Make sure we
don't truncate iomap->length for reads beyond the end of the file; in
that case, the entire range counts as a hole.
Finally, revert to taking a bitmap write lock when doing allocations.
It's unclear why that change didn't lead to any failures during testing.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
---
fs/gfs2/bmap.c | 43 +++++++++++++++++++++++--------------------
1 file changed, 23 insertions(+), 20 deletions(-)
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 55fc3c05103c..199d3f9bd668 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -718,7 +718,7 @@ int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
__be64 *ptr;
sector_t lblock;
sector_t lend;
- int ret;
+ int ret = 0;
int eob;
unsigned int len;
struct buffer_head *bh;
@@ -730,12 +730,14 @@ int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
goto out;
}
- if ((flags & IOMAP_REPORT) && gfs2_is_stuffed(ip)) {
- gfs2_stuffed_iomap(inode, iomap);
- if (pos >= iomap->length)
- return -ENOENT;
- ret = 0;
- goto out;
+ if (gfs2_is_stuffed(ip)) {
+ if (flags & IOMAP_REPORT) {
+ gfs2_stuffed_iomap(inode, iomap);
+ if (pos >= iomap->length)
+ ret = -ENOENT;
+ goto out;
+ }
+ BUG_ON(!(flags & IOMAP_WRITE));
}
lblock = pos >> inode->i_blkbits;
@@ -746,7 +748,7 @@ int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
iomap->type = IOMAP_HOLE;
iomap->length = (u64)(lend - lblock) << inode->i_blkbits;
iomap->flags = IOMAP_F_MERGED;
- bmap_lock(ip, 0);
+ bmap_lock(ip, flags & IOMAP_WRITE);
/*
* Directory data blocks have a struct gfs2_meta_header header, so the
@@ -789,27 +791,28 @@ int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
iomap->flags |= IOMAP_F_BOUNDARY;
iomap->length = (u64)len << inode->i_blkbits;
- ret = 0;
-
out_release:
release_metapath(&mp);
- bmap_unlock(ip, 0);
+ bmap_unlock(ip, flags & IOMAP_WRITE);
out:
trace_gfs2_iomap_end(ip, iomap, ret);
return ret;
do_alloc:
- if (!(flags & IOMAP_WRITE)) {
- if (pos >= i_size_read(inode)) {
+ if (flags & IOMAP_WRITE) {
+ ret = gfs2_iomap_alloc(inode, iomap, flags, &mp);
+ } else if (flags & IOMAP_REPORT) {
+ loff_t size = i_size_read(inode);
+ if (pos >= size)
ret = -ENOENT;
- goto out_release;
- }
- ret = 0;
- iomap->length = hole_size(inode, lblock, &mp);
- goto out_release;
+ else if (height <= ip->i_height)
+ iomap->length = hole_size(inode, lblock, &mp);
+ else
+ iomap->length = size - pos;
+ } else {
+ if (height <= ip->i_height)
+ iomap->length = hole_size(inode, lblock, &mp);
}
-
- ret = gfs2_iomap_alloc(inode, iomap, flags, &mp);
goto out_release;
}
--
2.14.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [Cluster-devel] [RHEL7 fs 0/3] gfs2: Fixes to "Implement iomap for block_map"
2018-02-06 18:31 [Cluster-devel] [RHEL7 fs 0/3] gfs2: Fixes to "Implement iomap for block_map" Andreas Gruenbacher
` (2 preceding siblings ...)
2018-02-06 18:31 ` [Cluster-devel] [RHEL7 fs 3/3] gfs2: Fixes to "Implement iomap for block_map" Andreas Gruenbacher
@ 2018-02-06 18:41 ` Andreas Gruenbacher
3 siblings, 0 replies; 5+ messages in thread
From: Andreas Gruenbacher @ 2018-02-06 18:41 UTC (permalink / raw)
To: cluster-devel.redhat.com
On 6 February 2018 at 19:31, Andreas Gruenbacher <agruenba@redhat.com> wrote:
> There are several regressions in commit "[fs] gfs2: Implement iomap for
> block_map", which are fixed in mainline commit "Fixes to "Implement
> iomap for block_map"".
>
> Because mainline commit "Fixes to "Implement iomap for block_map""
> depends on commit "gfs2: Clean up {lookup,fillup}_metapath", backport
> that as well.
>
> The regressions trigger a WARN_ON(iomap.length == 0) in iomap_apply in
> mainline. This WARN_ON hasn't been backported to RHEL7 yet, so in order
> to have a reasonable reproducer, backport that patch as well.
Please disregard this thread, this was meant to be sent to another mailing list.
Thanks,
Andreas
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2018-02-06 18:41 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-02-06 18:31 [Cluster-devel] [RHEL7 fs 0/3] gfs2: Fixes to "Implement iomap for block_map" Andreas Gruenbacher
2018-02-06 18:31 ` [Cluster-devel] [RHEL7 fs 1/3] iomap: warn on zero-length mappings Andreas Gruenbacher
2018-02-06 18:31 ` [Cluster-devel] [RHEL7 fs 2/3] gfs2: Clean up {lookup, fillup}_metapath Andreas Gruenbacher
2018-02-06 18:31 ` [Cluster-devel] [RHEL7 fs 3/3] gfs2: Fixes to "Implement iomap for block_map" Andreas Gruenbacher
2018-02-06 18:41 ` [Cluster-devel] [RHEL7 fs 0/3] " Andreas Gruenbacher
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).