All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chao Yu <yuchao0@huawei.com>
To: Andreas Gruenbacher <agruenba@redhat.com>
Cc: Christoph Hellwig <hch@infradead.org>,
	"Darrick J. Wong" <darrick.wong@oracle.com>,
	<linux-xfs@vger.kernel.org>, <linux-fsdevel@vger.kernel.org>,
	Gao Xiang <gaoxiang25@huawei.com>, <chao@kernel.org>
Subject: Re: [RFC PATCH] iomap: generalize IOMAP_INLINE to cover tail-packing case
Date: Fri, 12 Jul 2019 17:31:24 +0800	[thread overview]
Message-ID: <cb41acf2-f222-102a-d31b-02243c77996c@huawei.com> (raw)
In-Reply-To: <20190711122831.3970-1-agruenba@redhat.com>

On 2019/7/11 20:28, Andreas Gruenbacher wrote:
> Something along the lines of the attached, broken patch might work in
> the end.
> 
> Andreas
> 
> ---
>  fs/buffer.c           | 10 ++++--
>  fs/iomap.c            | 74 +++++++++++++++++++++++++++++--------------
>  include/linux/iomap.h |  3 ++
>  3 files changed, 61 insertions(+), 26 deletions(-)
> 
> diff --git a/fs/buffer.c b/fs/buffer.c
> index e450c55f6434..8d8668e377ab 100644
> --- a/fs/buffer.c
> +++ b/fs/buffer.c
> @@ -1873,8 +1873,8 @@ void page_zero_new_buffers(struct page *page, unsigned from, unsigned to)
>  EXPORT_SYMBOL(page_zero_new_buffers);
>  
>  static void
> -iomap_to_bh(struct inode *inode, sector_t block, struct buffer_head *bh,
> -		struct iomap *iomap)
> +iomap_to_bh(struct inode *inode, struct page *page, sector_t block,
> +		struct buffer_head *bh, struct iomap *iomap)
>  {
>  	loff_t offset = block << inode->i_blkbits;
>  
> @@ -1924,6 +1924,10 @@ iomap_to_bh(struct inode *inode, sector_t block, struct buffer_head *bh,
>  				inode->i_blkbits;
>  		set_buffer_mapped(bh);
>  		break;
> +	case IOMAP_INLINE:
> +		__iomap_read_inline_data(inode, page, iomap);
> +		set_buffer_uptodate(bh);
> +		break;
>  	}
>  }
>  
> @@ -1969,7 +1973,7 @@ int __block_write_begin_int(struct page *page, loff_t pos, unsigned len,
>  				if (err)
>  					break;
>  			} else {
> -				iomap_to_bh(inode, block, bh, iomap);
> +				iomap_to_bh(inode, page, block, bh, iomap);
>  			}
>  
>  			if (buffer_new(bh)) {
> diff --git a/fs/iomap.c b/fs/iomap.c
> index 45aa58e837b5..61188e95def2 100644
> --- a/fs/iomap.c
> +++ b/fs/iomap.c
> @@ -260,24 +260,47 @@ struct iomap_readpage_ctx {
>  	struct list_head	*pages;
>  };
>  
> -static void
> -iomap_read_inline_data(struct inode *inode, struct page *page,
> +#define offset_in_block(offset, inode) \
> +	((unsigned long)(offset) & (i_blocksize(inode) - 1))
> +
> +static bool
> +inline_data_within_block(struct inode *inode, struct iomap *iomap,
> +		unsigned int size)
> +{
> +	unsigned int off = offset_in_block(iomap->inline_data, inode);
> +
> +	return size <= i_blocksize(inode) - off;
> +}
> +
> +void
> +__iomap_read_inline_data(struct inode *inode, struct page *page,
>  		struct iomap *iomap)
>  {
> -	size_t size = i_size_read(inode);
> +	size_t size = offset_in_block(i_size_read(inode), inode);
> +	unsigned int poff = offset_in_page(iomap->offset);
> +	unsigned int bsize = i_blocksize(inode);
>  	void *addr;
>  
>  	if (PageUptodate(page))
>  		return;
>  
> -	BUG_ON(page->index);
> -	BUG_ON(size > PAGE_SIZE - offset_in_page(iomap->inline_data));
> +	BUG_ON(!inline_data_within_block(inode, iomap, size));
>  
>  	addr = kmap_atomic(page);
> -	memcpy(addr, iomap->inline_data, size);
> -	memset(addr + size, 0, PAGE_SIZE - size);
> +	memcpy(addr + poff, iomap->inline_data, size);
> +	memset(addr + poff + size, 0, bsize - size);
>  	kunmap_atomic(addr);
> -	SetPageUptodate(page);
> +}
> +
> +static void
> +iomap_read_inline_data(struct inode *inode, struct page *page,
> +		struct iomap *iomap)
> +{
> +	unsigned int poff = offset_in_page(iomap->offset);
> +	unsigned int bsize = i_blocksize(inode);
> +
> +	__iomap_read_inline_data(inode, page, iomap);
> +	iomap_set_range_uptodate(page, poff, bsize);
>  }
>  
>  static loff_t
> @@ -292,11 +315,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) {
> -		WARN_ON_ONCE(pos);
> +	if (iomap->type == IOMAP_INLINE)
>  		iomap_read_inline_data(inode, page, iomap);
> -		return PAGE_SIZE;

Hi Andreas,

Thanks for your patch.

In my erofs test case, filled inline data will be zeroed out due to we fallback
to following flow:

	if (iomap->type != IOMAP_MAPPED || pos >= i_size_read(inode)) {
		zero_user(page, poff, plen);

Should we return before this condition check?

Thanks,

> -	}
>  
>  	/* zero post-eof blocks as the page may be mapped */
>  	iomap_adjust_read_range(inode, iop, &pos, length, &poff, &plen);
> @@ -637,6 +657,11 @@ __iomap_write_begin(struct inode *inode, loff_t pos, unsigned len,
>  	if (PageUptodate(page))
>  		return 0;
>  
> +	if (iomap->type == IOMAP_INLINE) {
> +		iomap_read_inline_data(inode, page, iomap);
> +		return 0;
> +	}
> +
>  	do {
>  		iomap_adjust_read_range(inode, iop, &block_start,
>  				block_end - block_start, &poff, &plen);
> @@ -682,9 +707,7 @@ iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, unsigned flags,
>  		goto out_no_page;
>  	}
>  
> -	if (iomap->type == IOMAP_INLINE)
> -		iomap_read_inline_data(inode, page, iomap);
> -	else if (iomap->flags & IOMAP_F_BUFFER_HEAD)
> +	if (iomap->flags & IOMAP_F_BUFFER_HEAD)
>  		status = __block_write_begin_int(page, pos, len, NULL, iomap);
>  	else
>  		status = __iomap_write_begin(inode, pos, len, page, iomap);
> @@ -761,11 +784,11 @@ iomap_write_end_inline(struct inode *inode, struct page *page,
>  {
>  	void *addr;
>  
> -	WARN_ON_ONCE(!PageUptodate(page));
> -	BUG_ON(pos + copied > PAGE_SIZE - offset_in_page(iomap->inline_data));
> +	BUG_ON(!inline_data_within_block(inode, iomap, pos + copied));
>  
>  	addr = kmap_atomic(page);
> -	memcpy(iomap->inline_data + pos, addr + pos, copied);
> +	memcpy(iomap->inline_data + offset_in_block(pos, inode),
> +	       addr + offset_in_page(pos), copied);
>  	kunmap_atomic(addr);
>  
>  	mark_inode_dirty(inode);
> @@ -1064,7 +1087,7 @@ iomap_truncate_page(struct inode *inode, loff_t pos, bool *did_zero,
>  		const struct iomap_ops *ops)
>  {
>  	unsigned int blocksize = i_blocksize(inode);
> -	unsigned int off = pos & (blocksize - 1);
> +	unsigned int off = offset_in_block(pos, inode);
>  
>  	/* Block boundary? Nothing to do */
>  	if (!off)
> @@ -1772,21 +1795,26 @@ iomap_dio_inline_actor(struct inode *inode, loff_t pos, loff_t length,
>  	struct iov_iter *iter = dio->submit.iter;
>  	size_t copied;
>  
> -	BUG_ON(pos + length > PAGE_SIZE - offset_in_page(iomap->inline_data));
> +	BUG_ON(!inline_data_within_block(inode, iomap, pos + length));
>  
>  	if (dio->flags & IOMAP_DIO_WRITE) {
>  		loff_t size = inode->i_size;
>  
>  		if (pos > size)
> -			memset(iomap->inline_data + size, 0, pos - size);
> -		copied = copy_from_iter(iomap->inline_data + pos, length, iter);
> +			memset(iomap->inline_data +
> +			       offset_in_block(size, inode), 0, pos - size);
> +		copied = copy_from_iter(iomap->inline_data +
> +					offset_in_block(pos, inode),
> +					length, iter);
>  		if (copied) {
>  			if (pos + copied > size)
>  				i_size_write(inode, pos + copied);
>  			mark_inode_dirty(inode);
>  		}
>  	} else {
> -		copied = copy_to_iter(iomap->inline_data + pos, length, iter);
> +		copied = copy_to_iter(iomap->inline_data +
> +				      offset_in_block(pos, inode),
> +				      length, iter);
>  	}
>  	dio->size += copied;
>  	return copied;
> diff --git a/include/linux/iomap.h b/include/linux/iomap.h
> index 2103b94cb1bf..a8a60dd2fdc0 100644
> --- a/include/linux/iomap.h
> +++ b/include/linux/iomap.h
> @@ -131,6 +131,9 @@ static inline struct iomap_page *to_iomap_page(struct page *page)
>  	return NULL;
>  }
>  
> +void __iomap_read_inline_data(struct inode *inode, struct page *page,
> +		struct iomap *iomap);
> +
>  ssize_t iomap_file_buffered_write(struct kiocb *iocb, struct iov_iter *from,
>  		const struct iomap_ops *ops);
>  int iomap_readpage(struct page *page, const struct iomap_ops *ops);
> 

WARNING: multiple messages have this Message-ID (diff)
From: Chao Yu <yuchao0@huawei.com>
To: Andreas Gruenbacher <agruenba@redhat.com>
Cc: Christoph Hellwig <hch@infradead.org>,
	"Darrick J. Wong" <darrick.wong@oracle.com>,
	linux-xfs@vger.kernel.org, linux-fsdevel@vger.kernel.org,
	Gao Xiang <gaoxiang25@huawei.com>,
	chao@kernel.org
Subject: Re: [RFC PATCH] iomap: generalize IOMAP_INLINE to cover tail-packing case
Date: Fri, 12 Jul 2019 17:31:24 +0800	[thread overview]
Message-ID: <cb41acf2-f222-102a-d31b-02243c77996c@huawei.com> (raw)
In-Reply-To: <20190711122831.3970-1-agruenba@redhat.com>

On 2019/7/11 20:28, Andreas Gruenbacher wrote:
> Something along the lines of the attached, broken patch might work in
> the end.
> 
> Andreas
> 
> ---
>  fs/buffer.c           | 10 ++++--
>  fs/iomap.c            | 74 +++++++++++++++++++++++++++++--------------
>  include/linux/iomap.h |  3 ++
>  3 files changed, 61 insertions(+), 26 deletions(-)
> 
> diff --git a/fs/buffer.c b/fs/buffer.c
> index e450c55f6434..8d8668e377ab 100644
> --- a/fs/buffer.c
> +++ b/fs/buffer.c
> @@ -1873,8 +1873,8 @@ void page_zero_new_buffers(struct page *page, unsigned from, unsigned to)
>  EXPORT_SYMBOL(page_zero_new_buffers);
>  
>  static void
> -iomap_to_bh(struct inode *inode, sector_t block, struct buffer_head *bh,
> -		struct iomap *iomap)
> +iomap_to_bh(struct inode *inode, struct page *page, sector_t block,
> +		struct buffer_head *bh, struct iomap *iomap)
>  {
>  	loff_t offset = block << inode->i_blkbits;
>  
> @@ -1924,6 +1924,10 @@ iomap_to_bh(struct inode *inode, sector_t block, struct buffer_head *bh,
>  				inode->i_blkbits;
>  		set_buffer_mapped(bh);
>  		break;
> +	case IOMAP_INLINE:
> +		__iomap_read_inline_data(inode, page, iomap);
> +		set_buffer_uptodate(bh);
> +		break;
>  	}
>  }
>  
> @@ -1969,7 +1973,7 @@ int __block_write_begin_int(struct page *page, loff_t pos, unsigned len,
>  				if (err)
>  					break;
>  			} else {
> -				iomap_to_bh(inode, block, bh, iomap);
> +				iomap_to_bh(inode, page, block, bh, iomap);
>  			}
>  
>  			if (buffer_new(bh)) {
> diff --git a/fs/iomap.c b/fs/iomap.c
> index 45aa58e837b5..61188e95def2 100644
> --- a/fs/iomap.c
> +++ b/fs/iomap.c
> @@ -260,24 +260,47 @@ struct iomap_readpage_ctx {
>  	struct list_head	*pages;
>  };
>  
> -static void
> -iomap_read_inline_data(struct inode *inode, struct page *page,
> +#define offset_in_block(offset, inode) \
> +	((unsigned long)(offset) & (i_blocksize(inode) - 1))
> +
> +static bool
> +inline_data_within_block(struct inode *inode, struct iomap *iomap,
> +		unsigned int size)
> +{
> +	unsigned int off = offset_in_block(iomap->inline_data, inode);
> +
> +	return size <= i_blocksize(inode) - off;
> +}
> +
> +void
> +__iomap_read_inline_data(struct inode *inode, struct page *page,
>  		struct iomap *iomap)
>  {
> -	size_t size = i_size_read(inode);
> +	size_t size = offset_in_block(i_size_read(inode), inode);
> +	unsigned int poff = offset_in_page(iomap->offset);
> +	unsigned int bsize = i_blocksize(inode);
>  	void *addr;
>  
>  	if (PageUptodate(page))
>  		return;
>  
> -	BUG_ON(page->index);
> -	BUG_ON(size > PAGE_SIZE - offset_in_page(iomap->inline_data));
> +	BUG_ON(!inline_data_within_block(inode, iomap, size));
>  
>  	addr = kmap_atomic(page);
> -	memcpy(addr, iomap->inline_data, size);
> -	memset(addr + size, 0, PAGE_SIZE - size);
> +	memcpy(addr + poff, iomap->inline_data, size);
> +	memset(addr + poff + size, 0, bsize - size);
>  	kunmap_atomic(addr);
> -	SetPageUptodate(page);
> +}
> +
> +static void
> +iomap_read_inline_data(struct inode *inode, struct page *page,
> +		struct iomap *iomap)
> +{
> +	unsigned int poff = offset_in_page(iomap->offset);
> +	unsigned int bsize = i_blocksize(inode);
> +
> +	__iomap_read_inline_data(inode, page, iomap);
> +	iomap_set_range_uptodate(page, poff, bsize);
>  }
>  
>  static loff_t
> @@ -292,11 +315,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) {
> -		WARN_ON_ONCE(pos);
> +	if (iomap->type == IOMAP_INLINE)
>  		iomap_read_inline_data(inode, page, iomap);
> -		return PAGE_SIZE;

Hi Andreas,

Thanks for your patch.

In my erofs test case, filled inline data will be zeroed out due to we fallback
to following flow:

	if (iomap->type != IOMAP_MAPPED || pos >= i_size_read(inode)) {
		zero_user(page, poff, plen);

Should we return before this condition check?

Thanks,

> -	}
>  
>  	/* zero post-eof blocks as the page may be mapped */
>  	iomap_adjust_read_range(inode, iop, &pos, length, &poff, &plen);
> @@ -637,6 +657,11 @@ __iomap_write_begin(struct inode *inode, loff_t pos, unsigned len,
>  	if (PageUptodate(page))
>  		return 0;
>  
> +	if (iomap->type == IOMAP_INLINE) {
> +		iomap_read_inline_data(inode, page, iomap);
> +		return 0;
> +	}
> +
>  	do {
>  		iomap_adjust_read_range(inode, iop, &block_start,
>  				block_end - block_start, &poff, &plen);
> @@ -682,9 +707,7 @@ iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, unsigned flags,
>  		goto out_no_page;
>  	}
>  
> -	if (iomap->type == IOMAP_INLINE)
> -		iomap_read_inline_data(inode, page, iomap);
> -	else if (iomap->flags & IOMAP_F_BUFFER_HEAD)
> +	if (iomap->flags & IOMAP_F_BUFFER_HEAD)
>  		status = __block_write_begin_int(page, pos, len, NULL, iomap);
>  	else
>  		status = __iomap_write_begin(inode, pos, len, page, iomap);
> @@ -761,11 +784,11 @@ iomap_write_end_inline(struct inode *inode, struct page *page,
>  {
>  	void *addr;
>  
> -	WARN_ON_ONCE(!PageUptodate(page));
> -	BUG_ON(pos + copied > PAGE_SIZE - offset_in_page(iomap->inline_data));
> +	BUG_ON(!inline_data_within_block(inode, iomap, pos + copied));
>  
>  	addr = kmap_atomic(page);
> -	memcpy(iomap->inline_data + pos, addr + pos, copied);
> +	memcpy(iomap->inline_data + offset_in_block(pos, inode),
> +	       addr + offset_in_page(pos), copied);
>  	kunmap_atomic(addr);
>  
>  	mark_inode_dirty(inode);
> @@ -1064,7 +1087,7 @@ iomap_truncate_page(struct inode *inode, loff_t pos, bool *did_zero,
>  		const struct iomap_ops *ops)
>  {
>  	unsigned int blocksize = i_blocksize(inode);
> -	unsigned int off = pos & (blocksize - 1);
> +	unsigned int off = offset_in_block(pos, inode);
>  
>  	/* Block boundary? Nothing to do */
>  	if (!off)
> @@ -1772,21 +1795,26 @@ iomap_dio_inline_actor(struct inode *inode, loff_t pos, loff_t length,
>  	struct iov_iter *iter = dio->submit.iter;
>  	size_t copied;
>  
> -	BUG_ON(pos + length > PAGE_SIZE - offset_in_page(iomap->inline_data));
> +	BUG_ON(!inline_data_within_block(inode, iomap, pos + length));
>  
>  	if (dio->flags & IOMAP_DIO_WRITE) {
>  		loff_t size = inode->i_size;
>  
>  		if (pos > size)
> -			memset(iomap->inline_data + size, 0, pos - size);
> -		copied = copy_from_iter(iomap->inline_data + pos, length, iter);
> +			memset(iomap->inline_data +
> +			       offset_in_block(size, inode), 0, pos - size);
> +		copied = copy_from_iter(iomap->inline_data +
> +					offset_in_block(pos, inode),
> +					length, iter);
>  		if (copied) {
>  			if (pos + copied > size)
>  				i_size_write(inode, pos + copied);
>  			mark_inode_dirty(inode);
>  		}
>  	} else {
> -		copied = copy_to_iter(iomap->inline_data + pos, length, iter);
> +		copied = copy_to_iter(iomap->inline_data +
> +				      offset_in_block(pos, inode),
> +				      length, iter);
>  	}
>  	dio->size += copied;
>  	return copied;
> diff --git a/include/linux/iomap.h b/include/linux/iomap.h
> index 2103b94cb1bf..a8a60dd2fdc0 100644
> --- a/include/linux/iomap.h
> +++ b/include/linux/iomap.h
> @@ -131,6 +131,9 @@ static inline struct iomap_page *to_iomap_page(struct page *page)
>  	return NULL;
>  }
>  
> +void __iomap_read_inline_data(struct inode *inode, struct page *page,
> +		struct iomap *iomap);
> +
>  ssize_t iomap_file_buffered_write(struct kiocb *iocb, struct iov_iter *from,
>  		const struct iomap_ops *ops);
>  int iomap_readpage(struct page *page, const struct iomap_ops *ops);
> 

  reply	other threads:[~2019-07-12  9:31 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-03  7:55 [RFC PATCH] iomap: generalize IOMAP_INLINE to cover tail-packing case Chao Yu
2019-07-03  7:55 ` Chao Yu
2019-07-08  2:12 ` Chao Yu
2019-07-08  2:12   ` Chao Yu
2019-07-08 16:03 ` Christoph Hellwig
2019-07-09 13:52   ` Chao Yu
2019-07-09 23:32 ` Andreas Grünbacher
2019-07-10 10:30   ` Chao Yu
2019-07-10 10:30     ` Chao Yu
2019-07-10 21:50     ` Andreas Grünbacher
2019-07-10 23:42       ` Gao Xiang
2019-07-11 13:06         ` Matthew Wilcox
2019-07-11 13:54           ` Gao Xiang
2019-07-11 14:15       ` Chao Yu
2019-07-11 12:28     ` Andreas Gruenbacher
2019-07-12  9:31       ` Chao Yu [this message]
2019-07-12  9:31         ` Chao Yu
2019-07-12 11:54         ` Andreas Gruenbacher
2019-07-15  9:26           ` Chao Yu
2019-07-15  9:26             ` Chao Yu
2019-07-17  2:58             ` Chao Yu
2019-07-17  2:58               ` Chao Yu
2019-07-18 12:33           ` Christoph Hellwig
2019-07-18 12:31       ` Christoph Hellwig
2019-07-18 13:27         ` Gao Xiang
2019-07-18 13:27           ` Gao Xiang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=cb41acf2-f222-102a-d31b-02243c77996c@huawei.com \
    --to=yuchao0@huawei.com \
    --cc=agruenba@redhat.com \
    --cc=chao@kernel.org \
    --cc=darrick.wong@oracle.com \
    --cc=gaoxiang25@huawei.com \
    --cc=hch@infradead.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-xfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.