[Cluster-devel] GFS2: Patches pulled, linux-gfs2.git for-next rebased (again)

2018-02-05 Thread Bob Peterson
Hi,

Linus has pulled our second set of patches from the for-next branch of
the linux-gfs2.git tree, so I rebased the tree from Linus's master again.
So the current tree is back to having no unmerged GFS2 patches.

Regards,

Bob Peterson
Red Hat File Systems



[Cluster-devel] [PATCH] gfs2: Fixes to "Implement iomap for block_map"

2018-02-05 Thread Andreas Gruenbacher
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 
---
 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 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,
__be64 *ptr;
sector_t lblock;
sector_t lend;
-   int ret;
+   int ret = 0;
int eob;
unsigned int len;
struct buffer_head *bh;
@@ -728,12 +728,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;
@@ -744,7 +746,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
@@ -787,27 +789,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();
-   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, );
+   } 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, );
-   goto out_release;
+   else if (height <= ip->i_height)
+   iomap->length = hole_size(inode, lblock, );
+   else
+   iomap->length = size - pos;
+   } else {
+   if (height <= ip->i_height)
+   iomap->length = hole_size(inode, lblock, );
}
-
-   ret = gfs2_iomap_alloc(inode, iomap, flags, );
goto out_release;
 }
 
-- 
2.14.3