Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d505a96a authored by Andreas Gruenbacher's avatar Andreas Gruenbacher
Browse files

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: default avatarAndreas Gruenbacher <agruenba@redhat.com>
Reviewed-by: default avatarBob Peterson <rpeterso@redhat.com>
parent e184fde6
Loading
Loading
Loading
Loading
+42 −32
Original line number Diff line number Diff line
@@ -750,6 +750,7 @@ static int gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap,
		}
	} while (iomap->addr == IOMAP_NULL_ADDR);

	iomap->type = IOMAP_MAPPED;
	iomap->length = (u64)dblks << inode->i_blkbits;
	ip->i_height = mp->mp_fheight;
	gfs2_add_inode_blocks(&ip->i_inode, alloced);
@@ -759,17 +760,6 @@ static int gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap,
	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

/**
@@ -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_sbd *sdp = GFS2_SB(inode);
	loff_t size = i_size_read(inode);
	__be64 *ptr;
	sector_t lblock;
	sector_t lblock_stop;
	int ret;
	int eob;
	u64 len;
	struct buffer_head *bh;
	struct buffer_head *dibh = NULL, *bh;
	u8 height;

	if (!length)
		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 (flags & IOMAP_WRITE) {
			loff_t max_size = gfs2_max_stuffed_size(ip);

			if (pos + length > max_size)
				goto unstuff;
			iomap->length = max_size;
		} else {
			if (pos >= size) {
				if (flags & IOMAP_REPORT) {
			if (pos >= i_size_read(inode))
				return -ENOENT;
			gfs2_stuffed_iomap(inode, iomap);
			return 0;
					ret = -ENOENT;
					goto unlock;
				} else {
					/* report a hole */
					iomap->offset = pos;
					iomap->length = length;
					goto do_alloc;
				}
		BUG_ON(!(flags & IOMAP_WRITE));
			}
			iomap->length = size;
		}
		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;
	iomap->offset = lblock << inode->i_blkbits;
	lblock_stop = (pos + length - 1) >> inode->i_blkbits;
	len = lblock_stop - lblock + 1;
	iomap->length = len << inode->i_blkbits;

	down_read(&ip->i_rw_mutex);

	ret = gfs2_meta_inode_buffer(ip, &mp->mp_bh[0]);
	if (ret)
		goto unlock;
	get_bh(dibh);
	mp->mp_bh[0] = dibh;

	height = ip->i_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,
	iomap->bdev = inode->i_sb->s_bdev;
unlock:
	up_read(&ip->i_rw_mutex);
	if (dibh)
		brelse(dibh);
	return ret;

do_alloc:
	iomap->addr = IOMAP_NULL_ADDR;
	iomap->length = len << inode->i_blkbits;
	iomap->type = IOMAP_HOLE;
	iomap->flags = 0;
	if (flags & IOMAP_REPORT) {
		loff_t size = i_size_read(inode);
		if (pos >= size)
			ret = -ENOENT;
		else if (height == ip->i_height)
			ret = gfs2_hole_size(inode, lblock, len, mp, iomap);
		else
			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;
}
@@ -941,12 +957,6 @@ int gfs2_block_map(struct inode *inode, sector_t lblock,
	} else {
		ret = gfs2_iomap_get(inode, pos, length, 0, &iomap, &mp);
		release_metapath(&mp);

		/* Return unmapped buffer beyond the end of file. */
		if (ret == -ENOENT) {
			ret = 0;
			goto out;
		}
	}
	if (ret)
		goto out;
+1 −1
Original line number Diff line number Diff line
@@ -754,7 +754,7 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
		if (error)
			goto out;
		offset = iomap.offset + iomap.length;
		if (iomap.type != IOMAP_HOLE)
		if (!(iomap.flags & IOMAP_F_NEW))
			continue;
		error = sb_issue_zeroout(sb, iomap.addr >> inode->i_blkbits,
					 iomap.length >> inode->i_blkbits,