Message ID | 20221208104351.35038-7-paolo.valente@linaro.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | block, bfq: extend bfq to support multi-actuator drives | expand |
On 12/8/22 19:43, Paolo Valente wrote: > From: Federico Gavioli <f.gavioli97@gmail.com> > > This patch implements the code to gather the content of the > independent_access_ranges structure from the request_queue and copy > it into the queue's bfq_data. This copy is done at queue initialization. > > We copy the access ranges into the bfq_data to avoid taking the queue > lock each time we access the ranges. > > This implementation, however, puts a limit to the maximum independent > ranges supported by the scheduler. Such a limit is equal to the constant > BFQ_MAX_ACTUATORS. This limit was placed to avoid the allocation of > dynamic memory. > > Co-developed-by: Rory Chen <rory.c.chen@seagate.com> > Signed-off-by: Rory Chen <rory.c.chen@seagate.com> > Signed-off-by: Federico Gavioli <f.gavioli97@gmail.com> > Signed-off-by: Paolo Valente <paolo.valente@linaro.org> > --- > block/bfq-iosched.c | 60 +++++++++++++++++++++++++++++++++++++++------ > block/bfq-iosched.h | 8 +++++- > 2 files changed, 59 insertions(+), 9 deletions(-) > > diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c > index dcecba3c6e23..957ce61faaf2 100644 > --- a/block/bfq-iosched.c > +++ b/block/bfq-iosched.c > @@ -1839,10 +1839,25 @@ static bool bfq_bfqq_higher_class_or_weight(struct bfq_queue *bfqq, > */ > static unsigned int bfq_actuator_index(struct bfq_data *bfqd, struct bio *bio) > { > - /* > - * Multi-actuator support not complete yet, so always return 0 > - * for the moment (to keep incomplete mechanisms off). > - */ > + unsigned int i; > + sector_t end; > + > + /* no search needed if one or zero ranges present */ > + if (bfqd->num_actuators == 1) > + return 0; > + > + /* bio_end_sector(bio) gives the sector after the last one */ > + end = bio_end_sector(bio) - 1; > + > + for (i = 0; i < bfqd->num_actuators; i++) { > + if (end >= bfqd->sector[i] && > + end < bfqd->sector[i] + bfqd->nr_sectors[i]) > + return i; > + } > + > + WARN_ONCE(true, > + "bfq_actuator_index: bio sector out of ranges: end=%llu\n", > + end); > return 0; > } > > @@ -7160,6 +7175,8 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_type *e) > { > struct bfq_data *bfqd; > struct elevator_queue *eq; > + unsigned int i; > + struct blk_independent_access_ranges *ia_ranges = q->disk->ia_ranges; > > eq = elevator_alloc(q, e); > if (!eq) > @@ -7202,12 +7219,39 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_type *e) > > bfqd->queue = q; > > + bfqd->num_actuators = 1; > /* > - * Multi-actuator support not complete yet, unconditionally > - * set to only one actuator for the moment (to keep incomplete > - * mechanisms off). > + * If the disk supports multiple actuators, copy independent > + * access ranges from the request queue structure. > */ > - bfqd->num_actuators = 1; > + spin_lock_irq(&q->queue_lock); > + if (ia_ranges) { > + /* > + * Check if the disk ia_ranges size exceeds the current bfq > + * actuator limit. > + */ > + if (ia_ranges->nr_ia_ranges > BFQ_MAX_ACTUATORS) { > + pr_crit("nr_ia_ranges higher than act limit: iars=%d, max=%d.\n", > + ia_ranges->nr_ia_ranges, BFQ_MAX_ACTUATORS); > + pr_crit("Falling back to single actuator mode.\n"); > + } else { > + bfqd->num_actuators = ia_ranges->nr_ia_ranges; > + > + for (i = 0; i < bfqd->num_actuators; i++) { > + bfqd->sector[i] = ia_ranges->ia_range[i].sector; > + bfqd->nr_sectors[i] = > + ia_ranges->ia_range[i].nr_sectors; > + } > + } > + } > + > + /* Otherwise use single-actuator dev info */ > + if (bfqd->num_actuators == 1) { > + bfqd->sector[0] = 0; > + bfqd->nr_sectors[0] = > + bdev_nr_sectors(dev_to_bdev(disk_to_dev(q->disk))); get_capacity(q->disk) would be simpler. > + } > + spin_unlock_irq(&q->queue_lock); > > INIT_LIST_HEAD(&bfqd->dispatch); > > diff --git a/block/bfq-iosched.h b/block/bfq-iosched.h > index 1450990dba32..953980de6b4b 100644 > --- a/block/bfq-iosched.h > +++ b/block/bfq-iosched.h > @@ -810,7 +810,13 @@ struct bfq_data { > * case of single-actuator drives. > */ > unsigned int num_actuators; > - > + /* > + * Disk independent access ranges for each actuator > + * in this device. > + */ > + sector_t sector[BFQ_MAX_ACTUATORS]; > + sector_t nr_sectors[BFQ_MAX_ACTUATORS]; > + struct blk_independent_access_range ia_ranges[BFQ_MAX_ACTUATORS]; > }; > > enum bfqq_state_flags { With the nit above fixed, Reviewed-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c index dcecba3c6e23..957ce61faaf2 100644 --- a/block/bfq-iosched.c +++ b/block/bfq-iosched.c @@ -1839,10 +1839,25 @@ static bool bfq_bfqq_higher_class_or_weight(struct bfq_queue *bfqq, */ static unsigned int bfq_actuator_index(struct bfq_data *bfqd, struct bio *bio) { - /* - * Multi-actuator support not complete yet, so always return 0 - * for the moment (to keep incomplete mechanisms off). - */ + unsigned int i; + sector_t end; + + /* no search needed if one or zero ranges present */ + if (bfqd->num_actuators == 1) + return 0; + + /* bio_end_sector(bio) gives the sector after the last one */ + end = bio_end_sector(bio) - 1; + + for (i = 0; i < bfqd->num_actuators; i++) { + if (end >= bfqd->sector[i] && + end < bfqd->sector[i] + bfqd->nr_sectors[i]) + return i; + } + + WARN_ONCE(true, + "bfq_actuator_index: bio sector out of ranges: end=%llu\n", + end); return 0; } @@ -7160,6 +7175,8 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_type *e) { struct bfq_data *bfqd; struct elevator_queue *eq; + unsigned int i; + struct blk_independent_access_ranges *ia_ranges = q->disk->ia_ranges; eq = elevator_alloc(q, e); if (!eq) @@ -7202,12 +7219,39 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_type *e) bfqd->queue = q; + bfqd->num_actuators = 1; /* - * Multi-actuator support not complete yet, unconditionally - * set to only one actuator for the moment (to keep incomplete - * mechanisms off). + * If the disk supports multiple actuators, copy independent + * access ranges from the request queue structure. */ - bfqd->num_actuators = 1; + spin_lock_irq(&q->queue_lock); + if (ia_ranges) { + /* + * Check if the disk ia_ranges size exceeds the current bfq + * actuator limit. + */ + if (ia_ranges->nr_ia_ranges > BFQ_MAX_ACTUATORS) { + pr_crit("nr_ia_ranges higher than act limit: iars=%d, max=%d.\n", + ia_ranges->nr_ia_ranges, BFQ_MAX_ACTUATORS); + pr_crit("Falling back to single actuator mode.\n"); + } else { + bfqd->num_actuators = ia_ranges->nr_ia_ranges; + + for (i = 0; i < bfqd->num_actuators; i++) { + bfqd->sector[i] = ia_ranges->ia_range[i].sector; + bfqd->nr_sectors[i] = + ia_ranges->ia_range[i].nr_sectors; + } + } + } + + /* Otherwise use single-actuator dev info */ + if (bfqd->num_actuators == 1) { + bfqd->sector[0] = 0; + bfqd->nr_sectors[0] = + bdev_nr_sectors(dev_to_bdev(disk_to_dev(q->disk))); + } + spin_unlock_irq(&q->queue_lock); INIT_LIST_HEAD(&bfqd->dispatch); diff --git a/block/bfq-iosched.h b/block/bfq-iosched.h index 1450990dba32..953980de6b4b 100644 --- a/block/bfq-iosched.h +++ b/block/bfq-iosched.h @@ -810,7 +810,13 @@ struct bfq_data { * case of single-actuator drives. */ unsigned int num_actuators; - + /* + * Disk independent access ranges for each actuator + * in this device. + */ + sector_t sector[BFQ_MAX_ACTUATORS]; + sector_t nr_sectors[BFQ_MAX_ACTUATORS]; + struct blk_independent_access_range ia_ranges[BFQ_MAX_ACTUATORS]; }; enum bfqq_state_flags {