Skip to contentSkip to conversation

Bio allocation and error handling cleanups

PATCH In review David Sterba 5 participants 25 messages Jun 2, 2017 – Jun 12, 2017 Btrfs file system

lore
Share & tools
lore

David Sterba

author maintainer
#0 lore raw

cover Bio allocation and error handling cleanups

The error handling can be simplified as we do bio allocations using a bioset as was pointed out by Christoph in https://lkml.kernel.org/r/[email protected]

David Sterba (8):
btrfs: bioset allocations will never fail, adapt our helpers
btrfs: btrfs_bio_alloc never fails, skip error handling
btrfs: btrfs_bio_clone never fails, skip error handling
btrfs: btrfs_io_bio_alloc never fails, skip error handling
btrfs: sink gfp parameter to btrfs_bio_clone
btrfs: remove redundant parameters from btrfs_bio_alloc
btrfs: opencode trivial compressed_bio_alloc, simplify error handling
btrfs: pass bytes to btrfs_bio_alloc

 fs/btrfs/check-integrity.c |  5 ----
 fs/btrfs/compression.c     | 23 +++------------
 fs/btrfs/disk-io.c         |  3 --
 fs/btrfs/extent_io.c       | 71 ++++++++++++++++------------------------------
 fs/btrfs/extent_io.h       |  6 ++--
 fs/btrfs/inode.c           |  6 +---
 fs/btrfs/raid56.c          |  3 --
 fs/btrfs/scrub.c           | 25 ----------------
 fs/btrfs/volumes.c         |  3 +-
 9 files changed, 32 insertions(+), 113 deletions(-)
Signature · 1 line
2.12.0
author maintainer
#1 lore raw

PATCH 1/8 btrfs: bioset allocations will never fail, adapt our helpers

Christoph pointed out that bio allocations backed by a bioset will never fail. As we always use a bioset for all bio allocations, we can skip the error handling. This patch adjusts our low-level helpers, the cascaded changes to all callers will come next.

CC Christoph Hellwig <[email protected]>
CC Liu Bo <[email protected]>
---
 fs/btrfs/extent_io.c | 50 +++++++++++++++++++-------------------------------
 1 file changed, 19 insertions(+), 31 deletions(-)
fs/btrfs/extent_io.c +19 -31
index 5909f8214255..78a787c36a35 100644
@@ -2659,8 +2659,9 @@ static void end_bio_extent_readpage(struct bio *bio)
 }
 
 /*
- * this allocates from the btrfs_bioset.  We're returning a bio right now
- * but you can call btrfs_io_bio for the appropriate container_of magic
+ * The following helpers allocate a bio. As it's backed by a bioset, it'll
+ * never fail.  We're returning a bio right now but you can call btrfs_io_bio
+ * for the appropriate container_of magic
  */
 struct bio *
 btrfs_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs,
@@ -2670,22 +2671,12 @@ btrfs_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs,
 	struct bio *bio;
 
 	bio = bio_alloc_bioset(gfp_flags, nr_vecs, btrfs_bioset);
-
-	if (bio == NULL && (current->flags & PF_MEMALLOC)) {
-		while (!bio && (nr_vecs /= 2)) {
-			bio = bio_alloc_bioset(gfp_flags,
-					       nr_vecs, btrfs_bioset);
-		}
-	}
-
-	if (bio) {
-		bio->bi_bdev = bdev;
-		bio->bi_iter.bi_sector = first_sector;
-		btrfs_bio = btrfs_io_bio(bio);
-		btrfs_bio->csum = NULL;
-		btrfs_bio->csum_allocated = NULL;
-		btrfs_bio->end_io = NULL;
-	}
+	bio->bi_bdev = bdev;
+	bio->bi_iter.bi_sector = first_sector;
+	btrfs_bio = btrfs_io_bio(bio);
+	btrfs_bio->csum = NULL;
+	btrfs_bio->csum_allocated = NULL;
+	btrfs_bio->end_io = NULL;
 	return bio;
 }
 
@@ -2694,29 +2685,26 @@ struct bio *btrfs_bio_clone(struct bio *bio, gfp_t gfp_mask)
 	struct btrfs_io_bio *btrfs_bio;
 	struct bio *new;
 
+	/* Bio allocation backed by a bioset does not fail */
 	new = bio_clone_fast(bio, gfp_mask, btrfs_bioset);
-	if (new) {
-		btrfs_bio = btrfs_io_bio(new);
-		btrfs_bio->csum = NULL;
-		btrfs_bio->csum_allocated = NULL;
-		btrfs_bio->end_io = NULL;
-	}
+	btrfs_bio = btrfs_io_bio(new);
+	btrfs_bio->csum = NULL;
+	btrfs_bio->csum_allocated = NULL;
+	btrfs_bio->end_io = NULL;
 	return new;
 }
 
