]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - block/blk-sysfs.c
block: optionally merge discontiguous discard bios into a single request
[mirror_ubuntu-artful-kernel.git] / block / blk-sysfs.c
index 1dbce057592d3bacf9709718799c270d3f7827b5..070d81bae1d50af56fbc4d1a6135b54e7ede82f8 100644 (file)
@@ -89,7 +89,7 @@ queue_requests_store(struct request_queue *q, const char *page, size_t count)
 
 static ssize_t queue_ra_show(struct request_queue *q, char *page)
 {
-       unsigned long ra_kb = q->backing_dev_info.ra_pages <<
+       unsigned long ra_kb = q->backing_dev_info->ra_pages <<
                                        (PAGE_SHIFT - 10);
 
        return queue_var_show(ra_kb, (page));
@@ -104,7 +104,7 @@ queue_ra_store(struct request_queue *q, const char *page, size_t count)
        if (ret < 0)
                return ret;
 
-       q->backing_dev_info.ra_pages = ra_kb >> (PAGE_SHIFT - 10);
+       q->backing_dev_info->ra_pages = ra_kb >> (PAGE_SHIFT - 10);
 
        return ret;
 }
@@ -121,6 +121,12 @@ static ssize_t queue_max_segments_show(struct request_queue *q, char *page)
        return queue_var_show(queue_max_segments(q), (page));
 }
 
+static ssize_t queue_max_discard_segments_show(struct request_queue *q,
+               char *page)
+{
+       return queue_var_show(queue_max_discard_segments(q), (page));
+}
+
 static ssize_t queue_max_integrity_segments_show(struct request_queue *q, char *page)
 {
        return queue_var_show(q->limits.max_integrity_segments, (page));
@@ -236,7 +242,7 @@ queue_max_sectors_store(struct request_queue *q, const char *page, size_t count)
 
        spin_lock_irq(q->queue_lock);
        q->limits.max_sectors = max_sectors_kb << 1;
-       q->backing_dev_info.io_pages = max_sectors_kb >> (PAGE_SHIFT - 10);
+       q->backing_dev_info->io_pages = max_sectors_kb >> (PAGE_SHIFT - 10);
        spin_unlock_irq(q->queue_lock);
 
        return ret;
@@ -545,6 +551,11 @@ static struct queue_sysfs_entry queue_max_segments_entry = {
        .show = queue_max_segments_show,
 };
 
+static struct queue_sysfs_entry queue_max_discard_segments_entry = {
+       .attr = {.name = "max_discard_segments", .mode = S_IRUGO },
+       .show = queue_max_discard_segments_show,
+};
+
 static struct queue_sysfs_entry queue_max_integrity_segments_entry = {
        .attr = {.name = "max_integrity_segments", .mode = S_IRUGO },
        .show = queue_max_integrity_segments_show,
@@ -697,6 +708,7 @@ static struct attribute *default_attrs[] = {
        &queue_max_hw_sectors_entry.attr,
        &queue_max_sectors_entry.attr,
        &queue_max_segments_entry.attr,
+       &queue_max_discard_segments_entry.attr,
        &queue_max_integrity_segments_entry.attr,
        &queue_max_segment_size_entry.attr,
        &queue_iosched_entry.attr,
@@ -799,7 +811,7 @@ static void blk_release_queue(struct kobject *kobj)
                container_of(kobj, struct request_queue, kobj);
 
        wbt_exit(q);
-       bdi_exit(&q->backing_dev_info);
+       bdi_put(q->backing_dev_info);
        blkcg_exit_queue(q);
 
        if (q->elevator) {
@@ -814,13 +826,19 @@ static void blk_release_queue(struct kobject *kobj)
        if (q->queue_tags)
                __blk_queue_free_tags(q);
 
-       if (!q->mq_ops)
+       if (!q->mq_ops) {
+               if (q->exit_rq_fn)
+                       q->exit_rq_fn(q, q->fq->flush_rq);
                blk_free_flush_queue(q->fq);
-       else
+       } else {
                blk_mq_release(q);
+       }
 
        blk_trace_shutdown(q);
 
+       if (q->mq_ops)
+               blk_mq_debugfs_unregister(q);
+
        if (q->bio_split)
                bioset_free(q->bio_split);
 
@@ -897,16 +915,15 @@ int blk_register_queue(struct gendisk *disk)
 
        blk_wb_init(q);
 
-       if (!q->request_fn)
-               return 0;
-
-       ret = elv_register_queue(q);
-       if (ret) {
-               kobject_uevent(&q->kobj, KOBJ_REMOVE);
-               kobject_del(&q->kobj);
-               blk_trace_remove_sysfs(dev);
-               kobject_put(&dev->kobj);
-               return ret;
+       if (q->request_fn || (q->mq_ops && q->elevator)) {
+               ret = elv_register_queue(q);
+               if (ret) {
+                       kobject_uevent(&q->kobj, KOBJ_REMOVE);
+                       kobject_del(&q->kobj);
+                       blk_trace_remove_sysfs(dev);
+                       kobject_put(&dev->kobj);
+                       return ret;
+               }
        }
 
        return 0;
@@ -922,7 +939,7 @@ void blk_unregister_queue(struct gendisk *disk)
        if (q->mq_ops)
                blk_mq_unregister_dev(disk_to_dev(disk), q);
 
-       if (q->request_fn)
+       if (q->request_fn || (q->mq_ops && q->elevator))
                elv_unregister_queue(q);
 
        kobject_uevent(&q->kobj, KOBJ_REMOVE);