From patchwork Mon Jan 27 15:59:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Thumshirn X-Patchwork-Id: 11352843 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 53A9F159A for ; Mon, 27 Jan 2020 15:59:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1E20A22527 for ; Mon, 27 Jan 2020 15:59:40 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=wdc.com header.i=@wdc.com header.b="d15a2Rzq" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729547AbgA0P7j (ORCPT ); Mon, 27 Jan 2020 10:59:39 -0500 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:39164 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729203AbgA0P7i (ORCPT ); Mon, 27 Jan 2020 10:59:38 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1580140778; x=1611676778; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=3zZaUBi8IgRvalzSUqxsp0ZW56ruIM3Wf5bmAP4i5AA=; b=d15a2Rzq76QwoHDWS91JgPI9FyR5jDs/qp6IWUR+bqMbOw0XtLWUN9IA ugLOfzqcXkT4riBZvnJ7f0XieIoH+P1rCdBOTIlhrsu3gHHw7pNXQ/s7K PvH/dDCBS2HJJWnNTmjUjOCD8vwyVtZpmqtFCi91cTjnwx7mTwcToAdQX PLhEXmKKOWMNNEaUS/ws01CoBOTolMi0LzErd+nrQLwlqmF4Ur9mkelOp zVkvsnGzZxkzsTrpP3B0eTjQ8NitnY2RftmiVl5DIzZWNs0y316xHh8i4 ka7U7Mb2KmvIxr4FGETTMexy8MWOnFEObLg/j4W2ZQi8vk9XqVtF++nT1 A==; IronPort-SDR: 6wXWLMWVDMK5biDhSz9s57lNDiFCw9T61A/241ffJuEBjuXVUZw3hRAunOVE+02W8+tVrdkNet 3Ct1NLUHpEazq+B3kVK0CvZXwWqFR0FnDOtQq9rO5dfW+jDQp97GDqLmmba9y15o8TYXco7p+I 7Z/xQ4AGPT2IxI8VLKbjqHzHkUxuibFtDefriGsKcOxfrM4tUqeuPOcxIsZ+d2PXEwMUyXQHFh MpZAWB2d33YLldm2jBAdIA3B0fUX9HXyT7B/carzn35V+27P6lT15jold3ZxM8rul6TYHbdt87 528= X-IronPort-AV: E=Sophos;i="5.70,370,1574092800"; d="scan'208";a="132851974" Received: from uls-op-cesaip01.wdc.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 27 Jan 2020 23:59:38 +0800 IronPort-SDR: ajo94UrrttOT+Owxe3V+XVnmViQ4iL42CHewVhoAHxwWsDswqvKrxS+k5fGADr2A26P2W26Tsq tEYWgMBDGQnepHr4TXWzTi2N98u7Bu9xx2u88ovOmGEz467nF2sQ+X+7xNXiIbz84IbR5l172a vj9K9Dp1f9Pg+Fk6ZnRRIGry7q2ds5rdCVnGAqS1/hXd3R3plmDAqV87dTvSmyCGzL+8AAgwKw GDGiC8PrUw/HiSEOYsXOIQA/VHuX68cZBh8zwQewYhFSXLVD/F1vF0x3jo9aUT8HXy9DzyrYy7 lXM4v1fYBx2qzIYmCuTCTueb Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep01.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Jan 2020 07:52:53 -0800 IronPort-SDR: KrJ8GzD/dVXyKOGmqnvjvZ0+WSprcsQXIuUfeVc+e75nQ8vLbepV2VTW7LU7E7bAVKxpPmoSEz bzizRVGb3CSf+DoDG021545YyCRFDWePLJ5bjrLGmUcctbTBrma05UapfF6QR4oSeptuIMZTdp wFz6yiETJmkDlBTHv4LWfq7DUI2HAzvU0B3e7hT82pH8p/05kMbTu8kG6lPixtXsuoyOjL8wEL YXrM/dDvaAtHWGgvsRbMYYh09xJ+oc9G5C4y+4iTtbOe0hxiGr+UmKvAKa2ehMs4z8vuwTWb2v 3zA= WDCIronportException: Internal Received: from unknown (HELO redsun60.ssa.fujisawa.hgst.com) ([10.149.66.36]) by uls-op-cesaip02.wdc.com with ESMTP; 27 Jan 2020 07:59:37 -0800 From: Johannes Thumshirn To: David Sterba Cc: Nikolay Borisov , "linux-btrfs @ vger . kernel . org" , Johannes Thumshirn , Josef Bacik Subject: [PATCH v3 1/5] btrfs: remove buffer heads from super block reading Date: Tue, 28 Jan 2020 00:59:27 +0900 Message-Id: <20200127155931.10818-2-johannes.thumshirn@wdc.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200127155931.10818-1-johannes.thumshirn@wdc.com> References: <20200127155931.10818-1-johannes.thumshirn@wdc.com> MIME-Version: 1.0 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org Super-block reading in BTRFS is done using buffer_heads. Buffer_heads have some drawbacks, like not being able to propagate errors from the lower layers. Change the buffer_heads to BIOs and utilize the page cache for the page allocation. Compared to buffer_heads using BIOs are more lightweight and we skip several layers of buffer_head code until we either reach the page cache or build a BIO and submit it to read the blocks from disk. Signed-off-by: Johannes Thumshirn Reviewed-by: Josef Bacik --- Changes to v2: - open-code kunmap() + put_page() (David) - fix double kunmap() (David) - don't use bi_set_op_attrs() (David) Changes to v1: - move 'super_page' into for-loop in btrfs_scratch_superblocks() (Nikolay) - switch to using pagecahce instead of alloc_pages() (Nikolay, David) --- fs/btrfs/disk-io.c | 89 ++++++++++++++++++++++++++++++---------------- fs/btrfs/disk-io.h | 4 +-- fs/btrfs/volumes.c | 66 +++++++++++++++++++++------------- fs/btrfs/volumes.h | 2 -- 4 files changed, 102 insertions(+), 59 deletions(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index aea48d6ddc0c..1f30b234ac07 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -2635,11 +2635,12 @@ int __cold open_ctree(struct super_block *sb, u64 features; u16 csum_type; struct btrfs_key location; - struct buffer_head *bh; struct btrfs_super_block *disk_super; struct btrfs_fs_info *fs_info = btrfs_sb(sb); struct btrfs_root *tree_root; struct btrfs_root *chunk_root; + struct page *super_page; + u8 *superblock; int ret; int err = -EINVAL; int clear_free_space_tree = 0; @@ -2832,28 +2833,33 @@ int __cold open_ctree(struct super_block *sb, /* * Read super block and check the signature bytes only */ - bh = btrfs_read_dev_super(fs_devices->latest_bdev); - if (IS_ERR(bh)) { - err = PTR_ERR(bh); + ret = btrfs_read_dev_super(fs_devices->latest_bdev, &super_page); + if (ret) { + err = ret; goto fail_alloc; } + superblock = kmap(super_page); /* * Verify the type first, if that or the the checksum value are * corrupted, we'll find out */ - csum_type = btrfs_super_csum_type((struct btrfs_super_block *)bh->b_data); + csum_type = btrfs_super_csum_type((struct btrfs_super_block *) + superblock); if (!btrfs_supported_super_csum(csum_type)) { btrfs_err(fs_info, "unsupported checksum algorithm: %u", csum_type); err = -EINVAL; - brelse(bh); + kunmap(super_page); + put_page(super_page); goto fail_alloc; } ret = btrfs_init_csum_hash(fs_info, csum_type); if (ret) { err = ret; + kunmap(super_page); + put_page(super_page); goto fail_alloc; } @@ -2861,10 +2867,11 @@ int __cold open_ctree(struct super_block *sb, * We want to check superblock checksum, the type is stored inside. * Pass the whole disk block of size BTRFS_SUPER_INFO_SIZE (4k). */ - if (btrfs_check_super_csum(fs_info, bh->b_data)) { + if (btrfs_check_super_csum(fs_info, superblock)) { btrfs_err(fs_info, "superblock checksum mismatch"); err = -EINVAL; - brelse(bh); + kunmap(super_page); + put_page(super_page); goto fail_csum; } @@ -2873,8 +2880,9 @@ int __cold open_ctree(struct super_block *sb, * following bytes up to INFO_SIZE, the checksum is calculated from * the whole block of INFO_SIZE */ - memcpy(fs_info->super_copy, bh->b_data, sizeof(*fs_info->super_copy)); - brelse(bh); + memcpy(fs_info->super_copy, superblock, sizeof(*fs_info->super_copy)); + kunmap(super_page); + put_page(super_page); disk_super = fs_info->super_copy; @@ -3374,40 +3382,61 @@ static void btrfs_end_buffer_write_sync(struct buffer_head *bh, int uptodate) } int btrfs_read_dev_one_super(struct block_device *bdev, int copy_num, - struct buffer_head **bh_ret) + struct page **super_page) { - struct buffer_head *bh; struct btrfs_super_block *super; + struct bio_vec bio_vec; + struct bio bio; + struct page *page; u64 bytenr; + struct address_space *mapping = bdev->bd_inode->i_mapping; + gfp_t gfp_mask; + int ret; bytenr = btrfs_sb_offset(copy_num); if (bytenr + BTRFS_SUPER_INFO_SIZE >= i_size_read(bdev->bd_inode)) return -EINVAL; - bh = __bread(bdev, bytenr / BTRFS_BDEV_BLOCKSIZE, BTRFS_SUPER_INFO_SIZE); + gfp_mask = mapping_gfp_constraint(mapping, ~__GFP_FS) | __GFP_NOFAIL; + page = find_or_create_page(mapping, bytenr >> PAGE_SHIFT, gfp_mask); + if (!page) + return -ENOMEM; + + bio_init(&bio, &bio_vec, 1); + bio.bi_iter.bi_sector = bytenr >> SECTOR_SHIFT; + bio_set_dev(&bio, bdev); + bio.bi_opf = REQ_OP_READ; + bio_add_page(&bio, page, BTRFS_SUPER_INFO_SIZE, + offset_in_page(bytenr)); + + ret = submit_bio_wait(&bio); + unlock_page(page); /* * If we fail to read from the underlying devices, as of now * the best option we have is to mark it EIO. */ - if (!bh) + if (ret) { + put_page(page); return -EIO; + } - super = (struct btrfs_super_block *)bh->b_data; + super = kmap(page); if (btrfs_super_bytenr(super) != bytenr || btrfs_super_magic(super) != BTRFS_MAGIC) { - brelse(bh); + kunmap(page); + put_page(page); return -EINVAL; } + kunmap(page); - *bh_ret = bh; + *super_page = page; return 0; } -struct buffer_head *btrfs_read_dev_super(struct block_device *bdev) +int btrfs_read_dev_super(struct block_device *bdev, struct page **page) { - struct buffer_head *bh; - struct buffer_head *latest = NULL; + struct page *latest = NULL; struct btrfs_super_block *super; int i; u64 transid = 0; @@ -3419,25 +3448,25 @@ struct buffer_head *btrfs_read_dev_super(struct block_device *bdev) * later supers, using BTRFS_SUPER_MIRROR_MAX instead */ for (i = 0; i < 1; i++) { - ret = btrfs_read_dev_one_super(bdev, i, &bh); + ret = btrfs_read_dev_one_super(bdev, i, page); if (ret) continue; - super = (struct btrfs_super_block *)bh->b_data; + super = kmap(*page); if (!latest || btrfs_super_generation(super) > transid) { - brelse(latest); - latest = bh; + if (latest) { + kunmap(latest); + put_page(latest); + } + latest = *page; transid = btrfs_super_generation(super); - } else { - brelse(bh); } - } - if (!latest) - return ERR_PTR(ret); + kunmap(*page); + } - return latest; + return ret; } /* diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index 8c2d6cf1ce59..e04b233c436a 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h @@ -54,9 +54,9 @@ int __cold open_ctree(struct super_block *sb, char *options); void __cold close_ctree(struct btrfs_fs_info *fs_info); int write_all_supers(struct btrfs_fs_info *fs_info, int max_mirrors); -struct buffer_head *btrfs_read_dev_super(struct block_device *bdev); +int btrfs_read_dev_super(struct block_device *bdev, struct page **super_page); int btrfs_read_dev_one_super(struct block_device *bdev, int copy_num, - struct buffer_head **bh_ret); + struct page **super_page); int btrfs_commit_super(struct btrfs_fs_info *fs_info); struct btrfs_root *btrfs_read_fs_root(struct btrfs_root *tree_root, struct btrfs_key *location); diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 9cfc668f91f4..fd8b3db14d62 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -500,7 +499,7 @@ static struct btrfs_fs_devices *find_fsid_with_metadata_uuid( static int btrfs_get_bdev_and_sb(const char *device_path, fmode_t flags, void *holder, int flush, struct block_device **bdev, - struct buffer_head **bh) + struct page **super_page) { int ret; @@ -519,9 +518,8 @@ btrfs_get_bdev_and_sb(const char *device_path, fmode_t flags, void *holder, goto error; } invalidate_bdev(*bdev); - *bh = btrfs_read_dev_super(*bdev); - if (IS_ERR(*bh)) { - ret = PTR_ERR(*bh); + ret = btrfs_read_dev_super(*bdev, super_page); + if (ret) { blkdev_put(*bdev, flags); goto error; } @@ -530,7 +528,6 @@ btrfs_get_bdev_and_sb(const char *device_path, fmode_t flags, void *holder, error: *bdev = NULL; - *bh = NULL; return ret; } @@ -611,7 +608,7 @@ static int btrfs_open_one_device(struct btrfs_fs_devices *fs_devices, { struct request_queue *q; struct block_device *bdev; - struct buffer_head *bh; + struct page *super_page; struct btrfs_super_block *disk_super; u64 devid; int ret; @@ -622,17 +619,17 @@ static int btrfs_open_one_device(struct btrfs_fs_devices *fs_devices, return -EINVAL; ret = btrfs_get_bdev_and_sb(device->name->str, flags, holder, 1, - &bdev, &bh); + &bdev, &super_page); if (ret) return ret; - disk_super = (struct btrfs_super_block *)bh->b_data; + disk_super = kmap(super_page); devid = btrfs_stack_device_id(&disk_super->dev_item); if (devid != device->devid) - goto error_brelse; + goto error_free_page; if (memcmp(device->uuid, disk_super->dev_item.uuid, BTRFS_UUID_SIZE)) - goto error_brelse; + goto error_free_page; device->generation = btrfs_super_generation(disk_super); @@ -641,7 +638,7 @@ static int btrfs_open_one_device(struct btrfs_fs_devices *fs_devices, BTRFS_FEATURE_INCOMPAT_METADATA_UUID) { pr_err( "BTRFS: Invalid seeding and uuid-changed device detected\n"); - goto error_brelse; + goto error_free_page; } clear_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state); @@ -667,12 +664,14 @@ static int btrfs_open_one_device(struct btrfs_fs_devices *fs_devices, fs_devices->rw_devices++; list_add_tail(&device->dev_alloc_list, &fs_devices->alloc_list); } - brelse(bh); + kunmap(super_page); + put_page(super_page); return 0; -error_brelse: - brelse(bh); +error_free_page: + kunmap(super_page); + put_page(super_page); blkdev_put(bdev, flags); return -EINVAL; @@ -2209,14 +2208,15 @@ static struct btrfs_device *btrfs_find_device_by_path( u64 devid; u8 *dev_uuid; struct block_device *bdev; - struct buffer_head *bh; + struct page *super_page; struct btrfs_device *device; ret = btrfs_get_bdev_and_sb(device_path, FMODE_READ, - fs_info->bdev_holder, 0, &bdev, &bh); + fs_info->bdev_holder, 0, &bdev, + &super_page); if (ret) return ERR_PTR(ret); - disk_super = (struct btrfs_super_block *)bh->b_data; + disk_super = kmap(super_page); devid = btrfs_stack_device_id(&disk_super->dev_item); dev_uuid = disk_super->dev_item.uuid; if (btrfs_fs_incompat(fs_info, METADATA_UUID)) @@ -2226,7 +2226,8 @@ static struct btrfs_device *btrfs_find_device_by_path( device = btrfs_find_device(fs_info->fs_devices, devid, dev_uuid, disk_super->fsid, true); - brelse(bh); + kunmap(super_page); + put_page(super_page); if (!device) device = ERR_PTR(-ENOENT); blkdev_put(bdev, FMODE_READ); @@ -7319,25 +7320,40 @@ int btrfs_get_dev_stats(struct btrfs_fs_info *fs_info, void btrfs_scratch_superblocks(struct block_device *bdev, const char *device_path) { - struct buffer_head *bh; + struct bio_vec bio_vec; + struct bio bio; struct btrfs_super_block *disk_super; int copy_num; if (!bdev) return; + bio_init(&bio, &bio_vec, 1); for (copy_num = 0; copy_num < BTRFS_SUPER_MIRROR_MAX; copy_num++) { + u64 bytenr = btrfs_sb_offset(copy_num); + struct page *page; - if (btrfs_read_dev_one_super(bdev, copy_num, &bh)) + if (btrfs_read_dev_one_super(bdev, copy_num, &page)) continue; - disk_super = (struct btrfs_super_block *)bh->b_data; + disk_super = kmap(page) + offset_in_page(bytenr); memset(&disk_super->magic, 0, sizeof(disk_super->magic)); - set_buffer_dirty(bh); - sync_dirty_buffer(bh); - brelse(bh); + + bio.bi_iter.bi_sector = bytenr >> SECTOR_SHIFT; + bio_set_dev(&bio, bdev); + bio.bi_opf = REQ_OP_WRITE; + bio_add_page(&bio, page, BTRFS_SUPER_INFO_SIZE, + offset_in_page(bytenr)); + + lock_page(page); + submit_bio_wait(&bio); + unlock_page(page); + kunmap(page); + put_page(page); + bio_reset(&bio); + } /* Notify udev that device has changed */ diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 690d4f5a0653..3b8eb2a14960 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -17,8 +17,6 @@ extern struct mutex uuid_mutex; #define BTRFS_STRIPE_LEN SZ_64K -struct buffer_head; - struct btrfs_io_geometry { /* remaining bytes before crossing a stripe */ u64 len; From patchwork Mon Jan 27 15:59:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Thumshirn X-Patchwork-Id: 11352845 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 63C6B1398 for ; Mon, 27 Jan 2020 15:59:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 38BB622527 for ; Mon, 27 Jan 2020 15:59:41 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=wdc.com header.i=@wdc.com header.b="QIZluVQj" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729600AbgA0P7k (ORCPT ); Mon, 27 Jan 2020 10:59:40 -0500 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:39167 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729583AbgA0P7j (ORCPT ); Mon, 27 Jan 2020 10:59:39 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1580140780; x=1611676780; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=bRsbLRlcNrPhAoMuuLO7/xeRNDuKb4NYHXoGXWNn/34=; b=QIZluVQjxxYyH0LrljPodBFBDautLy1dqHyP/CuK+0zNyclLG6P/bksu nfet+/u2G+AsoET2EqHnYojpfgLb3MPIfYcm8DsyUx+itx9IZc7M6EjOP 5XnyhOQa4y2yHWh/LzsWNCcbWNdzyBZawKSU49u32tPZ8eUz460KXrTnT DkxqbhG37IjBqU/FIcQjZ7YViboFeGORr/yLfyAYm5pTa9gAs9r7Q2Gxc wsIKEwjx5H3JRYzcyTNzmXOwDHqVAnLiVCWH+aoxQEbOE2zecXWefDtyj zSYIvZTAxuCpO8pLcplB5jm7p57WXCYFkEu0yqrf5Zp+w74dWH3sC9VT4 Q==; IronPort-SDR: f5lF2JsQyO9va1+e+nB0TPYuVBfvSKVmSSfVoveNKyGCfUj9jHgRclQzeFydOd/qh/ebTCTpdf 9x4cvULejQOFy8ptU/iqtf5NtWb08NvCsw39Hx577CmhlP93RArnMBqzXv0C3ggieatEdd+PNM DpKj7dTS6dxivMfiUN8+cMWvycuX/y2po4bZiDzNePDhcPefhpRHVBakBnb8KBucAuWgg4zXh6 685e0dqYq8mxY8uebT5tGb7WtohgLP/zXet4oImgqfqv3Lc2Ah20/cWtYJ85aIzzRR0EYk7Ge4 I3w= X-IronPort-AV: E=Sophos;i="5.70,370,1574092800"; d="scan'208";a="132851975" Received: from uls-op-cesaip01.wdc.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 27 Jan 2020 23:59:39 +0800 IronPort-SDR: 4xQ67mHFmWFuzzCE4DX/lZS9LIcYxw6fYlmP2+IVvdqg3dZk7ir9YPXfnwTylc54muAvzusWpk QRwFp4OYqn9Z8ucJciGsffo5PzZz6qCQAHh4CJT+vbMzNn5oalJV3qtYT3ug/kuk7gt+pKeye4 6m4gcmSUSJ2AuypnclH/5yNtpVL4FNExe8KtWNHOdI5FEu/8iD+Ak5rjcAt68SNB6dTEG5K9Kc Qx8YrsIzGbOfL3VojWcgtRm6GtHy6N35L/tJLAOWhjUFs3CtV9OnU1x+lMHzcoepwxEBHM1q20 colQgXQWrE6VbsQ9PG/ptG46 Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep01.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Jan 2020 07:52:54 -0800 IronPort-SDR: RZHNdE6ILT5FTq+QFzegyOmbPXYYtmnlcqjO2in1hPmCygK57RGU8KLkpIcJQqWLR7koMPOkWh 6yFR0aSGGMa+MASEQ8pZsppuGaXynFOIZZrU3YtuZbWomLo5ROfslDS6DRIGIx/Xo5C3EnDYpm QWXz5Wo/cdA3jomuq0PUdUwzU+lMYqNtavLoRWN7D9BH8c54DTTeRPSBz/QllCNbCQMYw50NOF H/8LjZqjZHmV/X3zBGT9KyNq90s2FqSIHWlPmHt5uLodRzM5KnbFmmwJIgwAIya+YUmqmGlQkb 4X0= WDCIronportException: Internal Received: from unknown (HELO redsun60.ssa.fujisawa.hgst.com) ([10.149.66.36]) by uls-op-cesaip02.wdc.com with ESMTP; 27 Jan 2020 07:59:38 -0800 From: Johannes Thumshirn To: David Sterba Cc: Nikolay Borisov , "linux-btrfs @ vger . kernel . org" , Johannes Thumshirn , Josef Bacik Subject: [PATCH v3 2/5] btrfs: remove use of buffer_heads from superblock writeout Date: Tue, 28 Jan 2020 00:59:28 +0900 Message-Id: <20200127155931.10818-3-johannes.thumshirn@wdc.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200127155931.10818-1-johannes.thumshirn@wdc.com> References: <20200127155931.10818-1-johannes.thumshirn@wdc.com> MIME-Version: 1.0 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org Similar to the superblock read path, change the write path to using BIOs and pages instead of buffer_heads. This allows us to skip over the buffer_head code, for writing the superblock to disk. This is based on a patch originally authored by Nikolay Borisov. Co-developed-by: Nikolay Borisov Signed-off-by: Nikolay Borisov Signed-off-by: Johannes Thumshirn Reviewed-by: Nikolay Borisov Reviewed-by: Josef Bacik --- Changes to v2: - Don't use bi_set_op_attrs() (David) Changes to v1: - Remove left-over buffer_head.h include (David) --- fs/btrfs/disk-io.c | 111 ++++++++++++++++++++++++++------------------- 1 file changed, 64 insertions(+), 47 deletions(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 1f30b234ac07..c88bd6bbbf66 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -3360,25 +3359,33 @@ int __cold open_ctree(struct super_block *sb, } ALLOW_ERROR_INJECTION(open_ctree, ERRNO); -static void btrfs_end_buffer_write_sync(struct buffer_head *bh, int uptodate) +static void btrfs_end_super_write(struct bio *bio) { - if (uptodate) { - set_buffer_uptodate(bh); - } else { - struct btrfs_device *device = (struct btrfs_device *) - bh->b_private; - - btrfs_warn_rl_in_rcu(device->fs_info, - "lost page write due to IO error on %s", - rcu_str_deref(device->name)); - /* note, we don't set_buffer_write_io_error because we have - * our own ways of dealing with the IO errors - */ - clear_buffer_uptodate(bh); - btrfs_dev_stat_inc_and_print(device, BTRFS_DEV_STAT_WRITE_ERRS); + struct btrfs_device *device = bio->bi_private; + struct bio_vec *bvec; + struct bvec_iter_all iter_all; + struct page *page; + + bio_for_each_segment_all(bvec, bio, iter_all) { + page = bvec->bv_page; + + if (blk_status_to_errno(bio->bi_status)) { + btrfs_warn_rl_in_rcu(device->fs_info, + "lost page write due to IO error on %s", + rcu_str_deref(device->name)); + ClearPageUptodate(page); + SetPageError(page); + btrfs_dev_stat_inc_and_print(device, + BTRFS_DEV_STAT_WRITE_ERRS); + } else { + SetPageUptodate(page); + } + + put_page(page); + unlock_page(page); } - unlock_buffer(bh); - put_bh(bh); + + bio_put(bio); } int btrfs_read_dev_one_super(struct block_device *bdev, int copy_num, @@ -3477,16 +3484,16 @@ int btrfs_read_dev_super(struct block_device *bdev, struct page **page) * the expected device size at commit time. Note that max_mirrors must be * same for write and wait phases. * - * Return number of errors when buffer head is not found or submission fails. + * Return number of errors when page is not found or submission fails. */ static int write_dev_supers(struct btrfs_device *device, struct btrfs_super_block *sb, int max_mirrors) { struct btrfs_fs_info *fs_info = device->fs_info; + struct address_space *mapping = device->bdev->bd_inode->i_mapping; SHASH_DESC_ON_STACK(shash, fs_info->csum_shash); - struct buffer_head *bh; + gfp_t gfp_mask; int i; - int ret; int errors = 0; u64 bytenr; int op_flags; @@ -3496,7 +3503,13 @@ static int write_dev_supers(struct btrfs_device *device, shash->tfm = fs_info->csum_shash; + gfp_mask = mapping_gfp_constraint(mapping, ~__GFP_FS) | __GFP_NOFAIL; + for (i = 0; i < max_mirrors; i++) { + struct page *page; + struct bio *bio; + u8 *ptr; + bytenr = btrfs_sb_offset(i); if (bytenr + BTRFS_SUPER_INFO_SIZE >= device->commit_total_bytes) @@ -3509,26 +3522,22 @@ static int write_dev_supers(struct btrfs_device *device, BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE); crypto_shash_final(shash, sb->csum); - /* One reference for us, and we leave it for the caller */ - bh = __getblk(device->bdev, bytenr / BTRFS_BDEV_BLOCKSIZE, - BTRFS_SUPER_INFO_SIZE); - if (!bh) { + page = find_or_create_page(mapping, bytenr >> PAGE_SHIFT, + gfp_mask); + if (!page) { btrfs_err(device->fs_info, - "couldn't get super buffer head for bytenr %llu", + "couldn't get superblock page for bytenr %llu", bytenr); errors++; continue; } - memcpy(bh->b_data, sb, BTRFS_SUPER_INFO_SIZE); + /* Bump the refcount for wait_dev_supers() */ + get_page(page); - /* one reference for submit_bh */ - get_bh(bh); - - set_buffer_uptodate(bh); - lock_buffer(bh); - bh->b_end_io = btrfs_end_buffer_write_sync; - bh->b_private = device; + ptr = kmap(page); + memcpy(ptr, sb, BTRFS_SUPER_INFO_SIZE); + kunmap(page); /* * we fua the first super. The others we allow @@ -3537,9 +3546,17 @@ static int write_dev_supers(struct btrfs_device *device, op_flags = REQ_SYNC | REQ_META | REQ_PRIO; if (i == 0 && !btrfs_test_opt(device->fs_info, NOBARRIER)) op_flags |= REQ_FUA; - ret = btrfsic_submit_bh(REQ_OP_WRITE, op_flags, bh); - if (ret) - errors++; + + bio = bio_alloc(gfp_mask, 1); + bio_set_dev(bio, device->bdev); + bio->bi_iter.bi_sector = bytenr >> SECTOR_SHIFT; + bio->bi_private = device; + bio->bi_end_io = btrfs_end_super_write; + bio_add_page(bio, page, BTRFS_SUPER_INFO_SIZE, + offset_in_page(bytenr)); + + bio->bi_opf = REQ_OP_WRITE | op_flags; + btrfsic_submit_bio(bio); } return errors < i ? 0 : -1; } @@ -3548,12 +3565,11 @@ static int write_dev_supers(struct btrfs_device *device, * Wait for write completion of superblocks done by write_dev_supers, * @max_mirrors same for write and wait phases. * - * Return number of errors when buffer head is not found or not marked up to + * Return number of errors when page is not found or not marked up to * date. */ static int wait_dev_supers(struct btrfs_device *device, int max_mirrors) { - struct buffer_head *bh; int i; int errors = 0; bool primary_failed = false; @@ -3563,32 +3579,33 @@ static int wait_dev_supers(struct btrfs_device *device, int max_mirrors) max_mirrors = BTRFS_SUPER_MIRROR_MAX; for (i = 0; i < max_mirrors; i++) { + struct page *page; + bytenr = btrfs_sb_offset(i); if (bytenr + BTRFS_SUPER_INFO_SIZE >= device->commit_total_bytes) break; - bh = __find_get_block(device->bdev, - bytenr / BTRFS_BDEV_BLOCKSIZE, - BTRFS_SUPER_INFO_SIZE); - if (!bh) { + page = find_get_page(device->bdev->bd_inode->i_mapping, + bytenr >> PAGE_SHIFT); + if (!page) { errors++; if (i == 0) primary_failed = true; continue; } - wait_on_buffer(bh); - if (!buffer_uptodate(bh)) { + wait_on_page_locked(page); + if (PageError(page)) { errors++; if (i == 0) primary_failed = true; } /* drop our reference */ - brelse(bh); + put_page(page); /* drop the reference from the writing run */ - brelse(bh); + put_page(page); } /* log error, force error return */ From patchwork Mon Jan 27 15:59:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Thumshirn X-Patchwork-Id: 11352847 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2E616159A for ; Mon, 27 Jan 2020 15:59:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0D3A522527 for ; Mon, 27 Jan 2020 15:59:42 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=wdc.com header.i=@wdc.com header.b="A0GMGudS" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729614AbgA0P7l (ORCPT ); Mon, 27 Jan 2020 10:59:41 -0500 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:39169 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729598AbgA0P7k (ORCPT ); Mon, 27 Jan 2020 10:59:40 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1580140781; x=1611676781; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=DY2WAUOAB3R4OVQ1t9StJaVgz7kaMPPbDphATbQMRVE=; b=A0GMGudSNqeBrzuZJkZdRYeavJZ665TgWg/tzHw7xLVxiGh4XIB0kB8f UQhQLzO4SMtZTISqV5JLFMEmpvfXNYn3FRKdj6rg6LLu78ETTrKSzPjp5 zk4ckQlJB1C4KSOp0LjqXi6ahthLSDnrWbEjyjKQ+FEYharhSpLzX/m83 94NpQScWT6A93aBtTZ+oRiK9Jhppcm5WnZi+esVT/vyohW1DJku6GDOx9 xeHLfUWNFTsU7mMNPwt1k9StUlmgHa6oSevYZO0YPGL9B8VoPvgs1eciv fLx4A9QIUIVvx+1Rv1OT6xDuBNTAevU1MNrpq6htjo9bTjaTdACRo564C w==; IronPort-SDR: 4AYFCiT5t6O5gGS5Ql6jkQChAdaef994mewbhRyGiexVQYT9BRGf8BELConCYUDA5fwkE1hurR S6NHZQKCvPDvRWSCHPaPLu1eec2tPfG3NZFUEZrxkCG6B4DiQKvGfBBQsZBJy9gFEZ//esmXW3 jjiFPbbt+AcgFIkOjSSPKHHU9pWDb+Nhn4IOjAMr7TnI9AjAB8Bkuhjy8XvgEktPYCqLd7r5UH Uv7p5N/Thj9kiIxzIwsp3OnZxMoLhAfhKDX/WhJM47ZU/rhwG8Gttb+LPUw31D1lT96fOqa1MP b4Q= X-IronPort-AV: E=Sophos;i="5.70,370,1574092800"; d="scan'208";a="132851977" Received: from uls-op-cesaip01.wdc.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 27 Jan 2020 23:59:40 +0800 IronPort-SDR: 3ntxeP7sZPJ9in/1nHkUyU+681fvweowUMF6Hm5j7Aj3+5wfXdc4HhNh/G425kJWnZRlS5jEZg ZeLNFfUM0I5EClWoPMo+t9qvUd91cQXT5j76j6uvnpK9htiyZO5rlD26cEQ5vYX3jtKBp0h38B d5Z1Crne0OCbUQYT564SCHkSHrUbfuslc+dIqHUJE1zjPnHz9nO2K99WkUPK7f/aSgreEb/BZY 89cOR3LpUGZG+K7qkI3ROeWSRDR2771B8AGhonR5ipgZxDoiaIDVob/v6171nWkJyX8dkl8DVm f78JyzVnv1o48tgYAiGDyLwb Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep01.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Jan 2020 07:52:55 -0800 IronPort-SDR: SGRcN3s3h7iI6KV9gNzqQUJcpEoRO65+Gh/6s48cYYOxe93wsGPdMKgBGXD63ZJKoQl0tbmGa0 no7WQWB2Ec1ocR3OH/nf20FGZlbLjVnOBGZiWk6TUJG8m4h2fumMmXTrAVmKB3ArF91Ssomg5r Zl3HBDOei5GAqfPQTKMCmYBXWXEJ9eMvmT8tylgqk6REdwvLlgpX0gbl9iS8rJ0eGWAg5CkeuL 8tLsyml3P+n/4CE/WGvlBYsX4L1X2BpldQM0PAk6bPeBYc1F9B8uhgoS9BgJdS3OWr4zdZPt6G Lw0= WDCIronportException: Internal Received: from unknown (HELO redsun60.ssa.fujisawa.hgst.com) ([10.149.66.36]) by uls-op-cesaip02.wdc.com with ESMTP; 27 Jan 2020 07:59:39 -0800 From: Johannes Thumshirn To: David Sterba Cc: Nikolay Borisov , "linux-btrfs @ vger . kernel . org" , Johannes Thumshirn , Josef Bacik Subject: [PATCH v3 3/5] btrfs: remove btrfsic_submit_bh() Date: Tue, 28 Jan 2020 00:59:29 +0900 Message-Id: <20200127155931.10818-4-johannes.thumshirn@wdc.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200127155931.10818-1-johannes.thumshirn@wdc.com> References: <20200127155931.10818-1-johannes.thumshirn@wdc.com> MIME-Version: 1.0 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org Now that the last use of btrfsic_submit_bh() is gone, remove the function as well. Signed-off-by: Johannes Thumshirn Reviewed-by: Nikolay Borisov Reviewed-by: Josef Bacik --- fs/btrfs/check-integrity.c | 57 -------------------------------------- fs/btrfs/check-integrity.h | 2 -- 2 files changed, 59 deletions(-) diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c index a0ce69f2d27c..e7507985435e 100644 --- a/fs/btrfs/check-integrity.c +++ b/fs/btrfs/check-integrity.c @@ -2730,63 +2730,6 @@ static struct btrfsic_dev_state *btrfsic_dev_state_lookup(dev_t dev) &btrfsic_dev_state_hashtable); } -int btrfsic_submit_bh(int op, int op_flags, struct buffer_head *bh) -{ - struct btrfsic_dev_state *dev_state; - - if (!btrfsic_is_initialized) - return submit_bh(op, op_flags, bh); - - mutex_lock(&btrfsic_mutex); - /* since btrfsic_submit_bh() might also be called before - * btrfsic_mount(), this might return NULL */ - dev_state = btrfsic_dev_state_lookup(bh->b_bdev->bd_dev); - - /* Only called to write the superblock (incl. FLUSH/FUA) */ - if (NULL != dev_state && - (op == REQ_OP_WRITE) && bh->b_size > 0) { - u64 dev_bytenr; - - dev_bytenr = BTRFS_BDEV_BLOCKSIZE * bh->b_blocknr; - if (dev_state->state->print_mask & - BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH) - pr_info("submit_bh(op=0x%x,0x%x, blocknr=%llu (bytenr %llu), size=%zu, data=%p, bdev=%p)\n", - op, op_flags, (unsigned long long)bh->b_blocknr, - dev_bytenr, bh->b_size, bh->b_data, bh->b_bdev); - btrfsic_process_written_block(dev_state, dev_bytenr, - &bh->b_data, 1, NULL, - NULL, bh, op_flags); - } else if (NULL != dev_state && (op_flags & REQ_PREFLUSH)) { - if (dev_state->state->print_mask & - BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH) - pr_info("submit_bh(op=0x%x,0x%x FLUSH, bdev=%p)\n", - op, op_flags, bh->b_bdev); - if (!dev_state->dummy_block_for_bio_bh_flush.is_iodone) { - if ((dev_state->state->print_mask & - (BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH | - BTRFSIC_PRINT_MASK_VERBOSE))) - pr_info("btrfsic_submit_bh(%s) with FLUSH but dummy block already in use (ignored)!\n", - dev_state->name); - } else { - struct btrfsic_block *const block = - &dev_state->dummy_block_for_bio_bh_flush; - - block->is_iodone = 0; - block->never_written = 0; - block->iodone_w_error = 0; - block->flush_gen = dev_state->last_flush_gen + 1; - block->submit_bio_bh_rw = op_flags; - block->orig_bio_bh_private = bh->b_private; - block->orig_bio_bh_end_io.bh = bh->b_end_io; - block->next_in_same_bio = NULL; - bh->b_private = block; - bh->b_end_io = btrfsic_bh_end_io; - } - } - mutex_unlock(&btrfsic_mutex); - return submit_bh(op, op_flags, bh); -} - static void __btrfsic_submit_bio(struct bio *bio) { struct btrfsic_dev_state *dev_state; diff --git a/fs/btrfs/check-integrity.h b/fs/btrfs/check-integrity.h index 9bf4359cc44c..bcc730a06cb5 100644 --- a/fs/btrfs/check-integrity.h +++ b/fs/btrfs/check-integrity.h @@ -7,11 +7,9 @@ #define BTRFS_CHECK_INTEGRITY_H #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY -int btrfsic_submit_bh(int op, int op_flags, struct buffer_head *bh); void btrfsic_submit_bio(struct bio *bio); int btrfsic_submit_bio_wait(struct bio *bio); #else -#define btrfsic_submit_bh submit_bh #define btrfsic_submit_bio submit_bio #define btrfsic_submit_bio_wait submit_bio_wait #endif From patchwork Mon Jan 27 15:59:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Thumshirn X-Patchwork-Id: 11352849 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1C85E159A for ; Mon, 27 Jan 2020 15:59:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E59DE22527 for ; Mon, 27 Jan 2020 15:59:42 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=wdc.com header.i=@wdc.com header.b="GApss/gi" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729640AbgA0P7m (ORCPT ); Mon, 27 Jan 2020 10:59:42 -0500 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:39169 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729636AbgA0P7l (ORCPT ); Mon, 27 Jan 2020 10:59:41 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1580140782; x=1611676782; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=4XmU7DnFA5F5WMG30kokJMLVAtAX/4N6K9p/+pblNvo=; b=GApss/giIq6nVCJIcRtzfkhFhB/hhvQeoKIWSlJuB54N7S74ztq9y4Oc +wJDkG32FplrYyqa1KDQfhkC4PIR5Ou8gWB4JlPqib5R4TaP3CGIyvPIa 4cUTcwT2CErlXqCWwlXizRIG/f2tOa+4N7/BqItTqDveLjibSzkCEzvVZ kCdfG7dOiCEMBEBA5GGy3PavcAUwCPz6MSPcXw0t82Z3KC1c7tHHhFqEu IbPUN3HnTW8D/4nXEly9CamZ4jRQLn4pFuKbeeMR9iKB5c5LdpzEbYckH pOLWtCsofEzKU0xiCwAcUNRybuOXVtkZ6PTt9fGD5O92V4Kq9bSWz66C4 w==; IronPort-SDR: Z/KTmvMftIMGmEGjDstDw8lqvTxq0G3dzOoL1RozpR9bGa2Nu9FQjVbuthv3YdIvcmRv56vWSF gT//oMhWaITCGQH1A3HdZRdynJJsNRSEbQK8qc55N4vr5vEsJmfIlgVi7R+oUvvBqMbSzBL6dA SGWE1UwBVHmH8nOKNJYEOEbKC3U3ZoYdTv+zT9wHm9vw1XWfxt6kOarPxqMO0MjVJ1YUh2AnKu mzesg0CamwYdUIkincTA/FCT7F6/707LO2tjFVFFzXymUFRbkjghGCPQn1VV4+/FkoQMaFE282 Hz8= X-IronPort-AV: E=Sophos;i="5.70,370,1574092800"; d="scan'208";a="132851979" Received: from uls-op-cesaip01.wdc.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 27 Jan 2020 23:59:42 +0800 IronPort-SDR: 0QhwMvyQcHDTHi+HeFcs/5aB6KSa+AGQcUBj3g/skbvEP+p8iOF9Q2c8lSofsJCdSaMrGFqpLi yZ4cxZssluRINTVxURCS6JjBrlkKy2dEsXxNUf01lX6QWDg/32Q7fz0FlGw3yy3OOpX4XU8sPm iqWGdE0R9svzmuGsUQyYI45cPBXwu107rNKrxgf/3iZ3cjgZd7VUU3gMdN0/N/sddwc4/i+BMQ jeLSW4TNhwn5ai5ywDaG/5BXcfgEAO2UdX1HfP/BHuO2IPObIHRH5OnxHBiTvD8qA+1LPJ3vYG A58bV4uVdNq7J4u3aL61DQw/ Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep01.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Jan 2020 07:52:56 -0800 IronPort-SDR: yDp/UWhD88DhoxxlY5bhSnAGEJ/0vgf4wNtEK/q8rurllFBf1kr9aJCO6IB1FFrpwxaqi2xT8C h6ILWWT9A0k0gaMjS5s5y84Tbn+EfQSALdRd6cp/4JWTT3r1XxnzvvblM5nTyzkofEta0qco6W FNFl62QzxNa46WdMw3i/FZQMbCC0gHQMyhvTqUrXCiphyPsdETK3KXTAzMxZ0h3Lbbmuy8pqaS pNIKUWsTDvi0S1r01yFREewKj91+/kNPZUmBxF9u+dV1blvFXG2g7kZJxIRCKXWlDFOPiMDY1Y Ta0= WDCIronportException: Internal Received: from unknown (HELO redsun60.ssa.fujisawa.hgst.com) ([10.149.66.36]) by uls-op-cesaip02.wdc.com with ESMTP; 27 Jan 2020 07:59:40 -0800 From: Johannes Thumshirn To: David Sterba Cc: Nikolay Borisov , "linux-btrfs @ vger . kernel . org" , Johannes Thumshirn , Josef Bacik Subject: [PATCH v3 4/5] btrfs: remove buffer_heads from btrfsic_process_written_block() Date: Tue, 28 Jan 2020 00:59:30 +0900 Message-Id: <20200127155931.10818-5-johannes.thumshirn@wdc.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200127155931.10818-1-johannes.thumshirn@wdc.com> References: <20200127155931.10818-1-johannes.thumshirn@wdc.com> MIME-Version: 1.0 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org Now that the last caller of btrfsic_process_written_block() with buffer_heads is gone, remove the buffer_head processing path from it as well. Signed-off-by: Johannes Thumshirn Reviewed-by: Josef Bacik --- fs/btrfs/check-integrity.c | 103 +++++++++---------------------------- 1 file changed, 25 insertions(+), 78 deletions(-) diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c index e7507985435e..4f6db2fe482a 100644 --- a/fs/btrfs/check-integrity.c +++ b/fs/btrfs/check-integrity.c @@ -152,11 +152,8 @@ struct btrfsic_block { struct list_head ref_to_list; /* list */ struct list_head ref_from_list; /* list */ struct btrfsic_block *next_in_same_bio; - void *orig_bio_bh_private; - union { - bio_end_io_t *bio; - bh_end_io_t *bh; - } orig_bio_bh_end_io; + void *orig_bio_private; + bio_end_io_t *orig_bio_end_io; int submit_bio_bh_rw; u64 flush_gen; /* only valid if !never_written */ }; @@ -325,14 +322,12 @@ static void btrfsic_process_written_block(struct btrfsic_dev_state *dev_state, u64 dev_bytenr, char **mapped_datav, unsigned int num_pages, struct bio *bio, int *bio_is_patched, - struct buffer_head *bh, int submit_bio_bh_rw); static int btrfsic_process_written_superblock( struct btrfsic_state *state, struct btrfsic_block *const block, struct btrfs_super_block *const super_hdr); static void btrfsic_bio_end_io(struct bio *bp); -static void btrfsic_bh_end_io(struct buffer_head *bh, int uptodate); static int btrfsic_is_block_ref_by_superblock(const struct btrfsic_state *state, const struct btrfsic_block *block, int recursion_level); @@ -399,8 +394,8 @@ static void btrfsic_block_init(struct btrfsic_block *b) b->never_written = 0; b->mirror_num = 0; b->next_in_same_bio = NULL; - b->orig_bio_bh_private = NULL; - b->orig_bio_bh_end_io.bio = NULL; + b->orig_bio_private = NULL; + b->orig_bio_end_io = NULL; INIT_LIST_HEAD(&b->collision_resolving_node); INIT_LIST_HEAD(&b->all_blocks_node); INIT_LIST_HEAD(&b->ref_to_list); @@ -1743,7 +1738,6 @@ static void btrfsic_process_written_block(struct btrfsic_dev_state *dev_state, u64 dev_bytenr, char **mapped_datav, unsigned int num_pages, struct bio *bio, int *bio_is_patched, - struct buffer_head *bh, int submit_bio_bh_rw) { int is_metadata; @@ -1902,9 +1896,9 @@ static void btrfsic_process_written_block(struct btrfsic_dev_state *dev_state, block->is_iodone = 0; BUG_ON(NULL == bio_is_patched); if (!*bio_is_patched) { - block->orig_bio_bh_private = + block->orig_bio_private = bio->bi_private; - block->orig_bio_bh_end_io.bio = + block->orig_bio_end_io = bio->bi_end_io; block->next_in_same_bio = NULL; bio->bi_private = block; @@ -1916,25 +1910,17 @@ static void btrfsic_process_written_block(struct btrfsic_dev_state *dev_state, bio->bi_private; BUG_ON(NULL == chained_block); - block->orig_bio_bh_private = - chained_block->orig_bio_bh_private; - block->orig_bio_bh_end_io.bio = - chained_block->orig_bio_bh_end_io. - bio; + block->orig_bio_private = + chained_block->orig_bio_private; + block->orig_bio_end_io = + chained_block->orig_bio_end_io; block->next_in_same_bio = chained_block; bio->bi_private = block; } - } else if (NULL != bh) { - block->is_iodone = 0; - block->orig_bio_bh_private = bh->b_private; - block->orig_bio_bh_end_io.bh = bh->b_end_io; - block->next_in_same_bio = NULL; - bh->b_private = block; - bh->b_end_io = btrfsic_bh_end_io; } else { block->is_iodone = 1; - block->orig_bio_bh_private = NULL; - block->orig_bio_bh_end_io.bio = NULL; + block->orig_bio_private = NULL; + block->orig_bio_end_io = NULL; block->next_in_same_bio = NULL; } } @@ -2042,8 +2028,8 @@ static void btrfsic_process_written_block(struct btrfsic_dev_state *dev_state, block->is_iodone = 0; BUG_ON(NULL == bio_is_patched); if (!*bio_is_patched) { - block->orig_bio_bh_private = bio->bi_private; - block->orig_bio_bh_end_io.bio = bio->bi_end_io; + block->orig_bio_private = bio->bi_private; + block->orig_bio_end_io = bio->bi_end_io; block->next_in_same_bio = NULL; bio->bi_private = block; bio->bi_end_io = btrfsic_bio_end_io; @@ -2054,24 +2040,17 @@ static void btrfsic_process_written_block(struct btrfsic_dev_state *dev_state, bio->bi_private; BUG_ON(NULL == chained_block); - block->orig_bio_bh_private = - chained_block->orig_bio_bh_private; - block->orig_bio_bh_end_io.bio = - chained_block->orig_bio_bh_end_io.bio; + block->orig_bio_private = + chained_block->orig_bio_private; + block->orig_bio_end_io = + chained_block->orig_bio_end_io; block->next_in_same_bio = chained_block; bio->bi_private = block; } - } else if (NULL != bh) { - block->is_iodone = 0; - block->orig_bio_bh_private = bh->b_private; - block->orig_bio_bh_end_io.bh = bh->b_end_io; - block->next_in_same_bio = NULL; - bh->b_private = block; - bh->b_end_io = btrfsic_bh_end_io; } else { block->is_iodone = 1; - block->orig_bio_bh_private = NULL; - block->orig_bio_bh_end_io.bio = NULL; + block->orig_bio_private = NULL; + block->orig_bio_end_io = NULL; block->next_in_same_bio = NULL; } if (state->print_mask & BTRFSIC_PRINT_MASK_VERBOSE) @@ -2112,8 +2091,8 @@ static void btrfsic_bio_end_io(struct bio *bp) iodone_w_error = 1; BUG_ON(NULL == block); - bp->bi_private = block->orig_bio_bh_private; - bp->bi_end_io = block->orig_bio_bh_end_io.bio; + bp->bi_private = block->orig_bio_private; + bp->bi_end_io = block->orig_bio_end_io; do { struct btrfsic_block *next_block; @@ -2146,38 +2125,6 @@ static void btrfsic_bio_end_io(struct bio *bp) bp->bi_end_io(bp); } -static void btrfsic_bh_end_io(struct buffer_head *bh, int uptodate) -{ - struct btrfsic_block *block = (struct btrfsic_block *)bh->b_private; - int iodone_w_error = !uptodate; - struct btrfsic_dev_state *dev_state; - - BUG_ON(NULL == block); - dev_state = block->dev_state; - if ((dev_state->state->print_mask & BTRFSIC_PRINT_MASK_END_IO_BIO_BH)) - pr_info("bh_end_io(error=%d) for %c @%llu (%s/%llu/%d)\n", - iodone_w_error, - btrfsic_get_block_type(dev_state->state, block), - block->logical_bytenr, block->dev_state->name, - block->dev_bytenr, block->mirror_num); - - block->iodone_w_error = iodone_w_error; - if (block->submit_bio_bh_rw & REQ_PREFLUSH) { - dev_state->last_flush_gen++; - if ((dev_state->state->print_mask & - BTRFSIC_PRINT_MASK_END_IO_BIO_BH)) - pr_info("bh_end_io() new %s flush_gen=%llu\n", - dev_state->name, dev_state->last_flush_gen); - } - if (block->submit_bio_bh_rw & REQ_FUA) - block->flush_gen = 0; /* FUA completed means block is on disk */ - - bh->b_private = block->orig_bio_bh_private; - bh->b_end_io = block->orig_bio_bh_end_io.bh; - block->is_iodone = 1; /* for FLUSH, this releases the block */ - bh->b_end_io(bh, uptodate); -} - static int btrfsic_process_written_superblock( struct btrfsic_state *state, struct btrfsic_block *const superblock, @@ -2781,7 +2728,7 @@ static void __btrfsic_submit_bio(struct bio *bio) btrfsic_process_written_block(dev_state, dev_bytenr, mapped_datav, segs, bio, &bio_is_patched, - NULL, bio->bi_opf); + bio->bi_opf); bio_for_each_segment(bvec, bio, iter) kunmap(bvec.bv_page); kfree(mapped_datav); @@ -2805,8 +2752,8 @@ static void __btrfsic_submit_bio(struct bio *bio) block->iodone_w_error = 0; block->flush_gen = dev_state->last_flush_gen + 1; block->submit_bio_bh_rw = bio->bi_opf; - block->orig_bio_bh_private = bio->bi_private; - block->orig_bio_bh_end_io.bio = bio->bi_end_io; + block->orig_bio_private = bio->bi_private; + block->orig_bio_end_io = bio->bi_end_io; block->next_in_same_bio = NULL; bio->bi_private = block; bio->bi_end_io = btrfsic_bio_end_io; From patchwork Mon Jan 27 15:59:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Thumshirn X-Patchwork-Id: 11352851 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 008651398 for ; Mon, 27 Jan 2020 15:59:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D2954206D5 for ; Mon, 27 Jan 2020 15:59:44 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=wdc.com header.i=@wdc.com header.b="Ce+1BBpp" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729657AbgA0P7o (ORCPT ); Mon, 27 Jan 2020 10:59:44 -0500 Received: from esa3.hgst.iphmx.com ([216.71.153.141]:39169 "EHLO esa3.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729636AbgA0P7m (ORCPT ); Mon, 27 Jan 2020 10:59:42 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1580140783; x=1611676783; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=DIAsw2fAS2f6f2JmXgH9y7tsImjmph29un5wo68AgVg=; b=Ce+1BBppVcYezwQ5GpeCFFBomuW1REI3kerIU37Hd9YqeYYsd7EcT/PI TXxryqD4G+0uEYn6yso+RdNp8asH7ENvoTBVhx/aR00USzms96yJaitdW WTR2bOMS2iYMTRan30LZF5sB9eJCJpiYBswC26IXH3p0X/dcVLw9QaGmC EvnizXdTNTSgFqaKohd7fFYz9kBYgC9MFu3IjuvIoDs8xHR0KhWB/rzG5 ZNzh0eJ+VGXD22iHtDp3gFiWnRducNwF+qehjCE4QuDNnPObFmTCcEHl8 mHEPxkFenw5q/Ce6UxeTQ8/BUP5WJVNAHnqQCAcbWYKVYq65T20QDGglc Q==; IronPort-SDR: yq60XzxajenzZVVhVbDzgZzLgh1rDJoQuR+0QLCn3B14vn/KPSmHL9nbgun9VUvJEh52kfACid OjPhhxb9Jzo6MZzFfLz1eJvOBsI+Vwo8L6aXyTFEG3HPhSeAzmjWdorPEZptGXD+ZlADtvJieb dutvsUcEaHZBg/9s9YlMAw1NSAQuNlUi/+eIu4OQlCkUmcOUvRp7iq4cf2RvbroTtiEC9hgmjp C1EwLGyccjR2nxAdD7MYexA/Or+KMJTxKjUKy/flt57WOk/zh597c8i+wRvVEoG2rlp9Jv+CV3 zU0= X-IronPort-AV: E=Sophos;i="5.70,370,1574092800"; d="scan'208";a="132851981" Received: from uls-op-cesaip01.wdc.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 27 Jan 2020 23:59:43 +0800 IronPort-SDR: 5MjqyjqPxsb5GX/OWQKPTkZHrARQaeV+rKoKHTK6A47yED9/976iaR0zdrCQE8YBDwORTFPFPn EPngQ6YilJLZGka7SHJ9WWld9Ye5t+xTlLbEAbvMRirJzr6MNWaPIM6UIPx0I5KO1Y6no9R+4l 6n+p892bXo8yvP3jLUQ567q23k9r/RWNf5I7ik7IG2zI8cuUk5k/bhZ3PpKGUQpsXV2TblZwWd Kvxz2beSUcvq9L2zVEKMmtScPMtEoFc8LDDSvKg2MkKGoWi+3G1VnzWsKaAs2E3OovGPrZ+0Fw az9g0JdOEB4s1Zf93rnXL2cH Received: from uls-op-cesaip02.wdc.com ([10.248.3.37]) by uls-op-cesaep01.wdc.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Jan 2020 07:52:57 -0800 IronPort-SDR: tBQ3b6GePfYNuU3nYwmHhtlMan5gKZ8XY2LBSYhyixWP1EFtOwaEO5AFkJB6Ka8Bkc0zdopGH3 Mtw9O3G9Yl7HLZ2/oEfS5mcHXbRKeWsflSIiSRgVkKXNF18HpYf7Wa/X5YN5yTHOfhD66LtC08 qtdDOCIDln91Z+u+gN0wjiURQxETqVCBl2xkzJviGTh52iutXGHtMWu55fhQdY0yDb0eWFkaa9 43isFpF3bI5zxTapaEzgbnMJRoyNhVI1ToWGG3pNbQKF9YntV5cfBt57SBl3TYNI1g8tbowa6g qa8= WDCIronportException: Internal Received: from unknown (HELO redsun60.ssa.fujisawa.hgst.com) ([10.149.66.36]) by uls-op-cesaip02.wdc.com with ESMTP; 27 Jan 2020 07:59:41 -0800 From: Johannes Thumshirn To: David Sterba Cc: Nikolay Borisov , "linux-btrfs @ vger . kernel . org" , Johannes Thumshirn , Josef Bacik Subject: [PATCH v3 5/5] btrfs: remove buffer_heads form superblock mirror integrity checking Date: Tue, 28 Jan 2020 00:59:31 +0900 Message-Id: <20200127155931.10818-6-johannes.thumshirn@wdc.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200127155931.10818-1-johannes.thumshirn@wdc.com> References: <20200127155931.10818-1-johannes.thumshirn@wdc.com> MIME-Version: 1.0 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org The integrity checking code for the superblock mirrors is the last remaining user of buffer_heads in BTRFS, change it to using plain BIOs as well. Signed-off-by: Johannes Thumshirn Reviewed-by: Josef Bacik --- Changes to v2: - Open-code kunmap() + put_page() (David) - Remove __GFP_NOFAIL from allocation (Josef) - Merge error paths (David) Changes to v1: - Convert from alloc_page() to find_or_create_page() --- fs/btrfs/check-integrity.c | 58 +++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c index 4f6db2fe482a..d6ab6d3ca413 100644 --- a/fs/btrfs/check-integrity.c +++ b/fs/btrfs/check-integrity.c @@ -77,7 +77,6 @@ #include #include -#include #include #include #include @@ -762,29 +761,48 @@ static int btrfsic_process_superblock_dev_mirror( struct btrfs_fs_info *fs_info = state->fs_info; struct btrfs_super_block *super_tmp; u64 dev_bytenr; - struct buffer_head *bh; struct btrfsic_block *superblock_tmp; int pass; struct block_device *const superblock_bdev = device->bdev; + struct page *page; + struct bio bio; + struct bio_vec bio_vec; + struct address_space *mapping = superblock_bdev->bd_inode->i_mapping; + gfp_t gfp_mask; + int ret; /* super block bytenr is always the unmapped device bytenr */ dev_bytenr = btrfs_sb_offset(superblock_mirror_num); if (dev_bytenr + BTRFS_SUPER_INFO_SIZE > device->commit_total_bytes) return -1; - bh = __bread(superblock_bdev, dev_bytenr / BTRFS_BDEV_BLOCKSIZE, - BTRFS_SUPER_INFO_SIZE); - if (NULL == bh) + + gfp_mask = mapping_gfp_constraint(mapping, ~__GFP_FS); + + page = find_or_create_page(mapping, dev_bytenr >> PAGE_SHIFT, gfp_mask); + if (!page) + return -1; + + bio_init(&bio, &bio_vec, 1); + bio.bi_iter.bi_sector = dev_bytenr >> SECTOR_SHIFT; + bio_set_dev(&bio, superblock_bdev); + bio_set_op_attrs(&bio, REQ_OP_READ, 0); + bio_add_page(&bio, page, BTRFS_SUPER_INFO_SIZE, 0); + + ret = submit_bio_wait(&bio); + if (ret) return -1; - super_tmp = (struct btrfs_super_block *) - (bh->b_data + (dev_bytenr & (BTRFS_BDEV_BLOCKSIZE - 1))); + + unlock_page(page); + + super_tmp = kmap(page); if (btrfs_super_bytenr(super_tmp) != dev_bytenr || btrfs_super_magic(super_tmp) != BTRFS_MAGIC || memcmp(device->uuid, super_tmp->dev_item.uuid, BTRFS_UUID_SIZE) || btrfs_super_nodesize(super_tmp) != state->metablock_size || btrfs_super_sectorsize(super_tmp) != state->datablock_size) { - brelse(bh); - return 0; + ret = 0; + goto out_unmap; } superblock_tmp = @@ -795,8 +813,8 @@ static int btrfsic_process_superblock_dev_mirror( superblock_tmp = btrfsic_block_alloc(); if (NULL == superblock_tmp) { pr_info("btrfsic: error, kmalloc failed!\n"); - brelse(bh); - return -1; + ret = -1; + goto out_unmap; } /* for superblock, only the dev_bytenr makes sense */ superblock_tmp->dev_bytenr = dev_bytenr; @@ -880,8 +898,8 @@ static int btrfsic_process_superblock_dev_mirror( mirror_num)) { pr_info("btrfsic: btrfsic_map_block(bytenr @%llu, mirror %d) failed!\n", next_bytenr, mirror_num); - brelse(bh); - return -1; + ret = -1; + goto out_unmap; } next_block = btrfsic_block_lookup_or_add( @@ -890,8 +908,8 @@ static int btrfsic_process_superblock_dev_mirror( mirror_num, NULL); if (NULL == next_block) { btrfsic_release_block_ctx(&tmp_next_block_ctx); - brelse(bh); - return -1; + ret = -1; + goto out_unmap; } next_block->disk_key = tmp_disk_key; @@ -902,16 +920,18 @@ static int btrfsic_process_superblock_dev_mirror( BTRFSIC_GENERATION_UNKNOWN); btrfsic_release_block_ctx(&tmp_next_block_ctx); if (NULL == l) { - brelse(bh); - return -1; + ret = -1; + goto out_unmap; } } } if (state->print_mask & BTRFSIC_PRINT_MASK_INITIAL_ALL_TREES) btrfsic_dump_tree_sub(state, superblock_tmp, 0); - brelse(bh); - return 0; +out_unmap: + kunmap(page); + put_page(page); + return ret; } static struct btrfsic_stack_frame *btrfsic_stack_frame_alloc(void)