On Tue, Dec 21, 2021 at 12:06 PM Vishal Verma <vverma@xxxxxxxxxxxxxxxx> wrote: > > This adds nowait support to the RAID10 driver. Very similar to > raid1 driver changes. It makes RAID10 driver return with EAGAIN > for situations where it could wait for eg: > > - Waiting for the barrier, > - Too many pending I/Os to be queued, > - Reshape operation, > - Discard operation. > > wait_barrier() and regular_request_wait() fn are modified to return bool > to support error for wait barriers. They returns true in case of wait > or if wait is not required and returns false if wait was required > but not performed to support nowait. > > Signed-off-by: Vishal Verma <vverma@xxxxxxxxxxxxxxxx> > --- > drivers/md/raid10.c | 90 +++++++++++++++++++++++++++++++-------------- > 1 file changed, 62 insertions(+), 28 deletions(-) > > diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c > index dde98f65bd04..7ceae00e863e 100644 > --- a/drivers/md/raid10.c > +++ b/drivers/md/raid10.c > @@ -952,8 +952,9 @@ static void lower_barrier(struct r10conf *conf) > wake_up(&conf->wait_barrier); > } > > -static void wait_barrier(struct r10conf *conf) > +static bool wait_barrier(struct r10conf *conf, bool nowait) > { > + bool ret = true; > spin_lock_irq(&conf->resync_lock); > if (conf->barrier) { > struct bio_list *bio_list = current->bio_list; > @@ -968,26 +969,33 @@ static void wait_barrier(struct r10conf *conf) > * count down. > */ > raid10_log(conf->mddev, "wait barrier"); > - wait_event_lock_irq(conf->wait_barrier, > - !conf->barrier || > - (atomic_read(&conf->nr_pending) && > - bio_list && > - (!bio_list_empty(&bio_list[0]) || > - !bio_list_empty(&bio_list[1]))) || > - /* move on if recovery thread is > - * blocked by us > - */ > - (conf->mddev->thread->tsk == current && > - test_bit(MD_RECOVERY_RUNNING, > - &conf->mddev->recovery) && > - conf->nr_queued > 0), > - conf->resync_lock); > + /* Return false when nowait flag is set */ > + if (nowait) > + ret = false; > + else > + wait_event_lock_irq(conf->wait_barrier, > + !conf->barrier || > + (atomic_read(&conf->nr_pending) && > + bio_list && > + (!bio_list_empty(&bio_list[0]) || > + !bio_list_empty(&bio_list[1]))) || > + /* move on if recovery thread is > + * blocked by us > + */ > + (conf->mddev->thread->tsk == current && > + test_bit(MD_RECOVERY_RUNNING, > + &conf->mddev->recovery) && > + conf->nr_queued > 0), > + conf->resync_lock); > conf->nr_waiting--; > if (!conf->nr_waiting) > wake_up(&conf->wait_barrier); > } > - atomic_inc(&conf->nr_pending); > + /* Only increment nr_pending when we wait */ > + if (ret) > + atomic_inc(&conf->nr_pending); > spin_unlock_irq(&conf->resync_lock); > + return ret; > } > > static void allow_barrier(struct r10conf *conf) > @@ -1098,21 +1106,30 @@ static void raid10_unplug(struct blk_plug_cb *cb, bool from_schedule) > * currently. > * 2. If IO spans the reshape position. Need to wait for reshape to pass. > */ > -static void regular_request_wait(struct mddev *mddev, struct r10conf *conf, > +static bool regular_request_wait(struct mddev *mddev, struct r10conf *conf, > struct bio *bio, sector_t sectors) This doesn't sound right: regular_request_wait() is called in two places. But we are not checking the return value in either of them. Song [...]