提交 d505a96a 编写于 作者: A Andreas Gruenbacher

gfs2: Further iomap cleanups

In gfs2_iomap_alloc, set the type of newly allocated extents to
IOMAP_MAPPED so that iomap_to_bh will set the bh states correctly:
otherwise, the bhs would not be marked as mapped, confusing
__mpage_writepage.  This means that we need to check for the IOMAP_F_NEW
flag in fallocate_chunk now.

Further clean up gfs2_iomap_get and implement gfs2_stuffed_iomap here
directly.  For reads beyond the end of the file, return holes instead of
failing with -ENOENT so that we can get rid of that special case in
gfs2_block_map.
Signed-off-by: NAndreas Gruenbacher <agruenba@redhat.com>
Reviewed-by: NBob Peterson <rpeterso@redhat.com>
上级 e184fde6
...@@ -750,6 +750,7 @@ static int gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap, ...@@ -750,6 +750,7 @@ static int gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap,
} }
} while (iomap->addr == IOMAP_NULL_ADDR); } while (iomap->addr == IOMAP_NULL_ADDR);
iomap->type = IOMAP_MAPPED;
iomap->length = (u64)dblks << inode->i_blkbits; iomap->length = (u64)dblks << inode->i_blkbits;
ip->i_height = mp->mp_fheight; ip->i_height = mp->mp_fheight;
gfs2_add_inode_blocks(&ip->i_inode, alloced); gfs2_add_inode_blocks(&ip->i_inode, alloced);
...@@ -759,17 +760,6 @@ static int gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap, ...@@ -759,17 +760,6 @@ static int gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap,
return ret; return ret;
} }
static void gfs2_stuffed_iomap(struct inode *inode, struct iomap *iomap)
{
struct gfs2_inode *ip = GFS2_I(inode);
iomap->addr = (ip->i_no_addr << inode->i_blkbits) +
sizeof(struct gfs2_dinode);
iomap->offset = 0;
iomap->length = i_size_read(inode);
iomap->type = IOMAP_INLINE;
}
#define IOMAP_F_GFS2_BOUNDARY IOMAP_F_PRIVATE #define IOMAP_F_GFS2_BOUNDARY IOMAP_F_PRIVATE
/** /**
...@@ -789,37 +779,61 @@ static int gfs2_iomap_get(struct inode *inode, loff_t pos, loff_t length, ...@@ -789,37 +779,61 @@ static int gfs2_iomap_get(struct inode *inode, loff_t pos, loff_t length,
{ {
struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_inode *ip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode); struct gfs2_sbd *sdp = GFS2_SB(inode);
loff_t size = i_size_read(inode);
__be64 *ptr; __be64 *ptr;
sector_t lblock; sector_t lblock;
sector_t lblock_stop; sector_t lblock_stop;
int ret; int ret;
int eob; int eob;
u64 len; u64 len;
struct buffer_head *bh; struct buffer_head *dibh = NULL, *bh;
u8 height; u8 height;
if (!length) if (!length)
return -EINVAL; return -EINVAL;
down_read(&ip->i_rw_mutex);
ret = gfs2_meta_inode_buffer(ip, &dibh);
if (ret)
goto unlock;
if (gfs2_is_stuffed(ip)) { if (gfs2_is_stuffed(ip)) {
if (flags & IOMAP_REPORT) { if (flags & IOMAP_WRITE) {
if (pos >= i_size_read(inode)) loff_t max_size = gfs2_max_stuffed_size(ip);
return -ENOENT;
gfs2_stuffed_iomap(inode, iomap); if (pos + length > max_size)
return 0; goto unstuff;
iomap->length = max_size;
} else {
if (pos >= size) {
if (flags & IOMAP_REPORT) {
ret = -ENOENT;
goto unlock;
} else {
/* report a hole */
iomap->offset = pos;
iomap->length = length;
goto do_alloc;
}
}
iomap->length = size;
} }
BUG_ON(!(flags & IOMAP_WRITE)); iomap->addr = (ip->i_no_addr << inode->i_blkbits) +
sizeof(struct gfs2_dinode);
iomap->type = IOMAP_INLINE;
goto out;
} }
unstuff:
lblock = pos >> inode->i_blkbits; lblock = pos >> inode->i_blkbits;
iomap->offset = lblock << inode->i_blkbits; iomap->offset = lblock << inode->i_blkbits;
lblock_stop = (pos + length - 1) >> inode->i_blkbits; lblock_stop = (pos + length - 1) >> inode->i_blkbits;
len = lblock_stop - lblock + 1; len = lblock_stop - lblock + 1;
iomap->length = len << inode->i_blkbits;
down_read(&ip->i_rw_mutex); get_bh(dibh);
mp->mp_bh[0] = dibh;
ret = gfs2_meta_inode_buffer(ip, &mp->mp_bh[0]);
if (ret)
goto unlock;
height = ip->i_height; height = ip->i_height;
while ((lblock + 1) * sdp->sd_sb.sb_bsize > sdp->sd_heightsize[height]) while ((lblock + 1) * sdp->sd_sb.sb_bsize > sdp->sd_heightsize[height])
...@@ -853,21 +867,23 @@ static int gfs2_iomap_get(struct inode *inode, loff_t pos, loff_t length, ...@@ -853,21 +867,23 @@ static int gfs2_iomap_get(struct inode *inode, loff_t pos, loff_t length,
iomap->bdev = inode->i_sb->s_bdev; iomap->bdev = inode->i_sb->s_bdev;
unlock: unlock:
up_read(&ip->i_rw_mutex); up_read(&ip->i_rw_mutex);
if (dibh)
brelse(dibh);
return ret; return ret;
do_alloc: do_alloc:
iomap->addr = IOMAP_NULL_ADDR; iomap->addr = IOMAP_NULL_ADDR;
iomap->length = len << inode->i_blkbits;
iomap->type = IOMAP_HOLE; iomap->type = IOMAP_HOLE;
iomap->flags = 0;
if (flags & IOMAP_REPORT) { if (flags & IOMAP_REPORT) {
loff_t size = i_size_read(inode);
if (pos >= size) if (pos >= size)
ret = -ENOENT; ret = -ENOENT;
else if (height == ip->i_height) else if (height == ip->i_height)
ret = gfs2_hole_size(inode, lblock, len, mp, iomap); ret = gfs2_hole_size(inode, lblock, len, mp, iomap);
else else
iomap->length = size - pos; iomap->length = size - pos;
} else if (!(flags & IOMAP_WRITE)) {
if (pos < size && height == ip->i_height)
ret = gfs2_hole_size(inode, lblock, len, mp, iomap);
} }
goto out; goto out;
} }
...@@ -941,12 +957,6 @@ int gfs2_block_map(struct inode *inode, sector_t lblock, ...@@ -941,12 +957,6 @@ int gfs2_block_map(struct inode *inode, sector_t lblock,
} else { } else {
ret = gfs2_iomap_get(inode, pos, length, 0, &iomap, &mp); ret = gfs2_iomap_get(inode, pos, length, 0, &iomap, &mp);
release_metapath(&mp); release_metapath(&mp);
/* Return unmapped buffer beyond the end of file. */
if (ret == -ENOENT) {
ret = 0;
goto out;
}
} }
if (ret) if (ret)
goto out; goto out;
......
...@@ -754,7 +754,7 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len, ...@@ -754,7 +754,7 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
if (error) if (error)
goto out; goto out;
offset = iomap.offset + iomap.length; offset = iomap.offset + iomap.length;
if (iomap.type != IOMAP_HOLE) if (!(iomap.flags & IOMAP_F_NEW))
continue; continue;
error = sb_issue_zeroout(sb, iomap.addr >> inode->i_blkbits, error = sb_issue_zeroout(sb, iomap.addr >> inode->i_blkbits,
iomap.length >> inode->i_blkbits, iomap.length >> inode->i_blkbits,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册