On Wed, Feb 12, 2020 at 04:17:04PM +0900, Johannes Thumshirn wrote:
> @@ -762,29 +761,45 @@ 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;
> + 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)
> +
> + page = find_or_create_page(mapping, dev_bytenr >> PAGE_SHIFT, GFP_NOFS);
> + 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);
I beleve the same reasoning applies here regarding kmap, it's the bdev
mapping and we won't get a highmem 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 =