From: Yu Kuai <yuku...@huawei.com>

On the one hand covert to use folio while reading bdev inode, on the
other hand prevent to access bd_inode directly.

Signed-off-by: Yu Kuai <yuku...@huawei.com>
---
 fs/btrfs/disk-io.c | 71 +++++++++++++++++++++-------------------------
 fs/btrfs/volumes.c | 17 ++++++-----
 fs/btrfs/zoned.c   | 15 +++++-----
 3 files changed, 48 insertions(+), 55 deletions(-)

diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 401ea09ae4b8..c373806dc793 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -3620,28 +3620,24 @@ ALLOW_ERROR_INJECTION(open_ctree, ERRNO);
 static void btrfs_end_super_write(struct bio *bio)
 {
        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;
+       struct folio_iter fi;
 
+       bio_for_each_folio_all(fi, bio) {
                if (bio->bi_status) {
                        btrfs_warn_rl_in_rcu(device->fs_info,
                                "lost page write due to IO error on %s (%d)",
                                btrfs_dev_name(device),
                                blk_status_to_errno(bio->bi_status));
-                       ClearPageUptodate(page);
-                       SetPageError(page);
+                       folio_clear_uptodate(fi.folio);
+                       folio_set_error(fi.folio);
                        btrfs_dev_stat_inc_and_print(device,
                                                     BTRFS_DEV_STAT_WRITE_ERRS);
                } else {
-                       SetPageUptodate(page);
+                       folio_mark_uptodate(fi.folio);
                }
 
-               put_page(page);
-               unlock_page(page);
+               folio_put(fi.folio);
+               folio_unlock(fi.folio);
        }
 
        bio_put(bio);
@@ -3651,9 +3647,9 @@ struct btrfs_super_block *btrfs_read_dev_one_super(struct 
block_device *bdev,
                                                   int copy_num, bool 
drop_cache)
 {
        struct btrfs_super_block *super;
-       struct page *page;
+       struct folio *folio;
        u64 bytenr, bytenr_orig;
-       struct address_space *mapping = bdev->bd_inode->i_mapping;
+       unsigned int nofs_flag;
        int ret;
 
        bytenr_orig = btrfs_sb_offset(copy_num);
@@ -3674,16 +3670,17 @@ struct btrfs_super_block 
*btrfs_read_dev_one_super(struct block_device *bdev,
                 * Drop the page of the primary superblock, so later read will
                 * always read from the device.
                 */
-               invalidate_inode_pages2_range(mapping,
-                               bytenr >> PAGE_SHIFT,
+               invalidate_bdev_range(bdev, bytenr >> PAGE_SHIFT,
                                (bytenr + BTRFS_SUPER_INFO_SIZE) >> PAGE_SHIFT);
        }
 
-       page = read_cache_page_gfp(mapping, bytenr >> PAGE_SHIFT, GFP_NOFS);
-       if (IS_ERR(page))
-               return ERR_CAST(page);
+       nofs_flag = memalloc_nofs_save();
+       folio = bdev_read_folio(bdev, bytenr);
+       memalloc_nofs_restore(nofs_flag);
+       if (IS_ERR(folio))
+               return ERR_CAST(folio);
 
-       super = page_address(page);
+       super = folio_address(folio);
        if (btrfs_super_magic(super) != BTRFS_MAGIC) {
                btrfs_release_disk_super(super);
                return ERR_PTR(-ENODATA);
@@ -3740,7 +3737,6 @@ 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);
        int i;
        int errors = 0;
@@ -3753,7 +3749,7 @@ static int write_dev_supers(struct btrfs_device *device,
        shash->tfm = fs_info->csum_shash;
 
        for (i = 0; i < max_mirrors; i++) {
-               struct page *page;
+               struct folio *folio;
                struct bio *bio;
                struct btrfs_super_block *disk_super;
 
@@ -3778,9 +3774,10 @@ static int write_dev_supers(struct btrfs_device *device,
                                    BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE,
                                    sb->csum);
 
-               page = find_or_create_page(mapping, bytenr >> PAGE_SHIFT,
-                                          GFP_NOFS);
-               if (!page) {
+               folio = __bdev_get_folio(device->bdev, bytenr,
+                                        FGP_LOCK|FGP_ACCESSED|FGP_CREAT,
+                                        GFP_NOFS);
+               if (IS_ERR(folio)) {
                        btrfs_err(device->fs_info,
                            "couldn't get super block page for bytenr %llu",
                            bytenr);
@@ -3789,9 +3786,9 @@ static int write_dev_supers(struct btrfs_device *device,
                }
 
                /* Bump the refcount for wait_dev_supers() */
-               get_page(page);
+               folio_get(folio);
 
-               disk_super = page_address(page);
+               disk_super = folio_address(folio);
                memcpy(disk_super, sb, BTRFS_SUPER_INFO_SIZE);
 
                /*
@@ -3805,8 +3802,8 @@ static int write_dev_supers(struct btrfs_device *device,
                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_add_folio_nofail(bio, folio, BTRFS_SUPER_INFO_SIZE,
+                                    offset_in_folio(folio, bytenr));
 
                /*
                 * We FUA only the first super block.  The others we allow to
@@ -3842,7 +3839,7 @@ 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;
+               struct folio *folio;
 
                ret = btrfs_sb_log_location(device, i, READ, &bytenr);
                if (ret == -ENOENT) {
@@ -3857,27 +3854,23 @@ static int wait_dev_supers(struct btrfs_device *device, 
int max_mirrors)
                    device->commit_total_bytes)
                        break;
 
-               page = find_get_page(device->bdev->bd_inode->i_mapping,
-                                    bytenr >> PAGE_SHIFT);
-               if (!page) {
+               folio = __bdev_get_folio(device->bdev, bytenr, 0, 0);
+               if (!IS_ERR(folio)) {
                        errors++;
                        if (i == 0)
                                primary_failed = true;
                        continue;
                }
                /* Page is submitted locked and unlocked once the IO completes 
*/
-               wait_on_page_locked(page);
-               if (PageError(page)) {
+               folio_wait_locked(folio);
+               if (folio_test_error(folio)) {
                        errors++;
                        if (i == 0)
                                primary_failed = true;
                }
 
-               /* Drop our reference */
-               put_page(page);
-
-               /* Drop the reference from the writing run */
-               put_page(page);
+               /* Drop our reference and the reference from the writing run */
+               folio_put_refs(folio, 2);
        }
 
        /* log error, force error return */
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index c6f16625af51..b3538777683c 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -1230,16 +1230,16 @@ int btrfs_open_devices(struct btrfs_fs_devices 
*fs_devices,
 
 void btrfs_release_disk_super(struct btrfs_super_block *super)
 {
-       struct page *page = virt_to_page(super);
+       struct folio *folio = virt_to_folio(super);
 
-       put_page(page);
+       folio_put(folio);
 }
 
 static struct btrfs_super_block *btrfs_read_disk_super(struct block_device 
*bdev,
                                                       u64 bytenr, u64 
bytenr_orig)
 {
        struct btrfs_super_block *disk_super;
-       struct page *page;
+       struct folio *folio;
        void *p;
        pgoff_t index;
 
@@ -1257,15 +1257,14 @@ static struct btrfs_super_block 
*btrfs_read_disk_super(struct block_device *bdev
                return ERR_PTR(-EINVAL);
 
        /* pull in the page with our super */
-       page = read_cache_page_gfp(bdev->bd_inode->i_mapping, index, 
GFP_KERNEL);
+       folio = bdev_read_folio(bdev, index);
+       if (IS_ERR(folio))
+               return ERR_CAST(folio);
 
-       if (IS_ERR(page))
-               return ERR_CAST(page);
-
-       p = page_address(page);
+       p = folio_address(folio);
 
        /* align our pointer to the offset of the super block */
-       disk_super = p + offset_in_page(bytenr);
+       disk_super = p + offset_in_folio(folio, bytenr);
 
        if (btrfs_super_bytenr(disk_super) != bytenr_orig ||
            btrfs_super_magic(disk_super) != BTRFS_MAGIC) {
diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
index 188378ca19c7..aea0a433b3e5 100644
--- a/fs/btrfs/zoned.c
+++ b/fs/btrfs/zoned.c
@@ -120,8 +120,6 @@ static int sb_write_pointer(struct block_device *bdev, 
struct blk_zone *zones,
                return -ENOENT;
        } else if (full[0] && full[1]) {
                /* Compare two super blocks */
-               struct address_space *mapping = bdev->bd_inode->i_mapping;
-               struct page *page[BTRFS_NR_SB_LOG_ZONES];
                struct btrfs_super_block *super[BTRFS_NR_SB_LOG_ZONES];
                int i;
 
@@ -129,15 +127,18 @@ static int sb_write_pointer(struct block_device *bdev, 
struct blk_zone *zones,
                        u64 zone_end = (zones[i].start + zones[i].capacity) << 
SECTOR_SHIFT;
                        u64 bytenr = ALIGN_DOWN(zone_end, 
BTRFS_SUPER_INFO_SIZE) -
                                                BTRFS_SUPER_INFO_SIZE;
+                       struct folio *folio;
+                       unsigned int nofs_flag;
 
-                       page[i] = read_cache_page_gfp(mapping,
-                                       bytenr >> PAGE_SHIFT, GFP_NOFS);
-                       if (IS_ERR(page[i])) {
+                       nofs_flag = memalloc_nofs_save();
+                       folio = bdev_read_folio(bdev, bytenr);
+                       memalloc_nofs_restore(nofs_flag);
+                       if (IS_ERR(folio)) {
                                if (i == 1)
                                        btrfs_release_disk_super(super[0]);
-                               return PTR_ERR(page[i]);
+                               return PTR_ERR(folio);
                        }
-                       super[i] = page_address(page[i]);
+                       super[i] = folio_address(folio);
                }
 
                if (btrfs_super_generation(super[0]) >
-- 
2.39.2


Reply via email to