cfq-iosched: fix the setting of IOPS mode on SSDs
authorJens Axboe <axboe@fb.com>
Wed, 10 Jun 2015 14:01:20 +0000 (08:01 -0600)
committerJens Axboe <axboe@fb.com>
Wed, 10 Jun 2015 14:01:20 +0000 (08:01 -0600)
A previous commit wanted to make CFQ default to IOPS mode on
non-rotational storage, however it did so when the queue was
initialized and the non-rotational flag is only set later on
in the probe.

Add an elevator hook that gets called off the add_disk() path,
at that point we know that feature probing has finished, and
we can reliably check for the various flags that drivers can
set.

Fixes: 41c0126b ("block: Make CFQ default to IOPS mode on SSDs")
Tested-by: Romain Francoise <romain@orebokech.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
block/cfq-iosched.c
block/elevator.c
include/linux/elevator.h

index c808ad87652d2818f7770cc6abd59f02110ab4c8..d1d0cb235cd2dc86dd6bd6e1933be3ffdfb34d47 100644 (file)
@@ -4508,7 +4508,7 @@ static int cfq_init_queue(struct request_queue *q, struct elevator_type *e)
        cfqd->cfq_slice[1] = cfq_slice_sync;
        cfqd->cfq_target_latency = cfq_target_latency;
        cfqd->cfq_slice_async_rq = cfq_slice_async_rq;
-       cfqd->cfq_slice_idle = blk_queue_nonrot(q) ? 0 : cfq_slice_idle;
+       cfqd->cfq_slice_idle = cfq_slice_idle;
        cfqd->cfq_group_idle = cfq_group_idle;
        cfqd->cfq_latency = 1;
        cfqd->hw_tag = -1;
@@ -4525,6 +4525,18 @@ out_free:
        return ret;
 }
 
+static void cfq_registered_queue(struct request_queue *q)
+{
+       struct elevator_queue *e = q->elevator;
+       struct cfq_data *cfqd = e->elevator_data;
+
+       /*
+        * Default to IOPS mode with no idling for SSDs
+        */
+       if (blk_queue_nonrot(q))
+               cfqd->cfq_slice_idle = 0;
+}
+
 /*
  * sysfs parts below -->
  */
@@ -4640,6 +4652,7 @@ static struct elevator_type iosched_cfq = {
                .elevator_may_queue_fn =        cfq_may_queue,
                .elevator_init_fn =             cfq_init_queue,
                .elevator_exit_fn =             cfq_exit_queue,
+               .elevator_registered_fn =       cfq_registered_queue,
        },
        .icq_size       =       sizeof(struct cfq_io_cq),
        .icq_align      =       __alignof__(struct cfq_io_cq),
index 59794d0d38e34604a24b6e7a63bf309570b2f8fb..5f0452734a40277ffeb9f0a9bfc283f2fa6f8d84 100644 (file)
@@ -810,6 +810,8 @@ int elv_register_queue(struct request_queue *q)
                }
                kobject_uevent(&e->kobj, KOBJ_ADD);
                e->registered = 1;
+               if (e->type->ops.elevator_registered_fn)
+                       e->type->ops.elevator_registered_fn(q);
        }
        return error;
 }
index 45a91474487daff11a69bf55a31d7cd146c75f72..638b324f0291c2466fe285a0c4e94dee11fd87f0 100644 (file)
@@ -39,6 +39,7 @@ typedef void (elevator_deactivate_req_fn) (struct request_queue *, struct reques
 typedef int (elevator_init_fn) (struct request_queue *,
                                struct elevator_type *e);
 typedef void (elevator_exit_fn) (struct elevator_queue *);
+typedef void (elevator_registered_fn) (struct request_queue *);
 
 struct elevator_ops
 {
@@ -68,6 +69,7 @@ struct elevator_ops
 
        elevator_init_fn *elevator_init_fn;
        elevator_exit_fn *elevator_exit_fn;
+       elevator_registered_fn *elevator_registered_fn;
 };
 
 #define ELV_NAME_MAX   (16)