Commit b405435b authored by Matthew Wilcox (Oracle)'s avatar Matthew Wilcox (Oracle) Committed by Darrick J. Wong
Browse files

iomap: Support inline data with block size < page size



Remove the restriction that inline data must start on a page boundary
in a file.  This allows, for example, the first 2KiB to be stored out
of line and the trailing 30 bytes to be stored inline.

Signed-off-by: default avatarMatthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: default avatarDarrick J. Wong <djwong@kernel.org>
Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
parent 69f4a26c
Loading
Loading
Loading
Loading
+16 −18
Original line number Diff line number Diff line
@@ -209,28 +209,26 @@ static int iomap_read_inline_data(struct inode *inode, struct page *page,
		struct iomap *iomap)
{
	size_t size = i_size_read(inode) - iomap->offset;
	size_t poff = offset_in_page(iomap->offset);
	void *addr;

	if (PageUptodate(page))
		return 0;
		return PAGE_SIZE - poff;

	/* inline data must start page aligned in the file */
	if (WARN_ON_ONCE(offset_in_page(iomap->offset)))
		return -EIO;
	if (WARN_ON_ONCE(size > PAGE_SIZE -
			 offset_in_page(iomap->inline_data)))
		return -EIO;
	if (WARN_ON_ONCE(size > iomap->length))
		return -EIO;
	if (WARN_ON_ONCE(page_has_private(page)))
		return -EIO;
	if (poff > 0)
		iomap_page_create(inode, page);

	addr = kmap_atomic(page);
	addr = kmap_atomic(page) + poff;
	memcpy(addr, iomap->inline_data, size);
	memset(addr + size, 0, PAGE_SIZE - size);
	memset(addr + size, 0, PAGE_SIZE - poff - size);
	kunmap_atomic(addr);
	SetPageUptodate(page);
	return 0;
	iomap_set_range_uptodate(page, poff, PAGE_SIZE - poff);
	return PAGE_SIZE - poff;
}

static inline bool iomap_block_needs_zeroing(struct inode *inode,
@@ -252,13 +250,8 @@ iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
	unsigned poff, plen;
	sector_t sector;

	if (iomap->type == IOMAP_INLINE) {
		int ret = iomap_read_inline_data(inode, page, iomap);

		if (ret)
			return ret;
		return PAGE_SIZE;
	}
	if (iomap->type == IOMAP_INLINE)
		return iomap_read_inline_data(inode, page, iomap);

	/* zero post-eof blocks as the page may be mapped */
	iop = iomap_page_create(inode, page);
@@ -593,10 +586,15 @@ __iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, int flags,
static int iomap_write_begin_inline(struct inode *inode,
		struct page *page, struct iomap *srcmap)
{
	int ret;

	/* needs more work for the tailpacking case; disable for now */
	if (WARN_ON_ONCE(srcmap->offset != 0))
		return -EIO;
	return iomap_read_inline_data(inode, page, srcmap);
	ret = iomap_read_inline_data(inode, page, srcmap);
	if (ret < 0)
		return ret;
	return 0;
}

static int