All of lore.kernel.org
 help / color / mirror / Atom feed
From: Josef Bacik <josef@toxicpanda.com>
To: Qu Wenruo <wqu@suse.com>, linux-btrfs@vger.kernel.org
Cc: David Sterba <dsterba@suse.com>
Subject: Re: [PATCH v5 16/18] btrfs: introduce btrfs_subpage for data inodes
Date: Wed, 27 Jan 2021 11:56:39 -0500	[thread overview]
Message-ID: <62fa0a03-e375-8528-0e75-a593745eae1d@toxicpanda.com> (raw)
In-Reply-To: <20210126083402.142577-17-wqu@suse.com>

On 1/26/21 3:34 AM, Qu Wenruo wrote:
> To support subpage sector size, data also need extra info to make sure
> which sectors in a page are uptodate/dirty/...
> 
> This patch will make pages for data inodes to get btrfs_subpage
> structure attached, and detached when the page is freed.
> 
> This patch also slightly changes the timing when
> set_page_extent_mapped() to make sure:
> 
> - We have page->mapping set
>    page->mapping->host is used to grab btrfs_fs_info, thus we can only
>    call this function after page is mapped to an inode.
> 
>    One call site attaches pages to inode manually, thus we have to modify
>    the timing of set_page_extent_mapped() a little.
> 
> - As soon as possible, before other operations
>    Since memory allocation can fail, we have to do extra error handling.
>    Calling set_page_extent_mapped() as soon as possible can simply the
>    error handling for several call sites.
> 
> The idea is pretty much the same as iomap_page, but with more bitmaps
> for btrfs specific cases.
> 
> Currently the plan is to switch iomap if iomap can provide sector
> aligned write back (only write back dirty sectors, but not the full
> page, data balance require this feature).
> 
> So we will stick to btrfs specific bitmap for now.
> 
> Signed-off-by: Qu Wenruo <wqu@suse.com>
> Signed-off-by: David Sterba <dsterba@suse.com>
> ---
>   fs/btrfs/compression.c      | 10 ++++++--
>   fs/btrfs/extent_io.c        | 46 +++++++++++++++++++++++++++++++++----
>   fs/btrfs/extent_io.h        |  3 ++-
>   fs/btrfs/file.c             | 24 ++++++++-----------
>   fs/btrfs/free-space-cache.c | 15 +++++++++---
>   fs/btrfs/inode.c            | 14 +++++++----
>   fs/btrfs/ioctl.c            |  8 ++++++-
>   fs/btrfs/reflink.c          |  5 +++-
>   fs/btrfs/relocation.c       | 11 +++++++--
>   9 files changed, 103 insertions(+), 33 deletions(-)
> 
> diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
> index 5ae3fa0386b7..6d203acfdeb3 100644
> --- a/fs/btrfs/compression.c
> +++ b/fs/btrfs/compression.c
> @@ -542,13 +542,19 @@ static noinline int add_ra_bio_pages(struct inode *inode,
>   			goto next;
>   		}
>   
> -		end = last_offset + PAGE_SIZE - 1;
>   		/*
>   		 * at this point, we have a locked page in the page cache
>   		 * for these bytes in the file.  But, we have to make
>   		 * sure they map to this compressed extent on disk.
>   		 */
> -		set_page_extent_mapped(page);
> +		ret = set_page_extent_mapped(page);
> +		if (ret < 0) {
> +			unlock_page(page);
> +			put_page(page);
> +			break;
> +		}
> +
> +		end = last_offset + PAGE_SIZE - 1;
>   		lock_extent(tree, last_offset, end);
>   		read_lock(&em_tree->lock);
>   		em = lookup_extent_mapping(em_tree, last_offset,
> diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
> index 139a8a77ed72..eeee3213daaa 100644
> --- a/fs/btrfs/extent_io.c
> +++ b/fs/btrfs/extent_io.c
> @@ -3190,10 +3190,39 @@ static int attach_extent_buffer_page(struct extent_buffer *eb,
>   	return ret;
>   }
>   
> -void set_page_extent_mapped(struct page *page)
> +int set_page_extent_mapped(struct page *page)
>   {
> +	struct btrfs_fs_info *fs_info;
> +
> +	ASSERT(page->mapping);
> +
> +	if (PagePrivate(page))
> +		return 0;
> +
> +	fs_info = btrfs_sb(page->mapping->host->i_sb);
> +
> +	if (fs_info->sectorsize < PAGE_SIZE)
> +		return btrfs_attach_subpage(fs_info, page, BTRFS_SUBPAGE_DATA);
> +
> +	attach_page_private(page, (void *)EXTENT_PAGE_PRIVATE);
> +	return 0;
> +
> +}
> +
> +void clear_page_extent_mapped(struct page *page)
> +{
> +	struct btrfs_fs_info *fs_info;
> +
> +	ASSERT(page->mapping);
> +
>   	if (!PagePrivate(page))
> -		attach_page_private(page, (void *)EXTENT_PAGE_PRIVATE);
> +		return;
> +
> +	fs_info = btrfs_sb(page->mapping->host->i_sb);
> +	if (fs_info->sectorsize < PAGE_SIZE)
> +		return btrfs_detach_subpage(fs_info, page);
> +
> +	detach_page_private(page);
>   }
>   
>   static struct extent_map *
> @@ -3250,7 +3279,12 @@ int btrfs_do_readpage(struct page *page, struct extent_map **em_cached,
>   	unsigned long this_bio_flag = 0;
>   	struct extent_io_tree *tree = &BTRFS_I(inode)->io_tree;
>   
> -	set_page_extent_mapped(page);
> +	ret = set_page_extent_mapped(page);
> +	if (ret < 0) {
> +		unlock_extent(tree, start, end);
> +		SetPageError(page);
> +		goto out;
> +	}
>   
>   	if (!PageUptodate(page)) {
>   		if (cleancache_get_page(page) == 0) {
> @@ -3690,7 +3724,11 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,
>   		flush_dcache_page(page);
>   	}
>   
> -	set_page_extent_mapped(page);
> +	ret = set_page_extent_mapped(page);
> +	if (ret < 0) {
> +		SetPageError(page);
> +		goto done;
> +	}
>   
>   	if (!epd->extent_locked) {
>   		ret = writepage_delalloc(BTRFS_I(inode), page, wbc, start,
> diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
> index 2d8187c84812..047b3e66897f 100644
> --- a/fs/btrfs/extent_io.h
> +++ b/fs/btrfs/extent_io.h
> @@ -178,7 +178,8 @@ int btree_write_cache_pages(struct address_space *mapping,
>   void extent_readahead(struct readahead_control *rac);
>   int extent_fiemap(struct btrfs_inode *inode, struct fiemap_extent_info *fieinfo,
>   		  u64 start, u64 len);
> -void set_page_extent_mapped(struct page *page);
> +int set_page_extent_mapped(struct page *page);
> +void clear_page_extent_mapped(struct page *page);
>   
>   struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
>   					  u64 start, u64 owner_root, int level);
> diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
> index d81ae1f518f2..63b290210eaa 100644
> --- a/fs/btrfs/file.c
> +++ b/fs/btrfs/file.c
> @@ -1369,6 +1369,12 @@ static noinline int prepare_pages(struct inode *inode, struct page **pages,
>   			goto fail;
>   		}
>   
> +		err = set_page_extent_mapped(pages[i]);
> +		if (err < 0) {
> +			faili = i;
> +			goto fail;
> +		}
> +
>   		if (i == 0)
>   			err = prepare_uptodate_page(inode, pages[i], pos,
>   						    force_uptodate);
> @@ -1453,23 +1459,11 @@ lock_and_cleanup_extent_if_need(struct btrfs_inode *inode, struct page **pages,
>   	}
>   
>   	/*
> -	 * It's possible the pages are dirty right now, but we don't want
> -	 * to clean them yet because copy_from_user may catch a page fault
> -	 * and we might have to fall back to one page at a time.  If that
> -	 * happens, we'll unlock these pages and we'd have a window where
> -	 * reclaim could sneak in and drop the once-dirty page on the floor
> -	 * without writing it.
> -	 *
> -	 * We have the pages locked and the extent range locked, so there's
> -	 * no way someone can start IO on any dirty pages in this range.
> -	 *
> -	 * We'll call btrfs_dirty_pages() later on, and that will flip around
> -	 * delalloc bits and dirty the pages as required.
> +	 * We should be called after prepare_pages() which should have
> +	 * locked all pages in the range.
>   	 */
> -	for (i = 0; i < num_pages; i++) {
> -		set_page_extent_mapped(pages[i]);
> +	for (i = 0; i < num_pages; i++)
>   		WARN_ON(!PageLocked(pages[i]));
> -	}
>   
>   	return ret;
>   }
> diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
> index fd6ddd6b8165..35e5c6ee0584 100644
> --- a/fs/btrfs/free-space-cache.c
> +++ b/fs/btrfs/free-space-cache.c
> @@ -431,11 +431,22 @@ static int io_ctl_prepare_pages(struct btrfs_io_ctl *io_ctl, bool uptodate)
>   	int i;
>   
>   	for (i = 0; i < io_ctl->num_pages; i++) {
> +		int ret;
> +
>   		page = find_or_create_page(inode->i_mapping, i, mask);
>   		if (!page) {
>   			io_ctl_drop_pages(io_ctl);
>   			return -ENOMEM;
>   		}
> +
> +		ret = set_page_extent_mapped(page);
> +		if (ret < 0) {
> +			unlock_page(page);
> +			put_page(page);
> +			io_ctl_drop_pages(io_ctl);
> +			return ret;
> +		}
> +
>   		io_ctl->pages[i] = page;
>   		if (uptodate && !PageUptodate(page)) {
>   			btrfs_readpage(NULL, page);
> @@ -455,10 +466,8 @@ static int io_ctl_prepare_pages(struct btrfs_io_ctl *io_ctl, bool uptodate)
>   		}
>   	}
>   
> -	for (i = 0; i < io_ctl->num_pages; i++) {
> +	for (i = 0; i < io_ctl->num_pages; i++)
>   		clear_page_dirty_for_io(io_ctl->pages[i]);
> -		set_page_extent_mapped(io_ctl->pages[i]);
> -	}
>   
>   	return 0;
>   }
> diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
> index d1bb3cc8499b..a18e3c950f07 100644
> --- a/fs/btrfs/inode.c
> +++ b/fs/btrfs/inode.c
> @@ -4712,6 +4712,9 @@ int btrfs_truncate_block(struct btrfs_inode *inode, loff_t from, loff_t len,
>   		ret = -ENOMEM;
>   		goto out;
>   	}
> +	ret = set_page_extent_mapped(page);
> +	if (ret < 0)
> +		goto out_unlock;
>   
>   	if (!PageUptodate(page)) {
>   		ret = btrfs_readpage(NULL, page);
> @@ -4729,7 +4732,6 @@ int btrfs_truncate_block(struct btrfs_inode *inode, loff_t from, loff_t len,
>   	wait_on_page_writeback(page);
>   
>   	lock_extent_bits(io_tree, block_start, block_end, &cached_state);
> -	set_page_extent_mapped(page);
>   
>   	ordered = btrfs_lookup_ordered_extent(inode, block_start);
>   	if (ordered) {
> @@ -8107,7 +8109,7 @@ static int __btrfs_releasepage(struct page *page, gfp_t gfp_flags)
>   {
>   	int ret = try_release_extent_mapping(page, gfp_flags);
>   	if (ret == 1)
> -		detach_page_private(page);
> +		clear_page_extent_mapped(page);
>   	return ret;
>   }
>   
> @@ -8266,7 +8268,7 @@ static void btrfs_invalidatepage(struct page *page, unsigned int offset,
>   	}
>   
>   	ClearPageChecked(page);
> -	detach_page_private(page);
> +	clear_page_extent_mapped(page);
>   }
>   
>   /*
> @@ -8345,7 +8347,11 @@ vm_fault_t btrfs_page_mkwrite(struct vm_fault *vmf)
>   	wait_on_page_writeback(page);
>   
>   	lock_extent_bits(io_tree, page_start, page_end, &cached_state);
> -	set_page_extent_mapped(page);
> +	ret2 = set_page_extent_mapped(page);
> +	if (ret2 < 0) {
> +		ret = vmf_error(ret2);
> +		goto out_unlock;
> +	}

Sorry I missed this bit in my last reply, you need a

ret = vmf_error(ret2);
unlock_extent_cached(io_tree, page_start, page_end, &cached_state);
goto out_unlock;

Thanks,

Josef

  reply	other threads:[~2021-01-27 17:01 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-26  8:33 [PATCH v5 00/18] btrfs: add read-only support for subpage sector size Qu Wenruo
2021-01-26  8:33 ` [PATCH v5 01/18] btrfs: merge PAGE_CLEAR_DIRTY and PAGE_SET_WRITEBACK to PAGE_START_WRITEBACK Qu Wenruo
2021-01-27 15:56   ` Josef Bacik
2021-01-26  8:33 ` [PATCH v5 02/18] btrfs: set UNMAPPED bit early in btrfs_clone_extent_buffer() for subpage support Qu Wenruo
2021-01-27 15:56   ` Josef Bacik
2021-01-26  8:33 ` [PATCH v5 03/18] btrfs: introduce the skeleton of btrfs_subpage structure Qu Wenruo
2021-01-26  8:33 ` [PATCH v5 04/18] btrfs: make attach_extent_buffer_page() handle subpage case Qu Wenruo
2021-01-27 16:01   ` Josef Bacik
2021-01-26  8:33 ` [PATCH v5 05/18] btrfs: make grab_extent_buffer_from_page() " Qu Wenruo
2021-01-27 16:20   ` Josef Bacik
2021-01-26  8:33 ` [PATCH v5 06/18] btrfs: support subpage for extent buffer page release Qu Wenruo
2021-01-27 16:21   ` Josef Bacik
2021-02-01 15:32     ` David Sterba
2021-01-26  8:33 ` [PATCH v5 07/18] btrfs: attach private to dummy extent buffer pages Qu Wenruo
2021-01-27 16:21   ` Josef Bacik
2021-01-26  8:33 ` [PATCH v5 08/18] btrfs: introduce helpers for subpage uptodate status Qu Wenruo
2021-01-27 16:34   ` Josef Bacik
2021-01-26  8:33 ` [PATCH v5 09/18] btrfs: introduce helpers for subpage error status Qu Wenruo
2021-01-27 16:34   ` Josef Bacik
2021-01-26  8:33 ` [PATCH v5 10/18] btrfs: support subpage in set/clear_extent_buffer_uptodate() Qu Wenruo
2021-01-27 16:35   ` Josef Bacik
2021-01-26  8:33 ` [PATCH v5 11/18] btrfs: support subpage in btrfs_clone_extent_buffer Qu Wenruo
2021-01-27 16:35   ` Josef Bacik
2021-01-26  8:33 ` [PATCH v5 12/18] btrfs: support subpage in try_release_extent_buffer() Qu Wenruo
2021-01-27 16:37   ` Josef Bacik
2021-01-26  8:33 ` [PATCH v5 13/18] btrfs: introduce read_extent_buffer_subpage() Qu Wenruo
2021-01-27 16:39   ` Josef Bacik
2021-01-26  8:33 ` [PATCH v5 14/18] btrfs: support subpage in endio_readpage_update_page_status() Qu Wenruo
2021-01-27 16:42   ` Josef Bacik
2021-01-26  8:33 ` [PATCH v5 15/18] btrfs: introduce subpage metadata validation check Qu Wenruo
2021-01-27 16:47   ` Josef Bacik
2021-01-26  8:34 ` [PATCH v5 16/18] btrfs: introduce btrfs_subpage for data inodes Qu Wenruo
2021-01-27 16:56   ` Josef Bacik [this message]
2021-02-01 15:42     ` David Sterba
2021-01-26  8:34 ` [PATCH v5 17/18] btrfs: integrate page status update for data read path into begin/end_page_read() Qu Wenruo
2021-01-27 17:13   ` Josef Bacik
2021-02-01 15:47     ` David Sterba
2021-01-26  8:34 ` [PATCH v5 18/18] btrfs: allow RO mount of 4K sector size fs on 64K page system Qu Wenruo
2021-01-27 17:13   ` Josef Bacik
2021-02-01 15:49   ` David Sterba
2021-01-27 16:17 ` [PATCH v5 00/18] btrfs: add read-only support for subpage sector size Josef Bacik
2021-01-28  0:30   ` Qu Wenruo
2021-01-28 10:34     ` David Sterba
2021-01-28 10:51       ` Qu Wenruo
2021-02-01 14:50         ` David Sterba
2021-02-01 15:55 ` David Sterba
2021-02-02  9:21 ` [bug report] Unable to handle kernel paging request Anand Jain
2021-02-02 10:23   ` Qu Wenruo
2021-02-02 11:28     ` Anand Jain
2021-02-02 13:37       ` Anand Jain
2021-02-04  5:13         ` Qu Wenruo
2021-02-03 13:20 ` [PATCH v5 00/18] btrfs: add read-only support for subpage sector size David Sterba

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=62fa0a03-e375-8528-0e75-a593745eae1d@toxicpanda.com \
    --to=josef@toxicpanda.com \
    --cc=dsterba@suse.com \
    --cc=linux-btrfs@vger.kernel.org \
    --cc=wqu@suse.com \
    /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.