|
@@ -4098,3 +4098,144 @@ static ssize_t __FUNC(struct elevator_queue *e, const char *page, size_t count)
|
|
|
if (__data < (MIN)) \
|
|
|
__data = (MIN); \
|
|
|
else if (__data > (MAX)) \
|
|
|
+ __data = (MAX); \
|
|
|
+ if (__CONV) \
|
|
|
+ *(__PTR) = msecs_to_jiffies(__data); \
|
|
|
+ else \
|
|
|
+ *(__PTR) = __data; \
|
|
|
+ return ret; \
|
|
|
+}
|
|
|
+STORE_FUNCTION(cfq_quantum_store, &cfqd->cfq_quantum, 1, UINT_MAX, 0);
|
|
|
+STORE_FUNCTION(cfq_fifo_expire_sync_store, &cfqd->cfq_fifo_expire[1], 1,
|
|
|
+ UINT_MAX, 1);
|
|
|
+STORE_FUNCTION(cfq_fifo_expire_async_store, &cfqd->cfq_fifo_expire[0], 1,
|
|
|
+ UINT_MAX, 1);
|
|
|
+STORE_FUNCTION(cfq_back_seek_max_store, &cfqd->cfq_back_max, 0, UINT_MAX, 0);
|
|
|
+STORE_FUNCTION(cfq_back_seek_penalty_store, &cfqd->cfq_back_penalty, 1,
|
|
|
+ UINT_MAX, 0);
|
|
|
+STORE_FUNCTION(cfq_slice_idle_store, &cfqd->cfq_slice_idle, 0, UINT_MAX, 1);
|
|
|
+STORE_FUNCTION(cfq_group_idle_store, &cfqd->cfq_group_idle, 0, UINT_MAX, 1);
|
|
|
+STORE_FUNCTION(cfq_slice_sync_store, &cfqd->cfq_slice[1], 1, UINT_MAX, 1);
|
|
|
+STORE_FUNCTION(cfq_slice_async_store, &cfqd->cfq_slice[0], 1, UINT_MAX, 1);
|
|
|
+STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1,
|
|
|
+ UINT_MAX, 0);
|
|
|
+STORE_FUNCTION(cfq_low_latency_store, &cfqd->cfq_latency, 0, 1, 0);
|
|
|
+STORE_FUNCTION(cfq_target_latency_store, &cfqd->cfq_target_latency, 1, UINT_MAX, 1);
|
|
|
+#undef STORE_FUNCTION
|
|
|
+
|
|
|
+#define CFQ_ATTR(name) \
|
|
|
+ __ATTR(name, S_IRUGO|S_IWUSR, cfq_##name##_show, cfq_##name##_store)
|
|
|
+
|
|
|
+static struct elv_fs_entry cfq_attrs[] = {
|
|
|
+ CFQ_ATTR(quantum),
|
|
|
+ CFQ_ATTR(fifo_expire_sync),
|
|
|
+ CFQ_ATTR(fifo_expire_async),
|
|
|
+ CFQ_ATTR(back_seek_max),
|
|
|
+ CFQ_ATTR(back_seek_penalty),
|
|
|
+ CFQ_ATTR(slice_sync),
|
|
|
+ CFQ_ATTR(slice_async),
|
|
|
+ CFQ_ATTR(slice_async_rq),
|
|
|
+ CFQ_ATTR(slice_idle),
|
|
|
+ CFQ_ATTR(group_idle),
|
|
|
+ CFQ_ATTR(low_latency),
|
|
|
+ CFQ_ATTR(target_latency),
|
|
|
+ __ATTR_NULL
|
|
|
+};
|
|
|
+
|
|
|
+static struct elevator_type iosched_cfq = {
|
|
|
+ .ops = {
|
|
|
+ .elevator_merge_fn = cfq_merge,
|
|
|
+ .elevator_merged_fn = cfq_merged_request,
|
|
|
+ .elevator_merge_req_fn = cfq_merged_requests,
|
|
|
+ .elevator_allow_merge_fn = cfq_allow_merge,
|
|
|
+ .elevator_bio_merged_fn = cfq_bio_merged,
|
|
|
+ .elevator_dispatch_fn = cfq_dispatch_requests,
|
|
|
+ .elevator_add_req_fn = cfq_insert_request,
|
|
|
+ .elevator_activate_req_fn = cfq_activate_request,
|
|
|
+ .elevator_deactivate_req_fn = cfq_deactivate_request,
|
|
|
+ .elevator_completed_req_fn = cfq_completed_request,
|
|
|
+ .elevator_former_req_fn = elv_rb_former_request,
|
|
|
+ .elevator_latter_req_fn = elv_rb_latter_request,
|
|
|
+ .elevator_init_icq_fn = cfq_init_icq,
|
|
|
+ .elevator_exit_icq_fn = cfq_exit_icq,
|
|
|
+ .elevator_set_req_fn = cfq_set_request,
|
|
|
+ .elevator_put_req_fn = cfq_put_request,
|
|
|
+ .elevator_may_queue_fn = cfq_may_queue,
|
|
|
+ .elevator_init_fn = cfq_init_queue,
|
|
|
+ .elevator_exit_fn = cfq_exit_queue,
|
|
|
+ },
|
|
|
+ .icq_size = sizeof(struct cfq_io_cq),
|
|
|
+ .icq_align = __alignof__(struct cfq_io_cq),
|
|
|
+ .elevator_attrs = cfq_attrs,
|
|
|
+ .elevator_name = "cfq",
|
|
|
+ .elevator_owner = THIS_MODULE,
|
|
|
+};
|
|
|
+
|
|
|
+#ifdef CONFIG_CFQ_GROUP_IOSCHED
|
|
|
+static struct blkcg_policy blkcg_policy_cfq = {
|
|
|
+ .pd_size = sizeof(struct cfq_group),
|
|
|
+ .cftypes = cfq_blkcg_files,
|
|
|
+
|
|
|
+ .pd_init_fn = cfq_pd_init,
|
|
|
+ .pd_reset_stats_fn = cfq_pd_reset_stats,
|
|
|
+};
|
|
|
+#endif
|
|
|
+
|
|
|
+static int __init cfq_init(void)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * could be 0 on HZ < 1000 setups
|
|
|
+ */
|
|
|
+ if (!cfq_slice_async)
|
|
|
+ cfq_slice_async = 1;
|
|
|
+ if (!cfq_slice_idle)
|
|
|
+ cfq_slice_idle = 1;
|
|
|
+
|
|
|
+#ifdef CONFIG_CFQ_GROUP_IOSCHED
|
|
|
+ if (!cfq_group_idle)
|
|
|
+ cfq_group_idle = 1;
|
|
|
+
|
|
|
+ ret = blkcg_policy_register(&blkcg_policy_cfq);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+#else
|
|
|
+ cfq_group_idle = 0;
|
|
|
+#endif
|
|
|
+
|
|
|
+ ret = -ENOMEM;
|
|
|
+ cfq_pool = KMEM_CACHE(cfq_queue, 0);
|
|
|
+ if (!cfq_pool)
|
|
|
+ goto err_pol_unreg;
|
|
|
+
|
|
|
+ ret = elv_register(&iosched_cfq);
|
|
|
+ if (ret)
|
|
|
+ goto err_free_pool;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+
|
|
|
+err_free_pool:
|
|
|
+ kmem_cache_destroy(cfq_pool);
|
|
|
+err_pol_unreg:
|
|
|
+#ifdef CONFIG_CFQ_GROUP_IOSCHED
|
|
|
+ blkcg_policy_unregister(&blkcg_policy_cfq);
|
|
|
+#endif
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static void __exit cfq_exit(void)
|
|
|
+{
|
|
|
+#ifdef CONFIG_CFQ_GROUP_IOSCHED
|
|
|
+ blkcg_policy_unregister(&blkcg_policy_cfq);
|
|
|
+#endif
|
|
|
+ elv_unregister(&iosched_cfq);
|
|
|
+ kmem_cache_destroy(cfq_pool);
|
|
|
+}
|
|
|
+
|
|
|
+module_init(cfq_init);
|
|
|
+module_exit(cfq_exit);
|
|
|
+
|
|
|
+MODULE_AUTHOR("Jens Axboe");
|
|
|
+MODULE_LICENSE("GPL");
|
|
|
+MODULE_DESCRIPTION("Completely Fair Queueing IO scheduler");
|