diff mbox series

[PATCHv2,2/5] nvme: simplify passthrough bio cleanup

Message ID 20230407191636.2631046-3-kbusch@meta.com (mailing list archive)
State New
Headers show
Series nvme io_uring_cmd polling enhancements | expand

Commit Message

Keith Busch April 7, 2023, 7:16 p.m. UTC
From: Keith Busch <kbusch@kernel.org>

Set the bio's bi_end_io to handle the cleanup so that uring_cmd doesn't
need this complex pdu->{bio,req} switchero and restore.

Signed-off-by: Keith Busch <kbusch@kernel.org>
---
 drivers/nvme/host/ioctl.c | 26 +++++++++-----------------
 1 file changed, 9 insertions(+), 17 deletions(-)

Comments

kernel test robot April 8, 2023, 12:22 a.m. UTC | #1
Hi Keith,

kernel test robot noticed the following build warnings:

[auto build test WARNING on axboe-block/for-next]
[also build test WARNING on next-20230406]
[cannot apply to linus/master v6.3-rc5]
[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/Keith-Busch/block-add-request-polling-helper/20230408-031926
base:   https://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git for-next
patch link:    https://lore.kernel.org/r/20230407191636.2631046-3-kbusch%40meta.com
patch subject: [PATCHv2 2/5] nvme: simplify passthrough bio cleanup
config: ia64-allyesconfig (https://download.01.org/0day-ci/archive/20230408/202304080846.C2qDQtUd-lkp@intel.com/config)
compiler: ia64-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/9a32e7ca02dd8cff559b273fe161b5347b5b5c97
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Keith-Busch/block-add-request-polling-helper/20230408-031926
        git checkout 9a32e7ca02dd8cff559b273fe161b5347b5b5c97
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=ia64 olddefconfig
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=ia64 SHELL=/bin/bash drivers/nvme/

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202304080846.C2qDQtUd-lkp@intel.com/

All warnings (new ones prefixed by >>):

   drivers/nvme/host/ioctl.c: In function 'nvme_submit_user_cmd':
>> drivers/nvme/host/ioctl.c:232:21: warning: variable 'bio' set but not used [-Wunused-but-set-variable]
     232 |         struct bio *bio;
         |                     ^~~
   drivers/nvme/host/ioctl.c: In function 'nvme_uring_cmd_end_io_meta':
   drivers/nvme/host/ioctl.c:528:36: warning: unused variable 'pdu' [-Wunused-variable]
     528 |         struct nvme_uring_cmd_pdu *pdu = nvme_uring_cmd_pdu(ioucmd);
         |                                    ^~~


vim +/bio +232 drivers/nvme/host/ioctl.c

2405252a680e21 Christoph Hellwig 2021-04-10  222  
bcad2565b5d647 Christoph Hellwig 2022-05-11  223  static int nvme_submit_user_cmd(struct request_queue *q,
7b7fdb8e2dbc15 Christoph Hellwig 2023-01-08  224  		struct nvme_command *cmd, u64 ubuffer, unsigned bufflen,
7b7fdb8e2dbc15 Christoph Hellwig 2023-01-08  225  		void __user *meta_buffer, unsigned meta_len, u32 meta_seed,
7b7fdb8e2dbc15 Christoph Hellwig 2023-01-08  226  		u64 *result, unsigned timeout, unsigned int flags)
bcad2565b5d647 Christoph Hellwig 2022-05-11  227  {
62281b9ed671be Christoph Hellwig 2022-12-14  228  	struct nvme_ns *ns = q->queuedata;
bc8fb906b0ff93 Keith Busch       2022-09-19  229  	struct nvme_ctrl *ctrl;
bcad2565b5d647 Christoph Hellwig 2022-05-11  230  	struct request *req;
bcad2565b5d647 Christoph Hellwig 2022-05-11  231  	void *meta = NULL;
bcad2565b5d647 Christoph Hellwig 2022-05-11 @232  	struct bio *bio;
bc8fb906b0ff93 Keith Busch       2022-09-19  233  	u32 effects;
bcad2565b5d647 Christoph Hellwig 2022-05-11  234  	int ret;
bcad2565b5d647 Christoph Hellwig 2022-05-11  235  
470e900c8036ff Kanchan Joshi     2022-09-30  236  	req = nvme_alloc_user_request(q, cmd, 0, 0);
bcad2565b5d647 Christoph Hellwig 2022-05-11  237  	if (IS_ERR(req))
bcad2565b5d647 Christoph Hellwig 2022-05-11  238  		return PTR_ERR(req);
bcad2565b5d647 Christoph Hellwig 2022-05-11  239  
470e900c8036ff Kanchan Joshi     2022-09-30  240  	req->timeout = timeout;
470e900c8036ff Kanchan Joshi     2022-09-30  241  	if (ubuffer && bufflen) {
470e900c8036ff Kanchan Joshi     2022-09-30  242  		ret = nvme_map_user_request(req, ubuffer, bufflen, meta_buffer,
7b7fdb8e2dbc15 Christoph Hellwig 2023-01-08  243  				meta_len, meta_seed, &meta, NULL, flags);
470e900c8036ff Kanchan Joshi     2022-09-30  244  		if (ret)
470e900c8036ff Kanchan Joshi     2022-09-30  245  			return ret;
470e900c8036ff Kanchan Joshi     2022-09-30  246  	}
470e900c8036ff Kanchan Joshi     2022-09-30  247  
bcad2565b5d647 Christoph Hellwig 2022-05-11  248  	bio = req->bio;
bc8fb906b0ff93 Keith Busch       2022-09-19  249  	ctrl = nvme_req(req)->ctrl;
bcad2565b5d647 Christoph Hellwig 2022-05-11  250  
62281b9ed671be Christoph Hellwig 2022-12-14  251  	effects = nvme_passthru_start(ctrl, ns, cmd->common.opcode);
62281b9ed671be Christoph Hellwig 2022-12-14  252  	ret = nvme_execute_rq(req, false);
2405252a680e21 Christoph Hellwig 2021-04-10  253  	if (result)
2405252a680e21 Christoph Hellwig 2021-04-10  254  		*result = le64_to_cpu(nvme_req(req)->result.u64);
bcad2565b5d647 Christoph Hellwig 2022-05-11  255  	if (meta)
bcad2565b5d647 Christoph Hellwig 2022-05-11  256  		ret = nvme_finish_user_metadata(req, meta_buffer, meta,
bcad2565b5d647 Christoph Hellwig 2022-05-11  257  						meta_len, ret);
2405252a680e21 Christoph Hellwig 2021-04-10  258  	blk_mq_free_request(req);
bc8fb906b0ff93 Keith Busch       2022-09-19  259  
bc8fb906b0ff93 Keith Busch       2022-09-19  260  	if (effects)
bc8fb906b0ff93 Keith Busch       2022-09-19  261  		nvme_passthru_end(ctrl, effects, cmd, ret);
bc8fb906b0ff93 Keith Busch       2022-09-19  262  
2405252a680e21 Christoph Hellwig 2021-04-10  263  	return ret;
2405252a680e21 Christoph Hellwig 2021-04-10  264  }
2405252a680e21 Christoph Hellwig 2021-04-10  265
Kanchan Joshi April 10, 2023, 11:25 a.m. UTC | #2
On Fri, Apr 07, 2023 at 12:16:33PM -0700, Keith Busch wrote:
>From: Keith Busch <kbusch@kernel.org>
>
>Set the bio's bi_end_io to handle the cleanup so that uring_cmd doesn't
>need this complex pdu->{bio,req} switchero and restore.
>
>Signed-off-by: Keith Busch <kbusch@kernel.org>
>---
> drivers/nvme/host/ioctl.c | 26 +++++++++-----------------
> 1 file changed, 9 insertions(+), 17 deletions(-)
>
>diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c
>index d24ea2e051564..278c57ee0db91 100644
>--- a/drivers/nvme/host/ioctl.c
>+++ b/drivers/nvme/host/ioctl.c
>@@ -159,6 +159,11 @@ static struct request *nvme_alloc_user_request(struct request_queue *q,
> 	return req;
> }
>
>+static void nvme_uring_bio_end_io(struct bio *bio)
>+{
>+	blk_rq_unmap_user(bio);
>+}
>+
> static int nvme_map_user_request(struct request *req, u64 ubuffer,
> 		unsigned bufflen, void __user *meta_buffer, unsigned meta_len,
> 		u32 meta_seed, void **metap, struct io_uring_cmd *ioucmd,
>@@ -204,6 +209,7 @@ static int nvme_map_user_request(struct request *req, u64 ubuffer,
> 		*metap = meta;
> 	}
>
>+	bio->bi_end_io = nvme_uring_bio_end_io;
> 	return ret;
>
> out_unmap:
>@@ -249,8 +255,6 @@ static int nvme_submit_user_cmd(struct request_queue *q,
> 	if (meta)
> 		ret = nvme_finish_user_metadata(req, meta_buffer, meta,
> 						meta_len, ret);
>-	if (bio)
>-		blk_rq_unmap_user(bio);

Is it safe to call blk_rq_unamp_user in irq context?
Agree that current code does some complex stuff, but that's to ensure
what the code-comment [1] says.

Also for polled-io, new-code will hit this warn-on [2] on calling
bio_put_percpu_cache.

[1] 
623  *    A matching blk_rq_unmap_user() must be issued at the end of I/O, while
624  *    still in process context.
625  */
626 int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
627                         struct rq_map_data *map_data,


[2]
773         if ((bio->bi_opf & REQ_POLLED) && !WARN_ON_ONCE(in_interrupt())) {
774                 bio->bi_next = cache->free_list;
kernel test robot April 10, 2023, 9:02 p.m. UTC | #3
Hi Keith,

kernel test robot noticed the following build warnings:

[auto build test WARNING on axboe-block/for-next]
[also build test WARNING on next-20230406]
[cannot apply to linus/master v6.3-rc6]
[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/Keith-Busch/block-add-request-polling-helper/20230408-031926
base:   https://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git for-next
patch link:    https://lore.kernel.org/r/20230407191636.2631046-3-kbusch%40meta.com
patch subject: [PATCHv2 2/5] nvme: simplify passthrough bio cleanup
config: x86_64-rhel-8.3 (https://download.01.org/0day-ci/archive/20230411/202304110443.e026C3nq-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.3.0-8) 11.3.0
reproduce (this is a W=1 build):
        # https://github.com/intel-lab-lkp/linux/commit/9a32e7ca02dd8cff559b273fe161b5347b5b5c97
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Keith-Busch/block-add-request-polling-helper/20230408-031926
        git checkout 9a32e7ca02dd8cff559b273fe161b5347b5b5c97
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        make W=1 O=build_dir ARCH=x86_64 olddefconfig
        make W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash drivers/nvme/host/

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202304110443.e026C3nq-lkp@intel.com/

All warnings (new ones prefixed by >>):

   drivers/nvme/host/ioctl.c: In function 'nvme_submit_user_cmd':
   drivers/nvme/host/ioctl.c:232:21: warning: variable 'bio' set but not used [-Wunused-but-set-variable]
     232 |         struct bio *bio;
         |                     ^~~
   drivers/nvme/host/ioctl.c: In function 'nvme_uring_cmd_end_io_meta':
>> drivers/nvme/host/ioctl.c:528:36: warning: unused variable 'pdu' [-Wunused-variable]
     528 |         struct nvme_uring_cmd_pdu *pdu = nvme_uring_cmd_pdu(ioucmd);
         |                                    ^~~


vim +/pdu +528 drivers/nvme/host/ioctl.c

c0a7ba77e81b84 Jens Axboe    2022-09-21  523  
c0a7ba77e81b84 Jens Axboe    2022-09-21  524  static enum rq_end_io_ret nvme_uring_cmd_end_io_meta(struct request *req,
c0a7ba77e81b84 Jens Axboe    2022-09-21  525  						     blk_status_t err)
c0a7ba77e81b84 Jens Axboe    2022-09-21  526  {
c0a7ba77e81b84 Jens Axboe    2022-09-21  527  	struct io_uring_cmd *ioucmd = req->end_io_data;
c0a7ba77e81b84 Jens Axboe    2022-09-21 @528  	struct nvme_uring_cmd_pdu *pdu = nvme_uring_cmd_pdu(ioucmd);
c0a7ba77e81b84 Jens Axboe    2022-09-21  529  	void *cookie = READ_ONCE(ioucmd->cookie);
c0a7ba77e81b84 Jens Axboe    2022-09-21  530  
c0a7ba77e81b84 Jens Axboe    2022-09-21  531  	/*
c0a7ba77e81b84 Jens Axboe    2022-09-21  532  	 * For iopoll, complete it directly.
c0a7ba77e81b84 Jens Axboe    2022-09-21  533  	 * Otherwise, move the completion to task work.
c0a7ba77e81b84 Jens Axboe    2022-09-21  534  	 */
c0a7ba77e81b84 Jens Axboe    2022-09-21  535  	if (cookie != NULL && blk_rq_is_poll(req))
9d2789ac9d60c0 Jens Axboe    2023-03-20  536  		nvme_uring_task_meta_cb(ioucmd, IO_URING_F_UNLOCKED);
c0a7ba77e81b84 Jens Axboe    2022-09-21  537  	else
c0a7ba77e81b84 Jens Axboe    2022-09-21  538  		io_uring_cmd_complete_in_task(ioucmd, nvme_uring_task_meta_cb);
c0a7ba77e81b84 Jens Axboe    2022-09-21  539  
de671d6116b521 Jens Axboe    2022-09-21  540  	return RQ_END_IO_NONE;
456cba386e94f2 Kanchan Joshi 2022-05-11  541  }
456cba386e94f2 Kanchan Joshi 2022-05-11  542
Keith Busch April 11, 2023, 5:46 p.m. UTC | #4
On Mon, Apr 10, 2023 at 04:55:03PM +0530, Kanchan Joshi wrote:
> On Fri, Apr 07, 2023 at 12:16:33PM -0700, Keith Busch wrote:
> > +static void nvme_uring_bio_end_io(struct bio *bio)
> > +{
> > +	blk_rq_unmap_user(bio);
> > +}
> > +
> > static int nvme_map_user_request(struct request *req, u64 ubuffer,
> > 		unsigned bufflen, void __user *meta_buffer, unsigned meta_len,
> > 		u32 meta_seed, void **metap, struct io_uring_cmd *ioucmd,
> > @@ -204,6 +209,7 @@ static int nvme_map_user_request(struct request *req, u64 ubuffer,
> > 		*metap = meta;
> > 	}
> > 
> > +	bio->bi_end_io = nvme_uring_bio_end_io;
> > 	return ret;
> > 
> > out_unmap:
> > @@ -249,8 +255,6 @@ static int nvme_submit_user_cmd(struct request_queue *q,
> > 	if (meta)
> > 		ret = nvme_finish_user_metadata(req, meta_buffer, meta,
> > 						meta_len, ret);
> > -	if (bio)
> > -		blk_rq_unmap_user(bio);
> 
> Is it safe to call blk_rq_unamp_user in irq context?

Doh! I boxed my thinking into the polling mode that completely neglected the
more common use case. Thanks, now back to the drawing board for me...
diff mbox series

Patch

diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c
index d24ea2e051564..278c57ee0db91 100644
--- a/drivers/nvme/host/ioctl.c
+++ b/drivers/nvme/host/ioctl.c
@@ -159,6 +159,11 @@  static struct request *nvme_alloc_user_request(struct request_queue *q,
 	return req;
 }
 
+static void nvme_uring_bio_end_io(struct bio *bio)
+{
+	blk_rq_unmap_user(bio);
+}
+
 static int nvme_map_user_request(struct request *req, u64 ubuffer,
 		unsigned bufflen, void __user *meta_buffer, unsigned meta_len,
 		u32 meta_seed, void **metap, struct io_uring_cmd *ioucmd,
@@ -204,6 +209,7 @@  static int nvme_map_user_request(struct request *req, u64 ubuffer,
 		*metap = meta;
 	}
 
+	bio->bi_end_io = nvme_uring_bio_end_io;
 	return ret;
 
 out_unmap:
@@ -249,8 +255,6 @@  static int nvme_submit_user_cmd(struct request_queue *q,
 	if (meta)
 		ret = nvme_finish_user_metadata(req, meta_buffer, meta,
 						meta_len, ret);
-	if (bio)
-		blk_rq_unmap_user(bio);
 	blk_mq_free_request(req);
 
 	if (effects)
@@ -443,10 +447,7 @@  struct nvme_uring_data {
  * Expect build errors if this grows larger than that.
  */
 struct nvme_uring_cmd_pdu {
-	union {
-		struct bio *bio;
-		struct request *req;
-	};
+	struct request *req;
 	u32 meta_len;
 	u32 nvme_status;
 	union {
@@ -482,8 +483,6 @@  static void nvme_uring_task_meta_cb(struct io_uring_cmd *ioucmd,
 	if (pdu->meta_len)
 		status = nvme_finish_user_metadata(req, pdu->u.meta_buffer,
 					pdu->u.meta, pdu->meta_len, status);
-	if (req->bio)
-		blk_rq_unmap_user(req->bio);
 	blk_mq_free_request(req);
 
 	io_uring_cmd_done(ioucmd, status, result, issue_flags);
@@ -494,9 +493,6 @@  static void nvme_uring_task_cb(struct io_uring_cmd *ioucmd,
 {
 	struct nvme_uring_cmd_pdu *pdu = nvme_uring_cmd_pdu(ioucmd);
 
-	if (pdu->bio)
-		blk_rq_unmap_user(pdu->bio);
-
 	io_uring_cmd_done(ioucmd, pdu->nvme_status, pdu->u.result, issue_flags);
 }
 
@@ -507,7 +503,6 @@  static enum rq_end_io_ret nvme_uring_cmd_end_io(struct request *req,
 	struct nvme_uring_cmd_pdu *pdu = nvme_uring_cmd_pdu(ioucmd);
 	void *cookie = READ_ONCE(ioucmd->cookie);
 
-	req->bio = pdu->bio;
 	if (nvme_req(req)->flags & NVME_REQ_CANCELLED)
 		pdu->nvme_status = -EINTR;
 	else
@@ -533,9 +528,6 @@  static enum rq_end_io_ret nvme_uring_cmd_end_io_meta(struct request *req,
 	struct nvme_uring_cmd_pdu *pdu = nvme_uring_cmd_pdu(ioucmd);
 	void *cookie = READ_ONCE(ioucmd->cookie);
 
-	req->bio = pdu->bio;
-	pdu->req = req;
-
 	/*
 	 * For iopoll, complete it directly.
 	 * Otherwise, move the completion to task work.
@@ -624,8 +616,8 @@  static int nvme_uring_cmd_io(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
 			req->bio->bi_opf |= REQ_POLLED;
 		}
 	}
-	/* to free bio on completion, as req->bio will be null at that time */
-	pdu->bio = req->bio;
+
+	pdu->req = req;
 	pdu->meta_len = d.metadata_len;
 	req->end_io_data = ioucmd;
 	if (pdu->meta_len) {