From patchwork Thu Dec 10 06:38:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 11963399 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5431FC4361B for ; Thu, 10 Dec 2020 06:40:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id EF90B23C44 for ; Thu, 10 Dec 2020 06:40:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387480AbgLJGj5 (ORCPT ); Thu, 10 Dec 2020 01:39:57 -0500 Received: from mx2.suse.de ([195.135.220.15]:44098 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725789AbgLJGj5 (ORCPT ); Thu, 10 Dec 2020 01:39:57 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1607582350; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=YfOnHta0fEzKr+6XAB1v7VtZGz0rRZVR9Wst5PhJ9eU=; b=hlZGbyCn2if2epSEpvE7TA1OZKE1WsKiMWhmO0BBNMibK70Bi4g3j4Iaq7No/7YUxVY929 XdB+Y/jOr9E/rrb9+tjwWABaM6XJSSRakB2R8vJ/EHul3tx8CMt6umiXjeMJ8nimKNcsXH FNEU+slVvE3xDk4Toz3v0swcahQRIiY= Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id AC2A8AC6A for ; Thu, 10 Dec 2020 06:39:10 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v2 01/18] btrfs: extent_io: rename @offset parameter to @disk_bytenr for submit_extent_page() Date: Thu, 10 Dec 2020 14:38:48 +0800 Message-Id: <20201210063905.75727-2-wqu@suse.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201210063905.75727-1-wqu@suse.com> References: <20201210063905.75727-1-wqu@suse.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org The parameter @offset can't be more confusing. In fact that parameter is the disk bytenr for metadata/data. Rename it to @disk_bytenr and update the comment to reduce confusion. Since we're here, also rename all @offset passed into submit_extent_page() to @disk_bytenr. Signed-off-by: Qu Wenruo Reviewed-by: Josef Bacik --- fs/btrfs/extent_io.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 6e3b72e63e42..2650e8720394 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -3064,10 +3064,10 @@ struct bio *btrfs_bio_clone_partial(struct bio *orig, int offset, int size) * @opf: bio REQ_OP_* and REQ_* flags as one value * @wbc: optional writeback control for io accounting * @page: page to add to the bio + * @disk_bytenr:the logical bytenr where the write will be + * @size: portion of page that we want to write * @pg_offset: offset of the new bio or to check whether we are adding * a contiguous page to the previous one - * @size: portion of page that we want to write - * @offset: starting offset in the page * @bio_ret: must be valid pointer, newly allocated bio will be stored there * @end_io_func: end_io callback for new bio * @mirror_num: desired mirror to read/write @@ -3076,7 +3076,7 @@ struct bio *btrfs_bio_clone_partial(struct bio *orig, int offset, int size) */ static int submit_extent_page(unsigned int opf, struct writeback_control *wbc, - struct page *page, u64 offset, + struct page *page, u64 disk_bytenr, size_t size, unsigned long pg_offset, struct bio **bio_ret, bio_end_io_t end_io_func, @@ -3088,7 +3088,7 @@ static int submit_extent_page(unsigned int opf, int ret = 0; struct bio *bio; size_t io_size = min_t(size_t, size, PAGE_SIZE); - sector_t sector = offset >> 9; + sector_t sector = disk_bytenr >> 9; struct extent_io_tree *tree = &BTRFS_I(page->mapping->host)->io_tree; ASSERT(bio_ret); @@ -3122,7 +3122,7 @@ static int submit_extent_page(unsigned int opf, } } - bio = btrfs_bio_alloc(offset); + bio = btrfs_bio_alloc(disk_bytenr); bio_add_page(bio, page, io_size, pg_offset); bio->bi_end_io = end_io_func; bio->bi_private = tree; @@ -3244,7 +3244,7 @@ int btrfs_do_readpage(struct page *page, struct extent_map **em_cached, } while (cur <= end) { bool force_bio_submit = false; - u64 offset; + u64 disk_bytenr; if (cur >= last_byte) { char *userpage; @@ -3282,9 +3282,9 @@ int btrfs_do_readpage(struct page *page, struct extent_map **em_cached, cur_end = min(extent_map_end(em) - 1, end); iosize = ALIGN(iosize, blocksize); if (this_bio_flag & EXTENT_BIO_COMPRESSED) - offset = em->block_start; + disk_bytenr = em->block_start; else - offset = em->block_start + extent_offset; + disk_bytenr = em->block_start + extent_offset; block_start = em->block_start; if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) block_start = EXTENT_MAP_HOLE; @@ -3373,7 +3373,7 @@ int btrfs_do_readpage(struct page *page, struct extent_map **em_cached, } ret = submit_extent_page(REQ_OP_READ | read_flags, NULL, - page, offset, iosize, + page, disk_bytenr, iosize, pg_offset, bio, end_bio_extent_readpage, 0, *bio_flags, @@ -3550,8 +3550,8 @@ static noinline_for_stack int __extent_writepage_io(struct btrfs_inode *inode, blocksize = inode->vfs_inode.i_sb->s_blocksize; while (cur <= end) { + u64 disk_bytenr; u64 em_end; - u64 offset; if (cur >= i_size) { btrfs_writepage_endio_finish_ordered(page, cur, @@ -3571,7 +3571,7 @@ static noinline_for_stack int __extent_writepage_io(struct btrfs_inode *inode, BUG_ON(end < cur); iosize = min(em_end - cur, end - cur + 1); iosize = ALIGN(iosize, blocksize); - offset = em->block_start + extent_offset; + disk_bytenr = em->block_start + extent_offset; block_start = em->block_start; compressed = test_bit(EXTENT_FLAG_COMPRESSED, &em->flags); free_extent_map(em); @@ -3601,7 +3601,7 @@ static noinline_for_stack int __extent_writepage_io(struct btrfs_inode *inode, } ret = submit_extent_page(REQ_OP_WRITE | write_flags, wbc, - page, offset, iosize, pg_offset, + page, disk_bytenr, iosize, pg_offset, &epd->bio, end_bio_extent_writepage, 0, 0, 0, false); @@ -3925,7 +3925,7 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb, struct writeback_control *wbc, struct extent_page_data *epd) { - u64 offset = eb->start; + u64 disk_bytenr = eb->start; u32 nritems; int i, num_pages; unsigned long start, end; @@ -3958,7 +3958,7 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb, clear_page_dirty_for_io(p); set_page_writeback(p); ret = submit_extent_page(REQ_OP_WRITE | write_flags, wbc, - p, offset, PAGE_SIZE, 0, + p, disk_bytenr, PAGE_SIZE, 0, &epd->bio, end_bio_extent_buffer_writepage, 0, 0, 0, false); @@ -3971,7 +3971,7 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb, ret = -EIO; break; } - offset += PAGE_SIZE; + disk_bytenr += PAGE_SIZE; update_nr_written(wbc, 1); unlock_page(p); } From patchwork Thu Dec 10 06:38:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 11963405 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7AE47C0018C for ; Thu, 10 Dec 2020 06:40:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2014D23D50 for ; Thu, 10 Dec 2020 06:40:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387485AbgLJGj7 (ORCPT ); Thu, 10 Dec 2020 01:39:59 -0500 Received: from mx2.suse.de ([195.135.220.15]:44108 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387481AbgLJGj7 (ORCPT ); Thu, 10 Dec 2020 01:39:59 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1607582352; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=qmDjZY+tFrSsnqoJYWp4sxqtgO+W2q0468i3xz3L43c=; b=aIqrxn0oyk5QafTQtt582pBwOJbyC7dLAy96yvRUxZoyNUTvMYw+xQsQpgWY0ZtC32tDwl OP49kGnInODA6HP9iAigpOzOXT88p/YAqNgiGITL6Aspm7H+x2ZJCCjiRXNY+rIcMi9wcB 1p3Pme18x/z+TRC+xQym0JannTMuD7w= Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 58A93ACC6 for ; Thu, 10 Dec 2020 06:39:12 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v2 02/18] btrfs: extent_io: refactor __extent_writepage_io() to improve readability Date: Thu, 10 Dec 2020 14:38:49 +0800 Message-Id: <20201210063905.75727-3-wqu@suse.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201210063905.75727-1-wqu@suse.com> References: <20201210063905.75727-1-wqu@suse.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org The refactor involves the following modifications: - iosize alignment In fact we don't really need to manually do alignment at all. All extent maps should already be aligned, thus basic ASSERT() check would be enough. - redundant variables We have extra variable like blocksize/pg_offset/end. They are all unnecessary. @blocksize can be replaced by sectorsize size directly, and it's only used to verify the em start/size is aligned. @pg_offset can be easily calculated using @cur and page_offset(page). @end is just assigned to @page_end and never modified, use @page_end to replace it. - remove some BUG_ON()s The BUG_ON()s are for extent map, which we have tree-checker to check on-disk extent data item and runtime check. ASSERT() should be enough. Signed-off-by: Qu Wenruo Reviewed-by: Josef Bacik --- fs/btrfs/extent_io.c | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 2650e8720394..612fe60b367e 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -3515,17 +3515,14 @@ static noinline_for_stack int __extent_writepage_io(struct btrfs_inode *inode, unsigned long nr_written, int *nr_ret) { + struct btrfs_fs_info *fs_info = inode->root->fs_info; struct extent_io_tree *tree = &inode->io_tree; u64 start = page_offset(page); u64 page_end = start + PAGE_SIZE - 1; - u64 end; u64 cur = start; u64 extent_offset; u64 block_start; - u64 iosize; struct extent_map *em; - size_t pg_offset = 0; - size_t blocksize; int ret = 0; int nr = 0; const unsigned int write_flags = wbc_to_write_flags(wbc); @@ -3546,19 +3543,17 @@ static noinline_for_stack int __extent_writepage_io(struct btrfs_inode *inode, */ update_nr_written(wbc, nr_written + 1); - end = page_end; - blocksize = inode->vfs_inode.i_sb->s_blocksize; - - while (cur <= end) { + while (cur <= page_end) { u64 disk_bytenr; u64 em_end; + u32 iosize; if (cur >= i_size) { btrfs_writepage_endio_finish_ordered(page, cur, page_end, 1); break; } - em = btrfs_get_extent(inode, NULL, 0, cur, end - cur + 1); + em = btrfs_get_extent(inode, NULL, 0, cur, page_end - cur + 1); if (IS_ERR_OR_NULL(em)) { SetPageError(page); ret = PTR_ERR_OR_ZERO(em); @@ -3567,16 +3562,20 @@ static noinline_for_stack int __extent_writepage_io(struct btrfs_inode *inode, extent_offset = cur - em->start; em_end = extent_map_end(em); - BUG_ON(em_end <= cur); - BUG_ON(end < cur); - iosize = min(em_end - cur, end - cur + 1); - iosize = ALIGN(iosize, blocksize); - disk_bytenr = em->block_start + extent_offset; + ASSERT(cur <= em_end); + ASSERT(cur < page_end); + ASSERT(IS_ALIGNED(em->start, fs_info->sectorsize)); + ASSERT(IS_ALIGNED(em->len, fs_info->sectorsize)); block_start = em->block_start; compressed = test_bit(EXTENT_FLAG_COMPRESSED, &em->flags); + disk_bytenr = em->block_start + extent_offset; + + /* Note that em_end from extent_map_end() is exclusive */ + iosize = min(em_end, page_end + 1) - cur; free_extent_map(em); em = NULL; + /* * compressed and inline extents are written through other * paths in the FS @@ -3589,7 +3588,6 @@ static noinline_for_stack int __extent_writepage_io(struct btrfs_inode *inode, btrfs_writepage_endio_finish_ordered(page, cur, cur + iosize - 1, 1); cur += iosize; - pg_offset += iosize; continue; } @@ -3597,12 +3595,12 @@ static noinline_for_stack int __extent_writepage_io(struct btrfs_inode *inode, if (!PageWriteback(page)) { btrfs_err(inode->root->fs_info, "page %lu not writeback, cur %llu end %llu", - page->index, cur, end); + page->index, cur, page_end); } ret = submit_extent_page(REQ_OP_WRITE | write_flags, wbc, - page, disk_bytenr, iosize, pg_offset, - &epd->bio, + page, disk_bytenr, iosize, + cur - page_offset(page), &epd->bio, end_bio_extent_writepage, 0, 0, 0, false); if (ret) { @@ -3611,8 +3609,7 @@ static noinline_for_stack int __extent_writepage_io(struct btrfs_inode *inode, end_page_writeback(page); } - cur = cur + iosize; - pg_offset += iosize; + cur += iosize; nr++; } *nr_ret = nr; From patchwork Thu Dec 10 06:38:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 11963403 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 87E22C1B0D8 for ; Thu, 10 Dec 2020 06:40:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4353623B98 for ; Thu, 10 Dec 2020 06:40:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387494AbgLJGkA (ORCPT ); Thu, 10 Dec 2020 01:40:00 -0500 Received: from mx2.suse.de ([195.135.220.15]:44216 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387481AbgLJGkA (ORCPT ); Thu, 10 Dec 2020 01:40:00 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1607582354; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ddZsXFITmL0WGJwxBiWhU61AVm8mYTAI4G7SE3nb+7U=; b=gjke2TdAhxPAFQ6tl+Bb1s2J5r1KjBfrhMbZbO51ViQ8OK+6kh6Lpfs3uqEnLRtl+GEj1X 1nBjQoYLvVUOEk1L+a0q2T89uFzAVWhTwi4vmm2Oit+E7BddtKujmBnd1NNfrTTqKbmW4L mnPcnNuWKf1t5qn+TNtgRn15mdLnU6k= Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 264B9AD6D for ; Thu, 10 Dec 2020 06:39:14 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v2 03/18] btrfs: file: update comment for btrfs_dirty_pages() Date: Thu, 10 Dec 2020 14:38:50 +0800 Message-Id: <20201210063905.75727-4-wqu@suse.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201210063905.75727-1-wqu@suse.com> References: <20201210063905.75727-1-wqu@suse.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org The original comment is from the initial merge, which has several problems: - No holes check any more - No inline decision is made Update the out-of-date comment with more correct one. Signed-off-by: Qu Wenruo --- fs/btrfs/file.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 0e41459b8de6..a29b50208eee 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -453,12 +453,15 @@ static void btrfs_drop_pages(struct page **pages, size_t num_pages) } /* - * after copy_from_user, pages need to be dirtied and we need to make - * sure holes are created between the current EOF and the start of - * any next extents (if required). - * - * this also makes the decision about creating an inline extent vs - * doing real data extents, marking pages dirty and delalloc as required. + * After btrfs_copy_from_user(), update the following things for delalloc: + * - DELALLOC extent io tree bits + * Later btrfs_run_delalloc_range() relies on this bit to determine the + * writeback range. + * - Page status + * Including basic status like Dirty and Uptodate, and btrfs specific bit + * like Checked (for cow fixup) + * - Inode size update + * If needed */ int btrfs_dirty_pages(struct btrfs_inode *inode, struct page **pages, size_t num_pages, loff_t pos, size_t write_bytes, From patchwork Thu Dec 10 06:38:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 11963407 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BA041C4167B for ; Thu, 10 Dec 2020 06:40:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6774523C44 for ; Thu, 10 Dec 2020 06:40:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387497AbgLJGkE (ORCPT ); Thu, 10 Dec 2020 01:40:04 -0500 Received: from mx2.suse.de ([195.135.220.15]:44282 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387496AbgLJGkE (ORCPT ); Thu, 10 Dec 2020 01:40:04 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1607582357; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=3MYT7OdT61w2xAFuZTlre1acT7NXGekPZPGk/vnndeE=; b=f4o9k6zEZ7N/ob1jWV+IdMg3BVcCd4Gkmi4uhqjqG/Q3g9TEYhYNyt4e3ZBDJ+30CPfF/h no+XdMAVcz8tVtKJw2lrmv6jNcoQ6xkBNP/buLNwBe6qQh7MGNPhGF9NDEoJg+JJY0JAcd Vxhw6bgJlqDtriKXqYSXTR1GwYkPtaI= Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 7DD0EACE1; Thu, 10 Dec 2020 06:39:17 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Cc: Johannes Thumshirn Subject: [PATCH v2 04/18] btrfs: extent_io: introduce a helper to grab an existing extent buffer from a page Date: Thu, 10 Dec 2020 14:38:51 +0800 Message-Id: <20201210063905.75727-5-wqu@suse.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201210063905.75727-1-wqu@suse.com> References: <20201210063905.75727-1-wqu@suse.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org This patch will extract the code to grab an extent buffer from a page into a helper, grab_extent_buffer_from_page(). This reduces one indent level, and provides the work place for later expansion for subapge support. Reviewed-by: Johannes Thumshirn Signed-off-by: Qu Wenruo --- fs/btrfs/extent_io.c | 52 +++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 612fe60b367e..6350c2687c7e 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -5251,6 +5251,32 @@ struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info, } #endif +static struct extent_buffer *grab_extent_buffer_from_page(struct page *page) +{ + struct extent_buffer *exists; + + /* Page not yet attached to an extent buffer */ + if (!PagePrivate(page)) + return NULL; + + /* + * We could have already allocated an eb for this page + * and attached one so lets see if we can get a ref on + * the existing eb, and if we can we know it's good and + * we can just return that one, else we know we can just + * overwrite page->private. + */ + exists = (struct extent_buffer *)page->private; + if (atomic_inc_not_zero(&exists->refs)) { + mark_extent_buffer_accessed(exists, page); + return exists; + } + + WARN_ON(PageDirty(page)); + detach_page_private(page); + return NULL; +} + struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info, u64 start, u64 owner_root, int level) { @@ -5296,26 +5322,12 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info, } spin_lock(&mapping->private_lock); - if (PagePrivate(p)) { - /* - * We could have already allocated an eb for this page - * and attached one so lets see if we can get a ref on - * the existing eb, and if we can we know it's good and - * we can just return that one, else we know we can just - * overwrite page->private. - */ - exists = (struct extent_buffer *)p->private; - if (atomic_inc_not_zero(&exists->refs)) { - spin_unlock(&mapping->private_lock); - unlock_page(p); - put_page(p); - mark_extent_buffer_accessed(exists, p); - goto free_eb; - } - exists = NULL; - - WARN_ON(PageDirty(p)); - detach_page_private(p); + exists = grab_extent_buffer_from_page(p); + if (exists) { + spin_unlock(&mapping->private_lock); + unlock_page(p); + put_page(p); + goto free_eb; } attach_extent_buffer_page(eb, p); spin_unlock(&mapping->private_lock); From patchwork Thu Dec 10 06:38:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 11963409 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C9B1EC4361B for ; Thu, 10 Dec 2020 06:40:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 90DAC23C44 for ; Thu, 10 Dec 2020 06:40:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387516AbgLJGkn (ORCPT ); Thu, 10 Dec 2020 01:40:43 -0500 Received: from mx2.suse.de ([195.135.220.15]:44470 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387495AbgLJGkm (ORCPT ); Thu, 10 Dec 2020 01:40:42 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1607582359; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WAUi5Lo67vza2hNb6jv5/OvAnEriobO1LUkzYaN/sqs=; b=VhgvM0bBkiQ3qOoj75PtoirlA+To0a8PCmb4zVyhNWg+2qyCJ8idDryA8EQ+9FH9EqP4oU PhLFoEKzyFv8DYiJ/cjcSoct7bjI07feIlcxqwqr9x/Kpz+G/+bbepccpv+YRPzs0eB+yz cDW0bA/SC+OfouKX/RNwciBkXrYMkY0= Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 5F709ACF9 for ; Thu, 10 Dec 2020 06:39:19 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v2 05/18] btrfs: extent_io: introduce the skeleton of btrfs_subpage structure Date: Thu, 10 Dec 2020 14:38:52 +0800 Message-Id: <20201210063905.75727-6-wqu@suse.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201210063905.75727-1-wqu@suse.com> References: <20201210063905.75727-1-wqu@suse.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org For btrfs subpage support, we need a structure to record extra info for the status of each sectors of a page. This patch will introduce the skeleton structure for future btrfs subpage support. All subpage related code would go to subpage.[ch] to avoid populating the existing code base. Signed-off-by: Qu Wenruo Reviewed-by: Josef Bacik --- fs/btrfs/Makefile | 3 ++- fs/btrfs/subpage.c | 34 ++++++++++++++++++++++++++++++++++ fs/btrfs/subpage.h | 31 +++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 fs/btrfs/subpage.c create mode 100644 fs/btrfs/subpage.h diff --git a/fs/btrfs/Makefile b/fs/btrfs/Makefile index 9f1b1a88e317..942562e11456 100644 --- a/fs/btrfs/Makefile +++ b/fs/btrfs/Makefile @@ -11,7 +11,8 @@ btrfs-y += super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \ compression.o delayed-ref.o relocation.o delayed-inode.o scrub.o \ reada.o backref.o ulist.o qgroup.o send.o dev-replace.o raid56.o \ uuid-tree.o props.o free-space-tree.o tree-checker.o space-info.o \ - block-rsv.o delalloc-space.o block-group.o discard.o reflink.o + block-rsv.o delalloc-space.o block-group.o discard.o reflink.o \ + subpage.o btrfs-$(CONFIG_BTRFS_FS_POSIX_ACL) += acl.o btrfs-$(CONFIG_BTRFS_FS_CHECK_INTEGRITY) += check-integrity.o diff --git a/fs/btrfs/subpage.c b/fs/btrfs/subpage.c new file mode 100644 index 000000000000..9ca9f9ca61a9 --- /dev/null +++ b/fs/btrfs/subpage.c @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "subpage.h" + +int btrfs_attach_subpage(struct btrfs_fs_info *fs_info, struct page *page) +{ + struct btrfs_subpage *subpage; + + ASSERT(PageLocked(page)); + /* Either not subpage, or the page already has private attached */ + if (fs_info->sectorsize == PAGE_SIZE || PagePrivate(page)) + return 0; + + subpage = kzalloc(sizeof(*subpage), GFP_NOFS); + if (!subpage) + return -ENOMEM; + + spin_lock_init(&subpage->lock); + attach_page_private(page, subpage); + return 0; +} + +void btrfs_detach_subpage(struct btrfs_fs_info *fs_info, struct page *page) +{ + struct btrfs_subpage *subpage; + + /* Either not subpage, or already detached */ + if (fs_info->sectorsize == PAGE_SIZE || !PagePrivate(page)) + return; + + subpage = (struct btrfs_subpage *)detach_page_private(page); + ASSERT(subpage); + kfree(subpage); +} diff --git a/fs/btrfs/subpage.h b/fs/btrfs/subpage.h new file mode 100644 index 000000000000..96f3b226913e --- /dev/null +++ b/fs/btrfs/subpage.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef BTRFS_SUBPAGE_H +#define BTRFS_SUBPAGE_H + +#include +#include "ctree.h" + +/* + * Since the maximum page size btrfs is going to support is 64K while the + * minimum sectorsize is 4K, this means a u16 bitmap is enough. + * + * The regular bitmap requires 32 bits as minimal bitmap size, so we can't use + * existing bitmap_* helpers here. + */ +#define BTRFS_SUBPAGE_BITMAP_SIZE 16 + +/* + * Structure to trace status of each sector inside a page. + * + * Will be attached to page::private for both data and metadata inodes. + */ +struct btrfs_subpage { + /* Common members for both data and metadata pages */ + spinlock_t lock; +}; + +int btrfs_attach_subpage(struct btrfs_fs_info *fs_info, struct page *page); +void btrfs_detach_subpage(struct btrfs_fs_info *fs_info, struct page *page); + +#endif /* BTRFS_SUBPAGE_H */ From patchwork Thu Dec 10 06:38:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 11963421 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5906AC1B0D8 for ; Thu, 10 Dec 2020 06:40:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1E76823D50 for ; Thu, 10 Dec 2020 06:40:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387507AbgLJGkm (ORCPT ); Thu, 10 Dec 2020 01:40:42 -0500 Received: from mx2.suse.de ([195.135.220.15]:44472 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729120AbgLJGkm (ORCPT ); Thu, 10 Dec 2020 01:40:42 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1607582361; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=PS6dSHAIgpQp1wVFQuVvNGYMN1y1oFvnZ+gsJPVcpLc=; b=ktjbPVJQEsgVpFA7PrgjP56sRUeHqDB2j0zbYB9DTJqtovRi3UMAPHkfBw8mwiutfs+lWb hAwIWkjdBRa4G1utQgeYN28XhDmvTEOyftEnnctkk+MjXOcerSQ/4opwH0GGnBbbz1g/r0 V9QpmIKNrDVqdAmyYR498bnp45WoZq4= Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 56FA1AD19 for ; Thu, 10 Dec 2020 06:39:21 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v2 06/18] btrfs: extent_io: make attach_extent_buffer_page() to handle subpage case Date: Thu, 10 Dec 2020 14:38:53 +0800 Message-Id: <20201210063905.75727-7-wqu@suse.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201210063905.75727-1-wqu@suse.com> References: <20201210063905.75727-1-wqu@suse.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org For subpage case, we need to allocate new memory for each metadata page. So we need to: - Allow attach_extent_buffer_page() to return int To indicate allocation failure - Prealloc page->private for alloc_extent_buffer() We don't want to call memory allocation with spinlock hold, so do preallocation before we acquire the spin lock. - Handle subpage and regular case differently in attach_extent_buffer_page() For regular case, just do the usual thing. For subpage case, allocate new memory and update the tree_block bitmap. The bitmap update will be handled by new subpage specific helper, btrfs_subpage_set_tree_block(). Signed-off-by: Qu Wenruo --- fs/btrfs/extent_io.c | 69 +++++++++++++++++++++++++++++++++++--------- fs/btrfs/subpage.h | 44 ++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 14 deletions(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 6350c2687c7e..51dd7ec3c2b3 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -24,6 +24,7 @@ #include "rcu-string.h" #include "backref.h" #include "disk-io.h" +#include "subpage.h" static struct kmem_cache *extent_state_cache; static struct kmem_cache *extent_buffer_cache; @@ -3142,22 +3143,41 @@ static int submit_extent_page(unsigned int opf, return ret; } -static void attach_extent_buffer_page(struct extent_buffer *eb, +static int attach_extent_buffer_page(struct extent_buffer *eb, struct page *page) { - /* - * If the page is mapped to btree inode, we should hold the private - * lock to prevent race. - * For cloned or dummy extent buffers, their pages are not mapped and - * will not race with any other ebs. - */ - if (page->mapping) - lockdep_assert_held(&page->mapping->private_lock); + struct btrfs_fs_info *fs_info = eb->fs_info; + int ret; - if (!PagePrivate(page)) - attach_page_private(page, eb); - else - WARN_ON(page->private != (unsigned long)eb); + if (fs_info->sectorsize == PAGE_SIZE) { + /* + * If the page is mapped to btree inode, we should hold the + * private lock to prevent race. + * For cloned or dummy extent buffers, their pages are not + * mapped and will not race with any other ebs. + */ + if (page->mapping) + lockdep_assert_held(&page->mapping->private_lock); + + if (!PagePrivate(page)) + attach_page_private(page, eb); + else + WARN_ON(page->private != (unsigned long)eb); + return 0; + } + + /* Already mapped, just update the existing range */ + if (PagePrivate(page)) + goto update_bitmap; + + /* Do new allocation to attach subpage */ + ret = btrfs_attach_subpage(fs_info, page); + if (ret < 0) + return ret; + +update_bitmap: + btrfs_subpage_set_tree_block(fs_info, page, eb->start, eb->len); + return 0; } void set_page_extent_mapped(struct page *page) @@ -5067,12 +5087,19 @@ struct extent_buffer *btrfs_clone_extent_buffer(const struct extent_buffer *src) return NULL; for (i = 0; i < num_pages; i++) { + int ret; + p = alloc_page(GFP_NOFS); if (!p) { btrfs_release_extent_buffer(new); return NULL; } - attach_extent_buffer_page(new, p); + ret = attach_extent_buffer_page(new, p); + if (ret < 0) { + put_page(p); + btrfs_release_extent_buffer(new); + return NULL; + } WARN_ON(PageDirty(p)); SetPageUptodate(p); new->pages[i] = p; @@ -5321,6 +5348,18 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info, goto free_eb; } + /* + * Preallocate page->private for subpage case, so that + * we won't allocate memory with private_lock hold. + */ + ret = btrfs_attach_subpage(fs_info, p); + if (ret < 0) { + unlock_page(p); + put_page(p); + exists = ERR_PTR(-ENOMEM); + goto free_eb; + } + spin_lock(&mapping->private_lock); exists = grab_extent_buffer_from_page(p); if (exists) { @@ -5329,8 +5368,10 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info, put_page(p); goto free_eb; } + /* Should not fail, as we have attached the subpage already */ attach_extent_buffer_page(eb, p); spin_unlock(&mapping->private_lock); + WARN_ON(PageDirty(p)); eb->pages[i] = p; if (!PageUptodate(p)) diff --git a/fs/btrfs/subpage.h b/fs/btrfs/subpage.h index 96f3b226913e..c2ce603e7848 100644 --- a/fs/btrfs/subpage.h +++ b/fs/btrfs/subpage.h @@ -23,9 +23,53 @@ struct btrfs_subpage { /* Common members for both data and metadata pages */ spinlock_t lock; + union { + /* Structures only used by metadata */ + struct { + u16 tree_block_bitmap; + }; + /* structures only used by data */ + }; }; int btrfs_attach_subpage(struct btrfs_fs_info *fs_info, struct page *page); void btrfs_detach_subpage(struct btrfs_fs_info *fs_info, struct page *page); +/* + * Convert the [start, start + len) range into a u16 bitmap + * + * E.g. if start == page_offset() + 16K, len = 16K, we get 0x00f0. + */ +static inline u16 btrfs_subpage_calc_bitmap(struct btrfs_fs_info *fs_info, + struct page *page, u64 start, u32 len) +{ + int bit_start = (start - page_offset(page)) >> fs_info->sectorsize_bits; + int nbits = len >> fs_info->sectorsize_bits; + + /* Basic checks */ + ASSERT(PagePrivate(page) && page->private); + ASSERT(IS_ALIGNED(start, fs_info->sectorsize) && + IS_ALIGNED(len, fs_info->sectorsize)); + ASSERT(page_offset(page) <= start && + start + len <= page_offset(page) + PAGE_SIZE); + /* + * Here nbits can be 16, thus can go beyond u16 range. Here we make the + * first left shift to be calculated in unsigned long (u32), then + * truncate the result to u16. + */ + return (u16)(((1UL << nbits) - 1) << bit_start); +} + +static inline void btrfs_subpage_set_tree_block(struct btrfs_fs_info *fs_info, + struct page *page, u64 start, u32 len) +{ + struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private; + unsigned long flags; + u16 tmp = btrfs_subpage_calc_bitmap(fs_info, page, start, len); + + spin_lock_irqsave(&subpage->lock, flags); + subpage->tree_block_bitmap |= tmp; + spin_unlock_irqrestore(&subpage->lock, flags); +} + #endif /* BTRFS_SUBPAGE_H */ From patchwork Thu Dec 10 06:38:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 11963425 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 77225C2BBCF for ; Thu, 10 Dec 2020 06:41:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3598C23B98 for ; Thu, 10 Dec 2020 06:41:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387520AbgLJGko (ORCPT ); Thu, 10 Dec 2020 01:40:44 -0500 Received: from mx2.suse.de ([195.135.220.15]:44478 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387512AbgLJGko (ORCPT ); Thu, 10 Dec 2020 01:40:44 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1607582363; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=q8Q9e81kElaLMo39JPpupC99/jwWztHF3bGSwjwzKVU=; b=EZr1dhBh158hFrau76brJe0ilx8VCFTA2y/WBAhDP5tv0TjmdXKNpRggRHcCrB3tXY5ljp cT2X9YOe2NnrSRTKM7xzSlDYq3+p4MDsOi7mSFJpXN31xfZ/+2tJzIcpoGnD6jzF5iKYyf lv7fHVDr2JdUNNRAPPswvs5chLK7qI8= Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id D0487AD20 for ; Thu, 10 Dec 2020 06:39:23 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v2 07/18] btrfs: extent_io: make grab_extent_buffer_from_page() to handle subpage case Date: Thu, 10 Dec 2020 14:38:54 +0800 Message-Id: <20201210063905.75727-8-wqu@suse.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201210063905.75727-1-wqu@suse.com> References: <20201210063905.75727-1-wqu@suse.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org For subpage case, grab_extent_buffer_from_page() can't really get an extent buffer just from btrfs_subpage. Although we have btrfs_subpage::tree_block_bitmap, which can be used to grab the bytenr of an existing extent buffer, and can then go radix tree search to grab that existing eb. However we are still doing radix tree insert check in alloc_extent_buffer(), thus we don't really need to do the extra hassle, just let alloc_extent_buffer() to handle existing eb in radix tree. So for grab_extent_buffer_from_page(), just always return NULL for subpage case. Signed-off-by: Qu Wenruo --- fs/btrfs/extent_io.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 51dd7ec3c2b3..b99bd0402130 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -5278,10 +5278,19 @@ struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info, } #endif -static struct extent_buffer *grab_extent_buffer_from_page(struct page *page) +static struct extent_buffer *grab_extent_buffer_from_page( + struct btrfs_fs_info *fs_info, struct page *page) { struct extent_buffer *exists; + /* + * For subpage case, we completely rely on radix tree to ensure we + * don't try to insert two eb for the same bytenr. + * So here we alwasy return NULL and just continue. + */ + if (fs_info->sectorsize < PAGE_SIZE) + return NULL; + /* Page not yet attached to an extent buffer */ if (!PagePrivate(page)) return NULL; @@ -5361,7 +5370,7 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info, } spin_lock(&mapping->private_lock); - exists = grab_extent_buffer_from_page(p); + exists = grab_extent_buffer_from_page(fs_info, p); if (exists) { spin_unlock(&mapping->private_lock); unlock_page(p); From patchwork Thu Dec 10 06:38:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 11963411 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D0286C2BB40 for ; Thu, 10 Dec 2020 06:40:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A5D0E23B98 for ; Thu, 10 Dec 2020 06:40:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387517AbgLJGko (ORCPT ); Thu, 10 Dec 2020 01:40:44 -0500 Received: from mx2.suse.de ([195.135.220.15]:44480 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387509AbgLJGkn (ORCPT ); Thu, 10 Dec 2020 01:40:43 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1607582365; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ZnCrpoA00SFFkg7Z7w3jxgyxla+miDCFxeSFMF/iyK8=; b=VlZNw5izXftxjPpIYM/UkVFp9gQyq794AFy8eJjmIdsLXG9gZsTC8fAbJP3NkHRPoOcFE+ Vxm0LxErgO/2neVXG1N03rSA+1VxJ7JebgRQzZ7dTraYDY5pGj55H/9+QOT/QRQrJl2Z1P bHUVgZRbc3iV1IDjoeDlh9xJ0cZWa8M= Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id C9398AD2B for ; Thu, 10 Dec 2020 06:39:25 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v2 08/18] btrfs: extent_io: support subpage for extent buffer page release Date: Thu, 10 Dec 2020 14:38:55 +0800 Message-Id: <20201210063905.75727-9-wqu@suse.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201210063905.75727-1-wqu@suse.com> References: <20201210063905.75727-1-wqu@suse.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org In btrfs_release_extent_buffer_pages(), we need to add extra handling for subpage. To do so, introduce a new helper, detach_extent_buffer_page(), to do different handling for regular and subpage cases. For subpage case, the new trick is to clear the range of current extent buffer, and detach page private if and only if we're the last tree block of the page. This part is handled by the subpage helper, btrfs_subpage_clear_and_test_tree_block(). Signed-off-by: Qu Wenruo --- fs/btrfs/extent_io.c | 59 +++++++++++++++++++++++++++++++------------- fs/btrfs/subpage.h | 24 ++++++++++++++++++ 2 files changed, 66 insertions(+), 17 deletions(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index b99bd0402130..ee81a2a1baa2 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -4994,25 +4994,12 @@ int extent_buffer_under_io(const struct extent_buffer *eb) test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags)); } -/* - * Release all pages attached to the extent buffer. - */ -static void btrfs_release_extent_buffer_pages(struct extent_buffer *eb) +static void detach_extent_buffer_page(struct extent_buffer *eb, + struct page *page) { - int i; - int num_pages; - int mapped = !test_bit(EXTENT_BUFFER_UNMAPPED, &eb->bflags); - - BUG_ON(extent_buffer_under_io(eb)); - - num_pages = num_extent_pages(eb); - for (i = 0; i < num_pages; i++) { - struct page *page = eb->pages[i]; + struct btrfs_fs_info *fs_info = eb->fs_info; - if (!page) - continue; - if (mapped) - spin_lock(&page->mapping->private_lock); + if (fs_info->sectorsize == PAGE_SIZE) { /* * We do this since we'll remove the pages after we've * removed the eb from the radix tree, so we could race @@ -5031,6 +5018,44 @@ static void btrfs_release_extent_buffer_pages(struct extent_buffer *eb) */ detach_page_private(page); } + return; + } + + /* + * For subpage case, clear the range in tree_block_bitmap, + * and if we're the last one, detach private completely. + */ + if (PagePrivate(page)) { + bool last = false; + + last = btrfs_subpage_clear_and_test_tree_block(fs_info, page, + eb->start, eb->len); + if (last) + btrfs_detach_subpage(fs_info, page); + } +} + +/* + * Release all pages attached to the extent buffer. + */ +static void btrfs_release_extent_buffer_pages(struct extent_buffer *eb) +{ + int i; + int num_pages; + int mapped = !test_bit(EXTENT_BUFFER_UNMAPPED, &eb->bflags); + + ASSERT(!extent_buffer_under_io(eb)); + + num_pages = num_extent_pages(eb); + for (i = 0; i < num_pages; i++) { + struct page *page = eb->pages[i]; + + if (!page) + continue; + if (mapped) + spin_lock(&page->mapping->private_lock); + + detach_extent_buffer_page(eb, page); if (mapped) spin_unlock(&page->mapping->private_lock); diff --git a/fs/btrfs/subpage.h b/fs/btrfs/subpage.h index c2ce603e7848..87b4e028ae18 100644 --- a/fs/btrfs/subpage.h +++ b/fs/btrfs/subpage.h @@ -72,4 +72,28 @@ static inline void btrfs_subpage_set_tree_block(struct btrfs_fs_info *fs_info, spin_unlock_irqrestore(&subpage->lock, flags); } +/* + * Clear the bits in tree_block_bitmap and return if we're the last bit set + * int tree_block_bitmap. + * + * Return true if we're the last bits in the tree_block_bitmap. + * Return false otherwise. + */ +static inline bool btrfs_subpage_clear_and_test_tree_block( + struct btrfs_fs_info *fs_info, struct page *page, + u64 start, u32 len) +{ + struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private; + u16 tmp = btrfs_subpage_calc_bitmap(fs_info, page, start, len); + unsigned long flags; + bool last = false; + + spin_lock_irqsave(&subpage->lock, flags); + subpage->tree_block_bitmap &= ~tmp; + if (subpage->tree_block_bitmap == 0) + last = true; + spin_unlock_irqrestore(&subpage->lock, flags); + return last; +} + #endif /* BTRFS_SUBPAGE_H */ From patchwork Thu Dec 10 06:38:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 11963415 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.9 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, UNWANTED_LANGUAGE_BODY,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E3BDFC433FE for ; Thu, 10 Dec 2020 06:40:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A2DA823B98 for ; Thu, 10 Dec 2020 06:40:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387555AbgLJGk4 (ORCPT ); Thu, 10 Dec 2020 01:40:56 -0500 Received: from mx2.suse.de ([195.135.220.15]:44500 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387523AbgLJGkp (ORCPT ); Thu, 10 Dec 2020 01:40:45 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1607582367; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=3c7+npsXwevbKox7FM5Ar8W1LpWNlxK+1vJA8k2qtK8=; b=GdZNOsmF+PgCW8GzdDrMxYyilfmAToIcnKGM9o0WqV+5VqC4GdCJEVavDlHb0gs1CrJ8vU gRbNlAnyXqUZQLzK3Hcp5hVSvlJ3fFC8ZBecGFxi3bPloYxkHmAQgfg3blqgfAaiioIqMy 7Xdi5Ybmwal58EDHFJIIQ2Le9WV2ECc= Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 6B18FAD35 for ; Thu, 10 Dec 2020 06:39:27 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v2 09/18] btrfs: subpage: introduce helper for subpage uptodate status Date: Thu, 10 Dec 2020 14:38:56 +0800 Message-Id: <20201210063905.75727-10-wqu@suse.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201210063905.75727-1-wqu@suse.com> References: <20201210063905.75727-1-wqu@suse.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org This patch introduce the following functions to handle btrfs subpage uptodate status: - btrfs_subpage_set_uptodate() - btrfs_subpage_clear_uptodate() - btrfs_subpage_test_uptodate() Those helpers can only be called when the range is ensured to be inside the page. - btrfs_page_set_uptodate() - btrfs_page_clear_uptodate() - btrfs_page_test_uptodate() Those helpers can handle both regular sector size and subpage without problem. Signed-off-by: Qu Wenruo --- fs/btrfs/subpage.h | 98 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/fs/btrfs/subpage.h b/fs/btrfs/subpage.h index 87b4e028ae18..b3cf9171ec98 100644 --- a/fs/btrfs/subpage.h +++ b/fs/btrfs/subpage.h @@ -23,6 +23,7 @@ struct btrfs_subpage { /* Common members for both data and metadata pages */ spinlock_t lock; + u16 uptodate_bitmap; union { /* Structures only used by metadata */ struct { @@ -35,6 +36,17 @@ struct btrfs_subpage { int btrfs_attach_subpage(struct btrfs_fs_info *fs_info, struct page *page); void btrfs_detach_subpage(struct btrfs_fs_info *fs_info, struct page *page); +static inline void btrfs_subpage_clamp_range(struct page *page, + u64 *start, u32 *len) +{ + u64 orig_start = *start; + u32 orig_len = *len; + + *start = max_t(u64, page_offset(page), orig_start); + *len = min_t(u64, page_offset(page) + PAGE_SIZE, + orig_start + orig_len) - *start; +} + /* * Convert the [start, start + len) range into a u16 bitmap * @@ -96,4 +108,90 @@ static inline bool btrfs_subpage_clear_and_test_tree_block( return last; } +static inline void btrfs_subpage_set_uptodate(struct btrfs_fs_info *fs_info, + struct page *page, u64 start, u32 len) +{ + struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private; + u16 tmp = btrfs_subpage_calc_bitmap(fs_info, page, start, len); + unsigned long flags; + + spin_lock_irqsave(&subpage->lock, flags); + subpage->uptodate_bitmap |= tmp; + if (subpage->uptodate_bitmap == (u16)-1) + SetPageUptodate(page); + spin_unlock_irqrestore(&subpage->lock, flags); +} + +static inline void btrfs_subpage_clear_uptodate(struct btrfs_fs_info *fs_info, + struct page *page, u64 start, u32 len) +{ + struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private; + u16 tmp = btrfs_subpage_calc_bitmap(fs_info, page, start, len); + unsigned long flags; + + spin_lock_irqsave(&subpage->lock, flags); + subpage->tree_block_bitmap &= ~tmp; + ClearPageUptodate(page); + spin_unlock_irqrestore(&subpage->lock, flags); +} + +/* + * Unlike set/clear which is dependent on each page status, for test all bits + * are tested in the same way. + */ +#define DECLARE_BTRFS_SUBPAGE_TEST_OP(name) \ +static inline bool btrfs_subpage_test_##name(struct btrfs_fs_info *fs_info, \ + struct page *page, u64 start, u32 len) \ +{ \ + struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private; \ + u16 tmp = btrfs_subpage_calc_bitmap(fs_info, page, start, len); \ + unsigned long flags; \ + bool ret; \ + \ + spin_lock_irqsave(&subpage->lock, flags); \ + ret = ((subpage->name##_bitmap & tmp) == tmp); \ + spin_unlock_irqrestore(&subpage->lock, flags); \ + return ret; \ +} +DECLARE_BTRFS_SUBPAGE_TEST_OP(uptodate); + +/* + * Note that, in selftest, especially extent-io-tests, we can have empty + * fs_info passed in. + * Thanfully in selftest, we only test sectorsize == PAGE_SIZE cases so far + * thus we can fall back to regular sectorsize branch. + */ +#define DECLARE_BTRFS_PAGE_OPS(name, set_page_func, clear_page_func, \ + test_page_func) \ +static inline void btrfs_page_set_##name(struct btrfs_fs_info *fs_info, \ + struct page *page, u64 start, u32 len) \ +{ \ + if (unlikely(!fs_info) || fs_info->sectorsize == PAGE_SIZE) { \ + set_page_func(page); \ + return; \ + } \ + btrfs_subpage_clamp_range(page, &start, &len); \ + btrfs_subpage_set_##name(fs_info, page, start, len); \ +} \ +static inline void btrfs_page_clear_##name(struct btrfs_fs_info *fs_info, \ + struct page *page, u64 start, u32 len) \ +{ \ + if (unlikely(!fs_info) || fs_info->sectorsize == PAGE_SIZE) { \ + clear_page_func(page); \ + return; \ + } \ + btrfs_subpage_clamp_range(page, &start, &len); \ + btrfs_subpage_clear_##name(fs_info, page, start, len); \ +} \ +static inline bool btrfs_page_test_##name(struct btrfs_fs_info *fs_info, \ + struct page *page, u64 start, u32 len) \ +{ \ + if (unlikely(!fs_info) || fs_info->sectorsize == PAGE_SIZE) \ + return test_page_func(page); \ + btrfs_subpage_clamp_range(page, &start, &len); \ + return btrfs_subpage_test_##name(fs_info, page, start, len); \ +} +DECLARE_BTRFS_PAGE_OPS(uptodate, SetPageUptodate, ClearPageUptodate, + PageUptodate); + #endif /* BTRFS_SUBPAGE_H */ From patchwork Thu Dec 10 06:38:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 11963417 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8ABCCC0018C for ; Thu, 10 Dec 2020 06:40:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4E94023B98 for ; Thu, 10 Dec 2020 06:40:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387553AbgLJGk4 (ORCPT ); Thu, 10 Dec 2020 01:40:56 -0500 Received: from mx2.suse.de ([195.135.220.15]:44502 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387512AbgLJGkp (ORCPT ); Thu, 10 Dec 2020 01:40:45 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1607582369; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Po1PNkoSBlcr2Xk4AI/BCvY/NOfVRKelYZShrg026LI=; b=Yy/yTmf8mNbwd27OWEMvm4PwcvalwC8Tt8oD/sOTdjd+T7XHmlWR6VHGJ2MXBVCEPVvSxK hhAIvUOj+HCDlJ5CQtVI9EgaCaFjg67RXFOSqNM3NQoofcLJ9l+lQdEzuUkYbBQhIVx//7 suXBabqR9AgmC6eaK+PD8z7qAYDRQKQ= Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 2CE56AD4A for ; Thu, 10 Dec 2020 06:39:29 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v2 10/18] btrfs: subpage: introduce helper for subpage error status Date: Thu, 10 Dec 2020 14:38:57 +0800 Message-Id: <20201210063905.75727-11-wqu@suse.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201210063905.75727-1-wqu@suse.com> References: <20201210063905.75727-1-wqu@suse.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org This patch introduce the following functions to handle btrfs subpage error status: - btrfs_subpage_set_error() - btrfs_subpage_clear_error() - btrfs_subpage_test_error() Those helpers can only be called when the range is ensured to be inside the page. - btrfs_page_set_error() - btrfs_page_clear_error() - btrfs_page_test_error() Those helpers can handle both regular sector size and subpage without problem. Signed-off-by: Qu Wenruo --- fs/btrfs/subpage.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/fs/btrfs/subpage.h b/fs/btrfs/subpage.h index b3cf9171ec98..8592234d773e 100644 --- a/fs/btrfs/subpage.h +++ b/fs/btrfs/subpage.h @@ -24,6 +24,7 @@ struct btrfs_subpage { /* Common members for both data and metadata pages */ spinlock_t lock; u16 uptodate_bitmap; + u16 error_bitmap; union { /* Structures only used by metadata */ struct { @@ -135,6 +136,35 @@ static inline void btrfs_subpage_clear_uptodate(struct btrfs_fs_info *fs_info, spin_unlock_irqrestore(&subpage->lock, flags); } +static inline void btrfs_subpage_set_error(struct btrfs_fs_info *fs_info, + struct page *page, u64 start, + u32 len) +{ + struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private; + u16 tmp = btrfs_subpage_calc_bitmap(fs_info, page, start, len); + unsigned long flags; + + spin_lock_irqsave(&subpage->lock, flags); + subpage->error_bitmap |= tmp; + SetPageError(page); + spin_unlock_irqrestore(&subpage->lock, flags); +} + +static inline void btrfs_subpage_clear_error(struct btrfs_fs_info *fs_info, + struct page *page, u64 start, + u32 len) +{ + struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private; + u16 tmp = btrfs_subpage_calc_bitmap(fs_info, page, start, len); + unsigned long flags; + + spin_lock_irqsave(&subpage->lock, flags); + subpage->error_bitmap &= ~tmp; + if (subpage->error_bitmap == 0) + ClearPageError(page); + spin_unlock_irqrestore(&subpage->lock, flags); +} + /* * Unlike set/clear which is dependent on each page status, for test all bits * are tested in the same way. @@ -154,6 +184,7 @@ static inline bool btrfs_subpage_test_##name(struct btrfs_fs_info *fs_info, \ return ret; \ } DECLARE_BTRFS_SUBPAGE_TEST_OP(uptodate); +DECLARE_BTRFS_SUBPAGE_TEST_OP(error); /* * Note that, in selftest, especially extent-io-tests, we can have empty @@ -193,5 +224,6 @@ static inline bool btrfs_page_test_##name(struct btrfs_fs_info *fs_info, \ } DECLARE_BTRFS_PAGE_OPS(uptodate, SetPageUptodate, ClearPageUptodate, PageUptodate); +DECLARE_BTRFS_PAGE_OPS(error, SetPageError, ClearPageError, PageError); #endif /* BTRFS_SUBPAGE_H */ From patchwork Thu Dec 10 06:38:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 11963419 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 804AAC2BB40 for ; Thu, 10 Dec 2020 06:40:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 44C4623D57 for ; Thu, 10 Dec 2020 06:40:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387551AbgLJGk4 (ORCPT ); Thu, 10 Dec 2020 01:40:56 -0500 Received: from mx2.suse.de ([195.135.220.15]:44508 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387524AbgLJGkq (ORCPT ); Thu, 10 Dec 2020 01:40:46 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1607582370; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=KR6va1HHwGJ8WZ0JlPuUV+4CAGChKUm2xRppBWriwxg=; b=uZJpKb/Ruxsqut/6HCuXLnQFTn1q7q9wp/A0EOmpT59nnBT6WtchZ13JLRzbtPoKa0HJOr mzxhoiU7MehxE34m/8EdxBvVCN4Hqd/KbhyLBYvqC/o8B5PHMig46MXn27uSOeQKHKmvLw 3OM+7t3AF6fAXODnYF/ASz1cOXwOoJg= Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id D50D3AD4D for ; Thu, 10 Dec 2020 06:39:30 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v2 11/18] btrfs: extent_io: make set/clear_extent_buffer_uptodate() to support subpage size Date: Thu, 10 Dec 2020 14:38:58 +0800 Message-Id: <20201210063905.75727-12-wqu@suse.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201210063905.75727-1-wqu@suse.com> References: <20201210063905.75727-1-wqu@suse.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org For those functions, to support subpage size they just need to call btrfs_page_set/clear_uptodate() wrappers. Signed-off-by: Qu Wenruo --- fs/btrfs/extent_io.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index ee81a2a1baa2..141e414b1ab9 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -5611,30 +5611,33 @@ bool set_extent_buffer_dirty(struct extent_buffer *eb) void clear_extent_buffer_uptodate(struct extent_buffer *eb) { - int i; + struct btrfs_fs_info *fs_info = eb->fs_info; struct page *page; int num_pages; + int i; clear_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); num_pages = num_extent_pages(eb); for (i = 0; i < num_pages; i++) { page = eb->pages[i]; if (page) - ClearPageUptodate(page); + btrfs_page_clear_uptodate(fs_info, page, + eb->start, eb->len); } } void set_extent_buffer_uptodate(struct extent_buffer *eb) { - int i; + struct btrfs_fs_info *fs_info = eb->fs_info; struct page *page; int num_pages; + int i; set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); num_pages = num_extent_pages(eb); for (i = 0; i < num_pages; i++) { page = eb->pages[i]; - SetPageUptodate(page); + btrfs_page_set_uptodate(fs_info, page, eb->start, eb->len); } } From patchwork Thu Dec 10 06:38:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 11963413 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9DC63C1B0D8 for ; Thu, 10 Dec 2020 06:40:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6538023D50 for ; Thu, 10 Dec 2020 06:40:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387546AbgLJGk4 (ORCPT ); Thu, 10 Dec 2020 01:40:56 -0500 Received: from mx2.suse.de ([195.135.220.15]:44510 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387526AbgLJGkr (ORCPT ); Thu, 10 Dec 2020 01:40:47 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1607582373; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=16hOVy9/figJJmrvKBZ6vZO8aylb6nCxXkTXMPHWcOA=; b=jxRiOaWMz3Ge9RdtcskizlBrsrQDu2HzTo9OXWClPfTrJK6f3gBcNEacC8ZcON75mlsp2u uOncmU7de1Tv1ddkTNoOlvd17M9VfLWzeCTHCPCMMeoNopI08BBKoICr9qabAZEwDBHHFC zNsNXiCvtLFGHQ34lz1itS8Y0S+68s4= Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 143B1AD60 for ; Thu, 10 Dec 2020 06:39:33 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v2 12/18] btrfs: extent_io: implement try_release_extent_buffer() for subpage metadata support Date: Thu, 10 Dec 2020 14:38:59 +0800 Message-Id: <20201210063905.75727-13-wqu@suse.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201210063905.75727-1-wqu@suse.com> References: <20201210063905.75727-1-wqu@suse.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org Unlike the original try_release_extent_buffer, try_release_subpage_extent_buffer() will iterate through btrfs_subpage::tree_block_bitmap, and try to release each extent buffer. Signed-off-by: Qu Wenruo --- fs/btrfs/extent_io.c | 73 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 141e414b1ab9..4d55803302e9 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -6258,10 +6258,83 @@ void memmove_extent_buffer(const struct extent_buffer *dst, } } +static int try_release_subpage_extent_buffer(struct page *page) +{ + struct btrfs_fs_info *fs_info = btrfs_sb(page->mapping->host->i_sb); + u64 page_start = page_offset(page); + int bitmap_size = BTRFS_SUBPAGE_BITMAP_SIZE; + int bit_start = 0; + int ret; + + while (bit_start < bitmap_size) { + struct btrfs_subpage *subpage; + struct extent_buffer *eb; + unsigned long flags; + u16 tmp = 1 << bit_start; + u64 start; + + /* + * Make sure the page still has private, as previous run can + * detach the private + */ + spin_lock(&page->mapping->private_lock); + if (!PagePrivate(page)) { + spin_unlock(&page->mapping->private_lock); + break; + } + subpage = (struct btrfs_subpage *)page->private; + spin_unlock(&page->mapping->private_lock); + + spin_lock_irqsave(&subpage->lock, flags); + if (!(tmp & subpage->tree_block_bitmap)) { + spin_unlock_irqrestore(&subpage->lock, flags); + bit_start++; + continue; + } + spin_unlock_irqrestore(&subpage->lock, flags); + + start = bit_start * fs_info->sectorsize + page_start; + bit_start += fs_info->nodesize >> fs_info->sectorsize_bits; + /* + * Here we can't call find_extent_buffer() which will increase + * eb->refs. + */ + rcu_read_lock(); + eb = radix_tree_lookup(&fs_info->buffer_radix, + start >> fs_info->sectorsize_bits); + rcu_read_unlock(); + ASSERT(eb); + spin_lock(&eb->refs_lock); + if (atomic_read(&eb->refs) != 1 || extent_buffer_under_io(eb) || + !test_and_clear_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags)) { + spin_unlock(&eb->refs_lock); + continue; + } + /* + * Here we don't care the return value, we will always check + * the page private at the end. + * And release_extent_buffer() will release the refs_lock. + */ + release_extent_buffer(eb); + } + /* Finally to check if we have cleared page private */ + spin_lock(&page->mapping->private_lock); + if (!PagePrivate(page)) + ret = 1; + else + ret = 0; + spin_unlock(&page->mapping->private_lock); + return ret; + +} + int try_release_extent_buffer(struct page *page) { struct extent_buffer *eb; + if (btrfs_sb(page->mapping->host->i_sb)->sectorsize < PAGE_SIZE) + return try_release_subpage_extent_buffer(page); + /* * We need to make sure nobody is attaching this page to an eb right * now. From patchwork Thu Dec 10 06:39:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 11963427 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DF8A5C433FE for ; Thu, 10 Dec 2020 06:41:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8E9DE23B98 for ; Thu, 10 Dec 2020 06:41:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387536AbgLJGkz (ORCPT ); Thu, 10 Dec 2020 01:40:55 -0500 Received: from mx2.suse.de ([195.135.220.15]:44548 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387533AbgLJGkv (ORCPT ); Thu, 10 Dec 2020 01:40:51 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1607582374; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1iA49PfTq1t6V1UIpH48oCzLTKknby/i3YZN3FqRWks=; b=M3fpbwo0rhHfQrgjCaWHdSVe4ZO7EqpYIAahUpEOlV7Ae3rwG0M0vY8EL338g4EPcgPm5b L7vmSaj2e5eopMSi80gnWkyvHBgqtLgJ7QHrwtJcEju3ruOhehVHTIaPXsnAAZz47HztZy KxNOrQprRJ2fHIYKItLGbTO/QGuh3T4= Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id C5A1BAD5A for ; Thu, 10 Dec 2020 06:39:34 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v2 13/18] btrfs: extent_io: introduce read_extent_buffer_subpage() Date: Thu, 10 Dec 2020 14:39:00 +0800 Message-Id: <20201210063905.75727-14-wqu@suse.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201210063905.75727-1-wqu@suse.com> References: <20201210063905.75727-1-wqu@suse.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org Introduce a new helper, read_extent_buffer_subpage(), to do the subpage extent buffer read. The difference between regular and subpage routines are: - No page locking Here we completely rely on extent locking. Page locking can reduce the concurrency greatly, as if we lock one page to read one extent buffer, all the other extent buffers in the same page will have to wait. - Extent uptodate condition Despite the existing PageUptodate() and EXTENT_BUFFER_UPTODATE check, We also need to check btrfs_subpage::uptodate_bitmap. - No page loop Just one page, no need to loop, this greately simplified the subpage routine. This patch only implemented the bio submit part, no endio support yet. Signed-off-by: Qu Wenruo --- fs/btrfs/disk-io.c | 1 + fs/btrfs/extent_io.c | 70 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 765deefda92b..b6c03a8b0c72 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -602,6 +602,7 @@ int btrfs_validate_metadata_buffer(struct btrfs_io_bio *io_bio, ASSERT(page->private); eb = (struct extent_buffer *)page->private; + /* * The pending IO might have been the only thing that kept this buffer * in memory. Make sure we have a ref for all this other checks diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 4d55803302e9..1ec9de2aa910 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -5641,6 +5641,73 @@ void set_extent_buffer_uptodate(struct extent_buffer *eb) } } +static int read_extent_buffer_subpage(struct extent_buffer *eb, int wait, + int mirror_num) +{ + struct btrfs_fs_info *fs_info = eb->fs_info; + struct extent_io_tree *io_tree; + struct page *page = eb->pages[0]; + struct bio *bio = NULL; + int ret = 0; + + ASSERT(!test_bit(EXTENT_BUFFER_UNMAPPED, &eb->bflags)); + ASSERT(PagePrivate(page)); + io_tree = &BTRFS_I(fs_info->btree_inode)->io_tree; + + if (wait == WAIT_NONE) { + ret = try_lock_extent(io_tree, eb->start, + eb->start + eb->len - 1); + if (ret <= 0) + return ret; + } else { + ret = lock_extent(io_tree, eb->start, eb->start + eb->len - 1); + if (ret < 0) + return ret; + } + + ret = 0; + if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags) || + PageUptodate(page) || + btrfs_subpage_test_uptodate(fs_info, page, eb->start, eb->len)) { + set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); + unlock_extent(io_tree, eb->start, eb->start + eb->len - 1); + return ret; + } + + clear_bit(EXTENT_BUFFER_READ_ERR, &eb->bflags); + eb->read_mirror = 0; + atomic_set(&eb->io_pages, 1); + check_buffer_tree_ref(eb); + + ret = submit_extent_page(REQ_OP_READ | REQ_META, NULL, page, eb->start, + eb->len, eb->start - page_offset(page), &bio, + end_bio_extent_readpage, mirror_num, 0, 0, + true); + if (ret) { + /* + * In the endio function, if we hit something wrong we will + * increase the io_pages, so here we need to decrease it for error + * path. + */ + atomic_dec(&eb->io_pages); + } + if (bio) { + int tmp; + + tmp = submit_one_bio(bio, mirror_num, 0); + if (tmp < 0) + return tmp; + } + if (ret || wait != WAIT_COMPLETE) + return ret; + + wait_extent_bit(io_tree, eb->start, eb->start + eb->len - 1, + EXTENT_LOCKED); + if (!test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags)) + ret = -EIO; + return ret; +} + int read_extent_buffer_pages(struct extent_buffer *eb, int wait, int mirror_num) { int i; @@ -5657,6 +5724,9 @@ int read_extent_buffer_pages(struct extent_buffer *eb, int wait, int mirror_num) if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags)) return 0; + if (eb->fs_info->sectorsize < PAGE_SIZE) + return read_extent_buffer_subpage(eb, wait, mirror_num); + num_pages = num_extent_pages(eb); for (i = 0; i < num_pages; i++) { page = eb->pages[i]; From patchwork Thu Dec 10 06:39:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 11963423 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 32E3AC2BB48 for ; Thu, 10 Dec 2020 06:41:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E7CF223D50 for ; Thu, 10 Dec 2020 06:40:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387542AbgLJGk4 (ORCPT ); Thu, 10 Dec 2020 01:40:56 -0500 Received: from mx2.suse.de ([195.135.220.15]:44550 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387532AbgLJGkv (ORCPT ); Thu, 10 Dec 2020 01:40:51 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1607582376; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=P+t+YQg/b8gwwxpg9+2sjClOd1VpCSxMmcRxNyhwVyU=; b=gvY1iiUGBmlzTgdM8hCGPMJWa0RiNkrbAXEo4rIcaJxtsH4m1W++7cdpQn4KvdPACn/oLu w7SfaWEDGK7l/0JZV9awdaBnjldK6JQaDysxQGhp6T8UsgqjyDQmSwGyV5DPhy733ERLBS a9v2UKW553b25Twtnfq2B2apz90gTKY= Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 7A163AD77 for ; Thu, 10 Dec 2020 06:39:36 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v2 14/18] btrfs: extent_io: make endio_readpage_update_page_status() to handle subpage case Date: Thu, 10 Dec 2020 14:39:01 +0800 Message-Id: <20201210063905.75727-15-wqu@suse.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201210063905.75727-1-wqu@suse.com> References: <20201210063905.75727-1-wqu@suse.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org To handle subpage status update, add the following new tricks: - Use btrfs_page_*() helpers to update page status Now we can handle both cases well. - No page unlock for subpage metadata Since subpage metadata doesn't utilize page locking at all, skip it. For subpage data locking, it's handled in later commits. Signed-off-by: Qu Wenruo --- fs/btrfs/extent_io.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 1ec9de2aa910..64a19c1884fc 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -2841,15 +2841,26 @@ static void endio_readpage_release_extent(struct processed_extent *processed, processed->uptodate = uptodate; } -static void endio_readpage_update_page_status(struct page *page, bool uptodate) +static void endio_readpage_update_page_status(struct page *page, bool uptodate, + u64 start, u64 end) { + struct btrfs_fs_info *fs_info = btrfs_sb(page->mapping->host->i_sb); + u32 len; + + ASSERT(page_offset(page) <= start && + end <= page_offset(page) + PAGE_SIZE - 1); + len = end + 1 - start; + if (uptodate) { - SetPageUptodate(page); + btrfs_page_set_uptodate(fs_info, page, start, len); } else { - ClearPageUptodate(page); - SetPageError(page); + btrfs_page_clear_uptodate(fs_info, page, start, len); + btrfs_page_set_error(fs_info, page, start, len); } - unlock_page(page); + + if (fs_info->sectorsize == PAGE_SIZE) + unlock_page(page); + /* Subpage locking will be handled in later patches */ } /* @@ -2986,7 +2997,7 @@ static void end_bio_extent_readpage(struct bio *bio) bio_offset += len; /* Update page status and unlock */ - endio_readpage_update_page_status(page, uptodate); + endio_readpage_update_page_status(page, uptodate, start, end); endio_readpage_release_extent(&processed, BTRFS_I(inode), start, end, uptodate); } From patchwork Thu Dec 10 06:39:02 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 11963429 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0138DC4361B for ; Thu, 10 Dec 2020 06:41:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B154623C44 for ; Thu, 10 Dec 2020 06:41:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387561AbgLJGlE (ORCPT ); Thu, 10 Dec 2020 01:41:04 -0500 Received: from mx2.suse.de ([195.135.220.15]:44472 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387523AbgLJGlD (ORCPT ); Thu, 10 Dec 2020 01:41:03 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1607582378; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=HJGTzVPLfPoMAxVRuz+nVyvcG/38/B+4XaBbLMHGhKg=; b=MJeSzMGUelNqPIFx6HTeAxPxF+1IXNmPnoz4kFOmn2PHHkLDTZyRjud8QktWwtemUj47Lr kf65Mfc2jg62dko16X41/TPI2hKEHpNIUyLX/pH1WrtWcj+ZsfnFC+R0dC//DGb9+ebOWi nXS7y58n2oxXsFvWtUoeyjbHZgclJ+s= Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 3AB8EAD79 for ; Thu, 10 Dec 2020 06:39:38 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v2 15/18] btrfs: disk-io: introduce subpage metadata validation check Date: Thu, 10 Dec 2020 14:39:02 +0800 Message-Id: <20201210063905.75727-16-wqu@suse.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201210063905.75727-1-wqu@suse.com> References: <20201210063905.75727-1-wqu@suse.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org For subpage metadata validation check, there are some difference: - Read must finish in one bvec Since we're just reading one subpage range in one page, it should never be split into two bios nor two bvecs. - How to grab the existing eb Instead of grabbing eb using page->private, we have to go search radix tree as we don't have any direct pointer at hand. Signed-off-by: Qu Wenruo Reported-by: kernel test robot Reported-by: kernel test robot --- fs/btrfs/disk-io.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index b6c03a8b0c72..adda76895058 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -591,6 +591,84 @@ static int validate_extent_buffer(struct extent_buffer *eb) return ret; } +static int validate_subpage_buffer(struct page *page, u64 start, u64 end, + int mirror) +{ + struct btrfs_fs_info *fs_info = btrfs_sb(page->mapping->host->i_sb); + struct extent_buffer *eb; + int reads_done; + int ret = 0; + + if (!IS_ALIGNED(start, fs_info->sectorsize) || + !IS_ALIGNED(end - start + 1, fs_info->sectorsize) || + !IS_ALIGNED(end - start + 1, fs_info->nodesize)) { + WARN_ON(IS_ENABLED(CONFIG_BTRFS_DEBUG)); + btrfs_err(fs_info, "invalid tree read bytenr"); + return -EUCLEAN; + } + + /* + * We don't allow bio merge for subpage metadata read, so we should + * only get one eb for each endio hook. + */ + ASSERT(end == start + fs_info->nodesize - 1); + ASSERT(PagePrivate(page)); + + rcu_read_lock(); + eb = radix_tree_lookup(&fs_info->buffer_radix, + start / fs_info->sectorsize); + rcu_read_unlock(); + + /* + * When we are reading one tree block, eb must have been + * inserted into the radix tree. If not something is wrong. + */ + if (!eb) { + WARN_ON(IS_ENABLED(CONFIG_BTRFS_DEBUG)); + btrfs_err(fs_info, + "can't find extent buffer for bytenr %llu", + start); + return -EUCLEAN; + } + /* + * The pending IO might have been the only thing that kept + * this buffer in memory. Make sure we have a ref for all + * this other checks + */ + atomic_inc(&eb->refs); + + reads_done = atomic_dec_and_test(&eb->io_pages); + /* Subpage read must finish in page read */ + ASSERT(reads_done); + + eb->read_mirror = mirror; + if (test_bit(EXTENT_BUFFER_READ_ERR, &eb->bflags)) { + ret = -EIO; + goto err; + } + ret = validate_extent_buffer(eb); + if (ret < 0) + goto err; + + if (test_and_clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags)) + btree_readahead_hook(eb, ret); + + set_extent_buffer_uptodate(eb); + + free_extent_buffer(eb); + return ret; +err: + /* + * our io error hook is going to dec the io pages + * again, we have to make sure it has something to + * decrement + */ + atomic_inc(&eb->io_pages); + clear_extent_buffer_uptodate(eb); + free_extent_buffer(eb); + return ret; +} + int btrfs_validate_metadata_buffer(struct btrfs_io_bio *io_bio, struct page *page, u64 start, u64 end, int mirror) @@ -600,6 +678,10 @@ int btrfs_validate_metadata_buffer(struct btrfs_io_bio *io_bio, int reads_done; ASSERT(page->private); + + if (btrfs_sb(page->mapping->host->i_sb)->sectorsize < PAGE_SIZE) + return validate_subpage_buffer(page, start, end, mirror); + eb = (struct extent_buffer *)page->private; From patchwork Thu Dec 10 06:39:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 11963435 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 82464C433FE for ; Thu, 10 Dec 2020 06:41:32 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3E1C523B98 for ; Thu, 10 Dec 2020 06:41:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387568AbgLJGla (ORCPT ); Thu, 10 Dec 2020 01:41:30 -0500 Received: from mx2.suse.de ([195.135.220.15]:44726 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726874AbgLJGl3 (ORCPT ); Thu, 10 Dec 2020 01:41:29 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1607582380; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=oiFao7hSluPEqR1buVMmU5UrRddfvcZkBVp7YMVfy+Q=; b=EhpFBo/7DuiSxAtoLMiUPLUTjqMXl+bZTkugd1I9waFfQSSf1t0NRmLhnYUMx5JB0elHkb VXoUNVHpsCZa1qExH6VvYMmW1VcA4LslpiTlNKVR9a6sfKan18evqf5/da+FUIOcmls6+4 gGQdd55gczwLSvbb47daKqnaz8N96yM= Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 289FBAD80 for ; Thu, 10 Dec 2020 06:39:40 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v2 16/18] btrfs: introduce btrfs_subpage for data inodes Date: Thu, 10 Dec 2020 14:39:03 +0800 Message-Id: <20201210063905.75727-17-wqu@suse.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201210063905.75727-1-wqu@suse.com> References: <20201210063905.75727-1-wqu@suse.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org 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 Reported-by: kernel test robot Reported-by: kernel test robot --- fs/btrfs/compression.c | 10 ++++++-- fs/btrfs/extent_io.c | 47 +++++++++++++++++++++++++++++++++---- fs/btrfs/extent_io.h | 3 ++- fs/btrfs/file.c | 10 +++++--- fs/btrfs/free-space-cache.c | 15 +++++++++--- fs/btrfs/inode.c | 12 ++++++---- fs/btrfs/ioctl.c | 5 +++- fs/btrfs/reflink.c | 5 +++- fs/btrfs/relocation.c | 12 ++++++++-- 9 files changed, 98 insertions(+), 21 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 64a19c1884fc..4e4ed9c453ae 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -3191,10 +3191,40 @@ static int attach_extent_buffer_page(struct extent_buffer *eb, return 0; } -void set_page_extent_mapped(struct page *page) +int __must_check set_page_extent_mapped(struct page *page) { - if (!PagePrivate(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) { attach_page_private(page, (void *)EXTENT_PAGE_PRIVATE); + return 0; + } + + return btrfs_attach_subpage(fs_info, page); +} + +void clear_page_extent_mapped(struct page *page) +{ + struct btrfs_fs_info *fs_info; + + ASSERT(page->mapping); + + if (!PagePrivate(page)) + return; + + fs_info = btrfs_sb(page->mapping->host->i_sb); + if (fs_info->sectorsize == PAGE_SIZE) { + detach_page_private(page); + return; + } + + btrfs_detach_subpage(fs_info, page); } static struct extent_map * @@ -3251,7 +3281,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) { @@ -3693,7 +3728,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 19221095c635..349d044c1254 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 __must_check 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 a29b50208eee..9b878616b489 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -1373,6 +1373,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); @@ -1470,10 +1476,8 @@ lock_and_cleanup_extent_if_need(struct btrfs_inode *inode, struct page **pages, * We'll call btrfs_dirty_pages() later on, and that will flip around * delalloc bits and dirty the pages as required. */ - 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 71d0d14bc18b..c347b415060a 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 -ENOMEM; + } + 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 070716650df8..5b64715df92e 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -4720,6 +4720,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); @@ -4737,7 +4740,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) { @@ -8117,7 +8119,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; } @@ -8276,7 +8278,7 @@ static void btrfs_invalidatepage(struct page *page, unsigned int offset, } ClearPageChecked(page); - detach_page_private(page); + clear_page_extent_mapped(page); } /* @@ -8355,7 +8357,9 @@ 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); + ret = set_page_extent_mapped(page); + if (ret < 0) + goto out_unlock; /* * we can't set the delalloc bits if there are pending ordered diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index dde49a791f3e..1d58ffb9212f 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1319,6 +1319,10 @@ static int cluster_pages_for_defrag(struct inode *inode, if (!page) break; + ret = set_page_extent_mapped(page); + if (ret < 0) + break; + page_start = page_offset(page); page_end = page_start + PAGE_SIZE - 1; while (1) { @@ -1440,7 +1444,6 @@ static int cluster_pages_for_defrag(struct inode *inode, for (i = 0; i < i_done; i++) { clear_page_dirty_for_io(pages[i]); ClearPageChecked(pages[i]); - set_page_extent_mapped(pages[i]); set_page_dirty(pages[i]); unlock_page(pages[i]); put_page(pages[i]); diff --git a/fs/btrfs/reflink.c b/fs/btrfs/reflink.c index b03e7891394e..b24396cf2f99 100644 --- a/fs/btrfs/reflink.c +++ b/fs/btrfs/reflink.c @@ -81,7 +81,10 @@ static int copy_inline_to_page(struct btrfs_inode *inode, goto out_unlock; } - set_page_extent_mapped(page); + ret = set_page_extent_mapped(page); + if (ret < 0) + goto out_unlock; + clear_extent_bit(&inode->io_tree, file_offset, range_end, EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG, 0, 0, NULL); diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 19b7db8b2117..41ee0f376af3 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -2679,6 +2679,16 @@ static int relocate_file_extent_cluster(struct inode *inode, goto out; } } + ret = set_page_extent_mapped(page); + if (ret < 0) { + btrfs_delalloc_release_metadata(BTRFS_I(inode), + PAGE_SIZE, true); + btrfs_delalloc_release_extents(BTRFS_I(inode), + PAGE_SIZE); + unlock_page(page); + put_page(page); + goto out; + } if (PageReadahead(page)) { page_cache_async_readahead(inode->i_mapping, @@ -2706,8 +2716,6 @@ static int relocate_file_extent_cluster(struct inode *inode, lock_extent(&BTRFS_I(inode)->io_tree, page_start, page_end); - set_page_extent_mapped(page); - if (nr < cluster->nr && page_start + offset == cluster->boundary[nr]) { set_extent_bits(&BTRFS_I(inode)->io_tree, From patchwork Thu Dec 10 06:39:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 11963433 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BF8E2C4361B for ; Thu, 10 Dec 2020 06:41:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 80FDC23B98 for ; Thu, 10 Dec 2020 06:41:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387572AbgLJGlb (ORCPT ); Thu, 10 Dec 2020 01:41:31 -0500 Received: from mx2.suse.de ([195.135.220.15]:44728 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728974AbgLJGla (ORCPT ); Thu, 10 Dec 2020 01:41:30 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1607582382; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=GALDEq99Z8S+mHFMraFZOk/xU7D2UbhDTLXmSzVvz44=; b=V7A67/TW3ko7xe5EmHNplIAakkXmnE3ZLxODAMZXR8kS9tWWVHcDCnpyO8m+Ef5ZCuYbuI iDOHauEK/sD9VlwiDHTEH2QnSp+LoKcJwKL5TcxqTQwqpSRKub5Ee5WbYhE5mIiDH24V6K bSlXlOeuN4sQzyZ8c9+v8QKgaWEZVDU= Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 0AA4BAD9F for ; Thu, 10 Dec 2020 06:39:42 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v2 17/18] btrfs: integrate page status update for read path into begin/end_page_read() Date: Thu, 10 Dec 2020 14:39:04 +0800 Message-Id: <20201210063905.75727-18-wqu@suse.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201210063905.75727-1-wqu@suse.com> References: <20201210063905.75727-1-wqu@suse.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org In btrfs data page read path, the page status update are handled in two different locations: btrfs_do_read_page() { while (cur <= end) { /* No need to read from disk */ if (HOLE/PREALLOC/INLINE){ memset(); set_extent_uptodate(); continue; } /* Read from disk */ ret = submit_extent_page(end_bio_extent_readpage); } end_bio_extent_readpage() { endio_readpage_uptodate_page_status(); } This is fine for sectorsize == PAGE_SIZE case, as for above loop we should only hit one branch and then exit. But for subpage, there are more works to be done in page status update: - Page Unlock condition Unlike regular page size == sectorsize case, we can no longer just unlock a page. Only the last reader of the page can unlock the page. This means, we can unlock the page either in the while() loop, or in the endio function. - Page uptodate condition Since we have multiple sectors to read for a page, we can only mark the full page uptodate if all sectors are uptodate. To handle both subpage and regular cases, introduce a pair of functions to help handling page status update: - being_page_read() For regular case, it does nothing. For subpage case, it update the reader counters so that later end_page_read() can know who is the last one to unlock the page. - end_page_read() This is just endio_readpage_uptodate_page_status() renamed. The original name is a little too long and too specific for endio. The only new trick added is the condition for page unlock. Now for subage data, we unlock the page if we're the last reader. This does not only provide the basis for subpage data read, but also hide the special handling of page read from the main read loop. Signed-off-by: Qu Wenruo --- fs/btrfs/extent_io.c | 39 +++++++++++++++++++++++++----------- fs/btrfs/subpage.h | 47 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 68 insertions(+), 18 deletions(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 4e4ed9c453ae..56174e7f0ae8 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -2841,8 +2841,18 @@ static void endio_readpage_release_extent(struct processed_extent *processed, processed->uptodate = uptodate; } -static void endio_readpage_update_page_status(struct page *page, bool uptodate, - u64 start, u64 end) +static void begin_data_page_read(struct btrfs_fs_info *fs_info, struct page *page) +{ + ASSERT(PageLocked(page)); + if (fs_info->sectorsize == PAGE_SIZE) + return; + + ASSERT(PagePrivate(page) && page->private); + ASSERT(page->mapping->host != fs_info->btree_inode); + btrfs_subpage_start_reader(fs_info, page, page_offset(page), PAGE_SIZE); +} + +static void end_page_read(struct page *page, bool uptodate, u64 start, u64 end) { struct btrfs_fs_info *fs_info = btrfs_sb(page->mapping->host->i_sb); u32 len; @@ -2860,7 +2870,12 @@ static void endio_readpage_update_page_status(struct page *page, bool uptodate, if (fs_info->sectorsize == PAGE_SIZE) unlock_page(page); - /* Subpage locking will be handled in later patches */ + else if (page->mapping->host != fs_info->btree_inode) + /* + * For subpage data, unlock the page if we're the last reader. + * For subpage metadata, page lock is not utilized for read. + */ + btrfs_subpage_end_reader(fs_info, page, start, len); } /* @@ -2997,7 +3012,7 @@ static void end_bio_extent_readpage(struct bio *bio) bio_offset += len; /* Update page status and unlock */ - endio_readpage_update_page_status(page, uptodate, start, end); + end_page_read(page, uptodate, start, end); endio_readpage_release_extent(&processed, BTRFS_I(inode), start, end, uptodate); } @@ -3265,6 +3280,7 @@ int btrfs_do_readpage(struct page *page, struct extent_map **em_cached, unsigned int read_flags, u64 *prev_em_start) { struct inode *inode = page->mapping->host; + struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); u64 start = page_offset(page); const u64 end = start + PAGE_SIZE - 1; u64 cur = start; @@ -3308,6 +3324,7 @@ int btrfs_do_readpage(struct page *page, struct extent_map **em_cached, kunmap_atomic(userpage); } } + begin_data_page_read(fs_info, page); while (cur <= end) { bool force_bio_submit = false; u64 disk_bytenr; @@ -3325,13 +3342,14 @@ int btrfs_do_readpage(struct page *page, struct extent_map **em_cached, &cached, GFP_NOFS); unlock_extent_cached(tree, cur, cur + iosize - 1, &cached); + end_page_read(page, true, cur, cur + iosize - 1); break; } em = __get_extent_map(inode, page, pg_offset, cur, end - cur + 1, em_cached); if (IS_ERR_OR_NULL(em)) { - SetPageError(page); unlock_extent(tree, cur, end); + end_page_read(page, false, cur, end); break; } extent_offset = cur - em->start; @@ -3414,6 +3432,7 @@ int btrfs_do_readpage(struct page *page, struct extent_map **em_cached, &cached, GFP_NOFS); unlock_extent_cached(tree, cur, cur + iosize - 1, &cached); + end_page_read(page, true, cur, cur + iosize - 1); cur = cur + iosize; pg_offset += iosize; continue; @@ -3423,6 +3442,7 @@ int btrfs_do_readpage(struct page *page, struct extent_map **em_cached, EXTENT_UPTODATE, 1, NULL)) { check_page_uptodate(tree, page); unlock_extent(tree, cur, cur + iosize - 1); + end_page_read(page, true, cur, cur + iosize - 1); cur = cur + iosize; pg_offset += iosize; continue; @@ -3431,8 +3451,8 @@ int btrfs_do_readpage(struct page *page, struct extent_map **em_cached, * to date. Error out */ if (block_start == EXTENT_MAP_INLINE) { - SetPageError(page); unlock_extent(tree, cur, cur + iosize - 1); + end_page_read(page, false, cur, cur + iosize - 1); cur = cur + iosize; pg_offset += iosize; continue; @@ -3449,19 +3469,14 @@ int btrfs_do_readpage(struct page *page, struct extent_map **em_cached, nr++; *bio_flags = this_bio_flag; } else { - SetPageError(page); unlock_extent(tree, cur, cur + iosize - 1); + end_page_read(page, false, cur, cur + iosize - 1); goto out; } cur = cur + iosize; pg_offset += iosize; } out: - if (!nr) { - if (!PageError(page)) - SetPageUptodate(page); - unlock_page(page); - } return ret; } diff --git a/fs/btrfs/subpage.h b/fs/btrfs/subpage.h index 8592234d773e..6c801ef00d2d 100644 --- a/fs/btrfs/subpage.h +++ b/fs/btrfs/subpage.h @@ -31,6 +31,9 @@ struct btrfs_subpage { u16 tree_block_bitmap; }; /* structures only used by data */ + struct { + atomic_t readers; + }; }; }; @@ -48,6 +51,17 @@ static inline void btrfs_subpage_clamp_range(struct page *page, orig_start + orig_len) - *start; } +static inline void btrfs_subpage_assert(struct btrfs_fs_info *fs_info, + struct page *page, u64 start, u32 len) +{ + /* Basic checks */ + ASSERT(PagePrivate(page) && page->private); + ASSERT(IS_ALIGNED(start, fs_info->sectorsize) && + IS_ALIGNED(len, fs_info->sectorsize)); + ASSERT(page_offset(page) <= start && + start + len <= page_offset(page) + PAGE_SIZE); +} + /* * Convert the [start, start + len) range into a u16 bitmap * @@ -59,12 +73,8 @@ static inline u16 btrfs_subpage_calc_bitmap(struct btrfs_fs_info *fs_info, int bit_start = (start - page_offset(page)) >> fs_info->sectorsize_bits; int nbits = len >> fs_info->sectorsize_bits; - /* Basic checks */ - ASSERT(PagePrivate(page) && page->private); - ASSERT(IS_ALIGNED(start, fs_info->sectorsize) && - IS_ALIGNED(len, fs_info->sectorsize)); - ASSERT(page_offset(page) <= start && - start + len <= page_offset(page) + PAGE_SIZE); + btrfs_subpage_assert(fs_info, page, start, len); + /* * Here nbits can be 16, thus can go beyond u16 range. Here we make the * first left shift to be calculated in unsigned long (u32), then @@ -73,6 +83,31 @@ static inline u16 btrfs_subpage_calc_bitmap(struct btrfs_fs_info *fs_info, return (u16)(((1UL << nbits) - 1) << bit_start); } +static inline void btrfs_subpage_start_reader(struct btrfs_fs_info *fs_info, + struct page *page, u64 start, + u32 len) +{ + struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private; + int nbits = len >> fs_info->sectorsize_bits; + + btrfs_subpage_assert(fs_info, page, start, len); + + ASSERT(atomic_read(&subpage->readers) == 0); + atomic_set(&subpage->readers, nbits); +} + +static inline void btrfs_subpage_end_reader(struct btrfs_fs_info *fs_info, + struct page *page, u64 start, u32 len) +{ + struct btrfs_subpage *subpage = (struct btrfs_subpage *)page->private; + int nbits = len >> fs_info->sectorsize_bits; + + btrfs_subpage_assert(fs_info, page, start, len); + ASSERT(atomic_read(&subpage->readers) >= nbits); + if (atomic_sub_and_test(nbits, &subpage->readers)) + unlock_page(page); +} + static inline void btrfs_subpage_set_tree_block(struct btrfs_fs_info *fs_info, struct page *page, u64 start, u32 len) { From patchwork Thu Dec 10 06:39:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 11963431 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-18.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B9DC9C1B0D8 for ; Thu, 10 Dec 2020 06:41:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6A37323D58 for ; Thu, 10 Dec 2020 06:41:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387564AbgLJGlE (ORCPT ); Thu, 10 Dec 2020 01:41:04 -0500 Received: from mx2.suse.de ([195.135.220.15]:44470 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387556AbgLJGlE (ORCPT ); Thu, 10 Dec 2020 01:41:04 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1607582384; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=+sI0HPZ7NFYln9IBhJ+D7AbWHaYi8HKvTPdGX9iL2w0=; b=ZFoPe9LUpCwi0Ntz1RwJBlET7uFiMJlCYbOAq1jd0cxmJorkizP9wEIGm0a28hXv06HjSb 2Li9U07wfEVoYxKpEDfUaGpazlLtJ+A1DvK7JeQPsaEJDOnJIfcz6IrQxD0kua5v1SvoAo EN5ZnHP3eElsQ3DHSUrbtRxAn2e3758= Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id B34D5AD8A for ; Thu, 10 Dec 2020 06:39:44 +0000 (UTC) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v2 18/18] btrfs: allow RO mount of 4K sector size fs on 64K page system Date: Thu, 10 Dec 2020 14:39:05 +0800 Message-Id: <20201210063905.75727-19-wqu@suse.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201210063905.75727-1-wqu@suse.com> References: <20201210063905.75727-1-wqu@suse.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org This adds the basic RO mount ability for 4K sector size on 64K page system. Currently we only plan to support 4K and 64K page system. Signed-off-by: Qu Wenruo --- fs/btrfs/disk-io.c | 24 +++++++++++++++++++++--- fs/btrfs/super.c | 7 +++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index adda76895058..8ab6308ff852 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -2510,13 +2510,21 @@ static int validate_super(struct btrfs_fs_info *fs_info, btrfs_err(fs_info, "invalid sectorsize %llu", sectorsize); ret = -EINVAL; } - /* Only PAGE SIZE is supported yet */ - if (sectorsize != PAGE_SIZE) { + + /* + * For 4K page size, we only support 4K sector size. + * For 64K page size, we support RW for 64K sector size, and RO for + * 4K sector size. + */ + if ((SZ_4K == PAGE_SIZE && sectorsize != PAGE_SIZE) || + (SZ_64K == PAGE_SIZE && (sectorsize != SZ_4K && + sectorsize != SZ_64K))) { btrfs_err(fs_info, - "sectorsize %llu not supported yet, only support %lu", + "sectorsize %llu not supported yet for page size %lu", sectorsize, PAGE_SIZE); ret = -EINVAL; } + if (!is_power_of_2(nodesize) || nodesize < sectorsize || nodesize > BTRFS_MAX_METADATA_BLOCKSIZE) { btrfs_err(fs_info, "invalid nodesize %llu", nodesize); @@ -3272,6 +3280,16 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device goto fail_alloc; } + /* For 4K sector size support, it's only read-only yet */ + if (PAGE_SIZE == SZ_64K && sectorsize == SZ_4K) { + if (!sb_rdonly(sb) || btrfs_super_log_root(disk_super)) { + btrfs_err(fs_info, + "subpage sector size only support RO yet"); + err = -EINVAL; + goto fail_alloc; + } + } + ret = btrfs_init_workqueues(fs_info, fs_devices); if (ret) { err = ret; diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 022f20810089..a8068c389d60 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -1996,6 +1996,13 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) ret = -EINVAL; goto restore; } + if (fs_info->sectorsize < PAGE_SIZE) { + btrfs_warn(fs_info, + "read-write mount is not yet allowed for sector size %u page size %lu", + fs_info->sectorsize, PAGE_SIZE); + ret = -EINVAL; + goto restore; + } /* * NOTE: when remounting with a change that does writes, don't