OSDN Git Service

md: add support for REQ_NOWAIT
authorVishal Verma <vverma@digitalocean.com>
Tue, 21 Dec 2021 20:06:19 +0000 (20:06 +0000)
committerSong Liu <song@kernel.org>
Thu, 6 Jan 2022 16:37:02 +0000 (08:37 -0800)
commit 021a24460dc2 ("block: add QUEUE_FLAG_NOWAIT") added support
for checking whether a given bdev supports handling of REQ_NOWAIT or not.
Since then commit 6abc49468eea ("dm: add support for REQ_NOWAIT and enable
it for linear target") added support for REQ_NOWAIT for dm. This uses
a similar approach to incorporate REQ_NOWAIT for md based bios.

This patch was tested using t/io_uring tool within FIO. A nvme drive
was partitioned into 2 partitions and a simple raid 0 configuration
/dev/md0 was created.

md0 : active raid0 nvme4n1p1[1] nvme4n1p2[0]
      937423872 blocks super 1.2 512k chunks

Before patch:

$ ./t/io_uring /dev/md0 -p 0 -a 0 -d 1 -r 100

Running top while the above runs:

$ ps -eL | grep $(pidof io_uring)

  38396   38396 pts/2    00:00:00 io_uring
  38396   38397 pts/2    00:00:15 io_uring
  38396   38398 pts/2    00:00:13 iou-wrk-38397

We can see iou-wrk-38397 io worker thread created which gets created
when io_uring sees that the underlying device (/dev/md0 in this case)
doesn't support nowait.

After patch:

$ ./t/io_uring /dev/md0 -p 0 -a 0 -d 1 -r 100

Running top while the above runs:

$ ps -eL | grep $(pidof io_uring)

  38341   38341 pts/2    00:10:22 io_uring
  38341   38342 pts/2    00:10:37 io_uring

After running this patch, we don't see any io worker thread
being created which indicated that io_uring saw that the
underlying device does support nowait. This is the exact behaviour
noticed on a dm device which also supports nowait.

For all the other raid personalities except raid0, we would need
to train pieces which involves make_request fn in order for them
to correctly handle REQ_NOWAIT.

Reviewed-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Vishal Verma <vverma@digitalocean.com>
Signed-off-by: Song Liu <song@kernel.org>
drivers/md/md.c

index 7fbf6f0..c6de7d4 100644 (file)
@@ -418,6 +418,12 @@ check_suspended:
        rcu_read_lock();
        if (is_suspended(mddev, bio)) {
                DEFINE_WAIT(__wait);
+               /* Bail out if REQ_NOWAIT is set for the bio */
+               if (bio->bi_opf & REQ_NOWAIT) {
+                       rcu_read_unlock();
+                       bio_wouldblock_error(bio);
+                       return;
+               }
                for (;;) {
                        prepare_to_wait(&mddev->sb_wait, &__wait,
                                        TASK_UNINTERRUPTIBLE);
@@ -5787,6 +5793,7 @@ int md_run(struct mddev *mddev)
        int err;
        struct md_rdev *rdev;
        struct md_personality *pers;
+       bool nowait = true;
 
        if (list_empty(&mddev->disks))
                /* cannot run an array with no devices.. */
@@ -5857,8 +5864,13 @@ int md_run(struct mddev *mddev)
                        }
                }
                sysfs_notify_dirent_safe(rdev->sysfs_state);
+               nowait = nowait && blk_queue_nowait(bdev_get_queue(rdev->bdev));
        }
 
+       /* Set the NOWAIT flags if all underlying devices support it */
+       if (nowait)
+               blk_queue_flag_set(QUEUE_FLAG_NOWAIT, mddev->queue);
+
        if (!bioset_initialized(&mddev->bio_set)) {
                err = bioset_init(&mddev->bio_set, BIO_POOL_SIZE, 0, BIOSET_NEED_BVECS);
                if (err)
@@ -7003,6 +7015,15 @@ static int hot_add_disk(struct mddev *mddev, dev_t dev)
        if (!mddev->thread)
                md_update_sb(mddev, 1);
        /*
+        * If the new disk does not support REQ_NOWAIT,
+        * disable on the whole MD.
+        */
+       if (!blk_queue_nowait(bdev_get_queue(rdev->bdev))) {
+               pr_info("%s: Disabling nowait because %s does not support nowait\n",
+                       mdname(mddev), bdevname(rdev->bdev, b));
+               blk_queue_flag_clear(QUEUE_FLAG_NOWAIT, mddev->queue);
+       }
+       /*
         * Kick recovery, maybe this spare has to be added to the
         * array immediately.
         */