diff mbox series

[v3,7/8] block: add nowait flag for __blkdev_issue_zero_pages

Message ID 292fa1c611adb064efe16ab741aad65c2128ada8.1725459175.git.asml.silence@gmail.com (mailing list archive)
State New
Headers show
Series implement async block discards and other ops via io_uring | expand

Commit Message

Pavel Begunkov Sept. 4, 2024, 2:18 p.m. UTC
To reuse __blkdev_issue_zero_pages() in the following patch, we need to
make it work with non-blocking requests. Add a new nowait flag we can
pass inside. Return errors if something went wrong, and check
bio_alloc() for failures, which wasn't supposed to happen before because
of what gfp flags the callers are passing. Note that there might be a
bio passed back even when the function returned an error. To limit the
scope of the patch, don't add return code handling to callers, that can
be deferred to a follow up.

Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
---
 block/blk-lib.c        | 22 ++++++++++++++++++----
 include/linux/bio.h    |  4 ++++
 include/linux/blkdev.h |  1 +
 3 files changed, 23 insertions(+), 4 deletions(-)

Comments

kernel test robot Sept. 6, 2024, 3:23 a.m. UTC | #1
Hi Pavel,

kernel test robot noticed the following build warnings:

[auto build test WARNING on axboe-block/for-next]
[also build test WARNING on akpm-mm/mm-everything linus/master v6.11-rc6 next-20240905]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Pavel-Begunkov/io_uring-cmd-expose-iowq-to-cmds/20240904-222012
base:   https://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git for-next
patch link:    https://lore.kernel.org/r/292fa1c611adb064efe16ab741aad65c2128ada8.1725459175.git.asml.silence%40gmail.com
patch subject: [PATCH v3 7/8] block: add nowait flag for __blkdev_issue_zero_pages
config: i386-randconfig-141-20240906 (https://download.01.org/0day-ci/archive/20240906/202409061126.hKdAymJK-lkp@intel.com/config)
compiler: clang version 18.1.5 (https://github.com/llvm/llvm-project 617a15a9eac96088ae5e9134248d8236e34b91b1)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240906/202409061126.hKdAymJK-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202409061126.hKdAymJK-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> block/blk-lib.c:200:12: warning: variable 'opf' set but not used [-Wunused-but-set-variable]
     200 |         blk_opf_t opf = REQ_OP_WRITE;
         |                   ^
   1 warning generated.


vim +/opf +200 block/blk-lib.c

   195	
   196	int blkdev_issue_zero_pages_bio(struct block_device *bdev,
   197			sector_t sector, sector_t nr_sects, gfp_t gfp_mask,
   198			struct bio **biop, unsigned int flags)
   199	{
 > 200		blk_opf_t opf = REQ_OP_WRITE;
   201	
   202		if (flags & BLKDEV_ZERO_PAGES_NOWAIT) {
   203			sector_t max_bio_sectors = BIO_MAX_VECS << PAGE_SECTORS_SHIFT;
   204	
   205			if (nr_sects > max_bio_sectors)
   206				return -EAGAIN;
   207			opf |= REQ_NOWAIT;
   208		}
   209	
   210		while (nr_sects) {
   211			unsigned int nr_vecs = __blkdev_sectors_to_bio_pages(nr_sects);
   212			struct bio *bio;
   213	
   214			bio = bio_alloc(bdev, nr_vecs, REQ_OP_WRITE, gfp_mask);
   215			if (!bio)
   216				return -ENOMEM;
   217			bio->bi_iter.bi_sector = sector;
   218	
   219			if ((flags & BLKDEV_ZERO_KILLABLE) &&
   220			    fatal_signal_pending(current))
   221				return -EINTR;
   222	
   223			do {
   224				unsigned int len, added;
   225	
   226				len = min_t(sector_t,
   227					PAGE_SIZE, nr_sects << SECTOR_SHIFT);
   228				added = bio_add_page(bio, ZERO_PAGE(0), len, 0);
   229				if (added < len)
   230					break;
   231				nr_sects -= added >> SECTOR_SHIFT;
   232				sector += added >> SECTOR_SHIFT;
   233			} while (nr_sects);
   234	
   235			*biop = bio_chain_and_submit(*biop, bio);
   236			cond_resched();
   237		}
   238	
   239		return 0;
   240	}
   241
Jens Axboe Sept. 6, 2024, 1:41 p.m. UTC | #2
On 9/4/24 8:18 AM, Pavel Begunkov wrote:
> diff --git a/block/blk-lib.c b/block/blk-lib.c
> index c94c67a75f7e..a16b7c7965e8 100644
> --- a/block/blk-lib.c
> +++ b/block/blk-lib.c
> @@ -193,20 +193,32 @@ static unsigned int __blkdev_sectors_to_bio_pages(sector_t nr_sects)
>  	return min(pages, (sector_t)BIO_MAX_VECS);
>  }
>  
> -static void __blkdev_issue_zero_pages(struct block_device *bdev,
> +int blkdev_issue_zero_pages_bio(struct block_device *bdev,
>  		sector_t sector, sector_t nr_sects, gfp_t gfp_mask,
>  		struct bio **biop, unsigned int flags)
>  {
> +	blk_opf_t opf = REQ_OP_WRITE;
> +
> +	if (flags & BLKDEV_ZERO_PAGES_NOWAIT) {
> +		sector_t max_bio_sectors = BIO_MAX_VECS << PAGE_SECTORS_SHIFT;
> +
> +		if (nr_sects > max_bio_sectors)
> +			return -EAGAIN;
> +		opf |= REQ_NOWAIT;
> +	}
> +
>  	while (nr_sects) {
>  		unsigned int nr_vecs = __blkdev_sectors_to_bio_pages(nr_sects);
>  		struct bio *bio;
>  
>  		bio = bio_alloc(bdev, nr_vecs, REQ_OP_WRITE, gfp_mask);

as per the kernel test bot, I guess this one should be using opf rather
than REQ_OP_WRITE.
Pavel Begunkov Sept. 6, 2024, 1:46 p.m. UTC | #3
On 9/6/24 14:41, Jens Axboe wrote:
> On 9/4/24 8:18 AM, Pavel Begunkov wrote:
>> diff --git a/block/blk-lib.c b/block/blk-lib.c
>> index c94c67a75f7e..a16b7c7965e8 100644
>> --- a/block/blk-lib.c
>> +++ b/block/blk-lib.c
>> @@ -193,20 +193,32 @@ static unsigned int __blkdev_sectors_to_bio_pages(sector_t nr_sects)
>>   	return min(pages, (sector_t)BIO_MAX_VECS);
>>   }
>>   
>> -static void __blkdev_issue_zero_pages(struct block_device *bdev,
>> +int blkdev_issue_zero_pages_bio(struct block_device *bdev,
>>   		sector_t sector, sector_t nr_sects, gfp_t gfp_mask,
>>   		struct bio **biop, unsigned int flags)
>>   {
>> +	blk_opf_t opf = REQ_OP_WRITE;
>> +
>> +	if (flags & BLKDEV_ZERO_PAGES_NOWAIT) {
>> +		sector_t max_bio_sectors = BIO_MAX_VECS << PAGE_SECTORS_SHIFT;
>> +
>> +		if (nr_sects > max_bio_sectors)
>> +			return -EAGAIN;
>> +		opf |= REQ_NOWAIT;
>> +	}
>> +
>>   	while (nr_sects) {
>>   		unsigned int nr_vecs = __blkdev_sectors_to_bio_pages(nr_sects);
>>   		struct bio *bio;
>>   
>>   		bio = bio_alloc(bdev, nr_vecs, REQ_OP_WRITE, gfp_mask);
> 
> as per the kernel test bot, I guess this one should be using opf rather
> than REQ_OP_WRITE.

Right, I overlooked it. I'm going to resend the series later today.
diff mbox series

Patch

diff --git a/block/blk-lib.c b/block/blk-lib.c
index c94c67a75f7e..a16b7c7965e8 100644
--- a/block/blk-lib.c
+++ b/block/blk-lib.c
@@ -193,20 +193,32 @@  static unsigned int __blkdev_sectors_to_bio_pages(sector_t nr_sects)
 	return min(pages, (sector_t)BIO_MAX_VECS);
 }
 
-static void __blkdev_issue_zero_pages(struct block_device *bdev,
+int blkdev_issue_zero_pages_bio(struct block_device *bdev,
 		sector_t sector, sector_t nr_sects, gfp_t gfp_mask,
 		struct bio **biop, unsigned int flags)
 {
+	blk_opf_t opf = REQ_OP_WRITE;
+
+	if (flags & BLKDEV_ZERO_PAGES_NOWAIT) {
+		sector_t max_bio_sectors = BIO_MAX_VECS << PAGE_SECTORS_SHIFT;
+
+		if (nr_sects > max_bio_sectors)
+			return -EAGAIN;
+		opf |= REQ_NOWAIT;
+	}
+
 	while (nr_sects) {
 		unsigned int nr_vecs = __blkdev_sectors_to_bio_pages(nr_sects);
 		struct bio *bio;
 
 		bio = bio_alloc(bdev, nr_vecs, REQ_OP_WRITE, gfp_mask);
+		if (!bio)
+			return -ENOMEM;
 		bio->bi_iter.bi_sector = sector;
 
 		if ((flags & BLKDEV_ZERO_KILLABLE) &&
 		    fatal_signal_pending(current))
-			break;
+			return -EINTR;
 
 		do {
 			unsigned int len, added;
@@ -223,6 +235,8 @@  static void __blkdev_issue_zero_pages(struct block_device *bdev,
 		*biop = bio_chain_and_submit(*biop, bio);
 		cond_resched();
 	}
+
+	return 0;
 }
 
 static int blkdev_issue_zero_pages(struct block_device *bdev, sector_t sector,
@@ -236,7 +250,7 @@  static int blkdev_issue_zero_pages(struct block_device *bdev, sector_t sector,
 		return -EOPNOTSUPP;
 
 	blk_start_plug(&plug);
-	__blkdev_issue_zero_pages(bdev, sector, nr_sects, gfp, &bio, flags);
+	blkdev_issue_zero_pages_bio(bdev, sector, nr_sects, gfp, &bio, flags);
 	if (bio) {
 		if ((flags & BLKDEV_ZERO_KILLABLE) &&
 		    fatal_signal_pending(current)) {
@@ -286,7 +300,7 @@  int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
 	} else {
 		if (flags & BLKDEV_ZERO_NOFALLBACK)
 			return -EOPNOTSUPP;
-		__blkdev_issue_zero_pages(bdev, sector, nr_sects, gfp_mask,
+		blkdev_issue_zero_pages_bio(bdev, sector, nr_sects, gfp_mask,
 				biop, flags);
 	}
 	return 0;
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 78ead424484c..87d85b326e1e 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -686,4 +686,8 @@  struct bio *blk_alloc_discard_bio(struct block_device *bdev,
 
 sector_t bio_discard_limit(struct block_device *bdev, sector_t sector);
 
+int blkdev_issue_zero_pages_bio(struct block_device *bdev,
+		sector_t sector, sector_t nr_sects, gfp_t gfp_mask,
+		struct bio **biop, unsigned int flags);
+
 #endif /* __LINUX_BIO_H */
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 643c9020a35a..bf1aa951fda2 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1098,6 +1098,7 @@  int blkdev_issue_secure_erase(struct block_device *bdev, sector_t sector,
 #define BLKDEV_ZERO_NOUNMAP	(1 << 0)  /* do not free blocks */
 #define BLKDEV_ZERO_NOFALLBACK	(1 << 1)  /* don't write explicit zeroes */
 #define BLKDEV_ZERO_KILLABLE	(1 << 2)  /* interruptible by fatal signals */
+#define BLKDEV_ZERO_PAGES_NOWAIT (1 << 3) /* non-blocking submission  */
 
 extern int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
 		sector_t nr_sects, gfp_t gfp_mask, struct bio **biop,