11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Block device elevator/IO-scheduler. 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE 51da177e4SLinus Torvalds * 60fe23479SJens Axboe * 30042000 Jens Axboe <axboe@kernel.dk> : 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * Split the elevator a bit so that it is possible to choose a different 91da177e4SLinus Torvalds * one or even write a new "plug in". There are three pieces: 101da177e4SLinus Torvalds * - elevator_fn, inserts a new request in the queue list 111da177e4SLinus Torvalds * - elevator_merge_fn, decides whether a new buffer can be merged with 121da177e4SLinus Torvalds * an existing request 131da177e4SLinus Torvalds * - elevator_dequeue_fn, called when a request is taken off the active list 141da177e4SLinus Torvalds * 151da177e4SLinus Torvalds * 20082000 Dave Jones <davej@suse.de> : 161da177e4SLinus Torvalds * Removed tests for max-bomb-segments, which was breaking elvtune 171da177e4SLinus Torvalds * when run without -bN 181da177e4SLinus Torvalds * 191da177e4SLinus Torvalds * Jens: 201da177e4SLinus Torvalds * - Rework again to work with bio instead of buffer_heads 211da177e4SLinus Torvalds * - loose bi_dev comparisons, partition handling is right now 221da177e4SLinus Torvalds * - completely modularize elevator setup and teardown 231da177e4SLinus Torvalds * 241da177e4SLinus Torvalds */ 251da177e4SLinus Torvalds #include <linux/kernel.h> 261da177e4SLinus Torvalds #include <linux/fs.h> 271da177e4SLinus Torvalds #include <linux/blkdev.h> 281da177e4SLinus Torvalds #include <linux/elevator.h> 291da177e4SLinus Torvalds #include <linux/bio.h> 301da177e4SLinus Torvalds #include <linux/module.h> 311da177e4SLinus Torvalds #include <linux/slab.h> 321da177e4SLinus Torvalds #include <linux/init.h> 331da177e4SLinus Torvalds #include <linux/compiler.h> 342056a782SJens Axboe #include <linux/blktrace_api.h> 359817064bSJens Axboe #include <linux/hash.h> 360835da67SJens Axboe #include <linux/uaccess.h> 371da177e4SLinus Torvalds 3855782138SLi Zefan #include <trace/events/block.h> 3955782138SLi Zefan 40242f9dcbSJens Axboe #include "blk.h" 4172e06c25STejun Heo #include "blk-cgroup.h" 42242f9dcbSJens Axboe 431da177e4SLinus Torvalds static DEFINE_SPINLOCK(elv_list_lock); 441da177e4SLinus Torvalds static LIST_HEAD(elv_list); 451da177e4SLinus Torvalds 461da177e4SLinus Torvalds /* 479817064bSJens Axboe * Merge hash stuff. 489817064bSJens Axboe */ 499817064bSJens Axboe static const int elv_hash_shift = 6; 509817064bSJens Axboe #define ELV_HASH_BLOCK(sec) ((sec) >> 3) 514eb166d9SJens Axboe #define ELV_HASH_FN(sec) \ 524eb166d9SJens Axboe (hash_long(ELV_HASH_BLOCK((sec)), elv_hash_shift)) 539817064bSJens Axboe #define ELV_HASH_ENTRIES (1 << elv_hash_shift) 5483096ebfSTejun Heo #define rq_hash_key(rq) (blk_rq_pos(rq) + blk_rq_sectors(rq)) 559817064bSJens Axboe 569817064bSJens Axboe /* 57da775265SJens Axboe * Query io scheduler to see if the current process issuing bio may be 58da775265SJens Axboe * merged with rq. 59da775265SJens Axboe */ 60da775265SJens Axboe static int elv_iosched_allow_merge(struct request *rq, struct bio *bio) 61da775265SJens Axboe { 62165125e1SJens Axboe struct request_queue *q = rq->q; 63b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 64da775265SJens Axboe 6522f746e2STejun Heo if (e->type->ops.elevator_allow_merge_fn) 6622f746e2STejun Heo return e->type->ops.elevator_allow_merge_fn(q, rq, bio); 67da775265SJens Axboe 68da775265SJens Axboe return 1; 69da775265SJens Axboe } 70da775265SJens Axboe 71da775265SJens Axboe /* 721da177e4SLinus Torvalds * can we safely merge with this request? 731da177e4SLinus Torvalds */ 74050c8ea8STejun Heo bool elv_rq_merge_ok(struct request *rq, struct bio *bio) 751da177e4SLinus Torvalds { 76050c8ea8STejun Heo if (!blk_rq_merge_ok(rq, bio)) 777ba1ba12SMartin K. Petersen return 0; 787ba1ba12SMartin K. Petersen 79da775265SJens Axboe if (!elv_iosched_allow_merge(rq, bio)) 80da775265SJens Axboe return 0; 81da775265SJens Axboe 82da775265SJens Axboe return 1; 831da177e4SLinus Torvalds } 841da177e4SLinus Torvalds EXPORT_SYMBOL(elv_rq_merge_ok); 851da177e4SLinus Torvalds 861da177e4SLinus Torvalds static struct elevator_type *elevator_find(const char *name) 871da177e4SLinus Torvalds { 88a22b169dSVasily Tarasov struct elevator_type *e; 891da177e4SLinus Torvalds 9070cee26eSMatthias Kaehlcke list_for_each_entry(e, &elv_list, list) { 91a22b169dSVasily Tarasov if (!strcmp(e->elevator_name, name)) 921da177e4SLinus Torvalds return e; 931da177e4SLinus Torvalds } 941da177e4SLinus Torvalds 95a22b169dSVasily Tarasov return NULL; 96a22b169dSVasily Tarasov } 97a22b169dSVasily Tarasov 981da177e4SLinus Torvalds static void elevator_put(struct elevator_type *e) 991da177e4SLinus Torvalds { 1001da177e4SLinus Torvalds module_put(e->elevator_owner); 1011da177e4SLinus Torvalds } 1021da177e4SLinus Torvalds 1031da177e4SLinus Torvalds static struct elevator_type *elevator_get(const char *name) 1041da177e4SLinus Torvalds { 1052824bc93STejun Heo struct elevator_type *e; 1061da177e4SLinus Torvalds 1072a12dcd7SJens Axboe spin_lock(&elv_list_lock); 1082824bc93STejun Heo 1092824bc93STejun Heo e = elevator_find(name); 110e1640949SJens Axboe if (!e) { 111e1640949SJens Axboe spin_unlock(&elv_list_lock); 112490b94beSKees Cook request_module("%s-iosched", name); 113e1640949SJens Axboe spin_lock(&elv_list_lock); 114e1640949SJens Axboe e = elevator_find(name); 115e1640949SJens Axboe } 116e1640949SJens Axboe 1172824bc93STejun Heo if (e && !try_module_get(e->elevator_owner)) 1182824bc93STejun Heo e = NULL; 1192824bc93STejun Heo 1202a12dcd7SJens Axboe spin_unlock(&elv_list_lock); 1211da177e4SLinus Torvalds 1221da177e4SLinus Torvalds return e; 1231da177e4SLinus Torvalds } 1241da177e4SLinus Torvalds 125484fc254SWang Sheng-Hui static char chosen_elevator[ELV_NAME_MAX]; 1261da177e4SLinus Torvalds 1275f003976SNate Diller static int __init elevator_setup(char *str) 1281da177e4SLinus Torvalds { 129752a3b79SChuck Ebbert /* 130752a3b79SChuck Ebbert * Be backwards-compatible with previous kernels, so users 131752a3b79SChuck Ebbert * won't get the wrong elevator. 132752a3b79SChuck Ebbert */ 1331da177e4SLinus Torvalds strncpy(chosen_elevator, str, sizeof(chosen_elevator) - 1); 1349b41046cSOGAWA Hirofumi return 1; 1351da177e4SLinus Torvalds } 1361da177e4SLinus Torvalds 1371da177e4SLinus Torvalds __setup("elevator=", elevator_setup); 1381da177e4SLinus Torvalds 1393d1ab40fSAl Viro static struct kobj_type elv_ktype; 1403d1ab40fSAl Viro 141b374d18aSJens Axboe static struct elevator_queue *elevator_alloc(struct request_queue *q, 142165125e1SJens Axboe struct elevator_type *e) 1433d1ab40fSAl Viro { 144b374d18aSJens Axboe struct elevator_queue *eq; 1459817064bSJens Axboe int i; 1469817064bSJens Axboe 147b374d18aSJens Axboe eq = kmalloc_node(sizeof(*eq), GFP_KERNEL | __GFP_ZERO, q->node); 1489817064bSJens Axboe if (unlikely(!eq)) 1499817064bSJens Axboe goto err; 1509817064bSJens Axboe 15122f746e2STejun Heo eq->type = e; 152f9cb074bSGreg Kroah-Hartman kobject_init(&eq->kobj, &elv_ktype); 1533d1ab40fSAl Viro mutex_init(&eq->sysfs_lock); 1549817064bSJens Axboe 155b5deef90SJens Axboe eq->hash = kmalloc_node(sizeof(struct hlist_head) * ELV_HASH_ENTRIES, 156b5deef90SJens Axboe GFP_KERNEL, q->node); 1579817064bSJens Axboe if (!eq->hash) 1589817064bSJens Axboe goto err; 1599817064bSJens Axboe 1609817064bSJens Axboe for (i = 0; i < ELV_HASH_ENTRIES; i++) 1619817064bSJens Axboe INIT_HLIST_HEAD(&eq->hash[i]); 1629817064bSJens Axboe 1633d1ab40fSAl Viro return eq; 1649817064bSJens Axboe err: 1659817064bSJens Axboe kfree(eq); 1669817064bSJens Axboe elevator_put(e); 1679817064bSJens Axboe return NULL; 1683d1ab40fSAl Viro } 1693d1ab40fSAl Viro 1703d1ab40fSAl Viro static void elevator_release(struct kobject *kobj) 1713d1ab40fSAl Viro { 172b374d18aSJens Axboe struct elevator_queue *e; 1739817064bSJens Axboe 174b374d18aSJens Axboe e = container_of(kobj, struct elevator_queue, kobj); 17522f746e2STejun Heo elevator_put(e->type); 1769817064bSJens Axboe kfree(e->hash); 1773d1ab40fSAl Viro kfree(e); 1783d1ab40fSAl Viro } 1793d1ab40fSAl Viro 180165125e1SJens Axboe int elevator_init(struct request_queue *q, char *name) 1811da177e4SLinus Torvalds { 1821da177e4SLinus Torvalds struct elevator_type *e = NULL; 183f8fc877dSTejun Heo int err; 1841da177e4SLinus Torvalds 1851abec4fdSMike Snitzer if (unlikely(q->elevator)) 1861abec4fdSMike Snitzer return 0; 1871abec4fdSMike Snitzer 188cb98fc8bSTejun Heo INIT_LIST_HEAD(&q->queue_head); 189cb98fc8bSTejun Heo q->last_merge = NULL; 190cb98fc8bSTejun Heo q->end_sector = 0; 191cb98fc8bSTejun Heo q->boundary_rq = NULL; 192cb98fc8bSTejun Heo 1934eb166d9SJens Axboe if (name) { 1944eb166d9SJens Axboe e = elevator_get(name); 1954eb166d9SJens Axboe if (!e) 1961da177e4SLinus Torvalds return -EINVAL; 1974eb166d9SJens Axboe } 1981da177e4SLinus Torvalds 1994eb166d9SJens Axboe if (!e && *chosen_elevator) { 2004eb166d9SJens Axboe e = elevator_get(chosen_elevator); 2014eb166d9SJens Axboe if (!e) 2024eb166d9SJens Axboe printk(KERN_ERR "I/O scheduler %s not found\n", 2034eb166d9SJens Axboe chosen_elevator); 2044eb166d9SJens Axboe } 205248d5ca5SNate Diller 2064eb166d9SJens Axboe if (!e) { 2074eb166d9SJens Axboe e = elevator_get(CONFIG_DEFAULT_IOSCHED); 2084eb166d9SJens Axboe if (!e) { 2094eb166d9SJens Axboe printk(KERN_ERR 2104eb166d9SJens Axboe "Default I/O scheduler not found. " \ 2114eb166d9SJens Axboe "Using noop.\n"); 212248d5ca5SNate Diller e = elevator_get("noop"); 2135f003976SNate Diller } 2144eb166d9SJens Axboe } 2155f003976SNate Diller 2165a5bafdcSTejun Heo q->elevator = elevator_alloc(q, e); 2175a5bafdcSTejun Heo if (!q->elevator) 2181da177e4SLinus Torvalds return -ENOMEM; 2191da177e4SLinus Torvalds 220b2fab5acSTejun Heo err = e->ops.elevator_init_fn(q); 221f8fc877dSTejun Heo if (err) { 2225a5bafdcSTejun Heo kobject_put(&q->elevator->kobj); 223f8fc877dSTejun Heo return err; 224bc1c1169SJens Axboe } 2251da177e4SLinus Torvalds 2261abec4fdSMike Snitzer return 0; 2271da177e4SLinus Torvalds } 2282e662b65SJens Axboe EXPORT_SYMBOL(elevator_init); 2292e662b65SJens Axboe 230b374d18aSJens Axboe void elevator_exit(struct elevator_queue *e) 2311da177e4SLinus Torvalds { 2323d1ab40fSAl Viro mutex_lock(&e->sysfs_lock); 23322f746e2STejun Heo if (e->type->ops.elevator_exit_fn) 23422f746e2STejun Heo e->type->ops.elevator_exit_fn(e); 2353d1ab40fSAl Viro mutex_unlock(&e->sysfs_lock); 2361da177e4SLinus Torvalds 2373d1ab40fSAl Viro kobject_put(&e->kobj); 2381da177e4SLinus Torvalds } 2392e662b65SJens Axboe EXPORT_SYMBOL(elevator_exit); 2402e662b65SJens Axboe 2419817064bSJens Axboe static inline void __elv_rqhash_del(struct request *rq) 2429817064bSJens Axboe { 2439817064bSJens Axboe hlist_del_init(&rq->hash); 2449817064bSJens Axboe } 2459817064bSJens Axboe 246165125e1SJens Axboe static void elv_rqhash_del(struct request_queue *q, struct request *rq) 2479817064bSJens Axboe { 2489817064bSJens Axboe if (ELV_ON_HASH(rq)) 2499817064bSJens Axboe __elv_rqhash_del(rq); 2509817064bSJens Axboe } 2519817064bSJens Axboe 252165125e1SJens Axboe static void elv_rqhash_add(struct request_queue *q, struct request *rq) 2539817064bSJens Axboe { 254b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 2559817064bSJens Axboe 2569817064bSJens Axboe BUG_ON(ELV_ON_HASH(rq)); 2579817064bSJens Axboe hlist_add_head(&rq->hash, &e->hash[ELV_HASH_FN(rq_hash_key(rq))]); 2589817064bSJens Axboe } 2599817064bSJens Axboe 260165125e1SJens Axboe static void elv_rqhash_reposition(struct request_queue *q, struct request *rq) 2619817064bSJens Axboe { 2629817064bSJens Axboe __elv_rqhash_del(rq); 2639817064bSJens Axboe elv_rqhash_add(q, rq); 2649817064bSJens Axboe } 2659817064bSJens Axboe 266165125e1SJens Axboe static struct request *elv_rqhash_find(struct request_queue *q, sector_t offset) 2679817064bSJens Axboe { 268b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 2699817064bSJens Axboe struct hlist_head *hash_list = &e->hash[ELV_HASH_FN(offset)]; 2709817064bSJens Axboe struct hlist_node *entry, *next; 2719817064bSJens Axboe struct request *rq; 2729817064bSJens Axboe 2739817064bSJens Axboe hlist_for_each_entry_safe(rq, entry, next, hash_list, hash) { 2749817064bSJens Axboe BUG_ON(!ELV_ON_HASH(rq)); 2759817064bSJens Axboe 2769817064bSJens Axboe if (unlikely(!rq_mergeable(rq))) { 2779817064bSJens Axboe __elv_rqhash_del(rq); 2789817064bSJens Axboe continue; 2799817064bSJens Axboe } 2809817064bSJens Axboe 2819817064bSJens Axboe if (rq_hash_key(rq) == offset) 2829817064bSJens Axboe return rq; 2839817064bSJens Axboe } 2849817064bSJens Axboe 2859817064bSJens Axboe return NULL; 2869817064bSJens Axboe } 2879817064bSJens Axboe 2888922e16cSTejun Heo /* 2892e662b65SJens Axboe * RB-tree support functions for inserting/lookup/removal of requests 2902e662b65SJens Axboe * in a sorted RB tree. 2912e662b65SJens Axboe */ 292796d5116SJeff Moyer void elv_rb_add(struct rb_root *root, struct request *rq) 2932e662b65SJens Axboe { 2942e662b65SJens Axboe struct rb_node **p = &root->rb_node; 2952e662b65SJens Axboe struct rb_node *parent = NULL; 2962e662b65SJens Axboe struct request *__rq; 2972e662b65SJens Axboe 2982e662b65SJens Axboe while (*p) { 2992e662b65SJens Axboe parent = *p; 3002e662b65SJens Axboe __rq = rb_entry(parent, struct request, rb_node); 3012e662b65SJens Axboe 30283096ebfSTejun Heo if (blk_rq_pos(rq) < blk_rq_pos(__rq)) 3032e662b65SJens Axboe p = &(*p)->rb_left; 304796d5116SJeff Moyer else if (blk_rq_pos(rq) >= blk_rq_pos(__rq)) 3052e662b65SJens Axboe p = &(*p)->rb_right; 3062e662b65SJens Axboe } 3072e662b65SJens Axboe 3082e662b65SJens Axboe rb_link_node(&rq->rb_node, parent, p); 3092e662b65SJens Axboe rb_insert_color(&rq->rb_node, root); 3102e662b65SJens Axboe } 3112e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_add); 3122e662b65SJens Axboe 3132e662b65SJens Axboe void elv_rb_del(struct rb_root *root, struct request *rq) 3142e662b65SJens Axboe { 3152e662b65SJens Axboe BUG_ON(RB_EMPTY_NODE(&rq->rb_node)); 3162e662b65SJens Axboe rb_erase(&rq->rb_node, root); 3172e662b65SJens Axboe RB_CLEAR_NODE(&rq->rb_node); 3182e662b65SJens Axboe } 3192e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_del); 3202e662b65SJens Axboe 3212e662b65SJens Axboe struct request *elv_rb_find(struct rb_root *root, sector_t sector) 3222e662b65SJens Axboe { 3232e662b65SJens Axboe struct rb_node *n = root->rb_node; 3242e662b65SJens Axboe struct request *rq; 3252e662b65SJens Axboe 3262e662b65SJens Axboe while (n) { 3272e662b65SJens Axboe rq = rb_entry(n, struct request, rb_node); 3282e662b65SJens Axboe 32983096ebfSTejun Heo if (sector < blk_rq_pos(rq)) 3302e662b65SJens Axboe n = n->rb_left; 33183096ebfSTejun Heo else if (sector > blk_rq_pos(rq)) 3322e662b65SJens Axboe n = n->rb_right; 3332e662b65SJens Axboe else 3342e662b65SJens Axboe return rq; 3352e662b65SJens Axboe } 3362e662b65SJens Axboe 3372e662b65SJens Axboe return NULL; 3382e662b65SJens Axboe } 3392e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_find); 3402e662b65SJens Axboe 3412e662b65SJens Axboe /* 3428922e16cSTejun Heo * Insert rq into dispatch queue of q. Queue lock must be held on 343dbe7f76dSUwe Kleine-König * entry. rq is sort instead into the dispatch queue. To be used by 3442e662b65SJens Axboe * specific elevators. 3458922e16cSTejun Heo */ 346165125e1SJens Axboe void elv_dispatch_sort(struct request_queue *q, struct request *rq) 3478922e16cSTejun Heo { 3488922e16cSTejun Heo sector_t boundary; 3498922e16cSTejun Heo struct list_head *entry; 3504eb166d9SJens Axboe int stop_flags; 3518922e16cSTejun Heo 35206b86245STejun Heo if (q->last_merge == rq) 35306b86245STejun Heo q->last_merge = NULL; 3549817064bSJens Axboe 3559817064bSJens Axboe elv_rqhash_del(q, rq); 3569817064bSJens Axboe 35715853af9STejun Heo q->nr_sorted--; 35806b86245STejun Heo 3591b47f531SJens Axboe boundary = q->end_sector; 36002e031cbSChristoph Hellwig stop_flags = REQ_SOFTBARRIER | REQ_STARTED; 3618922e16cSTejun Heo list_for_each_prev(entry, &q->queue_head) { 3628922e16cSTejun Heo struct request *pos = list_entry_rq(entry); 3638922e16cSTejun Heo 36433659ebbSChristoph Hellwig if ((rq->cmd_flags & REQ_DISCARD) != 36533659ebbSChristoph Hellwig (pos->cmd_flags & REQ_DISCARD)) 366e17fc0a1SDavid Woodhouse break; 367783660b2SJens Axboe if (rq_data_dir(rq) != rq_data_dir(pos)) 368783660b2SJens Axboe break; 3694eb166d9SJens Axboe if (pos->cmd_flags & stop_flags) 3708922e16cSTejun Heo break; 37183096ebfSTejun Heo if (blk_rq_pos(rq) >= boundary) { 37283096ebfSTejun Heo if (blk_rq_pos(pos) < boundary) 3738922e16cSTejun Heo continue; 3748922e16cSTejun Heo } else { 37583096ebfSTejun Heo if (blk_rq_pos(pos) >= boundary) 3768922e16cSTejun Heo break; 3778922e16cSTejun Heo } 37883096ebfSTejun Heo if (blk_rq_pos(rq) >= blk_rq_pos(pos)) 3798922e16cSTejun Heo break; 3808922e16cSTejun Heo } 3818922e16cSTejun Heo 3828922e16cSTejun Heo list_add(&rq->queuelist, entry); 3838922e16cSTejun Heo } 3842e662b65SJens Axboe EXPORT_SYMBOL(elv_dispatch_sort); 3852e662b65SJens Axboe 3869817064bSJens Axboe /* 3872e662b65SJens Axboe * Insert rq into dispatch queue of q. Queue lock must be held on 3882e662b65SJens Axboe * entry. rq is added to the back of the dispatch queue. To be used by 3892e662b65SJens Axboe * specific elevators. 3909817064bSJens Axboe */ 3919817064bSJens Axboe void elv_dispatch_add_tail(struct request_queue *q, struct request *rq) 3929817064bSJens Axboe { 3939817064bSJens Axboe if (q->last_merge == rq) 3949817064bSJens Axboe q->last_merge = NULL; 3959817064bSJens Axboe 3969817064bSJens Axboe elv_rqhash_del(q, rq); 3979817064bSJens Axboe 3989817064bSJens Axboe q->nr_sorted--; 3999817064bSJens Axboe 4009817064bSJens Axboe q->end_sector = rq_end_sector(rq); 4019817064bSJens Axboe q->boundary_rq = rq; 4029817064bSJens Axboe list_add_tail(&rq->queuelist, &q->queue_head); 4039817064bSJens Axboe } 4042e662b65SJens Axboe EXPORT_SYMBOL(elv_dispatch_add_tail); 4052e662b65SJens Axboe 406165125e1SJens Axboe int elv_merge(struct request_queue *q, struct request **req, struct bio *bio) 4071da177e4SLinus Torvalds { 408b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 4099817064bSJens Axboe struct request *__rq; 41006b86245STejun Heo int ret; 41106b86245STejun Heo 4129817064bSJens Axboe /* 413488991e2SAlan D. Brunelle * Levels of merges: 414488991e2SAlan D. Brunelle * nomerges: No merges at all attempted 415488991e2SAlan D. Brunelle * noxmerges: Only simple one-hit cache try 416488991e2SAlan D. Brunelle * merges: All merge tries attempted 417488991e2SAlan D. Brunelle */ 418488991e2SAlan D. Brunelle if (blk_queue_nomerges(q)) 419488991e2SAlan D. Brunelle return ELEVATOR_NO_MERGE; 420488991e2SAlan D. Brunelle 421488991e2SAlan D. Brunelle /* 4229817064bSJens Axboe * First try one-hit cache. 4239817064bSJens Axboe */ 424050c8ea8STejun Heo if (q->last_merge && elv_rq_merge_ok(q->last_merge, bio)) { 425050c8ea8STejun Heo ret = blk_try_merge(q->last_merge, bio); 42606b86245STejun Heo if (ret != ELEVATOR_NO_MERGE) { 42706b86245STejun Heo *req = q->last_merge; 42806b86245STejun Heo return ret; 42906b86245STejun Heo } 43006b86245STejun Heo } 4311da177e4SLinus Torvalds 432488991e2SAlan D. Brunelle if (blk_queue_noxmerges(q)) 433ac9fafa1SAlan D. Brunelle return ELEVATOR_NO_MERGE; 434ac9fafa1SAlan D. Brunelle 4359817064bSJens Axboe /* 4369817064bSJens Axboe * See if our hash lookup can find a potential backmerge. 4379817064bSJens Axboe */ 4389817064bSJens Axboe __rq = elv_rqhash_find(q, bio->bi_sector); 4399817064bSJens Axboe if (__rq && elv_rq_merge_ok(__rq, bio)) { 4409817064bSJens Axboe *req = __rq; 4419817064bSJens Axboe return ELEVATOR_BACK_MERGE; 4429817064bSJens Axboe } 4439817064bSJens Axboe 44422f746e2STejun Heo if (e->type->ops.elevator_merge_fn) 44522f746e2STejun Heo return e->type->ops.elevator_merge_fn(q, req, bio); 4461da177e4SLinus Torvalds 4471da177e4SLinus Torvalds return ELEVATOR_NO_MERGE; 4481da177e4SLinus Torvalds } 4491da177e4SLinus Torvalds 4505e84ea3aSJens Axboe /* 4515e84ea3aSJens Axboe * Attempt to do an insertion back merge. Only check for the case where 4525e84ea3aSJens Axboe * we can append 'rq' to an existing request, so we can throw 'rq' away 4535e84ea3aSJens Axboe * afterwards. 4545e84ea3aSJens Axboe * 4555e84ea3aSJens Axboe * Returns true if we merged, false otherwise 4565e84ea3aSJens Axboe */ 4575e84ea3aSJens Axboe static bool elv_attempt_insert_merge(struct request_queue *q, 4585e84ea3aSJens Axboe struct request *rq) 4595e84ea3aSJens Axboe { 4605e84ea3aSJens Axboe struct request *__rq; 4615e84ea3aSJens Axboe 4625e84ea3aSJens Axboe if (blk_queue_nomerges(q)) 4635e84ea3aSJens Axboe return false; 4645e84ea3aSJens Axboe 4655e84ea3aSJens Axboe /* 4665e84ea3aSJens Axboe * First try one-hit cache. 4675e84ea3aSJens Axboe */ 4685e84ea3aSJens Axboe if (q->last_merge && blk_attempt_req_merge(q, q->last_merge, rq)) 4695e84ea3aSJens Axboe return true; 4705e84ea3aSJens Axboe 4715e84ea3aSJens Axboe if (blk_queue_noxmerges(q)) 4725e84ea3aSJens Axboe return false; 4735e84ea3aSJens Axboe 4745e84ea3aSJens Axboe /* 4755e84ea3aSJens Axboe * See if our hash lookup can find a potential backmerge. 4765e84ea3aSJens Axboe */ 4775e84ea3aSJens Axboe __rq = elv_rqhash_find(q, blk_rq_pos(rq)); 4785d381efbSJens Axboe if (__rq && blk_attempt_req_merge(q, __rq, rq)) 4795d381efbSJens Axboe return true; 4805e84ea3aSJens Axboe 4815d381efbSJens Axboe return false; 4825e84ea3aSJens Axboe } 4835e84ea3aSJens Axboe 484165125e1SJens Axboe void elv_merged_request(struct request_queue *q, struct request *rq, int type) 4851da177e4SLinus Torvalds { 486b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 4871da177e4SLinus Torvalds 48822f746e2STejun Heo if (e->type->ops.elevator_merged_fn) 48922f746e2STejun Heo e->type->ops.elevator_merged_fn(q, rq, type); 49006b86245STejun Heo 4912e662b65SJens Axboe if (type == ELEVATOR_BACK_MERGE) 4929817064bSJens Axboe elv_rqhash_reposition(q, rq); 4939817064bSJens Axboe 49406b86245STejun Heo q->last_merge = rq; 4951da177e4SLinus Torvalds } 4961da177e4SLinus Torvalds 497165125e1SJens Axboe void elv_merge_requests(struct request_queue *q, struct request *rq, 4981da177e4SLinus Torvalds struct request *next) 4991da177e4SLinus Torvalds { 500b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 5015e84ea3aSJens Axboe const int next_sorted = next->cmd_flags & REQ_SORTED; 5021da177e4SLinus Torvalds 50322f746e2STejun Heo if (next_sorted && e->type->ops.elevator_merge_req_fn) 50422f746e2STejun Heo e->type->ops.elevator_merge_req_fn(q, rq, next); 50506b86245STejun Heo 5069817064bSJens Axboe elv_rqhash_reposition(q, rq); 5079817064bSJens Axboe 5085e84ea3aSJens Axboe if (next_sorted) { 5095e84ea3aSJens Axboe elv_rqhash_del(q, next); 5109817064bSJens Axboe q->nr_sorted--; 5115e84ea3aSJens Axboe } 5125e84ea3aSJens Axboe 51306b86245STejun Heo q->last_merge = rq; 5141da177e4SLinus Torvalds } 5151da177e4SLinus Torvalds 516812d4026SDivyesh Shah void elv_bio_merged(struct request_queue *q, struct request *rq, 517812d4026SDivyesh Shah struct bio *bio) 518812d4026SDivyesh Shah { 519812d4026SDivyesh Shah struct elevator_queue *e = q->elevator; 520812d4026SDivyesh Shah 52122f746e2STejun Heo if (e->type->ops.elevator_bio_merged_fn) 52222f746e2STejun Heo e->type->ops.elevator_bio_merged_fn(q, rq, bio); 523812d4026SDivyesh Shah } 524812d4026SDivyesh Shah 525165125e1SJens Axboe void elv_requeue_request(struct request_queue *q, struct request *rq) 5261da177e4SLinus Torvalds { 5271da177e4SLinus Torvalds /* 5281da177e4SLinus Torvalds * it already went through dequeue, we need to decrement the 5291da177e4SLinus Torvalds * in_flight count again 5301da177e4SLinus Torvalds */ 5318922e16cSTejun Heo if (blk_account_rq(rq)) { 5320a7ae2ffSJens Axboe q->in_flight[rq_is_sync(rq)]--; 53333659ebbSChristoph Hellwig if (rq->cmd_flags & REQ_SORTED) 534cad97516SJens Axboe elv_deactivate_rq(q, rq); 5351da177e4SLinus Torvalds } 5361da177e4SLinus Torvalds 5374aff5e23SJens Axboe rq->cmd_flags &= ~REQ_STARTED; 5381da177e4SLinus Torvalds 539b710a480SJens Axboe __elv_add_request(q, rq, ELEVATOR_INSERT_REQUEUE); 5401da177e4SLinus Torvalds } 5411da177e4SLinus Torvalds 54226308eabSJerome Marchand void elv_drain_elevator(struct request_queue *q) 54315853af9STejun Heo { 54415853af9STejun Heo static int printed; 545e3c78ca5STejun Heo 546e3c78ca5STejun Heo lockdep_assert_held(q->queue_lock); 547e3c78ca5STejun Heo 54822f746e2STejun Heo while (q->elevator->type->ops.elevator_dispatch_fn(q, 1)) 54915853af9STejun Heo ; 550e3c78ca5STejun Heo if (q->nr_sorted && printed++ < 10) { 55115853af9STejun Heo printk(KERN_ERR "%s: forced dispatching is broken " 55215853af9STejun Heo "(nr_sorted=%u), please report this\n", 55322f746e2STejun Heo q->elevator->type->elevator_name, q->nr_sorted); 55415853af9STejun Heo } 55515853af9STejun Heo } 55615853af9STejun Heo 557b710a480SJens Axboe void __elv_add_request(struct request_queue *q, struct request *rq, int where) 5581da177e4SLinus Torvalds { 5595f3ea37cSArnaldo Carvalho de Melo trace_block_rq_insert(q, rq); 5602056a782SJens Axboe 5611da177e4SLinus Torvalds rq->q = q; 5621da177e4SLinus Torvalds 563b710a480SJens Axboe if (rq->cmd_flags & REQ_SOFTBARRIER) { 564b710a480SJens Axboe /* barriers are scheduling boundary, update end_sector */ 565b710a480SJens Axboe if (rq->cmd_type == REQ_TYPE_FS || 566b710a480SJens Axboe (rq->cmd_flags & REQ_DISCARD)) { 567b710a480SJens Axboe q->end_sector = rq_end_sector(rq); 568b710a480SJens Axboe q->boundary_rq = rq; 569b710a480SJens Axboe } 570b710a480SJens Axboe } else if (!(rq->cmd_flags & REQ_ELVPRIV) && 5713aa72873SJens Axboe (where == ELEVATOR_INSERT_SORT || 5723aa72873SJens Axboe where == ELEVATOR_INSERT_SORT_MERGE)) 573b710a480SJens Axboe where = ELEVATOR_INSERT_BACK; 574b710a480SJens Axboe 5758922e16cSTejun Heo switch (where) { 57628e7d184STejun Heo case ELEVATOR_INSERT_REQUEUE: 5778922e16cSTejun Heo case ELEVATOR_INSERT_FRONT: 5784aff5e23SJens Axboe rq->cmd_flags |= REQ_SOFTBARRIER; 5798922e16cSTejun Heo list_add(&rq->queuelist, &q->queue_head); 5808922e16cSTejun Heo break; 5818922e16cSTejun Heo 5828922e16cSTejun Heo case ELEVATOR_INSERT_BACK: 5834aff5e23SJens Axboe rq->cmd_flags |= REQ_SOFTBARRIER; 58415853af9STejun Heo elv_drain_elevator(q); 5858922e16cSTejun Heo list_add_tail(&rq->queuelist, &q->queue_head); 5868922e16cSTejun Heo /* 5878922e16cSTejun Heo * We kick the queue here for the following reasons. 5888922e16cSTejun Heo * - The elevator might have returned NULL previously 5898922e16cSTejun Heo * to delay requests and returned them now. As the 5908922e16cSTejun Heo * queue wasn't empty before this request, ll_rw_blk 5918922e16cSTejun Heo * won't run the queue on return, resulting in hang. 5928922e16cSTejun Heo * - Usually, back inserted requests won't be merged 5938922e16cSTejun Heo * with anything. There's no point in delaying queue 5948922e16cSTejun Heo * processing. 5958922e16cSTejun Heo */ 59624ecfbe2SChristoph Hellwig __blk_run_queue(q); 5978922e16cSTejun Heo break; 5988922e16cSTejun Heo 5995e84ea3aSJens Axboe case ELEVATOR_INSERT_SORT_MERGE: 6005e84ea3aSJens Axboe /* 6015e84ea3aSJens Axboe * If we succeed in merging this request with one in the 6025e84ea3aSJens Axboe * queue already, we are done - rq has now been freed, 6035e84ea3aSJens Axboe * so no need to do anything further. 6045e84ea3aSJens Axboe */ 6055e84ea3aSJens Axboe if (elv_attempt_insert_merge(q, rq)) 6065e84ea3aSJens Axboe break; 6078922e16cSTejun Heo case ELEVATOR_INSERT_SORT: 60833659ebbSChristoph Hellwig BUG_ON(rq->cmd_type != REQ_TYPE_FS && 60933659ebbSChristoph Hellwig !(rq->cmd_flags & REQ_DISCARD)); 6104aff5e23SJens Axboe rq->cmd_flags |= REQ_SORTED; 61115853af9STejun Heo q->nr_sorted++; 6129817064bSJens Axboe if (rq_mergeable(rq)) { 6139817064bSJens Axboe elv_rqhash_add(q, rq); 6149817064bSJens Axboe if (!q->last_merge) 61506b86245STejun Heo q->last_merge = rq; 6169817064bSJens Axboe } 6179817064bSJens Axboe 618ca23509fSTejun Heo /* 619ca23509fSTejun Heo * Some ioscheds (cfq) run q->request_fn directly, so 620ca23509fSTejun Heo * rq cannot be accessed after calling 621ca23509fSTejun Heo * elevator_add_req_fn. 622ca23509fSTejun Heo */ 62322f746e2STejun Heo q->elevator->type->ops.elevator_add_req_fn(q, rq); 6248922e16cSTejun Heo break; 6258922e16cSTejun Heo 626ae1b1539STejun Heo case ELEVATOR_INSERT_FLUSH: 627ae1b1539STejun Heo rq->cmd_flags |= REQ_SOFTBARRIER; 628ae1b1539STejun Heo blk_insert_flush(rq); 629ae1b1539STejun Heo break; 6308922e16cSTejun Heo default: 6318922e16cSTejun Heo printk(KERN_ERR "%s: bad insertion point %d\n", 63224c03d47SHarvey Harrison __func__, where); 6338922e16cSTejun Heo BUG(); 6348922e16cSTejun Heo } 6351da177e4SLinus Torvalds } 6362e662b65SJens Axboe EXPORT_SYMBOL(__elv_add_request); 6372e662b65SJens Axboe 6387eaceaccSJens Axboe void elv_add_request(struct request_queue *q, struct request *rq, int where) 6391da177e4SLinus Torvalds { 6401da177e4SLinus Torvalds unsigned long flags; 6411da177e4SLinus Torvalds 6421da177e4SLinus Torvalds spin_lock_irqsave(q->queue_lock, flags); 6437eaceaccSJens Axboe __elv_add_request(q, rq, where); 6441da177e4SLinus Torvalds spin_unlock_irqrestore(q->queue_lock, flags); 6451da177e4SLinus Torvalds } 6462e662b65SJens Axboe EXPORT_SYMBOL(elv_add_request); 6472e662b65SJens Axboe 648165125e1SJens Axboe struct request *elv_latter_request(struct request_queue *q, struct request *rq) 6491da177e4SLinus Torvalds { 650b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 6511da177e4SLinus Torvalds 65222f746e2STejun Heo if (e->type->ops.elevator_latter_req_fn) 65322f746e2STejun Heo return e->type->ops.elevator_latter_req_fn(q, rq); 6541da177e4SLinus Torvalds return NULL; 6551da177e4SLinus Torvalds } 6561da177e4SLinus Torvalds 657165125e1SJens Axboe struct request *elv_former_request(struct request_queue *q, struct request *rq) 6581da177e4SLinus Torvalds { 659b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 6601da177e4SLinus Torvalds 66122f746e2STejun Heo if (e->type->ops.elevator_former_req_fn) 66222f746e2STejun Heo return e->type->ops.elevator_former_req_fn(q, rq); 6631da177e4SLinus Torvalds return NULL; 6641da177e4SLinus Torvalds } 6651da177e4SLinus Torvalds 666165125e1SJens Axboe int elv_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask) 6671da177e4SLinus Torvalds { 668b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 6691da177e4SLinus Torvalds 67022f746e2STejun Heo if (e->type->ops.elevator_set_req_fn) 67122f746e2STejun Heo return e->type->ops.elevator_set_req_fn(q, rq, gfp_mask); 6721da177e4SLinus Torvalds return 0; 6731da177e4SLinus Torvalds } 6741da177e4SLinus Torvalds 675165125e1SJens Axboe void elv_put_request(struct request_queue *q, struct request *rq) 6761da177e4SLinus Torvalds { 677b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 6781da177e4SLinus Torvalds 67922f746e2STejun Heo if (e->type->ops.elevator_put_req_fn) 68022f746e2STejun Heo e->type->ops.elevator_put_req_fn(rq); 6811da177e4SLinus Torvalds } 6821da177e4SLinus Torvalds 683165125e1SJens Axboe int elv_may_queue(struct request_queue *q, int rw) 6841da177e4SLinus Torvalds { 685b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 6861da177e4SLinus Torvalds 68722f746e2STejun Heo if (e->type->ops.elevator_may_queue_fn) 68822f746e2STejun Heo return e->type->ops.elevator_may_queue_fn(q, rw); 6891da177e4SLinus Torvalds 6901da177e4SLinus Torvalds return ELV_MQUEUE_MAY; 6911da177e4SLinus Torvalds } 6921da177e4SLinus Torvalds 69311914a53SMike Anderson void elv_abort_queue(struct request_queue *q) 69411914a53SMike Anderson { 69511914a53SMike Anderson struct request *rq; 69611914a53SMike Anderson 697ae1b1539STejun Heo blk_abort_flushes(q); 698ae1b1539STejun Heo 69911914a53SMike Anderson while (!list_empty(&q->queue_head)) { 70011914a53SMike Anderson rq = list_entry_rq(q->queue_head.next); 70111914a53SMike Anderson rq->cmd_flags |= REQ_QUIET; 7025f3ea37cSArnaldo Carvalho de Melo trace_block_rq_abort(q, rq); 70353c663ceSKiyoshi Ueda /* 70453c663ceSKiyoshi Ueda * Mark this request as started so we don't trigger 70553c663ceSKiyoshi Ueda * any debug logic in the end I/O path. 70653c663ceSKiyoshi Ueda */ 70753c663ceSKiyoshi Ueda blk_start_request(rq); 70840cbbb78STejun Heo __blk_end_request_all(rq, -EIO); 70911914a53SMike Anderson } 71011914a53SMike Anderson } 71111914a53SMike Anderson EXPORT_SYMBOL(elv_abort_queue); 71211914a53SMike Anderson 713165125e1SJens Axboe void elv_completed_request(struct request_queue *q, struct request *rq) 7141da177e4SLinus Torvalds { 715b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 7161da177e4SLinus Torvalds 7171da177e4SLinus Torvalds /* 7181da177e4SLinus Torvalds * request is released from the driver, io must be done 7191da177e4SLinus Torvalds */ 7208922e16cSTejun Heo if (blk_account_rq(rq)) { 7210a7ae2ffSJens Axboe q->in_flight[rq_is_sync(rq)]--; 72233659ebbSChristoph Hellwig if ((rq->cmd_flags & REQ_SORTED) && 72322f746e2STejun Heo e->type->ops.elevator_completed_req_fn) 72422f746e2STejun Heo e->type->ops.elevator_completed_req_fn(q, rq); 7251bc691d3STejun Heo } 7268922e16cSTejun Heo } 7271da177e4SLinus Torvalds 7283d1ab40fSAl Viro #define to_elv(atr) container_of((atr), struct elv_fs_entry, attr) 7293d1ab40fSAl Viro 7303d1ab40fSAl Viro static ssize_t 7313d1ab40fSAl Viro elv_attr_show(struct kobject *kobj, struct attribute *attr, char *page) 7323d1ab40fSAl Viro { 7333d1ab40fSAl Viro struct elv_fs_entry *entry = to_elv(attr); 734b374d18aSJens Axboe struct elevator_queue *e; 7353d1ab40fSAl Viro ssize_t error; 7363d1ab40fSAl Viro 7373d1ab40fSAl Viro if (!entry->show) 7383d1ab40fSAl Viro return -EIO; 7393d1ab40fSAl Viro 740b374d18aSJens Axboe e = container_of(kobj, struct elevator_queue, kobj); 7413d1ab40fSAl Viro mutex_lock(&e->sysfs_lock); 74222f746e2STejun Heo error = e->type ? entry->show(e, page) : -ENOENT; 7433d1ab40fSAl Viro mutex_unlock(&e->sysfs_lock); 7443d1ab40fSAl Viro return error; 7453d1ab40fSAl Viro } 7463d1ab40fSAl Viro 7473d1ab40fSAl Viro static ssize_t 7483d1ab40fSAl Viro elv_attr_store(struct kobject *kobj, struct attribute *attr, 7493d1ab40fSAl Viro const char *page, size_t length) 7503d1ab40fSAl Viro { 7513d1ab40fSAl Viro struct elv_fs_entry *entry = to_elv(attr); 752b374d18aSJens Axboe struct elevator_queue *e; 7533d1ab40fSAl Viro ssize_t error; 7543d1ab40fSAl Viro 7553d1ab40fSAl Viro if (!entry->store) 7563d1ab40fSAl Viro return -EIO; 7573d1ab40fSAl Viro 758b374d18aSJens Axboe e = container_of(kobj, struct elevator_queue, kobj); 7593d1ab40fSAl Viro mutex_lock(&e->sysfs_lock); 76022f746e2STejun Heo error = e->type ? entry->store(e, page, length) : -ENOENT; 7613d1ab40fSAl Viro mutex_unlock(&e->sysfs_lock); 7623d1ab40fSAl Viro return error; 7633d1ab40fSAl Viro } 7643d1ab40fSAl Viro 76552cf25d0SEmese Revfy static const struct sysfs_ops elv_sysfs_ops = { 7663d1ab40fSAl Viro .show = elv_attr_show, 7673d1ab40fSAl Viro .store = elv_attr_store, 7683d1ab40fSAl Viro }; 7693d1ab40fSAl Viro 7703d1ab40fSAl Viro static struct kobj_type elv_ktype = { 7713d1ab40fSAl Viro .sysfs_ops = &elv_sysfs_ops, 7723d1ab40fSAl Viro .release = elevator_release, 7733d1ab40fSAl Viro }; 7743d1ab40fSAl Viro 7755a5bafdcSTejun Heo int elv_register_queue(struct request_queue *q) 7761da177e4SLinus Torvalds { 7775a5bafdcSTejun Heo struct elevator_queue *e = q->elevator; 7783d1ab40fSAl Viro int error; 7791da177e4SLinus Torvalds 780b2d6db58SGreg Kroah-Hartman error = kobject_add(&e->kobj, &q->kobj, "%s", "iosched"); 7813d1ab40fSAl Viro if (!error) { 78222f746e2STejun Heo struct elv_fs_entry *attr = e->type->elevator_attrs; 7833d1ab40fSAl Viro if (attr) { 784e572ec7eSAl Viro while (attr->attr.name) { 785e572ec7eSAl Viro if (sysfs_create_file(&e->kobj, &attr->attr)) 7863d1ab40fSAl Viro break; 787e572ec7eSAl Viro attr++; 7883d1ab40fSAl Viro } 7893d1ab40fSAl Viro } 7903d1ab40fSAl Viro kobject_uevent(&e->kobj, KOBJ_ADD); 791430c62fbSJens Axboe e->registered = 1; 7923d1ab40fSAl Viro } 7933d1ab40fSAl Viro return error; 7941da177e4SLinus Torvalds } 79501effb0dSMike Snitzer EXPORT_SYMBOL(elv_register_queue); 7961da177e4SLinus Torvalds 797f8fc877dSTejun Heo void elv_unregister_queue(struct request_queue *q) 7981da177e4SLinus Torvalds { 799f8fc877dSTejun Heo if (q) { 800f8fc877dSTejun Heo struct elevator_queue *e = q->elevator; 801f8fc877dSTejun Heo 8023d1ab40fSAl Viro kobject_uevent(&e->kobj, KOBJ_REMOVE); 8033d1ab40fSAl Viro kobject_del(&e->kobj); 804430c62fbSJens Axboe e->registered = 0; 8051da177e4SLinus Torvalds } 8061da177e4SLinus Torvalds } 80701effb0dSMike Snitzer EXPORT_SYMBOL(elv_unregister_queue); 8081da177e4SLinus Torvalds 8093d3c2379STejun Heo int elv_register(struct elevator_type *e) 8101da177e4SLinus Torvalds { 8111ffb96c5SThibaut VARENE char *def = ""; 8122a12dcd7SJens Axboe 8133d3c2379STejun Heo /* create icq_cache if requested */ 8143d3c2379STejun Heo if (e->icq_size) { 8153d3c2379STejun Heo if (WARN_ON(e->icq_size < sizeof(struct io_cq)) || 8163d3c2379STejun Heo WARN_ON(e->icq_align < __alignof__(struct io_cq))) 8173d3c2379STejun Heo return -EINVAL; 8183d3c2379STejun Heo 8193d3c2379STejun Heo snprintf(e->icq_cache_name, sizeof(e->icq_cache_name), 8203d3c2379STejun Heo "%s_io_cq", e->elevator_name); 8213d3c2379STejun Heo e->icq_cache = kmem_cache_create(e->icq_cache_name, e->icq_size, 8223d3c2379STejun Heo e->icq_align, 0, NULL); 8233d3c2379STejun Heo if (!e->icq_cache) 8243d3c2379STejun Heo return -ENOMEM; 8253d3c2379STejun Heo } 8263d3c2379STejun Heo 8273d3c2379STejun Heo /* register, don't allow duplicate names */ 8282a12dcd7SJens Axboe spin_lock(&elv_list_lock); 8293d3c2379STejun Heo if (elevator_find(e->elevator_name)) { 8303d3c2379STejun Heo spin_unlock(&elv_list_lock); 8313d3c2379STejun Heo if (e->icq_cache) 8323d3c2379STejun Heo kmem_cache_destroy(e->icq_cache); 8333d3c2379STejun Heo return -EBUSY; 8343d3c2379STejun Heo } 8351da177e4SLinus Torvalds list_add_tail(&e->list, &elv_list); 8362a12dcd7SJens Axboe spin_unlock(&elv_list_lock); 8371da177e4SLinus Torvalds 8383d3c2379STejun Heo /* print pretty message */ 8395f003976SNate Diller if (!strcmp(e->elevator_name, chosen_elevator) || 8405f003976SNate Diller (!*chosen_elevator && 8415f003976SNate Diller !strcmp(e->elevator_name, CONFIG_DEFAULT_IOSCHED))) 8421ffb96c5SThibaut VARENE def = " (default)"; 8431ffb96c5SThibaut VARENE 8444eb166d9SJens Axboe printk(KERN_INFO "io scheduler %s registered%s\n", e->elevator_name, 8454eb166d9SJens Axboe def); 8463d3c2379STejun Heo return 0; 8471da177e4SLinus Torvalds } 8481da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(elv_register); 8491da177e4SLinus Torvalds 8501da177e4SLinus Torvalds void elv_unregister(struct elevator_type *e) 8511da177e4SLinus Torvalds { 8523d3c2379STejun Heo /* unregister */ 8532a12dcd7SJens Axboe spin_lock(&elv_list_lock); 8541da177e4SLinus Torvalds list_del_init(&e->list); 8552a12dcd7SJens Axboe spin_unlock(&elv_list_lock); 8563d3c2379STejun Heo 8573d3c2379STejun Heo /* 8583d3c2379STejun Heo * Destroy icq_cache if it exists. icq's are RCU managed. Make 8593d3c2379STejun Heo * sure all RCU operations are complete before proceeding. 8603d3c2379STejun Heo */ 8613d3c2379STejun Heo if (e->icq_cache) { 8623d3c2379STejun Heo rcu_barrier(); 8633d3c2379STejun Heo kmem_cache_destroy(e->icq_cache); 8643d3c2379STejun Heo e->icq_cache = NULL; 8653d3c2379STejun Heo } 8661da177e4SLinus Torvalds } 8671da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(elv_unregister); 8681da177e4SLinus Torvalds 8691da177e4SLinus Torvalds /* 8701da177e4SLinus Torvalds * switch to new_e io scheduler. be careful not to introduce deadlocks - 8711da177e4SLinus Torvalds * we don't free the old io scheduler, before we have allocated what we 8721da177e4SLinus Torvalds * need for the new one. this way we have a chance of going back to the old 873cb98fc8bSTejun Heo * one, if the new one fails init for some reason. 8741da177e4SLinus Torvalds */ 875165125e1SJens Axboe static int elevator_switch(struct request_queue *q, struct elevator_type *new_e) 8761da177e4SLinus Torvalds { 8775a5bafdcSTejun Heo struct elevator_queue *old = q->elevator; 8785a5bafdcSTejun Heo bool registered = old->registered; 879*e8989faeSTejun Heo int err; 8801da177e4SLinus Torvalds 8815a5bafdcSTejun Heo /* 8825a5bafdcSTejun Heo * Turn on BYPASS and drain all requests w/ elevator private data. 8835a5bafdcSTejun Heo * Block layer doesn't call into a quiesced elevator - all requests 8845a5bafdcSTejun Heo * are directly put on the dispatch list without elevator data 8855a5bafdcSTejun Heo * using INSERT_BACK. All requests have SOFTBARRIER set and no 8865a5bafdcSTejun Heo * merge happens either. 8875a5bafdcSTejun Heo */ 888d732580bSTejun Heo blk_queue_bypass_start(q); 889cb98fc8bSTejun Heo 8905a5bafdcSTejun Heo /* unregister and clear all auxiliary data of the old elevator */ 8915a5bafdcSTejun Heo if (registered) 892f8fc877dSTejun Heo elv_unregister_queue(q); 8935a5bafdcSTejun Heo 8945a5bafdcSTejun Heo spin_lock_irq(q->queue_lock); 8955a5bafdcSTejun Heo ioc_clear_queue(q); 8965a5bafdcSTejun Heo spin_unlock_irq(q->queue_lock); 8975a5bafdcSTejun Heo 898*e8989faeSTejun Heo blkg_destroy_all(q, false); 89972e06c25STejun Heo 9005a5bafdcSTejun Heo /* allocate, init and register new elevator */ 9015a5bafdcSTejun Heo err = -ENOMEM; 9025a5bafdcSTejun Heo q->elevator = elevator_alloc(q, new_e); 9035a5bafdcSTejun Heo if (!q->elevator) 9045a5bafdcSTejun Heo goto fail_init; 9055a5bafdcSTejun Heo 906b2fab5acSTejun Heo err = new_e->ops.elevator_init_fn(q); 9075a5bafdcSTejun Heo if (err) { 9085a5bafdcSTejun Heo kobject_put(&q->elevator->kobj); 9095a5bafdcSTejun Heo goto fail_init; 9105a5bafdcSTejun Heo } 9115a5bafdcSTejun Heo 9125a5bafdcSTejun Heo if (registered) { 9135a5bafdcSTejun Heo err = elv_register_queue(q); 9145dd531a0SJens Axboe if (err) 9151da177e4SLinus Torvalds goto fail_register; 916430c62fbSJens Axboe } 9171da177e4SLinus Torvalds 9185a5bafdcSTejun Heo /* done, kill the old one and finish */ 9195a5bafdcSTejun Heo elevator_exit(old); 920d732580bSTejun Heo blk_queue_bypass_end(q); 92175ad23bcSNick Piggin 9225a5bafdcSTejun Heo blk_add_trace_msg(q, "elv switch: %s", new_e->elevator_name); 9234722dc52SAlan D. Brunelle 9245dd531a0SJens Axboe return 0; 9251da177e4SLinus Torvalds 9261da177e4SLinus Torvalds fail_register: 9275a5bafdcSTejun Heo elevator_exit(q->elevator); 9285a5bafdcSTejun Heo fail_init: 9295a5bafdcSTejun Heo /* switch failed, restore and re-register old elevator */ 9305a5bafdcSTejun Heo q->elevator = old; 9311da177e4SLinus Torvalds elv_register_queue(q); 932d732580bSTejun Heo blk_queue_bypass_end(q); 93375ad23bcSNick Piggin 9345dd531a0SJens Axboe return err; 9351da177e4SLinus Torvalds } 9361da177e4SLinus Torvalds 9375dd531a0SJens Axboe /* 9385dd531a0SJens Axboe * Switch this queue to the given IO scheduler. 9395dd531a0SJens Axboe */ 9405dd531a0SJens Axboe int elevator_change(struct request_queue *q, const char *name) 9411da177e4SLinus Torvalds { 9421da177e4SLinus Torvalds char elevator_name[ELV_NAME_MAX]; 9431da177e4SLinus Torvalds struct elevator_type *e; 9441da177e4SLinus Torvalds 945cd43e26fSMartin K. Petersen if (!q->elevator) 9465dd531a0SJens Axboe return -ENXIO; 947cd43e26fSMartin K. Petersen 948ee2e992cSLi Zefan strlcpy(elevator_name, name, sizeof(elevator_name)); 9498c279598SKOSAKI Motohiro e = elevator_get(strstrip(elevator_name)); 9501da177e4SLinus Torvalds if (!e) { 9511da177e4SLinus Torvalds printk(KERN_ERR "elevator: type %s not found\n", elevator_name); 9521da177e4SLinus Torvalds return -EINVAL; 9531da177e4SLinus Torvalds } 9541da177e4SLinus Torvalds 95522f746e2STejun Heo if (!strcmp(elevator_name, q->elevator->type->elevator_name)) { 9562ca7d93bSNate Diller elevator_put(e); 9575dd531a0SJens Axboe return 0; 9582ca7d93bSNate Diller } 9591da177e4SLinus Torvalds 9605dd531a0SJens Axboe return elevator_switch(q, e); 9615dd531a0SJens Axboe } 9625dd531a0SJens Axboe EXPORT_SYMBOL(elevator_change); 9635dd531a0SJens Axboe 9645dd531a0SJens Axboe ssize_t elv_iosched_store(struct request_queue *q, const char *name, 9655dd531a0SJens Axboe size_t count) 9665dd531a0SJens Axboe { 9675dd531a0SJens Axboe int ret; 9685dd531a0SJens Axboe 9695dd531a0SJens Axboe if (!q->elevator) 9701da177e4SLinus Torvalds return count; 9715dd531a0SJens Axboe 9725dd531a0SJens Axboe ret = elevator_change(q, name); 9735dd531a0SJens Axboe if (!ret) 9745dd531a0SJens Axboe return count; 9755dd531a0SJens Axboe 9765dd531a0SJens Axboe printk(KERN_ERR "elevator: switch to %s failed\n", name); 9775dd531a0SJens Axboe return ret; 9781da177e4SLinus Torvalds } 9791da177e4SLinus Torvalds 980165125e1SJens Axboe ssize_t elv_iosched_show(struct request_queue *q, char *name) 9811da177e4SLinus Torvalds { 982b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 983cd43e26fSMartin K. Petersen struct elevator_type *elv; 98470cee26eSMatthias Kaehlcke struct elevator_type *__e; 9851da177e4SLinus Torvalds int len = 0; 9861da177e4SLinus Torvalds 987e36f724bSMike Snitzer if (!q->elevator || !blk_queue_stackable(q)) 988cd43e26fSMartin K. Petersen return sprintf(name, "none\n"); 989cd43e26fSMartin K. Petersen 99022f746e2STejun Heo elv = e->type; 991cd43e26fSMartin K. Petersen 9922a12dcd7SJens Axboe spin_lock(&elv_list_lock); 99370cee26eSMatthias Kaehlcke list_for_each_entry(__e, &elv_list, list) { 9941da177e4SLinus Torvalds if (!strcmp(elv->elevator_name, __e->elevator_name)) 9951da177e4SLinus Torvalds len += sprintf(name+len, "[%s] ", elv->elevator_name); 9961da177e4SLinus Torvalds else 9971da177e4SLinus Torvalds len += sprintf(name+len, "%s ", __e->elevator_name); 9981da177e4SLinus Torvalds } 9992a12dcd7SJens Axboe spin_unlock(&elv_list_lock); 10001da177e4SLinus Torvalds 10011da177e4SLinus Torvalds len += sprintf(len+name, "\n"); 10021da177e4SLinus Torvalds return len; 10031da177e4SLinus Torvalds } 10041da177e4SLinus Torvalds 1005165125e1SJens Axboe struct request *elv_rb_former_request(struct request_queue *q, 1006165125e1SJens Axboe struct request *rq) 10072e662b65SJens Axboe { 10082e662b65SJens Axboe struct rb_node *rbprev = rb_prev(&rq->rb_node); 10092e662b65SJens Axboe 10102e662b65SJens Axboe if (rbprev) 10112e662b65SJens Axboe return rb_entry_rq(rbprev); 10122e662b65SJens Axboe 10132e662b65SJens Axboe return NULL; 10142e662b65SJens Axboe } 10152e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_former_request); 10162e662b65SJens Axboe 1017165125e1SJens Axboe struct request *elv_rb_latter_request(struct request_queue *q, 1018165125e1SJens Axboe struct request *rq) 10192e662b65SJens Axboe { 10202e662b65SJens Axboe struct rb_node *rbnext = rb_next(&rq->rb_node); 10212e662b65SJens Axboe 10222e662b65SJens Axboe if (rbnext) 10232e662b65SJens Axboe return rb_entry_rq(rbnext); 10242e662b65SJens Axboe 10252e662b65SJens Axboe return NULL; 10262e662b65SJens Axboe } 10272e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_latter_request); 1028