-/* this also allocates from the btrfs_bioset */
 struct bio *btrfs_io_bio_alloc(gfp_t gfp_mask, unsigned int nr_iovecs)
 {
 	struct btrfs_io_bio *btrfs_bio;
 	struct bio *bio;
 
+	/* Bio allocation backed by a bioset does not fail */
 	bio = bio_alloc_bioset(gfp_mask, nr_iovecs, btrfs_bioset);
-	if (bio) {
-		btrfs_bio = btrfs_io_bio(bio);
-		btrfs_bio->csum = NULL;
-		btrfs_bio->csum_allocated = NULL;
-		btrfs_bio->end_io = NULL;
-	}
+	btrfs_bio = btrfs_io_bio(bio);
+	btrfs_bio->csum = NULL;
+	btrfs_bio->csum_allocated = NULL;
+	btrfs_bio->end_io = NULL;
 	return bio;
 }
 
Signature · 1 line
2.12.0
author maintainer
#8 lore raw

PATCH 2/8 btrfs: btrfs_bio_alloc never fails, skip error handling

In reply to David Sterba

Update direct callers of btrfs_bio_alloc that do error handling, that we can now remove.

---
 fs/btrfs/extent_io.c | 3 ---
 1 file changed, 3 deletions(-)
fs/btrfs/extent_io.c +0 -3
index 78a787c36a35..17f80a18e787 100644
@@ -2807,9 +2807,6 @@ static int submit_extent_page(int op, int op_flags, struct extent_io_tree *tree,
 
 	bio = btrfs_bio_alloc(bdev, sector, BIO_MAX_PAGES,
 			GFP_NOFS | __GFP_HIGH);
-	if (!bio)
-		return -ENOMEM;
-
 	bio_add_page(bio, page, page_size, offset);
 	bio->bi_end_io = end_io_func;
 	bio->bi_private = tree;
Signature · 1 line
2.12.0
author maintainer
#10 lore raw

PATCH 3/8 btrfs: btrfs_bio_clone never fails, skip error handling

In reply to David Sterba

Update direct callers of btrfs_bio_clone that do error handling, that we can now remove.

---
 fs/btrfs/inode.c   | 4 ----
 fs/btrfs/volumes.c | 1 -
 2 files changed, 5 deletions(-)
fs/btrfs/inode.c +0 -4
index 0a1ec5cd3b8f..c8ed81edd40e 100644
@@ -8584,10 +8584,6 @@ static void btrfs_submit_direct(struct bio *dio_bio, struct inode *inode,
 	skip_sum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM;
 
 	bio = btrfs_bio_clone(dio_bio, GFP_NOFS);
-	if (!bio) {
-		ret = -ENOMEM;
-		goto free_ordered;
-	}
 
 	dip = kzalloc(sizeof(*dip), GFP_NOFS);
 	if (!dip) {
fs/btrfs/volumes.c +0 -1
index e28c113785bb..864b203cc4aa 100644
@@ -6257,7 +6257,6 @@ int btrfs_map_bio(struct btrfs_fs_info *fs_info, struct bio *bio,
 
 		if (dev_nr < total_devs - 1) {
 			bio = btrfs_bio_clone(first_bio, GFP_NOFS);
-			BUG_ON(!bio); /* -ENOMEM */
 		} else
 			bio = first_bio;
 
Signature · 1 line
2.12.0
author maintainer
#18 lore raw

PATCH 6/8 btrfs: remove redundant parameters from btrfs_bio_alloc

In reply to David Sterba

All callers pass gfp_flags=GFP_NOFS and nr_vecs=BIO_MAX_PAGES.

---
 fs/btrfs/compression.c | 2 +-
 fs/btrfs/extent_io.c   | 9 +++------
 fs/btrfs/extent_io.h   | 4 +---
 3 files changed, 5 insertions(+), 10 deletions(-)
fs/btrfs/compression.c +1 -1
index ba511dd454d5..7ad0a1c4be68 100644
@@ -56,7 +56,7 @@ static inline int compressed_bio_size(struct btrfs_fs_info *fs_info,
 static struct bio *compressed_bio_alloc(struct block_device *bdev,
 					u64 first_byte, gfp_t gfp_flags)
 {
-	return btrfs_bio_alloc(bdev, first_byte >> 9, BIO_MAX_PAGES, gfp_flags);
+	return btrfs_bio_alloc(bdev, first_byte >> 9);
 }
 
 static int check_compressed_csum(struct btrfs_inode *inode,
fs/btrfs/extent_io.c +3 -6
index a8f135286fa5..5730b4e747f1 100644
@@ -2658,14 +2658,12 @@ static void end_bio_extent_readpage(struct bio *bio)
  * never fail.  We're returning a bio right now but you can call btrfs_io_bio
  * for the appropriate container_of magic
  */
-struct bio *
-btrfs_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs,
-		gfp_t gfp_flags)
+struct bio *btrfs_bio_alloc(struct block_device *bdev, u64 first_sector)
 {
 	struct btrfs_io_bio *btrfs_bio;
 	struct bio *bio;
 
-	bio = bio_alloc_bioset(gfp_flags, nr_vecs, btrfs_bioset);
+	bio = bio_alloc_bioset(GFP_NOFS, BIO_MAX_PAGES, btrfs_bioset);
 	bio->bi_bdev = bdev;
 	bio->bi_iter.bi_sector = first_sector;
 	btrfs_bio = btrfs_io_bio(bio);
@@ -2800,8 +2798,7 @@ static int submit_extent_page(int op, int op_flags, struct extent_io_tree *tree,
 		}
 	}
 
-	bio = btrfs_bio_alloc(bdev, sector, BIO_MAX_PAGES,
-			GFP_NOFS | __GFP_HIGH);
+	bio = btrfs_bio_alloc(bdev, sector);
 	bio_add_page(bio, page, page_size, offset);
 	bio->bi_end_io = end_io_func;
 	bio->bi_private = tree;
fs/btrfs/extent_io.h +1 -3
index 4fe643a5aeaf..fb7a938ecbc9 100644
@@ -462,9 +462,7 @@ void extent_clear_unlock_delalloc(struct inode *inode, u64 start, u64 end,
 				 u64 delalloc_end, struct page *locked_page,
 				 unsigned bits_to_clear,
 				 unsigned long page_ops);
-struct bio *
-btrfs_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs,
-		gfp_t gfp_flags);
+struct bio *btrfs_bio_alloc(struct block_device *bdev, u64 first_sector);
 struct bio *btrfs_io_bio_alloc(gfp_t gfp_mask, unsigned int nr_iovecs);
 struct bio *btrfs_bio_clone(struct bio *bio);
 struct bio *btrfs_bio_clone_partial(struct bio *orig, int offset, int size);
Signature · 1 line
2.12.0
author maintainer
#16 lore raw

PATCH 5/8 btrfs: sink gfp parameter to btrfs_bio_clone

In reply to David Sterba

All callers pass GFP_NOFS.

---
 fs/btrfs/extent_io.c | 4 ++--
 fs/btrfs/extent_io.h | 2 +-
 fs/btrfs/inode.c     | 2 +-
 fs/btrfs/volumes.c   | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)
fs/btrfs/extent_io.c +2 -2
index a10906915bc9..a8f135286fa5 100644
@@ -2675,13 +2675,13 @@ btrfs_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs,
 	return bio;
 }
 
-struct bio *btrfs_bio_clone(struct bio *bio, gfp_t gfp_mask)
+struct bio *btrfs_bio_clone(struct bio *bio)
 {
 	struct btrfs_io_bio *btrfs_bio;
 	struct bio *new;
 
 	/* Bio allocation backed by a bioset does not fail */
-	new = bio_clone_fast(bio, gfp_mask, btrfs_bioset);
+	new = bio_clone_fast(bio, GFP_NOFS, btrfs_bioset);
 	btrfs_bio = btrfs_io_bio(new);
 	btrfs_bio->csum = NULL;
 	btrfs_bio->csum_allocated = NULL;
fs/btrfs/extent_io.h +1 -1
index e3512c5d8770..4fe643a5aeaf 100644
@@ -466,7 +466,7 @@ struct bio *
 btrfs_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs,
 		gfp_t gfp_flags);
 struct bio *btrfs_io_bio_alloc(gfp_t gfp_mask, unsigned int nr_iovecs);
-struct bio *btrfs_bio_clone(struct bio *bio, gfp_t gfp_mask);
+struct bio *btrfs_bio_clone(struct bio *bio);
 struct bio *btrfs_bio_clone_partial(struct bio *orig, int offset, int size);
 
 struct btrfs_fs_info;
fs/btrfs/inode.c +1 -1
index c8ed81edd40e..5112f2c45600 100644
@@ -8583,7 +8583,7 @@ static void btrfs_submit_direct(struct bio *dio_bio, struct inode *inode,
 
 	skip_sum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM;
 
-	bio = btrfs_bio_clone(dio_bio, GFP_NOFS);
+	bio = btrfs_bio_clone(dio_bio);
 
 	dip = kzalloc(sizeof(*dip), GFP_NOFS);
 	if (!dip) {
fs/btrfs/volumes.c +1 -1
index 864b203cc4aa..70bcebef7aa6 100644
@@ -6256,7 +6256,7 @@ int btrfs_map_bio(struct btrfs_fs_info *fs_info, struct bio *bio,
 		}
 
 		if (dev_nr < total_devs - 1) {
-			bio = btrfs_bio_clone(first_bio, GFP_NOFS);
+			bio = btrfs_bio_clone(first_bio);
 		} else
 			bio = first_bio;
 
Signature · 1 line
2.12.0
author maintainer
#21 lore raw

PATCH 7/8 btrfs: opencode trivial compressed_bio_alloc, simplify error handling

In reply to David Sterba

compressed_bio_alloc is now a trivial wrapper around btrfs_bio_alloc, no point keeping it. The error handling can be simplified, as we know btrfs_bio_alloc will never fail.

---
 fs/btrfs/compression.c | 23 ++++-------------------
 1 file changed, 4 insertions(+), 19 deletions(-)
fs/btrfs/compression.c +4 -19
index 7ad0a1c4be68..2df080c4ece0 100644
@@ -53,12 +53,6 @@ static inline int compressed_bio_size(struct btrfs_fs_info *fs_info,
 		(DIV_ROUND_UP(disk_size, fs_info->sectorsize)) * csum_size;
 }
 
-static struct bio *compressed_bio_alloc(struct block_device *bdev,
-					u64 first_byte, gfp_t gfp_flags)
-{
-	return btrfs_bio_alloc(bdev, first_byte >> 9);
-}
-
 static int check_compressed_csum(struct btrfs_inode *inode,
 				 struct compressed_bio *cb,
 				 u64 disk_start)
@@ -311,11 +305,7 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
 
 	bdev = fs_info->fs_devices->latest_bdev;
 
-	bio = compressed_bio_alloc(bdev, first_byte, GFP_NOFS);
-	if (!bio) {
-		kfree(cb);
-		return -ENOMEM;
-	}
+	bio = btrfs_bio_alloc(bdev, first_byte >> 9);
 	bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
 	bio->bi_private = cb;
 	bio->bi_end_io = end_compressed_bio_write;
@@ -362,8 +352,7 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
 
 			bio_put(bio);
 
-			bio = compressed_bio_alloc(bdev, first_byte, GFP_NOFS);
-			BUG_ON(!bio);
+			bio = btrfs_bio_alloc(bdev, first_byte >> 9);
 			bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
 			bio->bi_private = cb;
 			bio->bi_end_io = end_compressed_bio_write;
@@ -606,9 +595,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
 	/* include any pages we added in add_ra-bio_pages */
 	cb->len = bio->bi_iter.bi_size;
 
-	comp_bio = compressed_bio_alloc(bdev, cur_disk_byte, GFP_NOFS);
-	if (!comp_bio)
-		goto fail2;
+	comp_bio = btrfs_bio_alloc(bdev, cur_disk_byte >> 9);
 	bio_set_op_attrs (comp_bio, REQ_OP_READ, 0);
 	comp_bio->bi_private = cb;
 	comp_bio->bi_end_io = end_compressed_bio_read;
@@ -659,9 +646,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
 
 			bio_put(comp_bio);
 
-			comp_bio = compressed_bio_alloc(bdev, cur_disk_byte,
-							GFP_NOFS);
-			BUG_ON(!comp_bio);
+			comp_bio = btrfs_bio_alloc(bdev, cur_disk_byte >> 9);
 			bio_set_op_attrs(comp_bio, REQ_OP_READ, 0);
 			comp_bio->bi_private = cb;
 			comp_bio->bi_end_io = end_compressed_bio_read;
Signature · 1 line
2.12.0
author maintainer
#14 lore raw

PATCH 4/8 btrfs: btrfs_io_bio_alloc never fails, skip error handling

In reply to David Sterba

Update direct callers of btrfs_io_bio_alloc that do error handling, that we can now remove.

---
 fs/btrfs/check-integrity.c |  5 -----
 fs/btrfs/disk-io.c         |  3 ---
 fs/btrfs/extent_io.c       |  5 -----
 fs/btrfs/raid56.c          |  3 ---
 fs/btrfs/scrub.c           | 25 -------------------------
 5 files changed, 41 deletions(-)
fs/btrfs/check-integrity.c +0 -5
index 6cabc8acee2a..8d1ba84b61f3 100644
@@ -1639,11 +1639,6 @@ static int btrfsic_read_block(struct btrfsic_state *state,
 		unsigned int j;
 
 		bio = btrfs_io_bio_alloc(GFP_NOFS, num_pages - i);
-		if (!bio) {
-			pr_info("btrfsic: bio_alloc() for %u pages failed!\n",
-			       num_pages - i);
-			return -1;
-		}
 		bio->bi_bdev = block_ctx->dev->bdev;
 		bio->bi_iter.bi_sector = dev_bytenr >> 9;
 		bio_set_op_attrs(bio, REQ_OP_READ, 0);
fs/btrfs/disk-io.c +0 -3
index cb79bce3a972..9f2ffe2c6afb 100644
@@ -3533,9 +3533,6 @@ static int write_dev_flush(struct btrfs_device *device, int wait)
 	 */
 	device->flush_bio = NULL;
 	bio = btrfs_io_bio_alloc(GFP_NOFS, 0);
-	if (!bio)
-		return -ENOMEM;
-
 	bio->bi_end_io = btrfs_end_empty_barrier;
 	bio->bi_bdev = device->bdev;
 	bio->bi_opf = REQ_OP_WRITE | REQ_SYNC | REQ_PREFLUSH;
fs/btrfs/extent_io.c +0 -5
index 17f80a18e787..a10906915bc9 100644
@@ -1988,8 +1988,6 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 ino, u64 start,
 	BUG_ON(!mirror_num);
 
 	bio = btrfs_io_bio_alloc(GFP_NOFS, 1);
-	if (!bio)
-		return -EIO;
 	bio->bi_iter.bi_size = 0;
 	map_length = length;
 
@@ -2334,9 +2332,6 @@ struct bio *btrfs_create_repair_bio(struct inode *inode, struct bio *failed_bio,
 	struct btrfs_io_bio *btrfs_bio;
 
 	bio = btrfs_io_bio_alloc(GFP_NOFS, 1);
-	if (!bio)
-		return NULL;
-
 	bio->bi_end_io = endio_func;
 	bio->bi_iter.bi_sector = failrec->logical >> 9;
 	bio->bi_bdev = fs_info->fs_devices->latest_bdev;
fs/btrfs/raid56.c +0 -3
index d8ea0eb76325..6938da452041 100644
@@ -1102,9 +1102,6 @@ static int rbio_add_io_page(struct btrfs_raid_bio *rbio,
 
 	/* put a new bio on the list */
 	bio = btrfs_io_bio_alloc(GFP_NOFS, bio_max_len >> PAGE_SHIFT?:1);
-	if (!bio)
-		return -ENOMEM;
-
 	bio->bi_iter.bi_size = 0;
 	bio->bi_bdev = stripe->dev->bdev;
 	bio->bi_iter.bi_sector = disk_start >> 9;
fs/btrfs/scrub.c +0 -25
index e99be644b19f..75f1966ca1d3 100644
@@ -1729,11 +1729,6 @@ static void scrub_recheck_block(struct btrfs_fs_info *fs_info,
 
 		WARN_ON(!page->page);
 		bio = btrfs_io_bio_alloc(GFP_NOFS, 1);
-		if (!bio) {
-			page->io_error = 1;
-			sblock->no_io_error_seen = 0;
-			continue;
-		}
 		bio->bi_bdev = page->dev->bdev;
 
 		bio_add_page(bio, page->page, PAGE_SIZE, 0);
@@ -1822,8 +1817,6 @@ static int scrub_repair_page_from_good_copy(struct scrub_block *sblock_bad,
 		}
 
 		bio = btrfs_io_bio_alloc(GFP_NOFS, 1);
-		if (!bio)
-			return -EIO;
 		bio->bi_bdev = page_bad->dev->bdev;
 		bio->bi_iter.bi_sector = page_bad->physical >> 9;
 		bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
@@ -1915,10 +1908,6 @@ static int scrub_add_page_to_wr_bio(struct scrub_ctx *sctx,
 		if (!bio) {
 			bio = btrfs_io_bio_alloc(GFP_KERNEL,
 					sctx->pages_per_wr_bio);
-			if (!bio) {
-				mutex_unlock(&sctx->wr_lock);
-				return -ENOMEM;
-			}
 			sbio->bio = bio;
 		}
 
@@ -2320,8 +2309,6 @@ static int scrub_add_page_to_rd_bio(struct scrub_ctx *sctx,
 		if (!bio) {
 			bio = btrfs_io_bio_alloc(GFP_KERNEL,
 					sctx->pages_per_rd_bio);
-			if (!bio)
-				return -ENOMEM;
 			sbio->bio = bio;
 		}
 
@@ -2448,9 +2435,6 @@ static void scrub_missing_raid56_pages(struct scrub_block *sblock)
 	}
 
 	bio = btrfs_io_bio_alloc(GFP_NOFS, 0);
-	if (!bio)
-		goto bbio_out;
-
 	bio->bi_iter.bi_sector = logical >> 9;
 	bio->bi_private = sblock;
 	bio->bi_end_io = scrub_missing_raid56_end_io;
@@ -3027,9 +3011,6 @@ static void scrub_parity_check_and_repair(struct scrub_parity *sparity)
 		goto bbio_out;
 
 	bio = btrfs_io_bio_alloc(GFP_NOFS, 0);
-	if (!bio)
-		goto bbio_out;
-
 	bio->bi_iter.bi_sector = sparity->logic_start >> 9;
 	bio->bi_private = sparity;
 	bio->bi_end_io = scrub_parity_bio_endio;
@@ -4637,12 +4618,6 @@ static int write_page_nocow(struct scrub_ctx *sctx,
 		return -EIO;
 	}
 	bio = btrfs_io_bio_alloc(GFP_NOFS, 1);
-	if (!bio) {
-		spin_lock(&sctx->stat_lock);
-		sctx->stat.malloc_errors++;
-		spin_unlock(&sctx->stat_lock);
-		return -ENOMEM;
-	}
 	bio->bi_iter.bi_size = 0;
 	bio->bi_iter.bi_sector = physical_for_dev_replace >> 9;
 	bio->bi_bdev = dev->bdev;
Signature · 1 line
2.12.0
author maintainer
#23 lore raw

PATCH 8/8 btrfs: pass bytes to btrfs_bio_alloc

In reply to David Sterba

Most callers of btrfs_bio_alloc convert from bytes to sectors. Hide that in the helper and simplify the logic in the callsers.

---
 fs/btrfs/compression.c | 8 ++++----
 fs/btrfs/extent_io.c   | 6 +++---
 fs/btrfs/extent_io.h   | 2 +-
 3 files changed, 8 insertions(+), 8 deletions(-)
fs/btrfs/compression.c +4 -4
index 2df080c4ece0..fd6508bcff77 100644
@@ -305,7 +305,7 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
 
 	bdev = fs_info->fs_devices->latest_bdev;
 
-	bio = btrfs_bio_alloc(bdev, first_byte >> 9);
+	bio = btrfs_bio_alloc(bdev, first_byte);
 	bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
 	bio->bi_private = cb;
 	bio->bi_end_io = end_compressed_bio_write;
@@ -352,7 +352,7 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
 
 			bio_put(bio);
 
-			bio = btrfs_bio_alloc(bdev, first_byte >> 9);
+			bio = btrfs_bio_alloc(bdev, first_byte);
 			bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
 			bio->bi_private = cb;
 			bio->bi_end_io = end_compressed_bio_write;
@@ -595,7 +595,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
 	/* include any pages we added in add_ra-bio_pages */
 	cb->len = bio->bi_iter.bi_size;
 
-	comp_bio = btrfs_bio_alloc(bdev, cur_disk_byte >> 9);
+	comp_bio = btrfs_bio_alloc(bdev, cur_disk_byte);
 	bio_set_op_attrs (comp_bio, REQ_OP_READ, 0);
 	comp_bio->bi_private = cb;
 	comp_bio->bi_end_io = end_compressed_bio_read;
@@ -646,7 +646,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
 
 			bio_put(comp_bio);
 
-			comp_bio = btrfs_bio_alloc(bdev, cur_disk_byte >> 9);
+			comp_bio = btrfs_bio_alloc(bdev, cur_disk_byte);
 			bio_set_op_attrs(comp_bio, REQ_OP_READ, 0);
 			comp_bio->bi_private = cb;
 			comp_bio->bi_end_io = end_compressed_bio_read;
fs/btrfs/extent_io.c +3 -3
index 5730b4e747f1..cb4754e57ace 100644
@@ -2658,14 +2658,14 @@ static void end_bio_extent_readpage(struct bio *bio)
  * never fail.  We're returning a bio right now but you can call btrfs_io_bio
  * for the appropriate container_of magic
  */
-struct bio *btrfs_bio_alloc(struct block_device *bdev, u64 first_sector)
+struct bio *btrfs_bio_alloc(struct block_device *bdev, u64 first_byte)
 {
 	struct btrfs_io_bio *btrfs_bio;
 	struct bio *bio;
 
 	bio = bio_alloc_bioset(GFP_NOFS, BIO_MAX_PAGES, btrfs_bioset);
 	bio->bi_bdev = bdev;
-	bio->bi_iter.bi_sector = first_sector;
+	bio->bi_iter.bi_sector = first_byte >> 9;
 	btrfs_bio = btrfs_io_bio(bio);
 	btrfs_bio->csum = NULL;
 	btrfs_bio->csum_allocated = NULL;
@@ -2798,7 +2798,7 @@ static int submit_extent_page(int op, int op_flags, struct extent_io_tree *tree,
 		}
 	}
 
-	bio = btrfs_bio_alloc(bdev, sector);
+	bio = btrfs_bio_alloc(bdev, sector << 9);
 	bio_add_page(bio, page, page_size, offset);
 	bio->bi_end_io = end_io_func;
 	bio->bi_private = tree;
fs/btrfs/extent_io.h +1 -1
index fb7a938ecbc9..8071e3977614 100644
@@ -462,7 +462,7 @@ void extent_clear_unlock_delalloc(struct inode *inode, u64 start, u64 end,
 				 u64 delalloc_end, struct page *locked_page,
 				 unsigned bits_to_clear,
 				 unsigned long page_ops);
-struct bio *btrfs_bio_alloc(struct block_device *bdev, u64 first_sector);
+struct bio *btrfs_bio_alloc(struct block_device *bdev, u64 first_byte);
 struct bio *btrfs_io_bio_alloc(gfp_t gfp_mask, unsigned int nr_iovecs);
 struct bio *btrfs_bio_clone(struct bio *bio);
 struct bio *btrfs_bio_clone_partial(struct bio *orig, int offset, int size);
Signature · 1 line
2.12.0
Reviewed-by on v1 1/8
#2 lore raw

Re: [PATCH 1/8] btrfs: bioset allocations will never fail, adapt our helpers

In reply to David Sterba
Quoted 4 lines · David Sterba

Christoph pointed out that bio allocations backed by a bioset will never fail. As we always use a bioset for all bio allocations, we can skip the error handling. This patch adjusts our low-level helpers, the cascaded changes to all callers will come next.

Looks good,

#3 lore raw

Re: [PATCH 1/8] btrfs: bioset allocations will never fail, adapt our helpers

In reply to David Sterba
Quoted 2 lines · David Sterba

Christoph pointed out that bio allocations backed by a bioset will never fail.

David,

Looks like this feature comes when __GFP_DIRECT_RECLAIM is set and we aren't, such as [1]. Any idea why? Looks like I am missing something ?

[1]
-----
static int submit_extent_page(int op, int op_flags, struct extent_io_tree *tree, ::

bio = btrfs_bio_alloc(bdev, sector, BIO_MAX_PAGES,

                GFP_NOFS | __GFP_HIGH);

------

Thanks, Anand

Quoted 97 lines

As we always use a bioset for all bio allocations, we can skip
the error handling. This patch adjusts our low-level helpers, the cascaded changes to all callers will come next.

CC Christoph Hellwig <[email protected]>
CC Liu Bo <[email protected]>
---
 fs/btrfs/extent_io.c | 50 +++++++++++++++++++-------------------------------
 1 file changed, 19 insertions(+), 31 deletions(-)
fs/btrfs/extent_io.c +19 -31
index 5909f8214255..78a787c36a35 100644
@@ -2659,8 +2659,9 @@ static void end_bio_extent_readpage(struct bio *bio)
 }
 
 /*
- * this allocates from the btrfs_bioset.  We're returning a bio right now
- * but you can call btrfs_io_bio for the appropriate container_of magic
+ * The following helpers allocate a bio. As it's backed by a bioset, it'll
+ * never fail.  We're returning a bio right now but you can call btrfs_io_bio
+ * for the appropriate container_of magic
  */
 struct bio *
 btrfs_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs,
@@ -2670,22 +2671,12 @@ btrfs_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs,
 	struct bio *bio;
 
 	bio = bio_alloc_bioset(gfp_flags, nr_vecs, btrfs_bioset);
-
-	if (bio == NULL && (current->flags & PF_MEMALLOC)) {
-		while (!bio && (nr_vecs /= 2)) {
-			bio = bio_alloc_bioset(gfp_flags,
-					       nr_vecs, btrfs_bioset);
-		}
-	}
-
-	if (bio) {
-		bio->bi_bdev = bdev;
-		bio->bi_iter.bi_sector = first_sector;
-		btrfs_bio = btrfs_io_bio(bio);
-		btrfs_bio->csum = NULL;
-		btrfs_bio->csum_allocated = NULL;
-		btrfs_bio->end_io = NULL;
-	}
+	bio->bi_bdev = bdev;
+	bio->bi_iter.bi_sector = first_sector;
+	btrfs_bio = btrfs_io_bio(bio);
+	btrfs_bio->csum = NULL;
+	btrfs_bio->csum_allocated = NULL;
+	btrfs_bio->end_io = NULL;
 	return bio;
 }
 
@@ -2694,29 +2685,26 @@ struct bio *btrfs_bio_clone(struct bio *bio, gfp_t gfp_mask)
 	struct btrfs_io_bio *btrfs_bio;
 	struct bio *new;
 
+	/* Bio allocation backed by a bioset does not fail */
 	new = bio_clone_fast(bio, gfp_mask, btrfs_bioset);
-	if (new) {
-		btrfs_bio = btrfs_io_bio(new);
-		btrfs_bio->csum = NULL;
-		btrfs_bio->csum_allocated = NULL;
-		btrfs_bio->end_io = NULL;
-	}
+	btrfs_bio = btrfs_io_bio(new);
+	btrfs_bio->csum = NULL;
+	btrfs_bio->csum_allocated = NULL;
+	btrfs_bio->end_io = NULL;
 	return new;
 }
 
-/* this also allocates from the btrfs_bioset */
 struct bio *btrfs_io_bio_alloc(gfp_t gfp_mask, unsigned int nr_iovecs)
 {
 	struct btrfs_io_bio *btrfs_bio;
 	struct bio *bio;
 
+	/* Bio allocation backed by a bioset does not fail */
 	bio = bio_alloc_bioset(gfp_mask, nr_iovecs, btrfs_bioset);
-	if (bio) {
-		btrfs_bio = btrfs_io_bio(bio);
-		btrfs_bio->csum = NULL;
-		btrfs_bio->csum_allocated = NULL;
-		btrfs_bio->end_io = NULL;
-	}
+	btrfs_bio = btrfs_io_bio(bio);
+	btrfs_bio->csum = NULL;
+	btrfs_bio->csum_allocated = NULL;
+	btrfs_bio->end_io = NULL;
 	return bio;
 }
 
#4 lore raw

Re: [PATCH 1/8] btrfs: bioset allocations will never fail, adapt our helpers

Quoted 13 lines · Anand Jain
Quoted 2 lines · David Sterba

Christoph pointed out that bio allocations backed by a bioset will never fail.

David,

Looks like this feature comes when __GFP_DIRECT_RECLAIM is set and we aren't, such as [1]. Any idea why? Looks like I am missing something ?

Quoted 8 lines

[1]
-----
static int submit_extent_page(int op, int op_flags, struct extent_io_tree *tree,
::

bio = btrfs_bio_alloc(bdev, sector, BIO_MAX_PAGES,

                GFP_NOFS | __GFP_HIGH);

#define __GFP_RECLAIM ((__force gfp_t)(___GFP_DIRECT_RECLAIM|___GFP_KSWAPD_RECLAIM))

#define GFP_NOFS (__GFP_RECLAIM | __GFP_IO)

#6 lore raw

Re: [PATCH 1/8] btrfs: bioset allocations will never fail, adapt our helpers

In reply to Anand Jain
Quoted 7 lines · Anand Jain
Quoted 2 lines · David Sterba

Christoph pointed out that bio allocations backed by a bioset will never fail.

Looks like this feature comes when __GFP_DIRECT_RECLAIM is set and we aren't, such as [1]. Any idea why? Looks like I am missing something ?

bio_alloc_bioset:

 406  *   When @bs is not NULL, if %__GFP_DIRECT_RECLAIM is set then bio_alloc will
 407  *   always be able to allocate a bio. This is due to the mempool guarantees.
Quoted 8 lines

[1]
-----
static int submit_extent_page(int op, int op_flags, struct extent_io_tree *tree,
::

bio = btrfs_bio_alloc(bdev, sector, BIO_MAX_PAGES,

                 GFP_NOFS | __GFP_HIGH);

GFP_NOFS contains __GFP_DIRECT_RECLAIM, so what's the problem? __GFP_HIGH allows using the reserves, but should not otherwise change the constraints. And it's use seems unnecessary, as far as I could track in the history.

#5 lore raw

Re: [PATCH 1/8] btrfs: bioset allocations will never fail, adapt our helpers

In reply to Christoph Hellwig
Quoted 6 lines

#define __GFP_RECLAIM ((__force gfp_t)(___GFP_DIRECT_RECLAIM|___GFP_KSWAPD_RECLAIM))

#define GFP_NOFS (__GFP_RECLAIM | __GFP_IO)

Ah. Thanks.

#19 lore raw

Re: [PATCH 6/8] btrfs: remove redundant parameters from btrfs_bio_alloc

In reply to David Sterba
Quoted 1 line · David Sterba

All callers pass gfp_flags=GFP_NOFS and nr_vecs=BIO_MAX_PAGES.

The line (in the other thread) mentioning the reason to remove
__GFP_HIGH can go into the commit log here.

fs/btrfs/extent_io.c static int submit_extent_page(int op, int op_flags, struct extent_io_tree *tree, · line 2801

Quoted 3 lines
fs/btrfs/extent_io.c +1 -2
-	bio = btrfs_bio_alloc(bdev, sector, BIO_MAX_PAGES,
-			GFP_NOFS | __GFP_HIGH);
+	bio = btrfs_bio_alloc(bdev, sector);

Thanks, Anand

Reviewed-by on v1 7/8
#22 lore raw

Re: [PATCH 7/8] btrfs: opencode trivial compressed_bio_alloc, simplify error handling

In reply to David Sterba
Quoted 3 lines · David Sterba

compressed_bio_alloc is now a trivial wrapper around btrfs_bio_alloc, no point keeping it. The error handling can be simplified, as we know btrfs_bio_alloc will never fail.

#12 lore raw

Re: [PATCH 3/8] btrfs: btrfs_bio_clone never fails, skip error handling

In reply to David Sterba
Quoted 10 lines · David Sterba

Update direct callers of btrfs_bio_clone that do error handling, that we can now remove.

---
 fs/btrfs/inode.c   | 4 ----
 fs/btrfs/volumes.c | 1 -
 2 files changed, 5 deletions(-)

fs/btrfs/volumes.c int btrfs_map_bio(struct btrfs_fs_info *fs_info, struct bio *bio, · line 6261

Quoted 5 lines
fs/btrfs/volumes.c +0 -1
 		if (dev_nr < total_devs - 1) {
 			bio = btrfs_bio_clone(first_bio, GFP_NOFS);
-			BUG_ON(!bio); /* -ENOMEM */
 		} else
 			bio = first_bio;

Could you please get rid of the extra curly braces now, too?

#20 lore raw

Re: [PATCH 6/8] btrfs: remove redundant parameters from btrfs_bio_alloc

In reply to Anand Jain
Quoted 7 lines · Anand Jain
Quoted 1 line · David Sterba

All callers pass gfp_flags=GFP_NOFS and nr_vecs=BIO_MAX_PAGES.

The line (in the other thread) mentioning the reason to remove
__GFP_HIGH can go into the commit log here.

Makes sense, patch updated.

#13 lore raw

Re: [PATCH 3/8] btrfs: btrfs_bio_clone never fails, skip error handling

In reply to Omar Sandoval
Quoted 11 lines · Omar Sandoval
Quoted 10 lines · David Sterba

Update direct callers of btrfs_bio_clone that do error handling, that we can now remove.

---
 fs/btrfs/inode.c   | 4 ----
 fs/btrfs/volumes.c | 1 -
 2 files changed, 5 deletions(-)
Quoted 7 lines

fs/btrfs/volumes.c int btrfs_map_bio(struct btrfs_fs_info *fs_info, struct bio *bio, · line 6261

Quoted 5 lines
fs/btrfs/volumes.c +0 -1
 		if (dev_nr < total_devs - 1) {
 			bio = btrfs_bio_clone(first_bio, GFP_NOFS);
-			BUG_ON(!bio); /* -ENOMEM */
 		} else
 			bio = first_bio;

Could you please get rid of the extra curly braces now, too?

Sure, patch updated.