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> 37c8158819SLin Ming #include <linux/pm_runtime.h> 381da177e4SLinus Torvalds 3955782138SLi Zefan #include <trace/events/block.h> 4055782138SLi Zefan 41242f9dcbSJens Axboe #include "blk.h" 4272e06c25STejun Heo #include "blk-cgroup.h" 43242f9dcbSJens Axboe 441da177e4SLinus Torvalds static DEFINE_SPINLOCK(elv_list_lock); 451da177e4SLinus Torvalds static LIST_HEAD(elv_list); 461da177e4SLinus Torvalds 471da177e4SLinus Torvalds /* 489817064bSJens Axboe * Merge hash stuff. 499817064bSJens Axboe */ 5083096ebfSTejun Heo #define rq_hash_key(rq) (blk_rq_pos(rq) + blk_rq_sectors(rq)) 519817064bSJens Axboe 529817064bSJens Axboe /* 53da775265SJens Axboe * Query io scheduler to see if the current process issuing bio may be 54da775265SJens Axboe * merged with rq. 55da775265SJens Axboe */ 56da775265SJens Axboe static int elv_iosched_allow_merge(struct request *rq, struct bio *bio) 57da775265SJens Axboe { 58165125e1SJens Axboe struct request_queue *q = rq->q; 59b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 60da775265SJens Axboe 6122f746e2STejun Heo if (e->type->ops.elevator_allow_merge_fn) 6222f746e2STejun Heo return e->type->ops.elevator_allow_merge_fn(q, rq, bio); 63da775265SJens Axboe 64da775265SJens Axboe return 1; 65da775265SJens Axboe } 66da775265SJens Axboe 67da775265SJens Axboe /* 681da177e4SLinus Torvalds * can we safely merge with this request? 691da177e4SLinus Torvalds */ 70050c8ea8STejun Heo bool elv_rq_merge_ok(struct request *rq, struct bio *bio) 711da177e4SLinus Torvalds { 72050c8ea8STejun Heo if (!blk_rq_merge_ok(rq, bio)) 737ba1ba12SMartin K. Petersen return 0; 747ba1ba12SMartin K. Petersen 75da775265SJens Axboe if (!elv_iosched_allow_merge(rq, bio)) 76da775265SJens Axboe return 0; 77da775265SJens Axboe 78da775265SJens Axboe return 1; 791da177e4SLinus Torvalds } 801da177e4SLinus Torvalds EXPORT_SYMBOL(elv_rq_merge_ok); 811da177e4SLinus Torvalds 821da177e4SLinus Torvalds static struct elevator_type *elevator_find(const char *name) 831da177e4SLinus Torvalds { 84a22b169dSVasily Tarasov struct elevator_type *e; 851da177e4SLinus Torvalds 8670cee26eSMatthias Kaehlcke list_for_each_entry(e, &elv_list, list) { 87a22b169dSVasily Tarasov if (!strcmp(e->elevator_name, name)) 881da177e4SLinus Torvalds return e; 891da177e4SLinus Torvalds } 901da177e4SLinus Torvalds 91a22b169dSVasily Tarasov return NULL; 92a22b169dSVasily Tarasov } 93a22b169dSVasily Tarasov 941da177e4SLinus Torvalds static void elevator_put(struct elevator_type *e) 951da177e4SLinus Torvalds { 961da177e4SLinus Torvalds module_put(e->elevator_owner); 971da177e4SLinus Torvalds } 981da177e4SLinus Torvalds 9921c3c5d2STejun Heo static struct elevator_type *elevator_get(const char *name, bool try_loading) 1001da177e4SLinus Torvalds { 1012824bc93STejun Heo struct elevator_type *e; 1021da177e4SLinus Torvalds 1032a12dcd7SJens Axboe spin_lock(&elv_list_lock); 1042824bc93STejun Heo 1052824bc93STejun Heo e = elevator_find(name); 10621c3c5d2STejun Heo if (!e && try_loading) { 107e1640949SJens Axboe spin_unlock(&elv_list_lock); 108490b94beSKees Cook request_module("%s-iosched", name); 109e1640949SJens Axboe spin_lock(&elv_list_lock); 110e1640949SJens Axboe e = elevator_find(name); 111e1640949SJens Axboe } 112e1640949SJens Axboe 1132824bc93STejun Heo if (e && !try_module_get(e->elevator_owner)) 1142824bc93STejun Heo e = NULL; 1152824bc93STejun Heo 1162a12dcd7SJens Axboe spin_unlock(&elv_list_lock); 1171da177e4SLinus Torvalds 1181da177e4SLinus Torvalds return e; 1191da177e4SLinus Torvalds } 1201da177e4SLinus Torvalds 121484fc254SWang Sheng-Hui static char chosen_elevator[ELV_NAME_MAX]; 1221da177e4SLinus Torvalds 1235f003976SNate Diller static int __init elevator_setup(char *str) 1241da177e4SLinus Torvalds { 125752a3b79SChuck Ebbert /* 126752a3b79SChuck Ebbert * Be backwards-compatible with previous kernels, so users 127752a3b79SChuck Ebbert * won't get the wrong elevator. 128752a3b79SChuck Ebbert */ 1291da177e4SLinus Torvalds strncpy(chosen_elevator, str, sizeof(chosen_elevator) - 1); 1309b41046cSOGAWA Hirofumi return 1; 1311da177e4SLinus Torvalds } 1321da177e4SLinus Torvalds 1331da177e4SLinus Torvalds __setup("elevator=", elevator_setup); 1341da177e4SLinus Torvalds 135bb813f4cSTejun Heo /* called during boot to load the elevator chosen by the elevator param */ 136bb813f4cSTejun Heo void __init load_default_elevator_module(void) 137bb813f4cSTejun Heo { 138bb813f4cSTejun Heo struct elevator_type *e; 139bb813f4cSTejun Heo 140bb813f4cSTejun Heo if (!chosen_elevator[0]) 141bb813f4cSTejun Heo return; 142bb813f4cSTejun Heo 143bb813f4cSTejun Heo spin_lock(&elv_list_lock); 144bb813f4cSTejun Heo e = elevator_find(chosen_elevator); 145bb813f4cSTejun Heo spin_unlock(&elv_list_lock); 146bb813f4cSTejun Heo 147bb813f4cSTejun Heo if (!e) 148bb813f4cSTejun Heo request_module("%s-iosched", chosen_elevator); 149bb813f4cSTejun Heo } 150bb813f4cSTejun Heo 1513d1ab40fSAl Viro static struct kobj_type elv_ktype; 1523d1ab40fSAl Viro 153d50235b7SJianpeng Ma struct elevator_queue *elevator_alloc(struct request_queue *q, 154165125e1SJens Axboe struct elevator_type *e) 1553d1ab40fSAl Viro { 156b374d18aSJens Axboe struct elevator_queue *eq; 1579817064bSJens Axboe 158c1b511ebSJoe Perches eq = kzalloc_node(sizeof(*eq), GFP_KERNEL, q->node); 1599817064bSJens Axboe if (unlikely(!eq)) 1609817064bSJens Axboe goto err; 1619817064bSJens Axboe 16222f746e2STejun Heo eq->type = e; 163f9cb074bSGreg Kroah-Hartman kobject_init(&eq->kobj, &elv_ktype); 1643d1ab40fSAl Viro mutex_init(&eq->sysfs_lock); 165242d98f0SSasha Levin hash_init(eq->hash); 1669817064bSJens Axboe 1673d1ab40fSAl Viro return eq; 1689817064bSJens Axboe err: 1699817064bSJens Axboe kfree(eq); 1709817064bSJens Axboe elevator_put(e); 1719817064bSJens Axboe return NULL; 1723d1ab40fSAl Viro } 173d50235b7SJianpeng Ma EXPORT_SYMBOL(elevator_alloc); 1743d1ab40fSAl Viro 1753d1ab40fSAl Viro static void elevator_release(struct kobject *kobj) 1763d1ab40fSAl Viro { 177b374d18aSJens Axboe struct elevator_queue *e; 1789817064bSJens Axboe 179b374d18aSJens Axboe e = container_of(kobj, struct elevator_queue, kobj); 18022f746e2STejun Heo elevator_put(e->type); 1813d1ab40fSAl Viro kfree(e); 1823d1ab40fSAl Viro } 1833d1ab40fSAl Viro 184165125e1SJens Axboe int elevator_init(struct request_queue *q, char *name) 1851da177e4SLinus Torvalds { 1861da177e4SLinus Torvalds struct elevator_type *e = NULL; 187f8fc877dSTejun Heo int err; 1881da177e4SLinus Torvalds 189eb1c160bSTomoki Sekiyama /* 190eb1c160bSTomoki Sekiyama * q->sysfs_lock must be held to provide mutual exclusion between 191eb1c160bSTomoki Sekiyama * elevator_switch() and here. 192eb1c160bSTomoki Sekiyama */ 193eb1c160bSTomoki Sekiyama lockdep_assert_held(&q->sysfs_lock); 194eb1c160bSTomoki Sekiyama 1951abec4fdSMike Snitzer if (unlikely(q->elevator)) 1961abec4fdSMike Snitzer return 0; 1971abec4fdSMike Snitzer 198cb98fc8bSTejun Heo INIT_LIST_HEAD(&q->queue_head); 199cb98fc8bSTejun Heo q->last_merge = NULL; 200cb98fc8bSTejun Heo q->end_sector = 0; 201cb98fc8bSTejun Heo q->boundary_rq = NULL; 202cb98fc8bSTejun Heo 2034eb166d9SJens Axboe if (name) { 20421c3c5d2STejun Heo e = elevator_get(name, true); 2054eb166d9SJens Axboe if (!e) 2061da177e4SLinus Torvalds return -EINVAL; 2074eb166d9SJens Axboe } 2081da177e4SLinus Torvalds 20921c3c5d2STejun Heo /* 21021c3c5d2STejun Heo * Use the default elevator specified by config boot param or 21121c3c5d2STejun Heo * config option. Don't try to load modules as we could be running 21221c3c5d2STejun Heo * off async and request_module() isn't allowed from async. 21321c3c5d2STejun Heo */ 2144eb166d9SJens Axboe if (!e && *chosen_elevator) { 21521c3c5d2STejun Heo e = elevator_get(chosen_elevator, false); 2164eb166d9SJens Axboe if (!e) 2174eb166d9SJens Axboe printk(KERN_ERR "I/O scheduler %s not found\n", 2184eb166d9SJens Axboe chosen_elevator); 2194eb166d9SJens Axboe } 220248d5ca5SNate Diller 2214eb166d9SJens Axboe if (!e) { 22221c3c5d2STejun Heo e = elevator_get(CONFIG_DEFAULT_IOSCHED, false); 2234eb166d9SJens Axboe if (!e) { 2244eb166d9SJens Axboe printk(KERN_ERR 2254eb166d9SJens Axboe "Default I/O scheduler not found. " \ 2264eb166d9SJens Axboe "Using noop.\n"); 22721c3c5d2STejun Heo e = elevator_get("noop", false); 2285f003976SNate Diller } 2294eb166d9SJens Axboe } 2305f003976SNate Diller 231d50235b7SJianpeng Ma err = e->ops.elevator_init_fn(q, e); 232d32f6b57SSudip Mukherjee if (err) 233d32f6b57SSudip Mukherjee elevator_put(e); 234d32f6b57SSudip Mukherjee return err; 2351da177e4SLinus Torvalds } 2362e662b65SJens Axboe EXPORT_SYMBOL(elevator_init); 2372e662b65SJens Axboe 238b374d18aSJens Axboe void elevator_exit(struct elevator_queue *e) 2391da177e4SLinus Torvalds { 2403d1ab40fSAl Viro mutex_lock(&e->sysfs_lock); 24122f746e2STejun Heo if (e->type->ops.elevator_exit_fn) 24222f746e2STejun Heo e->type->ops.elevator_exit_fn(e); 2433d1ab40fSAl Viro mutex_unlock(&e->sysfs_lock); 2441da177e4SLinus Torvalds 2453d1ab40fSAl Viro kobject_put(&e->kobj); 2461da177e4SLinus Torvalds } 2472e662b65SJens Axboe EXPORT_SYMBOL(elevator_exit); 2482e662b65SJens Axboe 2499817064bSJens Axboe static inline void __elv_rqhash_del(struct request *rq) 2509817064bSJens Axboe { 251242d98f0SSasha Levin hash_del(&rq->hash); 252360f92c2SJens Axboe rq->cmd_flags &= ~REQ_HASHED; 2539817064bSJens Axboe } 2549817064bSJens Axboe 255165125e1SJens Axboe static void elv_rqhash_del(struct request_queue *q, struct request *rq) 2569817064bSJens Axboe { 2579817064bSJens Axboe if (ELV_ON_HASH(rq)) 2589817064bSJens Axboe __elv_rqhash_del(rq); 2599817064bSJens Axboe } 2609817064bSJens Axboe 261165125e1SJens Axboe static void elv_rqhash_add(struct request_queue *q, struct request *rq) 2629817064bSJens Axboe { 263b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 2649817064bSJens Axboe 2659817064bSJens Axboe BUG_ON(ELV_ON_HASH(rq)); 266242d98f0SSasha Levin hash_add(e->hash, &rq->hash, rq_hash_key(rq)); 267360f92c2SJens Axboe rq->cmd_flags |= REQ_HASHED; 2689817064bSJens Axboe } 2699817064bSJens Axboe 270165125e1SJens Axboe static void elv_rqhash_reposition(struct request_queue *q, struct request *rq) 2719817064bSJens Axboe { 2729817064bSJens Axboe __elv_rqhash_del(rq); 2739817064bSJens Axboe elv_rqhash_add(q, rq); 2749817064bSJens Axboe } 2759817064bSJens Axboe 276165125e1SJens Axboe static struct request *elv_rqhash_find(struct request_queue *q, sector_t offset) 2779817064bSJens Axboe { 278b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 279b67bfe0dSSasha Levin struct hlist_node *next; 2809817064bSJens Axboe struct request *rq; 2819817064bSJens Axboe 282ee89f812SLinus Torvalds hash_for_each_possible_safe(e->hash, rq, next, hash, offset) { 2839817064bSJens Axboe BUG_ON(!ELV_ON_HASH(rq)); 2849817064bSJens Axboe 2859817064bSJens Axboe if (unlikely(!rq_mergeable(rq))) { 2869817064bSJens Axboe __elv_rqhash_del(rq); 2879817064bSJens Axboe continue; 2889817064bSJens Axboe } 2899817064bSJens Axboe 2909817064bSJens Axboe if (rq_hash_key(rq) == offset) 2919817064bSJens Axboe return rq; 2929817064bSJens Axboe } 2939817064bSJens Axboe 2949817064bSJens Axboe return NULL; 2959817064bSJens Axboe } 2969817064bSJens Axboe 2978922e16cSTejun Heo /* 2982e662b65SJens Axboe * RB-tree support functions for inserting/lookup/removal of requests 2992e662b65SJens Axboe * in a sorted RB tree. 3002e662b65SJens Axboe */ 301796d5116SJeff Moyer void elv_rb_add(struct rb_root *root, struct request *rq) 3022e662b65SJens Axboe { 3032e662b65SJens Axboe struct rb_node **p = &root->rb_node; 3042e662b65SJens Axboe struct rb_node *parent = NULL; 3052e662b65SJens Axboe struct request *__rq; 3062e662b65SJens Axboe 3072e662b65SJens Axboe while (*p) { 3082e662b65SJens Axboe parent = *p; 3092e662b65SJens Axboe __rq = rb_entry(parent, struct request, rb_node); 3102e662b65SJens Axboe 31183096ebfSTejun Heo if (blk_rq_pos(rq) < blk_rq_pos(__rq)) 3122e662b65SJens Axboe p = &(*p)->rb_left; 313796d5116SJeff Moyer else if (blk_rq_pos(rq) >= blk_rq_pos(__rq)) 3142e662b65SJens Axboe p = &(*p)->rb_right; 3152e662b65SJens Axboe } 3162e662b65SJens Axboe 3172e662b65SJens Axboe rb_link_node(&rq->rb_node, parent, p); 3182e662b65SJens Axboe rb_insert_color(&rq->rb_node, root); 3192e662b65SJens Axboe } 3202e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_add); 3212e662b65SJens Axboe 3222e662b65SJens Axboe void elv_rb_del(struct rb_root *root, struct request *rq) 3232e662b65SJens Axboe { 3242e662b65SJens Axboe BUG_ON(RB_EMPTY_NODE(&rq->rb_node)); 3252e662b65SJens Axboe rb_erase(&rq->rb_node, root); 3262e662b65SJens Axboe RB_CLEAR_NODE(&rq->rb_node); 3272e662b65SJens Axboe } 3282e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_del); 3292e662b65SJens Axboe 3302e662b65SJens Axboe struct request *elv_rb_find(struct rb_root *root, sector_t sector) 3312e662b65SJens Axboe { 3322e662b65SJens Axboe struct rb_node *n = root->rb_node; 3332e662b65SJens Axboe struct request *rq; 3342e662b65SJens Axboe 3352e662b65SJens Axboe while (n) { 3362e662b65SJens Axboe rq = rb_entry(n, struct request, rb_node); 3372e662b65SJens Axboe 33883096ebfSTejun Heo if (sector < blk_rq_pos(rq)) 3392e662b65SJens Axboe n = n->rb_left; 34083096ebfSTejun Heo else if (sector > blk_rq_pos(rq)) 3412e662b65SJens Axboe n = n->rb_right; 3422e662b65SJens Axboe else 3432e662b65SJens Axboe return rq; 3442e662b65SJens Axboe } 3452e662b65SJens Axboe 3462e662b65SJens Axboe return NULL; 3472e662b65SJens Axboe } 3482e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_find); 3492e662b65SJens Axboe 3502e662b65SJens Axboe /* 3518922e16cSTejun Heo * Insert rq into dispatch queue of q. Queue lock must be held on 352dbe7f76dSUwe Kleine-König * entry. rq is sort instead into the dispatch queue. To be used by 3532e662b65SJens Axboe * specific elevators. 3548922e16cSTejun Heo */ 355165125e1SJens Axboe void elv_dispatch_sort(struct request_queue *q, struct request *rq) 3568922e16cSTejun Heo { 3578922e16cSTejun Heo sector_t boundary; 3588922e16cSTejun Heo struct list_head *entry; 3594eb166d9SJens Axboe int stop_flags; 3608922e16cSTejun Heo 36106b86245STejun Heo if (q->last_merge == rq) 36206b86245STejun Heo q->last_merge = NULL; 3639817064bSJens Axboe 3649817064bSJens Axboe elv_rqhash_del(q, rq); 3659817064bSJens Axboe 36615853af9STejun Heo q->nr_sorted--; 36706b86245STejun Heo 3681b47f531SJens Axboe boundary = q->end_sector; 36902e031cbSChristoph Hellwig stop_flags = REQ_SOFTBARRIER | REQ_STARTED; 3708922e16cSTejun Heo list_for_each_prev(entry, &q->queue_head) { 3718922e16cSTejun Heo struct request *pos = list_entry_rq(entry); 3728922e16cSTejun Heo 37333659ebbSChristoph Hellwig if ((rq->cmd_flags & REQ_DISCARD) != 37433659ebbSChristoph Hellwig (pos->cmd_flags & REQ_DISCARD)) 375e17fc0a1SDavid Woodhouse break; 376783660b2SJens Axboe if (rq_data_dir(rq) != rq_data_dir(pos)) 377783660b2SJens Axboe break; 3784eb166d9SJens Axboe if (pos->cmd_flags & stop_flags) 3798922e16cSTejun Heo break; 38083096ebfSTejun Heo if (blk_rq_pos(rq) >= boundary) { 38183096ebfSTejun Heo if (blk_rq_pos(pos) < boundary) 3828922e16cSTejun Heo continue; 3838922e16cSTejun Heo } else { 38483096ebfSTejun Heo if (blk_rq_pos(pos) >= boundary) 3858922e16cSTejun Heo break; 3868922e16cSTejun Heo } 38783096ebfSTejun Heo if (blk_rq_pos(rq) >= blk_rq_pos(pos)) 3888922e16cSTejun Heo break; 3898922e16cSTejun Heo } 3908922e16cSTejun Heo 3918922e16cSTejun Heo list_add(&rq->queuelist, entry); 3928922e16cSTejun Heo } 3932e662b65SJens Axboe EXPORT_SYMBOL(elv_dispatch_sort); 3942e662b65SJens Axboe 3959817064bSJens Axboe /* 3962e662b65SJens Axboe * Insert rq into dispatch queue of q. Queue lock must be held on 3972e662b65SJens Axboe * entry. rq is added to the back of the dispatch queue. To be used by 3982e662b65SJens Axboe * specific elevators. 3999817064bSJens Axboe */ 4009817064bSJens Axboe void elv_dispatch_add_tail(struct request_queue *q, struct request *rq) 4019817064bSJens Axboe { 4029817064bSJens Axboe if (q->last_merge == rq) 4039817064bSJens Axboe q->last_merge = NULL; 4049817064bSJens Axboe 4059817064bSJens Axboe elv_rqhash_del(q, rq); 4069817064bSJens Axboe 4079817064bSJens Axboe q->nr_sorted--; 4089817064bSJens Axboe 4099817064bSJens Axboe q->end_sector = rq_end_sector(rq); 4109817064bSJens Axboe q->boundary_rq = rq; 4119817064bSJens Axboe list_add_tail(&rq->queuelist, &q->queue_head); 4129817064bSJens Axboe } 4132e662b65SJens Axboe EXPORT_SYMBOL(elv_dispatch_add_tail); 4142e662b65SJens Axboe 415165125e1SJens Axboe int elv_merge(struct request_queue *q, struct request **req, struct bio *bio) 4161da177e4SLinus Torvalds { 417b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 4189817064bSJens Axboe struct request *__rq; 41906b86245STejun Heo int ret; 42006b86245STejun Heo 4219817064bSJens Axboe /* 422488991e2SAlan D. Brunelle * Levels of merges: 423488991e2SAlan D. Brunelle * nomerges: No merges at all attempted 424488991e2SAlan D. Brunelle * noxmerges: Only simple one-hit cache try 425488991e2SAlan D. Brunelle * merges: All merge tries attempted 426488991e2SAlan D. Brunelle */ 427488991e2SAlan D. Brunelle if (blk_queue_nomerges(q)) 428488991e2SAlan D. Brunelle return ELEVATOR_NO_MERGE; 429488991e2SAlan D. Brunelle 430488991e2SAlan D. Brunelle /* 4319817064bSJens Axboe * First try one-hit cache. 4329817064bSJens Axboe */ 433050c8ea8STejun Heo if (q->last_merge && elv_rq_merge_ok(q->last_merge, bio)) { 434050c8ea8STejun Heo ret = blk_try_merge(q->last_merge, bio); 43506b86245STejun Heo if (ret != ELEVATOR_NO_MERGE) { 43606b86245STejun Heo *req = q->last_merge; 43706b86245STejun Heo return ret; 43806b86245STejun Heo } 43906b86245STejun Heo } 4401da177e4SLinus Torvalds 441488991e2SAlan D. Brunelle if (blk_queue_noxmerges(q)) 442ac9fafa1SAlan D. Brunelle return ELEVATOR_NO_MERGE; 443ac9fafa1SAlan D. Brunelle 4449817064bSJens Axboe /* 4459817064bSJens Axboe * See if our hash lookup can find a potential backmerge. 4469817064bSJens Axboe */ 447*4f024f37SKent Overstreet __rq = elv_rqhash_find(q, bio->bi_iter.bi_sector); 4489817064bSJens Axboe if (__rq && elv_rq_merge_ok(__rq, bio)) { 4499817064bSJens Axboe *req = __rq; 4509817064bSJens Axboe return ELEVATOR_BACK_MERGE; 4519817064bSJens Axboe } 4529817064bSJens Axboe 45322f746e2STejun Heo if (e->type->ops.elevator_merge_fn) 45422f746e2STejun Heo return e->type->ops.elevator_merge_fn(q, req, bio); 4551da177e4SLinus Torvalds 4561da177e4SLinus Torvalds return ELEVATOR_NO_MERGE; 4571da177e4SLinus Torvalds } 4581da177e4SLinus Torvalds 4595e84ea3aSJens Axboe /* 4605e84ea3aSJens Axboe * Attempt to do an insertion back merge. Only check for the case where 4615e84ea3aSJens Axboe * we can append 'rq' to an existing request, so we can throw 'rq' away 4625e84ea3aSJens Axboe * afterwards. 4635e84ea3aSJens Axboe * 4645e84ea3aSJens Axboe * Returns true if we merged, false otherwise 4655e84ea3aSJens Axboe */ 4665e84ea3aSJens Axboe static bool elv_attempt_insert_merge(struct request_queue *q, 4675e84ea3aSJens Axboe struct request *rq) 4685e84ea3aSJens Axboe { 4695e84ea3aSJens Axboe struct request *__rq; 470bee0393cSShaohua Li bool ret; 4715e84ea3aSJens Axboe 4725e84ea3aSJens Axboe if (blk_queue_nomerges(q)) 4735e84ea3aSJens Axboe return false; 4745e84ea3aSJens Axboe 4755e84ea3aSJens Axboe /* 4765e84ea3aSJens Axboe * First try one-hit cache. 4775e84ea3aSJens Axboe */ 4785e84ea3aSJens Axboe if (q->last_merge && blk_attempt_req_merge(q, q->last_merge, rq)) 4795e84ea3aSJens Axboe return true; 4805e84ea3aSJens Axboe 4815e84ea3aSJens Axboe if (blk_queue_noxmerges(q)) 4825e84ea3aSJens Axboe return false; 4835e84ea3aSJens Axboe 484bee0393cSShaohua Li ret = false; 4855e84ea3aSJens Axboe /* 4865e84ea3aSJens Axboe * See if our hash lookup can find a potential backmerge. 4875e84ea3aSJens Axboe */ 488bee0393cSShaohua Li while (1) { 4895e84ea3aSJens Axboe __rq = elv_rqhash_find(q, blk_rq_pos(rq)); 490bee0393cSShaohua Li if (!__rq || !blk_attempt_req_merge(q, __rq, rq)) 491bee0393cSShaohua Li break; 4925e84ea3aSJens Axboe 493bee0393cSShaohua Li /* The merged request could be merged with others, try again */ 494bee0393cSShaohua Li ret = true; 495bee0393cSShaohua Li rq = __rq; 496bee0393cSShaohua Li } 497bee0393cSShaohua Li 498bee0393cSShaohua Li return ret; 4995e84ea3aSJens Axboe } 5005e84ea3aSJens Axboe 501165125e1SJens Axboe void elv_merged_request(struct request_queue *q, struct request *rq, int type) 5021da177e4SLinus Torvalds { 503b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 5041da177e4SLinus Torvalds 50522f746e2STejun Heo if (e->type->ops.elevator_merged_fn) 50622f746e2STejun Heo e->type->ops.elevator_merged_fn(q, rq, type); 50706b86245STejun Heo 5082e662b65SJens Axboe if (type == ELEVATOR_BACK_MERGE) 5099817064bSJens Axboe elv_rqhash_reposition(q, rq); 5109817064bSJens Axboe 51106b86245STejun Heo q->last_merge = rq; 5121da177e4SLinus Torvalds } 5131da177e4SLinus Torvalds 514165125e1SJens Axboe void elv_merge_requests(struct request_queue *q, struct request *rq, 5151da177e4SLinus Torvalds struct request *next) 5161da177e4SLinus Torvalds { 517b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 5185e84ea3aSJens Axboe const int next_sorted = next->cmd_flags & REQ_SORTED; 5191da177e4SLinus Torvalds 52022f746e2STejun Heo if (next_sorted && e->type->ops.elevator_merge_req_fn) 52122f746e2STejun Heo e->type->ops.elevator_merge_req_fn(q, rq, next); 52206b86245STejun Heo 5239817064bSJens Axboe elv_rqhash_reposition(q, rq); 5249817064bSJens Axboe 5255e84ea3aSJens Axboe if (next_sorted) { 5265e84ea3aSJens Axboe elv_rqhash_del(q, next); 5279817064bSJens Axboe q->nr_sorted--; 5285e84ea3aSJens Axboe } 5295e84ea3aSJens Axboe 53006b86245STejun Heo q->last_merge = rq; 5311da177e4SLinus Torvalds } 5321da177e4SLinus Torvalds 533812d4026SDivyesh Shah void elv_bio_merged(struct request_queue *q, struct request *rq, 534812d4026SDivyesh Shah struct bio *bio) 535812d4026SDivyesh Shah { 536812d4026SDivyesh Shah struct elevator_queue *e = q->elevator; 537812d4026SDivyesh Shah 53822f746e2STejun Heo if (e->type->ops.elevator_bio_merged_fn) 53922f746e2STejun Heo e->type->ops.elevator_bio_merged_fn(q, rq, bio); 540812d4026SDivyesh Shah } 541812d4026SDivyesh Shah 54247fafbc7SRafael J. Wysocki #ifdef CONFIG_PM 543c8158819SLin Ming static void blk_pm_requeue_request(struct request *rq) 544c8158819SLin Ming { 545c8158819SLin Ming if (rq->q->dev && !(rq->cmd_flags & REQ_PM)) 546c8158819SLin Ming rq->q->nr_pending--; 547c8158819SLin Ming } 548c8158819SLin Ming 549c8158819SLin Ming static void blk_pm_add_request(struct request_queue *q, struct request *rq) 550c8158819SLin Ming { 551c8158819SLin Ming if (q->dev && !(rq->cmd_flags & REQ_PM) && q->nr_pending++ == 0 && 552c8158819SLin Ming (q->rpm_status == RPM_SUSPENDED || q->rpm_status == RPM_SUSPENDING)) 553c8158819SLin Ming pm_request_resume(q->dev); 554c8158819SLin Ming } 555c8158819SLin Ming #else 556c8158819SLin Ming static inline void blk_pm_requeue_request(struct request *rq) {} 557c8158819SLin Ming static inline void blk_pm_add_request(struct request_queue *q, 558c8158819SLin Ming struct request *rq) 559c8158819SLin Ming { 560c8158819SLin Ming } 561c8158819SLin Ming #endif 562c8158819SLin Ming 563165125e1SJens Axboe void elv_requeue_request(struct request_queue *q, struct request *rq) 5641da177e4SLinus Torvalds { 5651da177e4SLinus Torvalds /* 5661da177e4SLinus Torvalds * it already went through dequeue, we need to decrement the 5671da177e4SLinus Torvalds * in_flight count again 5681da177e4SLinus Torvalds */ 5698922e16cSTejun Heo if (blk_account_rq(rq)) { 5700a7ae2ffSJens Axboe q->in_flight[rq_is_sync(rq)]--; 57133659ebbSChristoph Hellwig if (rq->cmd_flags & REQ_SORTED) 572cad97516SJens Axboe elv_deactivate_rq(q, rq); 5731da177e4SLinus Torvalds } 5741da177e4SLinus Torvalds 5754aff5e23SJens Axboe rq->cmd_flags &= ~REQ_STARTED; 5761da177e4SLinus Torvalds 577c8158819SLin Ming blk_pm_requeue_request(rq); 578c8158819SLin Ming 579b710a480SJens Axboe __elv_add_request(q, rq, ELEVATOR_INSERT_REQUEUE); 5801da177e4SLinus Torvalds } 5811da177e4SLinus Torvalds 58226308eabSJerome Marchand void elv_drain_elevator(struct request_queue *q) 58315853af9STejun Heo { 58415853af9STejun Heo static int printed; 585e3c78ca5STejun Heo 586e3c78ca5STejun Heo lockdep_assert_held(q->queue_lock); 587e3c78ca5STejun Heo 58822f746e2STejun Heo while (q->elevator->type->ops.elevator_dispatch_fn(q, 1)) 58915853af9STejun Heo ; 590e3c78ca5STejun Heo if (q->nr_sorted && printed++ < 10) { 59115853af9STejun Heo printk(KERN_ERR "%s: forced dispatching is broken " 59215853af9STejun Heo "(nr_sorted=%u), please report this\n", 59322f746e2STejun Heo q->elevator->type->elevator_name, q->nr_sorted); 59415853af9STejun Heo } 59515853af9STejun Heo } 59615853af9STejun Heo 597b710a480SJens Axboe void __elv_add_request(struct request_queue *q, struct request *rq, int where) 5981da177e4SLinus Torvalds { 5995f3ea37cSArnaldo Carvalho de Melo trace_block_rq_insert(q, rq); 6002056a782SJens Axboe 601c8158819SLin Ming blk_pm_add_request(q, rq); 602c8158819SLin Ming 6031da177e4SLinus Torvalds rq->q = q; 6041da177e4SLinus Torvalds 605b710a480SJens Axboe if (rq->cmd_flags & REQ_SOFTBARRIER) { 606b710a480SJens Axboe /* barriers are scheduling boundary, update end_sector */ 607e2a60da7SMartin K. Petersen if (rq->cmd_type == REQ_TYPE_FS) { 608b710a480SJens Axboe q->end_sector = rq_end_sector(rq); 609b710a480SJens Axboe q->boundary_rq = rq; 610b710a480SJens Axboe } 611b710a480SJens Axboe } else if (!(rq->cmd_flags & REQ_ELVPRIV) && 6123aa72873SJens Axboe (where == ELEVATOR_INSERT_SORT || 6133aa72873SJens Axboe where == ELEVATOR_INSERT_SORT_MERGE)) 614b710a480SJens Axboe where = ELEVATOR_INSERT_BACK; 615b710a480SJens Axboe 6168922e16cSTejun Heo switch (where) { 61728e7d184STejun Heo case ELEVATOR_INSERT_REQUEUE: 6188922e16cSTejun Heo case ELEVATOR_INSERT_FRONT: 6194aff5e23SJens Axboe rq->cmd_flags |= REQ_SOFTBARRIER; 6208922e16cSTejun Heo list_add(&rq->queuelist, &q->queue_head); 6218922e16cSTejun Heo break; 6228922e16cSTejun Heo 6238922e16cSTejun Heo case ELEVATOR_INSERT_BACK: 6244aff5e23SJens Axboe rq->cmd_flags |= REQ_SOFTBARRIER; 62515853af9STejun Heo elv_drain_elevator(q); 6268922e16cSTejun Heo list_add_tail(&rq->queuelist, &q->queue_head); 6278922e16cSTejun Heo /* 6288922e16cSTejun Heo * We kick the queue here for the following reasons. 6298922e16cSTejun Heo * - The elevator might have returned NULL previously 6308922e16cSTejun Heo * to delay requests and returned them now. As the 6318922e16cSTejun Heo * queue wasn't empty before this request, ll_rw_blk 6328922e16cSTejun Heo * won't run the queue on return, resulting in hang. 6338922e16cSTejun Heo * - Usually, back inserted requests won't be merged 6348922e16cSTejun Heo * with anything. There's no point in delaying queue 6358922e16cSTejun Heo * processing. 6368922e16cSTejun Heo */ 63724ecfbe2SChristoph Hellwig __blk_run_queue(q); 6388922e16cSTejun Heo break; 6398922e16cSTejun Heo 6405e84ea3aSJens Axboe case ELEVATOR_INSERT_SORT_MERGE: 6415e84ea3aSJens Axboe /* 6425e84ea3aSJens Axboe * If we succeed in merging this request with one in the 6435e84ea3aSJens Axboe * queue already, we are done - rq has now been freed, 6445e84ea3aSJens Axboe * so no need to do anything further. 6455e84ea3aSJens Axboe */ 6465e84ea3aSJens Axboe if (elv_attempt_insert_merge(q, rq)) 6475e84ea3aSJens Axboe break; 6488922e16cSTejun Heo case ELEVATOR_INSERT_SORT: 649e2a60da7SMartin K. Petersen BUG_ON(rq->cmd_type != REQ_TYPE_FS); 6504aff5e23SJens Axboe rq->cmd_flags |= REQ_SORTED; 65115853af9STejun Heo q->nr_sorted++; 6529817064bSJens Axboe if (rq_mergeable(rq)) { 6539817064bSJens Axboe elv_rqhash_add(q, rq); 6549817064bSJens Axboe if (!q->last_merge) 65506b86245STejun Heo q->last_merge = rq; 6569817064bSJens Axboe } 6579817064bSJens Axboe 658ca23509fSTejun Heo /* 659ca23509fSTejun Heo * Some ioscheds (cfq) run q->request_fn directly, so 660ca23509fSTejun Heo * rq cannot be accessed after calling 661ca23509fSTejun Heo * elevator_add_req_fn. 662ca23509fSTejun Heo */ 66322f746e2STejun Heo q->elevator->type->ops.elevator_add_req_fn(q, rq); 6648922e16cSTejun Heo break; 6658922e16cSTejun Heo 666ae1b1539STejun Heo case ELEVATOR_INSERT_FLUSH: 667ae1b1539STejun Heo rq->cmd_flags |= REQ_SOFTBARRIER; 668ae1b1539STejun Heo blk_insert_flush(rq); 669ae1b1539STejun Heo break; 6708922e16cSTejun Heo default: 6718922e16cSTejun Heo printk(KERN_ERR "%s: bad insertion point %d\n", 67224c03d47SHarvey Harrison __func__, where); 6738922e16cSTejun Heo BUG(); 6748922e16cSTejun Heo } 6751da177e4SLinus Torvalds } 6762e662b65SJens Axboe EXPORT_SYMBOL(__elv_add_request); 6772e662b65SJens Axboe 6787eaceaccSJens Axboe void elv_add_request(struct request_queue *q, struct request *rq, int where) 6791da177e4SLinus Torvalds { 6801da177e4SLinus Torvalds unsigned long flags; 6811da177e4SLinus Torvalds 6821da177e4SLinus Torvalds spin_lock_irqsave(q->queue_lock, flags); 6837eaceaccSJens Axboe __elv_add_request(q, rq, where); 6841da177e4SLinus Torvalds spin_unlock_irqrestore(q->queue_lock, flags); 6851da177e4SLinus Torvalds } 6862e662b65SJens Axboe EXPORT_SYMBOL(elv_add_request); 6872e662b65SJens Axboe 688165125e1SJens Axboe struct request *elv_latter_request(struct request_queue *q, struct request *rq) 6891da177e4SLinus Torvalds { 690b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 6911da177e4SLinus Torvalds 69222f746e2STejun Heo if (e->type->ops.elevator_latter_req_fn) 69322f746e2STejun Heo return e->type->ops.elevator_latter_req_fn(q, rq); 6941da177e4SLinus Torvalds return NULL; 6951da177e4SLinus Torvalds } 6961da177e4SLinus Torvalds 697165125e1SJens Axboe struct request *elv_former_request(struct request_queue *q, struct request *rq) 6981da177e4SLinus Torvalds { 699b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 7001da177e4SLinus Torvalds 70122f746e2STejun Heo if (e->type->ops.elevator_former_req_fn) 70222f746e2STejun Heo return e->type->ops.elevator_former_req_fn(q, rq); 7031da177e4SLinus Torvalds return NULL; 7041da177e4SLinus Torvalds } 7051da177e4SLinus Torvalds 706852c788fSTejun Heo int elv_set_request(struct request_queue *q, struct request *rq, 707852c788fSTejun Heo struct bio *bio, gfp_t gfp_mask) 7081da177e4SLinus Torvalds { 709b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 7101da177e4SLinus Torvalds 71122f746e2STejun Heo if (e->type->ops.elevator_set_req_fn) 712852c788fSTejun Heo return e->type->ops.elevator_set_req_fn(q, rq, bio, gfp_mask); 7131da177e4SLinus Torvalds return 0; 7141da177e4SLinus Torvalds } 7151da177e4SLinus Torvalds 716165125e1SJens Axboe void elv_put_request(struct request_queue *q, struct request *rq) 7171da177e4SLinus Torvalds { 718b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 7191da177e4SLinus Torvalds 72022f746e2STejun Heo if (e->type->ops.elevator_put_req_fn) 72122f746e2STejun Heo e->type->ops.elevator_put_req_fn(rq); 7221da177e4SLinus Torvalds } 7231da177e4SLinus Torvalds 724165125e1SJens Axboe int elv_may_queue(struct request_queue *q, int rw) 7251da177e4SLinus Torvalds { 726b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 7271da177e4SLinus Torvalds 72822f746e2STejun Heo if (e->type->ops.elevator_may_queue_fn) 72922f746e2STejun Heo return e->type->ops.elevator_may_queue_fn(q, rw); 7301da177e4SLinus Torvalds 7311da177e4SLinus Torvalds return ELV_MQUEUE_MAY; 7321da177e4SLinus Torvalds } 7331da177e4SLinus Torvalds 734165125e1SJens Axboe void elv_completed_request(struct request_queue *q, struct request *rq) 7351da177e4SLinus Torvalds { 736b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 7371da177e4SLinus Torvalds 7381da177e4SLinus Torvalds /* 7391da177e4SLinus Torvalds * request is released from the driver, io must be done 7401da177e4SLinus Torvalds */ 7418922e16cSTejun Heo if (blk_account_rq(rq)) { 7420a7ae2ffSJens Axboe q->in_flight[rq_is_sync(rq)]--; 74333659ebbSChristoph Hellwig if ((rq->cmd_flags & REQ_SORTED) && 74422f746e2STejun Heo e->type->ops.elevator_completed_req_fn) 74522f746e2STejun Heo e->type->ops.elevator_completed_req_fn(q, rq); 7461bc691d3STejun Heo } 7478922e16cSTejun Heo } 7481da177e4SLinus Torvalds 7493d1ab40fSAl Viro #define to_elv(atr) container_of((atr), struct elv_fs_entry, attr) 7503d1ab40fSAl Viro 7513d1ab40fSAl Viro static ssize_t 7523d1ab40fSAl Viro elv_attr_show(struct kobject *kobj, struct attribute *attr, char *page) 7533d1ab40fSAl Viro { 7543d1ab40fSAl Viro struct elv_fs_entry *entry = to_elv(attr); 755b374d18aSJens Axboe struct elevator_queue *e; 7563d1ab40fSAl Viro ssize_t error; 7573d1ab40fSAl Viro 7583d1ab40fSAl Viro if (!entry->show) 7593d1ab40fSAl Viro return -EIO; 7603d1ab40fSAl Viro 761b374d18aSJens Axboe e = container_of(kobj, struct elevator_queue, kobj); 7623d1ab40fSAl Viro mutex_lock(&e->sysfs_lock); 76322f746e2STejun Heo error = e->type ? entry->show(e, page) : -ENOENT; 7643d1ab40fSAl Viro mutex_unlock(&e->sysfs_lock); 7653d1ab40fSAl Viro return error; 7663d1ab40fSAl Viro } 7673d1ab40fSAl Viro 7683d1ab40fSAl Viro static ssize_t 7693d1ab40fSAl Viro elv_attr_store(struct kobject *kobj, struct attribute *attr, 7703d1ab40fSAl Viro const char *page, size_t length) 7713d1ab40fSAl Viro { 7723d1ab40fSAl Viro struct elv_fs_entry *entry = to_elv(attr); 773b374d18aSJens Axboe struct elevator_queue *e; 7743d1ab40fSAl Viro ssize_t error; 7753d1ab40fSAl Viro 7763d1ab40fSAl Viro if (!entry->store) 7773d1ab40fSAl Viro return -EIO; 7783d1ab40fSAl Viro 779b374d18aSJens Axboe e = container_of(kobj, struct elevator_queue, kobj); 7803d1ab40fSAl Viro mutex_lock(&e->sysfs_lock); 78122f746e2STejun Heo error = e->type ? entry->store(e, page, length) : -ENOENT; 7823d1ab40fSAl Viro mutex_unlock(&e->sysfs_lock); 7833d1ab40fSAl Viro return error; 7843d1ab40fSAl Viro } 7853d1ab40fSAl Viro 78652cf25d0SEmese Revfy static const struct sysfs_ops elv_sysfs_ops = { 7873d1ab40fSAl Viro .show = elv_attr_show, 7883d1ab40fSAl Viro .store = elv_attr_store, 7893d1ab40fSAl Viro }; 7903d1ab40fSAl Viro 7913d1ab40fSAl Viro static struct kobj_type elv_ktype = { 7923d1ab40fSAl Viro .sysfs_ops = &elv_sysfs_ops, 7933d1ab40fSAl Viro .release = elevator_release, 7943d1ab40fSAl Viro }; 7953d1ab40fSAl Viro 7965a5bafdcSTejun Heo int elv_register_queue(struct request_queue *q) 7971da177e4SLinus Torvalds { 7985a5bafdcSTejun Heo struct elevator_queue *e = q->elevator; 7993d1ab40fSAl Viro int error; 8001da177e4SLinus Torvalds 801b2d6db58SGreg Kroah-Hartman error = kobject_add(&e->kobj, &q->kobj, "%s", "iosched"); 8023d1ab40fSAl Viro if (!error) { 80322f746e2STejun Heo struct elv_fs_entry *attr = e->type->elevator_attrs; 8043d1ab40fSAl Viro if (attr) { 805e572ec7eSAl Viro while (attr->attr.name) { 806e572ec7eSAl Viro if (sysfs_create_file(&e->kobj, &attr->attr)) 8073d1ab40fSAl Viro break; 808e572ec7eSAl Viro attr++; 8093d1ab40fSAl Viro } 8103d1ab40fSAl Viro } 8113d1ab40fSAl Viro kobject_uevent(&e->kobj, KOBJ_ADD); 812430c62fbSJens Axboe e->registered = 1; 8133d1ab40fSAl Viro } 8143d1ab40fSAl Viro return error; 8151da177e4SLinus Torvalds } 81601effb0dSMike Snitzer EXPORT_SYMBOL(elv_register_queue); 8171da177e4SLinus Torvalds 818f8fc877dSTejun Heo void elv_unregister_queue(struct request_queue *q) 8191da177e4SLinus Torvalds { 820f8fc877dSTejun Heo if (q) { 821f8fc877dSTejun Heo struct elevator_queue *e = q->elevator; 822f8fc877dSTejun Heo 8233d1ab40fSAl Viro kobject_uevent(&e->kobj, KOBJ_REMOVE); 8243d1ab40fSAl Viro kobject_del(&e->kobj); 825430c62fbSJens Axboe e->registered = 0; 8261da177e4SLinus Torvalds } 8271da177e4SLinus Torvalds } 82801effb0dSMike Snitzer EXPORT_SYMBOL(elv_unregister_queue); 8291da177e4SLinus Torvalds 830e567bf71SJens Axboe int elv_register(struct elevator_type *e) 8311da177e4SLinus Torvalds { 8321ffb96c5SThibaut VARENE char *def = ""; 8332a12dcd7SJens Axboe 8343d3c2379STejun Heo /* create icq_cache if requested */ 8353d3c2379STejun Heo if (e->icq_size) { 8363d3c2379STejun Heo if (WARN_ON(e->icq_size < sizeof(struct io_cq)) || 8373d3c2379STejun Heo WARN_ON(e->icq_align < __alignof__(struct io_cq))) 8383d3c2379STejun Heo return -EINVAL; 8393d3c2379STejun Heo 8403d3c2379STejun Heo snprintf(e->icq_cache_name, sizeof(e->icq_cache_name), 8413d3c2379STejun Heo "%s_io_cq", e->elevator_name); 8423d3c2379STejun Heo e->icq_cache = kmem_cache_create(e->icq_cache_name, e->icq_size, 8433d3c2379STejun Heo e->icq_align, 0, NULL); 8443d3c2379STejun Heo if (!e->icq_cache) 8453d3c2379STejun Heo return -ENOMEM; 8463d3c2379STejun Heo } 8473d3c2379STejun Heo 8483d3c2379STejun Heo /* register, don't allow duplicate names */ 8492a12dcd7SJens Axboe spin_lock(&elv_list_lock); 8503d3c2379STejun Heo if (elevator_find(e->elevator_name)) { 8513d3c2379STejun Heo spin_unlock(&elv_list_lock); 8523d3c2379STejun Heo if (e->icq_cache) 8533d3c2379STejun Heo kmem_cache_destroy(e->icq_cache); 8543d3c2379STejun Heo return -EBUSY; 8553d3c2379STejun Heo } 8561da177e4SLinus Torvalds list_add_tail(&e->list, &elv_list); 8572a12dcd7SJens Axboe spin_unlock(&elv_list_lock); 8581da177e4SLinus Torvalds 8593d3c2379STejun Heo /* print pretty message */ 8605f003976SNate Diller if (!strcmp(e->elevator_name, chosen_elevator) || 8615f003976SNate Diller (!*chosen_elevator && 8625f003976SNate Diller !strcmp(e->elevator_name, CONFIG_DEFAULT_IOSCHED))) 8631ffb96c5SThibaut VARENE def = " (default)"; 8641ffb96c5SThibaut VARENE 8654eb166d9SJens Axboe printk(KERN_INFO "io scheduler %s registered%s\n", e->elevator_name, 8664eb166d9SJens Axboe def); 8673d3c2379STejun Heo return 0; 8681da177e4SLinus Torvalds } 8691da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(elv_register); 8701da177e4SLinus Torvalds 8711da177e4SLinus Torvalds void elv_unregister(struct elevator_type *e) 8721da177e4SLinus Torvalds { 8733d3c2379STejun Heo /* unregister */ 8742a12dcd7SJens Axboe spin_lock(&elv_list_lock); 8751da177e4SLinus Torvalds list_del_init(&e->list); 8762a12dcd7SJens Axboe spin_unlock(&elv_list_lock); 8773d3c2379STejun Heo 8783d3c2379STejun Heo /* 8793d3c2379STejun Heo * Destroy icq_cache if it exists. icq's are RCU managed. Make 8803d3c2379STejun Heo * sure all RCU operations are complete before proceeding. 8813d3c2379STejun Heo */ 8823d3c2379STejun Heo if (e->icq_cache) { 8833d3c2379STejun Heo rcu_barrier(); 8843d3c2379STejun Heo kmem_cache_destroy(e->icq_cache); 8853d3c2379STejun Heo e->icq_cache = NULL; 8863d3c2379STejun Heo } 8871da177e4SLinus Torvalds } 8881da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(elv_unregister); 8891da177e4SLinus Torvalds 8901da177e4SLinus Torvalds /* 8911da177e4SLinus Torvalds * switch to new_e io scheduler. be careful not to introduce deadlocks - 8921da177e4SLinus Torvalds * we don't free the old io scheduler, before we have allocated what we 8931da177e4SLinus Torvalds * need for the new one. this way we have a chance of going back to the old 894cb98fc8bSTejun Heo * one, if the new one fails init for some reason. 8951da177e4SLinus Torvalds */ 896165125e1SJens Axboe static int elevator_switch(struct request_queue *q, struct elevator_type *new_e) 8971da177e4SLinus Torvalds { 8985a5bafdcSTejun Heo struct elevator_queue *old = q->elevator; 8995a5bafdcSTejun Heo bool registered = old->registered; 900e8989faeSTejun Heo int err; 9011da177e4SLinus Torvalds 9025a5bafdcSTejun Heo /* 9035a5bafdcSTejun Heo * Turn on BYPASS and drain all requests w/ elevator private data. 9045a5bafdcSTejun Heo * Block layer doesn't call into a quiesced elevator - all requests 9055a5bafdcSTejun Heo * are directly put on the dispatch list without elevator data 9065a5bafdcSTejun Heo * using INSERT_BACK. All requests have SOFTBARRIER set and no 9075a5bafdcSTejun Heo * merge happens either. 9085a5bafdcSTejun Heo */ 909d732580bSTejun Heo blk_queue_bypass_start(q); 910cb98fc8bSTejun Heo 9115a5bafdcSTejun Heo /* unregister and clear all auxiliary data of the old elevator */ 9125a5bafdcSTejun Heo if (registered) 913f8fc877dSTejun Heo elv_unregister_queue(q); 9145a5bafdcSTejun Heo 9155a5bafdcSTejun Heo spin_lock_irq(q->queue_lock); 9165a5bafdcSTejun Heo ioc_clear_queue(q); 9175a5bafdcSTejun Heo spin_unlock_irq(q->queue_lock); 9185a5bafdcSTejun Heo 9195a5bafdcSTejun Heo /* allocate, init and register new elevator */ 920d50235b7SJianpeng Ma err = new_e->ops.elevator_init_fn(q, new_e); 921d50235b7SJianpeng Ma if (err) 9225a5bafdcSTejun Heo goto fail_init; 9235a5bafdcSTejun Heo 9245a5bafdcSTejun Heo if (registered) { 9255a5bafdcSTejun Heo err = elv_register_queue(q); 9265dd531a0SJens Axboe if (err) 9271da177e4SLinus Torvalds goto fail_register; 928430c62fbSJens Axboe } 9291da177e4SLinus Torvalds 9305a5bafdcSTejun Heo /* done, kill the old one and finish */ 9315a5bafdcSTejun Heo elevator_exit(old); 932d732580bSTejun Heo blk_queue_bypass_end(q); 93375ad23bcSNick Piggin 9345a5bafdcSTejun Heo blk_add_trace_msg(q, "elv switch: %s", new_e->elevator_name); 9354722dc52SAlan D. Brunelle 9365dd531a0SJens Axboe return 0; 9371da177e4SLinus Torvalds 9381da177e4SLinus Torvalds fail_register: 9395a5bafdcSTejun Heo elevator_exit(q->elevator); 9405a5bafdcSTejun Heo fail_init: 9415a5bafdcSTejun Heo /* switch failed, restore and re-register old elevator */ 9425a5bafdcSTejun Heo q->elevator = old; 9431da177e4SLinus Torvalds elv_register_queue(q); 944d732580bSTejun Heo blk_queue_bypass_end(q); 94575ad23bcSNick Piggin 9465dd531a0SJens Axboe return err; 9471da177e4SLinus Torvalds } 9481da177e4SLinus Torvalds 9495dd531a0SJens Axboe /* 9505dd531a0SJens Axboe * Switch this queue to the given IO scheduler. 9515dd531a0SJens Axboe */ 9527c8a3679STomoki Sekiyama static int __elevator_change(struct request_queue *q, const char *name) 9531da177e4SLinus Torvalds { 9541da177e4SLinus Torvalds char elevator_name[ELV_NAME_MAX]; 9551da177e4SLinus Torvalds struct elevator_type *e; 9561da177e4SLinus Torvalds 957cd43e26fSMartin K. Petersen if (!q->elevator) 9585dd531a0SJens Axboe return -ENXIO; 959cd43e26fSMartin K. Petersen 960ee2e992cSLi Zefan strlcpy(elevator_name, name, sizeof(elevator_name)); 96121c3c5d2STejun Heo e = elevator_get(strstrip(elevator_name), true); 9621da177e4SLinus Torvalds if (!e) { 9631da177e4SLinus Torvalds printk(KERN_ERR "elevator: type %s not found\n", elevator_name); 9641da177e4SLinus Torvalds return -EINVAL; 9651da177e4SLinus Torvalds } 9661da177e4SLinus Torvalds 96722f746e2STejun Heo if (!strcmp(elevator_name, q->elevator->type->elevator_name)) { 9682ca7d93bSNate Diller elevator_put(e); 9695dd531a0SJens Axboe return 0; 9702ca7d93bSNate Diller } 9711da177e4SLinus Torvalds 9725dd531a0SJens Axboe return elevator_switch(q, e); 9735dd531a0SJens Axboe } 9747c8a3679STomoki Sekiyama 9757c8a3679STomoki Sekiyama int elevator_change(struct request_queue *q, const char *name) 9767c8a3679STomoki Sekiyama { 9777c8a3679STomoki Sekiyama int ret; 9787c8a3679STomoki Sekiyama 9797c8a3679STomoki Sekiyama /* Protect q->elevator from elevator_init() */ 9807c8a3679STomoki Sekiyama mutex_lock(&q->sysfs_lock); 9817c8a3679STomoki Sekiyama ret = __elevator_change(q, name); 9827c8a3679STomoki Sekiyama mutex_unlock(&q->sysfs_lock); 9837c8a3679STomoki Sekiyama 9847c8a3679STomoki Sekiyama return ret; 9857c8a3679STomoki Sekiyama } 9865dd531a0SJens Axboe EXPORT_SYMBOL(elevator_change); 9875dd531a0SJens Axboe 9885dd531a0SJens Axboe ssize_t elv_iosched_store(struct request_queue *q, const char *name, 9895dd531a0SJens Axboe size_t count) 9905dd531a0SJens Axboe { 9915dd531a0SJens Axboe int ret; 9925dd531a0SJens Axboe 9935dd531a0SJens Axboe if (!q->elevator) 9941da177e4SLinus Torvalds return count; 9955dd531a0SJens Axboe 9967c8a3679STomoki Sekiyama ret = __elevator_change(q, name); 9975dd531a0SJens Axboe if (!ret) 9985dd531a0SJens Axboe return count; 9995dd531a0SJens Axboe 10005dd531a0SJens Axboe printk(KERN_ERR "elevator: switch to %s failed\n", name); 10015dd531a0SJens Axboe return ret; 10021da177e4SLinus Torvalds } 10031da177e4SLinus Torvalds 1004165125e1SJens Axboe ssize_t elv_iosched_show(struct request_queue *q, char *name) 10051da177e4SLinus Torvalds { 1006b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 1007cd43e26fSMartin K. Petersen struct elevator_type *elv; 100870cee26eSMatthias Kaehlcke struct elevator_type *__e; 10091da177e4SLinus Torvalds int len = 0; 10101da177e4SLinus Torvalds 1011e36f724bSMike Snitzer if (!q->elevator || !blk_queue_stackable(q)) 1012cd43e26fSMartin K. Petersen return sprintf(name, "none\n"); 1013cd43e26fSMartin K. Petersen 101422f746e2STejun Heo elv = e->type; 1015cd43e26fSMartin K. Petersen 10162a12dcd7SJens Axboe spin_lock(&elv_list_lock); 101770cee26eSMatthias Kaehlcke list_for_each_entry(__e, &elv_list, list) { 10181da177e4SLinus Torvalds if (!strcmp(elv->elevator_name, __e->elevator_name)) 10191da177e4SLinus Torvalds len += sprintf(name+len, "[%s] ", elv->elevator_name); 10201da177e4SLinus Torvalds else 10211da177e4SLinus Torvalds len += sprintf(name+len, "%s ", __e->elevator_name); 10221da177e4SLinus Torvalds } 10232a12dcd7SJens Axboe spin_unlock(&elv_list_lock); 10241da177e4SLinus Torvalds 10251da177e4SLinus Torvalds len += sprintf(len+name, "\n"); 10261da177e4SLinus Torvalds return len; 10271da177e4SLinus Torvalds } 10281da177e4SLinus Torvalds 1029165125e1SJens Axboe struct request *elv_rb_former_request(struct request_queue *q, 1030165125e1SJens Axboe struct request *rq) 10312e662b65SJens Axboe { 10322e662b65SJens Axboe struct rb_node *rbprev = rb_prev(&rq->rb_node); 10332e662b65SJens Axboe 10342e662b65SJens Axboe if (rbprev) 10352e662b65SJens Axboe return rb_entry_rq(rbprev); 10362e662b65SJens Axboe 10372e662b65SJens Axboe return NULL; 10382e662b65SJens Axboe } 10392e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_former_request); 10402e662b65SJens Axboe 1041165125e1SJens Axboe struct request *elv_rb_latter_request(struct request_queue *q, 1042165125e1SJens Axboe struct request *rq) 10432e662b65SJens Axboe { 10442e662b65SJens Axboe struct rb_node *rbnext = rb_next(&rq->rb_node); 10452e662b65SJens Axboe 10462e662b65SJens Axboe if (rbnext) 10472e662b65SJens Axboe return rb_entry_rq(rbnext); 10482e662b65SJens Axboe 10492e662b65SJens Axboe return NULL; 10502e662b65SJens Axboe } 10512e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_latter_request); 1052