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> 34cb98fc8bSTejun Heo #include <linux/delay.h> 352056a782SJens Axboe #include <linux/blktrace_api.h> 369817064bSJens Axboe #include <linux/hash.h> 370835da67SJens Axboe #include <linux/uaccess.h> 381da177e4SLinus Torvalds 3955782138SLi Zefan #include <trace/events/block.h> 4055782138SLi Zefan 41242f9dcbSJens Axboe #include "blk.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 65da775265SJens Axboe if (e->ops->elevator_allow_merge_fn) 66da775265SJens Axboe return e->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 */ 7472ed0bf6SAdrian Bunk int elv_rq_merge_ok(struct request *rq, struct bio *bio) 751da177e4SLinus Torvalds { 761da177e4SLinus Torvalds if (!rq_mergeable(rq)) 771da177e4SLinus Torvalds return 0; 781da177e4SLinus Torvalds 791da177e4SLinus Torvalds /* 80e17fc0a1SDavid Woodhouse * Don't merge file system requests and discard requests 81e17fc0a1SDavid Woodhouse */ 827b6d91daSChristoph Hellwig if ((bio->bi_rw & REQ_DISCARD) != (rq->bio->bi_rw & REQ_DISCARD)) 83e17fc0a1SDavid Woodhouse return 0; 84e17fc0a1SDavid Woodhouse 85e17fc0a1SDavid Woodhouse /* 868d57a98cSAdrian Hunter * Don't merge discard requests and secure discard requests 878d57a98cSAdrian Hunter */ 888d57a98cSAdrian Hunter if ((bio->bi_rw & REQ_SECURE) != (rq->bio->bi_rw & REQ_SECURE)) 898d57a98cSAdrian Hunter return 0; 908d57a98cSAdrian Hunter 918d57a98cSAdrian Hunter /* 921da177e4SLinus Torvalds * different data direction or already started, don't merge 931da177e4SLinus Torvalds */ 941da177e4SLinus Torvalds if (bio_data_dir(bio) != rq_data_dir(rq)) 951da177e4SLinus Torvalds return 0; 961da177e4SLinus Torvalds 971da177e4SLinus Torvalds /* 98da775265SJens Axboe * must be same device and not a special request 991da177e4SLinus Torvalds */ 100bb4067e3SJens Axboe if (rq->rq_disk != bio->bi_bdev->bd_disk || rq->special) 1011da177e4SLinus Torvalds return 0; 102da775265SJens Axboe 1037ba1ba12SMartin K. Petersen /* 1047ba1ba12SMartin K. Petersen * only merge integrity protected bio into ditto rq 1057ba1ba12SMartin K. Petersen */ 1067ba1ba12SMartin K. Petersen if (bio_integrity(bio) != blk_integrity_rq(rq)) 1077ba1ba12SMartin K. Petersen return 0; 1087ba1ba12SMartin K. Petersen 109da775265SJens Axboe if (!elv_iosched_allow_merge(rq, bio)) 110da775265SJens Axboe return 0; 111da775265SJens Axboe 112da775265SJens Axboe return 1; 1131da177e4SLinus Torvalds } 1141da177e4SLinus Torvalds EXPORT_SYMBOL(elv_rq_merge_ok); 1151da177e4SLinus Torvalds 116*73c10101SJens Axboe int elv_try_merge(struct request *__rq, struct bio *bio) 1171da177e4SLinus Torvalds { 1181da177e4SLinus Torvalds int ret = ELEVATOR_NO_MERGE; 1191da177e4SLinus Torvalds 1201da177e4SLinus Torvalds /* 1211da177e4SLinus Torvalds * we can merge and sequence is ok, check if it's possible 1221da177e4SLinus Torvalds */ 1231da177e4SLinus Torvalds if (elv_rq_merge_ok(__rq, bio)) { 12483096ebfSTejun Heo if (blk_rq_pos(__rq) + blk_rq_sectors(__rq) == bio->bi_sector) 1251da177e4SLinus Torvalds ret = ELEVATOR_BACK_MERGE; 12683096ebfSTejun Heo else if (blk_rq_pos(__rq) - bio_sectors(bio) == bio->bi_sector) 1271da177e4SLinus Torvalds ret = ELEVATOR_FRONT_MERGE; 1281da177e4SLinus Torvalds } 1291da177e4SLinus Torvalds 1301da177e4SLinus Torvalds return ret; 1311da177e4SLinus Torvalds } 1321da177e4SLinus Torvalds 1331da177e4SLinus Torvalds static struct elevator_type *elevator_find(const char *name) 1341da177e4SLinus Torvalds { 135a22b169dSVasily Tarasov struct elevator_type *e; 1361da177e4SLinus Torvalds 13770cee26eSMatthias Kaehlcke list_for_each_entry(e, &elv_list, list) { 138a22b169dSVasily Tarasov if (!strcmp(e->elevator_name, name)) 1391da177e4SLinus Torvalds return e; 1401da177e4SLinus Torvalds } 1411da177e4SLinus Torvalds 142a22b169dSVasily Tarasov return NULL; 143a22b169dSVasily Tarasov } 144a22b169dSVasily Tarasov 1451da177e4SLinus Torvalds static void elevator_put(struct elevator_type *e) 1461da177e4SLinus Torvalds { 1471da177e4SLinus Torvalds module_put(e->elevator_owner); 1481da177e4SLinus Torvalds } 1491da177e4SLinus Torvalds 1501da177e4SLinus Torvalds static struct elevator_type *elevator_get(const char *name) 1511da177e4SLinus Torvalds { 1522824bc93STejun Heo struct elevator_type *e; 1531da177e4SLinus Torvalds 1542a12dcd7SJens Axboe spin_lock(&elv_list_lock); 1552824bc93STejun Heo 1562824bc93STejun Heo e = elevator_find(name); 157e1640949SJens Axboe if (!e) { 158e1640949SJens Axboe char elv[ELV_NAME_MAX + strlen("-iosched")]; 159e1640949SJens Axboe 160e1640949SJens Axboe spin_unlock(&elv_list_lock); 161e1640949SJens Axboe 162a506aedcSwzt.wzt@gmail.com snprintf(elv, sizeof(elv), "%s-iosched", name); 163e1640949SJens Axboe 164e180f594Smaximilian attems request_module("%s", elv); 165e1640949SJens Axboe spin_lock(&elv_list_lock); 166e1640949SJens Axboe e = elevator_find(name); 167e1640949SJens Axboe } 168e1640949SJens Axboe 1692824bc93STejun Heo if (e && !try_module_get(e->elevator_owner)) 1702824bc93STejun Heo e = NULL; 1712824bc93STejun Heo 1722a12dcd7SJens Axboe spin_unlock(&elv_list_lock); 1731da177e4SLinus Torvalds 1741da177e4SLinus Torvalds return e; 1751da177e4SLinus Torvalds } 1761da177e4SLinus Torvalds 177165125e1SJens Axboe static void *elevator_init_queue(struct request_queue *q, 178165125e1SJens Axboe struct elevator_queue *eq) 1791da177e4SLinus Torvalds { 180bb37b94cSJens Axboe return eq->ops->elevator_init_fn(q); 181bc1c1169SJens Axboe } 1821da177e4SLinus Torvalds 183165125e1SJens Axboe static void elevator_attach(struct request_queue *q, struct elevator_queue *eq, 184bc1c1169SJens Axboe void *data) 185bc1c1169SJens Axboe { 1861da177e4SLinus Torvalds q->elevator = eq; 187bc1c1169SJens Axboe eq->elevator_data = data; 1881da177e4SLinus Torvalds } 1891da177e4SLinus Torvalds 1901da177e4SLinus Torvalds static char chosen_elevator[16]; 1911da177e4SLinus Torvalds 1925f003976SNate Diller static int __init elevator_setup(char *str) 1931da177e4SLinus Torvalds { 194752a3b79SChuck Ebbert /* 195752a3b79SChuck Ebbert * Be backwards-compatible with previous kernels, so users 196752a3b79SChuck Ebbert * won't get the wrong elevator. 197752a3b79SChuck Ebbert */ 1981da177e4SLinus Torvalds strncpy(chosen_elevator, str, sizeof(chosen_elevator) - 1); 1999b41046cSOGAWA Hirofumi return 1; 2001da177e4SLinus Torvalds } 2011da177e4SLinus Torvalds 2021da177e4SLinus Torvalds __setup("elevator=", elevator_setup); 2031da177e4SLinus Torvalds 2043d1ab40fSAl Viro static struct kobj_type elv_ktype; 2053d1ab40fSAl Viro 206b374d18aSJens Axboe static struct elevator_queue *elevator_alloc(struct request_queue *q, 207165125e1SJens Axboe struct elevator_type *e) 2083d1ab40fSAl Viro { 209b374d18aSJens Axboe struct elevator_queue *eq; 2109817064bSJens Axboe int i; 2119817064bSJens Axboe 212b374d18aSJens Axboe eq = kmalloc_node(sizeof(*eq), GFP_KERNEL | __GFP_ZERO, q->node); 2139817064bSJens Axboe if (unlikely(!eq)) 2149817064bSJens Axboe goto err; 2159817064bSJens Axboe 2163d1ab40fSAl Viro eq->ops = &e->ops; 2173d1ab40fSAl Viro eq->elevator_type = e; 218f9cb074bSGreg Kroah-Hartman kobject_init(&eq->kobj, &elv_ktype); 2193d1ab40fSAl Viro mutex_init(&eq->sysfs_lock); 2209817064bSJens Axboe 221b5deef90SJens Axboe eq->hash = kmalloc_node(sizeof(struct hlist_head) * ELV_HASH_ENTRIES, 222b5deef90SJens Axboe GFP_KERNEL, q->node); 2239817064bSJens Axboe if (!eq->hash) 2249817064bSJens Axboe goto err; 2259817064bSJens Axboe 2269817064bSJens Axboe for (i = 0; i < ELV_HASH_ENTRIES; i++) 2279817064bSJens Axboe INIT_HLIST_HEAD(&eq->hash[i]); 2289817064bSJens Axboe 2293d1ab40fSAl Viro return eq; 2309817064bSJens Axboe err: 2319817064bSJens Axboe kfree(eq); 2329817064bSJens Axboe elevator_put(e); 2339817064bSJens Axboe return NULL; 2343d1ab40fSAl Viro } 2353d1ab40fSAl Viro 2363d1ab40fSAl Viro static void elevator_release(struct kobject *kobj) 2373d1ab40fSAl Viro { 238b374d18aSJens Axboe struct elevator_queue *e; 2399817064bSJens Axboe 240b374d18aSJens Axboe e = container_of(kobj, struct elevator_queue, kobj); 2413d1ab40fSAl Viro elevator_put(e->elevator_type); 2429817064bSJens Axboe kfree(e->hash); 2433d1ab40fSAl Viro kfree(e); 2443d1ab40fSAl Viro } 2453d1ab40fSAl Viro 246165125e1SJens Axboe int elevator_init(struct request_queue *q, char *name) 2471da177e4SLinus Torvalds { 2481da177e4SLinus Torvalds struct elevator_type *e = NULL; 2491da177e4SLinus Torvalds struct elevator_queue *eq; 250bc1c1169SJens Axboe void *data; 2511da177e4SLinus Torvalds 2521abec4fdSMike Snitzer if (unlikely(q->elevator)) 2531abec4fdSMike Snitzer return 0; 2541abec4fdSMike Snitzer 255cb98fc8bSTejun Heo INIT_LIST_HEAD(&q->queue_head); 256cb98fc8bSTejun Heo q->last_merge = NULL; 257cb98fc8bSTejun Heo q->end_sector = 0; 258cb98fc8bSTejun Heo q->boundary_rq = NULL; 259cb98fc8bSTejun Heo 2604eb166d9SJens Axboe if (name) { 2614eb166d9SJens Axboe e = elevator_get(name); 2624eb166d9SJens Axboe if (!e) 2631da177e4SLinus Torvalds return -EINVAL; 2644eb166d9SJens Axboe } 2651da177e4SLinus Torvalds 2664eb166d9SJens Axboe if (!e && *chosen_elevator) { 2674eb166d9SJens Axboe e = elevator_get(chosen_elevator); 2684eb166d9SJens Axboe if (!e) 2694eb166d9SJens Axboe printk(KERN_ERR "I/O scheduler %s not found\n", 2704eb166d9SJens Axboe chosen_elevator); 2714eb166d9SJens Axboe } 272248d5ca5SNate Diller 2734eb166d9SJens Axboe if (!e) { 2744eb166d9SJens Axboe e = elevator_get(CONFIG_DEFAULT_IOSCHED); 2754eb166d9SJens Axboe if (!e) { 2764eb166d9SJens Axboe printk(KERN_ERR 2774eb166d9SJens Axboe "Default I/O scheduler not found. " \ 2784eb166d9SJens Axboe "Using noop.\n"); 279248d5ca5SNate Diller e = elevator_get("noop"); 2805f003976SNate Diller } 2814eb166d9SJens Axboe } 2825f003976SNate Diller 283b5deef90SJens Axboe eq = elevator_alloc(q, e); 2843d1ab40fSAl Viro if (!eq) 2851da177e4SLinus Torvalds return -ENOMEM; 2861da177e4SLinus Torvalds 287bc1c1169SJens Axboe data = elevator_init_queue(q, eq); 288bc1c1169SJens Axboe if (!data) { 2893d1ab40fSAl Viro kobject_put(&eq->kobj); 290bc1c1169SJens Axboe return -ENOMEM; 291bc1c1169SJens Axboe } 2921da177e4SLinus Torvalds 293bc1c1169SJens Axboe elevator_attach(q, eq, data); 2941abec4fdSMike Snitzer return 0; 2951da177e4SLinus Torvalds } 2962e662b65SJens Axboe EXPORT_SYMBOL(elevator_init); 2972e662b65SJens Axboe 298b374d18aSJens Axboe void elevator_exit(struct elevator_queue *e) 2991da177e4SLinus Torvalds { 3003d1ab40fSAl Viro mutex_lock(&e->sysfs_lock); 3011da177e4SLinus Torvalds if (e->ops->elevator_exit_fn) 3021da177e4SLinus Torvalds e->ops->elevator_exit_fn(e); 3033d1ab40fSAl Viro e->ops = NULL; 3043d1ab40fSAl Viro mutex_unlock(&e->sysfs_lock); 3051da177e4SLinus Torvalds 3063d1ab40fSAl Viro kobject_put(&e->kobj); 3071da177e4SLinus Torvalds } 3082e662b65SJens Axboe EXPORT_SYMBOL(elevator_exit); 3092e662b65SJens Axboe 3109817064bSJens Axboe static inline void __elv_rqhash_del(struct request *rq) 3119817064bSJens Axboe { 3129817064bSJens Axboe hlist_del_init(&rq->hash); 3139817064bSJens Axboe } 3149817064bSJens Axboe 315165125e1SJens Axboe static void elv_rqhash_del(struct request_queue *q, struct request *rq) 3169817064bSJens Axboe { 3179817064bSJens Axboe if (ELV_ON_HASH(rq)) 3189817064bSJens Axboe __elv_rqhash_del(rq); 3199817064bSJens Axboe } 3209817064bSJens Axboe 321165125e1SJens Axboe static void elv_rqhash_add(struct request_queue *q, struct request *rq) 3229817064bSJens Axboe { 323b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 3249817064bSJens Axboe 3259817064bSJens Axboe BUG_ON(ELV_ON_HASH(rq)); 3269817064bSJens Axboe hlist_add_head(&rq->hash, &e->hash[ELV_HASH_FN(rq_hash_key(rq))]); 3279817064bSJens Axboe } 3289817064bSJens Axboe 329165125e1SJens Axboe static void elv_rqhash_reposition(struct request_queue *q, struct request *rq) 3309817064bSJens Axboe { 3319817064bSJens Axboe __elv_rqhash_del(rq); 3329817064bSJens Axboe elv_rqhash_add(q, rq); 3339817064bSJens Axboe } 3349817064bSJens Axboe 335165125e1SJens Axboe static struct request *elv_rqhash_find(struct request_queue *q, sector_t offset) 3369817064bSJens Axboe { 337b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 3389817064bSJens Axboe struct hlist_head *hash_list = &e->hash[ELV_HASH_FN(offset)]; 3399817064bSJens Axboe struct hlist_node *entry, *next; 3409817064bSJens Axboe struct request *rq; 3419817064bSJens Axboe 3429817064bSJens Axboe hlist_for_each_entry_safe(rq, entry, next, hash_list, hash) { 3439817064bSJens Axboe BUG_ON(!ELV_ON_HASH(rq)); 3449817064bSJens Axboe 3459817064bSJens Axboe if (unlikely(!rq_mergeable(rq))) { 3469817064bSJens Axboe __elv_rqhash_del(rq); 3479817064bSJens Axboe continue; 3489817064bSJens Axboe } 3499817064bSJens Axboe 3509817064bSJens Axboe if (rq_hash_key(rq) == offset) 3519817064bSJens Axboe return rq; 3529817064bSJens Axboe } 3539817064bSJens Axboe 3549817064bSJens Axboe return NULL; 3559817064bSJens Axboe } 3569817064bSJens Axboe 3578922e16cSTejun Heo /* 3582e662b65SJens Axboe * RB-tree support functions for inserting/lookup/removal of requests 3592e662b65SJens Axboe * in a sorted RB tree. 3602e662b65SJens Axboe */ 3612e662b65SJens Axboe struct request *elv_rb_add(struct rb_root *root, struct request *rq) 3622e662b65SJens Axboe { 3632e662b65SJens Axboe struct rb_node **p = &root->rb_node; 3642e662b65SJens Axboe struct rb_node *parent = NULL; 3652e662b65SJens Axboe struct request *__rq; 3662e662b65SJens Axboe 3672e662b65SJens Axboe while (*p) { 3682e662b65SJens Axboe parent = *p; 3692e662b65SJens Axboe __rq = rb_entry(parent, struct request, rb_node); 3702e662b65SJens Axboe 37183096ebfSTejun Heo if (blk_rq_pos(rq) < blk_rq_pos(__rq)) 3722e662b65SJens Axboe p = &(*p)->rb_left; 37383096ebfSTejun Heo else if (blk_rq_pos(rq) > blk_rq_pos(__rq)) 3742e662b65SJens Axboe p = &(*p)->rb_right; 3752e662b65SJens Axboe else 3762e662b65SJens Axboe return __rq; 3772e662b65SJens Axboe } 3782e662b65SJens Axboe 3792e662b65SJens Axboe rb_link_node(&rq->rb_node, parent, p); 3802e662b65SJens Axboe rb_insert_color(&rq->rb_node, root); 3812e662b65SJens Axboe return NULL; 3822e662b65SJens Axboe } 3832e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_add); 3842e662b65SJens Axboe 3852e662b65SJens Axboe void elv_rb_del(struct rb_root *root, struct request *rq) 3862e662b65SJens Axboe { 3872e662b65SJens Axboe BUG_ON(RB_EMPTY_NODE(&rq->rb_node)); 3882e662b65SJens Axboe rb_erase(&rq->rb_node, root); 3892e662b65SJens Axboe RB_CLEAR_NODE(&rq->rb_node); 3902e662b65SJens Axboe } 3912e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_del); 3922e662b65SJens Axboe 3932e662b65SJens Axboe struct request *elv_rb_find(struct rb_root *root, sector_t sector) 3942e662b65SJens Axboe { 3952e662b65SJens Axboe struct rb_node *n = root->rb_node; 3962e662b65SJens Axboe struct request *rq; 3972e662b65SJens Axboe 3982e662b65SJens Axboe while (n) { 3992e662b65SJens Axboe rq = rb_entry(n, struct request, rb_node); 4002e662b65SJens Axboe 40183096ebfSTejun Heo if (sector < blk_rq_pos(rq)) 4022e662b65SJens Axboe n = n->rb_left; 40383096ebfSTejun Heo else if (sector > blk_rq_pos(rq)) 4042e662b65SJens Axboe n = n->rb_right; 4052e662b65SJens Axboe else 4062e662b65SJens Axboe return rq; 4072e662b65SJens Axboe } 4082e662b65SJens Axboe 4092e662b65SJens Axboe return NULL; 4102e662b65SJens Axboe } 4112e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_find); 4122e662b65SJens Axboe 4132e662b65SJens Axboe /* 4148922e16cSTejun Heo * Insert rq into dispatch queue of q. Queue lock must be held on 415dbe7f76dSUwe Kleine-König * entry. rq is sort instead into the dispatch queue. To be used by 4162e662b65SJens Axboe * specific elevators. 4178922e16cSTejun Heo */ 418165125e1SJens Axboe void elv_dispatch_sort(struct request_queue *q, struct request *rq) 4198922e16cSTejun Heo { 4208922e16cSTejun Heo sector_t boundary; 4218922e16cSTejun Heo struct list_head *entry; 4224eb166d9SJens Axboe int stop_flags; 4238922e16cSTejun Heo 424*73c10101SJens Axboe BUG_ON(rq->cmd_flags & REQ_ON_PLUG); 425*73c10101SJens Axboe 42606b86245STejun Heo if (q->last_merge == rq) 42706b86245STejun Heo q->last_merge = NULL; 4289817064bSJens Axboe 4299817064bSJens Axboe elv_rqhash_del(q, rq); 4309817064bSJens Axboe 43115853af9STejun Heo q->nr_sorted--; 43206b86245STejun Heo 4331b47f531SJens Axboe boundary = q->end_sector; 43402e031cbSChristoph Hellwig stop_flags = REQ_SOFTBARRIER | REQ_STARTED; 4358922e16cSTejun Heo list_for_each_prev(entry, &q->queue_head) { 4368922e16cSTejun Heo struct request *pos = list_entry_rq(entry); 4378922e16cSTejun Heo 43833659ebbSChristoph Hellwig if ((rq->cmd_flags & REQ_DISCARD) != 43933659ebbSChristoph Hellwig (pos->cmd_flags & REQ_DISCARD)) 440e17fc0a1SDavid Woodhouse break; 441783660b2SJens Axboe if (rq_data_dir(rq) != rq_data_dir(pos)) 442783660b2SJens Axboe break; 4434eb166d9SJens Axboe if (pos->cmd_flags & stop_flags) 4448922e16cSTejun Heo break; 44583096ebfSTejun Heo if (blk_rq_pos(rq) >= boundary) { 44683096ebfSTejun Heo if (blk_rq_pos(pos) < boundary) 4478922e16cSTejun Heo continue; 4488922e16cSTejun Heo } else { 44983096ebfSTejun Heo if (blk_rq_pos(pos) >= boundary) 4508922e16cSTejun Heo break; 4518922e16cSTejun Heo } 45283096ebfSTejun Heo if (blk_rq_pos(rq) >= blk_rq_pos(pos)) 4538922e16cSTejun Heo break; 4548922e16cSTejun Heo } 4558922e16cSTejun Heo 4568922e16cSTejun Heo list_add(&rq->queuelist, entry); 4578922e16cSTejun Heo } 4582e662b65SJens Axboe EXPORT_SYMBOL(elv_dispatch_sort); 4592e662b65SJens Axboe 4609817064bSJens Axboe /* 4612e662b65SJens Axboe * Insert rq into dispatch queue of q. Queue lock must be held on 4622e662b65SJens Axboe * entry. rq is added to the back of the dispatch queue. To be used by 4632e662b65SJens Axboe * specific elevators. 4649817064bSJens Axboe */ 4659817064bSJens Axboe void elv_dispatch_add_tail(struct request_queue *q, struct request *rq) 4669817064bSJens Axboe { 4679817064bSJens Axboe if (q->last_merge == rq) 4689817064bSJens Axboe q->last_merge = NULL; 4699817064bSJens Axboe 4709817064bSJens Axboe elv_rqhash_del(q, rq); 4719817064bSJens Axboe 4729817064bSJens Axboe q->nr_sorted--; 4739817064bSJens Axboe 4749817064bSJens Axboe q->end_sector = rq_end_sector(rq); 4759817064bSJens Axboe q->boundary_rq = rq; 4769817064bSJens Axboe list_add_tail(&rq->queuelist, &q->queue_head); 4779817064bSJens Axboe } 4782e662b65SJens Axboe EXPORT_SYMBOL(elv_dispatch_add_tail); 4792e662b65SJens Axboe 480165125e1SJens Axboe int elv_merge(struct request_queue *q, struct request **req, struct bio *bio) 4811da177e4SLinus Torvalds { 482b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 4839817064bSJens Axboe struct request *__rq; 48406b86245STejun Heo int ret; 48506b86245STejun Heo 4869817064bSJens Axboe /* 487488991e2SAlan D. Brunelle * Levels of merges: 488488991e2SAlan D. Brunelle * nomerges: No merges at all attempted 489488991e2SAlan D. Brunelle * noxmerges: Only simple one-hit cache try 490488991e2SAlan D. Brunelle * merges: All merge tries attempted 491488991e2SAlan D. Brunelle */ 492488991e2SAlan D. Brunelle if (blk_queue_nomerges(q)) 493488991e2SAlan D. Brunelle return ELEVATOR_NO_MERGE; 494488991e2SAlan D. Brunelle 495488991e2SAlan D. Brunelle /* 4969817064bSJens Axboe * First try one-hit cache. 4979817064bSJens Axboe */ 49806b86245STejun Heo if (q->last_merge) { 49906b86245STejun Heo ret = elv_try_merge(q->last_merge, bio); 50006b86245STejun Heo if (ret != ELEVATOR_NO_MERGE) { 50106b86245STejun Heo *req = q->last_merge; 50206b86245STejun Heo return ret; 50306b86245STejun Heo } 50406b86245STejun Heo } 5051da177e4SLinus Torvalds 506488991e2SAlan D. Brunelle if (blk_queue_noxmerges(q)) 507ac9fafa1SAlan D. Brunelle return ELEVATOR_NO_MERGE; 508ac9fafa1SAlan D. Brunelle 5099817064bSJens Axboe /* 5109817064bSJens Axboe * See if our hash lookup can find a potential backmerge. 5119817064bSJens Axboe */ 5129817064bSJens Axboe __rq = elv_rqhash_find(q, bio->bi_sector); 5139817064bSJens Axboe if (__rq && elv_rq_merge_ok(__rq, bio)) { 5149817064bSJens Axboe *req = __rq; 5159817064bSJens Axboe return ELEVATOR_BACK_MERGE; 5169817064bSJens Axboe } 5179817064bSJens Axboe 5181da177e4SLinus Torvalds if (e->ops->elevator_merge_fn) 5191da177e4SLinus Torvalds return e->ops->elevator_merge_fn(q, req, bio); 5201da177e4SLinus Torvalds 5211da177e4SLinus Torvalds return ELEVATOR_NO_MERGE; 5221da177e4SLinus Torvalds } 5231da177e4SLinus Torvalds 524165125e1SJens Axboe void elv_merged_request(struct request_queue *q, struct request *rq, int type) 5251da177e4SLinus Torvalds { 526b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 5271da177e4SLinus Torvalds 5281da177e4SLinus Torvalds if (e->ops->elevator_merged_fn) 5292e662b65SJens Axboe e->ops->elevator_merged_fn(q, rq, type); 53006b86245STejun Heo 5312e662b65SJens Axboe if (type == ELEVATOR_BACK_MERGE) 5329817064bSJens Axboe elv_rqhash_reposition(q, rq); 5339817064bSJens Axboe 53406b86245STejun Heo q->last_merge = rq; 5351da177e4SLinus Torvalds } 5361da177e4SLinus Torvalds 537165125e1SJens Axboe void elv_merge_requests(struct request_queue *q, struct request *rq, 5381da177e4SLinus Torvalds struct request *next) 5391da177e4SLinus Torvalds { 540b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 5411da177e4SLinus Torvalds 5421da177e4SLinus Torvalds if (e->ops->elevator_merge_req_fn) 5431da177e4SLinus Torvalds e->ops->elevator_merge_req_fn(q, rq, next); 54406b86245STejun Heo 5459817064bSJens Axboe elv_rqhash_reposition(q, rq); 5469817064bSJens Axboe elv_rqhash_del(q, next); 5479817064bSJens Axboe 5489817064bSJens Axboe q->nr_sorted--; 54906b86245STejun Heo q->last_merge = rq; 5501da177e4SLinus Torvalds } 5511da177e4SLinus Torvalds 552812d4026SDivyesh Shah void elv_bio_merged(struct request_queue *q, struct request *rq, 553812d4026SDivyesh Shah struct bio *bio) 554812d4026SDivyesh Shah { 555812d4026SDivyesh Shah struct elevator_queue *e = q->elevator; 556812d4026SDivyesh Shah 557812d4026SDivyesh Shah if (e->ops->elevator_bio_merged_fn) 558812d4026SDivyesh Shah e->ops->elevator_bio_merged_fn(q, rq, bio); 559812d4026SDivyesh Shah } 560812d4026SDivyesh Shah 561165125e1SJens Axboe void elv_requeue_request(struct request_queue *q, struct request *rq) 5621da177e4SLinus Torvalds { 5631da177e4SLinus Torvalds /* 5641da177e4SLinus Torvalds * it already went through dequeue, we need to decrement the 5651da177e4SLinus Torvalds * in_flight count again 5661da177e4SLinus Torvalds */ 5678922e16cSTejun Heo if (blk_account_rq(rq)) { 5680a7ae2ffSJens Axboe q->in_flight[rq_is_sync(rq)]--; 56933659ebbSChristoph Hellwig if (rq->cmd_flags & REQ_SORTED) 570cad97516SJens Axboe elv_deactivate_rq(q, rq); 5711da177e4SLinus Torvalds } 5721da177e4SLinus Torvalds 5734aff5e23SJens Axboe rq->cmd_flags &= ~REQ_STARTED; 5741da177e4SLinus Torvalds 57530e9656cSTejun Heo elv_insert(q, rq, ELEVATOR_INSERT_REQUEUE); 5761da177e4SLinus Torvalds } 5771da177e4SLinus Torvalds 57826308eabSJerome Marchand void elv_drain_elevator(struct request_queue *q) 57915853af9STejun Heo { 58015853af9STejun Heo static int printed; 58115853af9STejun Heo while (q->elevator->ops->elevator_dispatch_fn(q, 1)) 58215853af9STejun Heo ; 58315853af9STejun Heo if (q->nr_sorted == 0) 58415853af9STejun Heo return; 58515853af9STejun Heo if (printed++ < 10) { 58615853af9STejun Heo printk(KERN_ERR "%s: forced dispatching is broken " 58715853af9STejun Heo "(nr_sorted=%u), please report this\n", 58815853af9STejun Heo q->elevator->elevator_type->elevator_name, q->nr_sorted); 58915853af9STejun Heo } 59015853af9STejun Heo } 59115853af9STejun Heo 5926c7e8ceeSJens Axboe /* 5936c7e8ceeSJens Axboe * Call with queue lock held, interrupts disabled 5946c7e8ceeSJens Axboe */ 595f600abe2SJens Axboe void elv_quiesce_start(struct request_queue *q) 5966c7e8ceeSJens Axboe { 597cd43e26fSMartin K. Petersen if (!q->elevator) 598cd43e26fSMartin K. Petersen return; 599cd43e26fSMartin K. Petersen 6006c7e8ceeSJens Axboe queue_flag_set(QUEUE_FLAG_ELVSWITCH, q); 6016c7e8ceeSJens Axboe 6026c7e8ceeSJens Axboe /* 6036c7e8ceeSJens Axboe * make sure we don't have any requests in flight 6046c7e8ceeSJens Axboe */ 6056c7e8ceeSJens Axboe elv_drain_elevator(q); 6066c7e8ceeSJens Axboe while (q->rq.elvpriv) { 607a7f55792STejun Heo __blk_run_queue(q); 6086c7e8ceeSJens Axboe spin_unlock_irq(q->queue_lock); 6096c7e8ceeSJens Axboe msleep(10); 6106c7e8ceeSJens Axboe spin_lock_irq(q->queue_lock); 6116c7e8ceeSJens Axboe elv_drain_elevator(q); 6126c7e8ceeSJens Axboe } 6136c7e8ceeSJens Axboe } 6146c7e8ceeSJens Axboe 615f600abe2SJens Axboe void elv_quiesce_end(struct request_queue *q) 6166c7e8ceeSJens Axboe { 6176c7e8ceeSJens Axboe queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q); 6186c7e8ceeSJens Axboe } 6196c7e8ceeSJens Axboe 620165125e1SJens Axboe void elv_insert(struct request_queue *q, struct request *rq, int where) 6211da177e4SLinus Torvalds { 622dac07ec1SJens Axboe int unplug_it = 1; 623797e7dbbSTejun Heo 6245f3ea37cSArnaldo Carvalho de Melo trace_block_rq_insert(q, rq); 6252056a782SJens Axboe 6261da177e4SLinus Torvalds rq->q = q; 6271da177e4SLinus Torvalds 6288922e16cSTejun Heo switch (where) { 62928e7d184STejun Heo case ELEVATOR_INSERT_REQUEUE: 63028e7d184STejun Heo /* 63128e7d184STejun Heo * Most requeues happen because of a busy condition, 63228e7d184STejun Heo * don't force unplug of the queue for that case. 63328e7d184STejun Heo * Clear unplug_it and fall through. 63428e7d184STejun Heo */ 63528e7d184STejun Heo unplug_it = 0; 63628e7d184STejun Heo 6378922e16cSTejun Heo case ELEVATOR_INSERT_FRONT: 6384aff5e23SJens Axboe rq->cmd_flags |= REQ_SOFTBARRIER; 6398922e16cSTejun Heo list_add(&rq->queuelist, &q->queue_head); 6408922e16cSTejun Heo break; 6418922e16cSTejun Heo 6428922e16cSTejun Heo case ELEVATOR_INSERT_BACK: 6434aff5e23SJens Axboe rq->cmd_flags |= REQ_SOFTBARRIER; 64415853af9STejun Heo elv_drain_elevator(q); 6458922e16cSTejun Heo list_add_tail(&rq->queuelist, &q->queue_head); 6468922e16cSTejun Heo /* 6478922e16cSTejun Heo * We kick the queue here for the following reasons. 6488922e16cSTejun Heo * - The elevator might have returned NULL previously 6498922e16cSTejun Heo * to delay requests and returned them now. As the 6508922e16cSTejun Heo * queue wasn't empty before this request, ll_rw_blk 6518922e16cSTejun Heo * won't run the queue on return, resulting in hang. 6528922e16cSTejun Heo * - Usually, back inserted requests won't be merged 6538922e16cSTejun Heo * with anything. There's no point in delaying queue 6548922e16cSTejun Heo * processing. 6558922e16cSTejun Heo */ 656a7f55792STejun Heo __blk_run_queue(q); 6578922e16cSTejun Heo break; 6588922e16cSTejun Heo 6598922e16cSTejun Heo case ELEVATOR_INSERT_SORT: 66033659ebbSChristoph Hellwig BUG_ON(rq->cmd_type != REQ_TYPE_FS && 66133659ebbSChristoph Hellwig !(rq->cmd_flags & REQ_DISCARD)); 6624aff5e23SJens Axboe rq->cmd_flags |= REQ_SORTED; 66315853af9STejun Heo q->nr_sorted++; 6649817064bSJens Axboe if (rq_mergeable(rq)) { 6659817064bSJens Axboe elv_rqhash_add(q, rq); 6669817064bSJens Axboe if (!q->last_merge) 66706b86245STejun Heo q->last_merge = rq; 6689817064bSJens Axboe } 6699817064bSJens Axboe 670ca23509fSTejun Heo /* 671ca23509fSTejun Heo * Some ioscheds (cfq) run q->request_fn directly, so 672ca23509fSTejun Heo * rq cannot be accessed after calling 673ca23509fSTejun Heo * elevator_add_req_fn. 674ca23509fSTejun Heo */ 675ca23509fSTejun Heo q->elevator->ops->elevator_add_req_fn(q, rq); 6768922e16cSTejun Heo break; 6778922e16cSTejun Heo 678ae1b1539STejun Heo case ELEVATOR_INSERT_FLUSH: 679ae1b1539STejun Heo rq->cmd_flags |= REQ_SOFTBARRIER; 680ae1b1539STejun Heo blk_insert_flush(rq); 681ae1b1539STejun Heo break; 682ae1b1539STejun Heo 6838922e16cSTejun Heo default: 6848922e16cSTejun Heo printk(KERN_ERR "%s: bad insertion point %d\n", 68524c03d47SHarvey Harrison __func__, where); 6868922e16cSTejun Heo BUG(); 6878922e16cSTejun Heo } 6881da177e4SLinus Torvalds 689dac07ec1SJens Axboe if (unplug_it && blk_queue_plugged(q)) { 6901faa16d2SJens Axboe int nrq = q->rq.count[BLK_RW_SYNC] + q->rq.count[BLK_RW_ASYNC] 6910a7ae2ffSJens Axboe - queue_in_flight(q); 6921da177e4SLinus Torvalds 693c374f127STejun Heo if (nrq >= q->unplug_thresh) 6941da177e4SLinus Torvalds __generic_unplug_device(q); 6951da177e4SLinus Torvalds } 6961da177e4SLinus Torvalds } 6971da177e4SLinus Torvalds 698165125e1SJens Axboe void __elv_add_request(struct request_queue *q, struct request *rq, int where, 69930e9656cSTejun Heo int plug) 70030e9656cSTejun Heo { 701*73c10101SJens Axboe BUG_ON(rq->cmd_flags & REQ_ON_PLUG); 702*73c10101SJens Axboe 70302e031cbSChristoph Hellwig if (rq->cmd_flags & REQ_SOFTBARRIER) { 70428e7d184STejun Heo /* barriers are scheduling boundary, update end_sector */ 70533659ebbSChristoph Hellwig if (rq->cmd_type == REQ_TYPE_FS || 70633659ebbSChristoph Hellwig (rq->cmd_flags & REQ_DISCARD)) { 70730e9656cSTejun Heo q->end_sector = rq_end_sector(rq); 70830e9656cSTejun Heo q->boundary_rq = rq; 70930e9656cSTejun Heo } 7104eb166d9SJens Axboe } else if (!(rq->cmd_flags & REQ_ELVPRIV) && 7114eb166d9SJens Axboe where == ELEVATOR_INSERT_SORT) 71230e9656cSTejun Heo where = ELEVATOR_INSERT_BACK; 71330e9656cSTejun Heo 71430e9656cSTejun Heo if (plug) 71530e9656cSTejun Heo blk_plug_device(q); 71630e9656cSTejun Heo 71730e9656cSTejun Heo elv_insert(q, rq, where); 71830e9656cSTejun Heo } 7192e662b65SJens Axboe EXPORT_SYMBOL(__elv_add_request); 7202e662b65SJens Axboe 721165125e1SJens Axboe void elv_add_request(struct request_queue *q, struct request *rq, int where, 7221da177e4SLinus Torvalds int plug) 7231da177e4SLinus Torvalds { 7241da177e4SLinus Torvalds unsigned long flags; 7251da177e4SLinus Torvalds 7261da177e4SLinus Torvalds spin_lock_irqsave(q->queue_lock, flags); 7271da177e4SLinus Torvalds __elv_add_request(q, rq, where, plug); 7281da177e4SLinus Torvalds spin_unlock_irqrestore(q->queue_lock, flags); 7291da177e4SLinus Torvalds } 7302e662b65SJens Axboe EXPORT_SYMBOL(elv_add_request); 7312e662b65SJens Axboe 732165125e1SJens Axboe int elv_queue_empty(struct request_queue *q) 7331da177e4SLinus Torvalds { 734b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 7351da177e4SLinus Torvalds 7368922e16cSTejun Heo if (!list_empty(&q->queue_head)) 7378922e16cSTejun Heo return 0; 7388922e16cSTejun Heo 7391da177e4SLinus Torvalds if (e->ops->elevator_queue_empty_fn) 7401da177e4SLinus Torvalds return e->ops->elevator_queue_empty_fn(q); 7411da177e4SLinus Torvalds 7428922e16cSTejun Heo return 1; 7431da177e4SLinus Torvalds } 7442e662b65SJens Axboe EXPORT_SYMBOL(elv_queue_empty); 7452e662b65SJens Axboe 746165125e1SJens Axboe struct request *elv_latter_request(struct request_queue *q, struct request *rq) 7471da177e4SLinus Torvalds { 748b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 7491da177e4SLinus Torvalds 7501da177e4SLinus Torvalds if (e->ops->elevator_latter_req_fn) 7511da177e4SLinus Torvalds return e->ops->elevator_latter_req_fn(q, rq); 7521da177e4SLinus Torvalds return NULL; 7531da177e4SLinus Torvalds } 7541da177e4SLinus Torvalds 755165125e1SJens Axboe struct request *elv_former_request(struct request_queue *q, struct request *rq) 7561da177e4SLinus Torvalds { 757b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 7581da177e4SLinus Torvalds 7591da177e4SLinus Torvalds if (e->ops->elevator_former_req_fn) 7601da177e4SLinus Torvalds return e->ops->elevator_former_req_fn(q, rq); 7611da177e4SLinus Torvalds return NULL; 7621da177e4SLinus Torvalds } 7631da177e4SLinus Torvalds 764165125e1SJens Axboe int elv_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask) 7651da177e4SLinus Torvalds { 766b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 7671da177e4SLinus Torvalds 7681da177e4SLinus Torvalds if (e->ops->elevator_set_req_fn) 769cb78b285SJens Axboe return e->ops->elevator_set_req_fn(q, rq, gfp_mask); 7701da177e4SLinus Torvalds 771c186794dSMike Snitzer rq->elevator_private[0] = NULL; 7721da177e4SLinus Torvalds return 0; 7731da177e4SLinus Torvalds } 7741da177e4SLinus Torvalds 775165125e1SJens Axboe void elv_put_request(struct request_queue *q, struct request *rq) 7761da177e4SLinus Torvalds { 777b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 7781da177e4SLinus Torvalds 7791da177e4SLinus Torvalds if (e->ops->elevator_put_req_fn) 780bb37b94cSJens Axboe e->ops->elevator_put_req_fn(rq); 7811da177e4SLinus Torvalds } 7821da177e4SLinus Torvalds 783165125e1SJens Axboe int elv_may_queue(struct request_queue *q, int rw) 7841da177e4SLinus Torvalds { 785b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 7861da177e4SLinus Torvalds 7871da177e4SLinus Torvalds if (e->ops->elevator_may_queue_fn) 788cb78b285SJens Axboe return e->ops->elevator_may_queue_fn(q, rw); 7891da177e4SLinus Torvalds 7901da177e4SLinus Torvalds return ELV_MQUEUE_MAY; 7911da177e4SLinus Torvalds } 7921da177e4SLinus Torvalds 79311914a53SMike Anderson void elv_abort_queue(struct request_queue *q) 79411914a53SMike Anderson { 79511914a53SMike Anderson struct request *rq; 79611914a53SMike Anderson 797ae1b1539STejun Heo blk_abort_flushes(q); 798ae1b1539STejun Heo 79911914a53SMike Anderson while (!list_empty(&q->queue_head)) { 80011914a53SMike Anderson rq = list_entry_rq(q->queue_head.next); 80111914a53SMike Anderson rq->cmd_flags |= REQ_QUIET; 8025f3ea37cSArnaldo Carvalho de Melo trace_block_rq_abort(q, rq); 80353c663ceSKiyoshi Ueda /* 80453c663ceSKiyoshi Ueda * Mark this request as started so we don't trigger 80553c663ceSKiyoshi Ueda * any debug logic in the end I/O path. 80653c663ceSKiyoshi Ueda */ 80753c663ceSKiyoshi Ueda blk_start_request(rq); 80840cbbb78STejun Heo __blk_end_request_all(rq, -EIO); 80911914a53SMike Anderson } 81011914a53SMike Anderson } 81111914a53SMike Anderson EXPORT_SYMBOL(elv_abort_queue); 81211914a53SMike Anderson 813165125e1SJens Axboe void elv_completed_request(struct request_queue *q, struct request *rq) 8141da177e4SLinus Torvalds { 815b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 8161da177e4SLinus Torvalds 8171da177e4SLinus Torvalds /* 8181da177e4SLinus Torvalds * request is released from the driver, io must be done 8191da177e4SLinus Torvalds */ 8208922e16cSTejun Heo if (blk_account_rq(rq)) { 8210a7ae2ffSJens Axboe q->in_flight[rq_is_sync(rq)]--; 82233659ebbSChristoph Hellwig if ((rq->cmd_flags & REQ_SORTED) && 82333659ebbSChristoph Hellwig e->ops->elevator_completed_req_fn) 8241bc691d3STejun Heo e->ops->elevator_completed_req_fn(q, rq); 8251bc691d3STejun Heo } 8268922e16cSTejun Heo } 8271da177e4SLinus Torvalds 8283d1ab40fSAl Viro #define to_elv(atr) container_of((atr), struct elv_fs_entry, attr) 8293d1ab40fSAl Viro 8303d1ab40fSAl Viro static ssize_t 8313d1ab40fSAl Viro elv_attr_show(struct kobject *kobj, struct attribute *attr, char *page) 8323d1ab40fSAl Viro { 8333d1ab40fSAl Viro struct elv_fs_entry *entry = to_elv(attr); 834b374d18aSJens Axboe struct elevator_queue *e; 8353d1ab40fSAl Viro ssize_t error; 8363d1ab40fSAl Viro 8373d1ab40fSAl Viro if (!entry->show) 8383d1ab40fSAl Viro return -EIO; 8393d1ab40fSAl Viro 840b374d18aSJens Axboe e = container_of(kobj, struct elevator_queue, kobj); 8413d1ab40fSAl Viro mutex_lock(&e->sysfs_lock); 8423d1ab40fSAl Viro error = e->ops ? entry->show(e, page) : -ENOENT; 8433d1ab40fSAl Viro mutex_unlock(&e->sysfs_lock); 8443d1ab40fSAl Viro return error; 8453d1ab40fSAl Viro } 8463d1ab40fSAl Viro 8473d1ab40fSAl Viro static ssize_t 8483d1ab40fSAl Viro elv_attr_store(struct kobject *kobj, struct attribute *attr, 8493d1ab40fSAl Viro const char *page, size_t length) 8503d1ab40fSAl Viro { 8513d1ab40fSAl Viro struct elv_fs_entry *entry = to_elv(attr); 852b374d18aSJens Axboe struct elevator_queue *e; 8533d1ab40fSAl Viro ssize_t error; 8543d1ab40fSAl Viro 8553d1ab40fSAl Viro if (!entry->store) 8563d1ab40fSAl Viro return -EIO; 8573d1ab40fSAl Viro 858b374d18aSJens Axboe e = container_of(kobj, struct elevator_queue, kobj); 8593d1ab40fSAl Viro mutex_lock(&e->sysfs_lock); 8603d1ab40fSAl Viro error = e->ops ? entry->store(e, page, length) : -ENOENT; 8613d1ab40fSAl Viro mutex_unlock(&e->sysfs_lock); 8623d1ab40fSAl Viro return error; 8633d1ab40fSAl Viro } 8643d1ab40fSAl Viro 86552cf25d0SEmese Revfy static const struct sysfs_ops elv_sysfs_ops = { 8663d1ab40fSAl Viro .show = elv_attr_show, 8673d1ab40fSAl Viro .store = elv_attr_store, 8683d1ab40fSAl Viro }; 8693d1ab40fSAl Viro 8703d1ab40fSAl Viro static struct kobj_type elv_ktype = { 8713d1ab40fSAl Viro .sysfs_ops = &elv_sysfs_ops, 8723d1ab40fSAl Viro .release = elevator_release, 8733d1ab40fSAl Viro }; 8743d1ab40fSAl Viro 8751da177e4SLinus Torvalds int elv_register_queue(struct request_queue *q) 8761da177e4SLinus Torvalds { 877b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 8783d1ab40fSAl Viro int error; 8791da177e4SLinus Torvalds 880b2d6db58SGreg Kroah-Hartman error = kobject_add(&e->kobj, &q->kobj, "%s", "iosched"); 8813d1ab40fSAl Viro if (!error) { 882e572ec7eSAl Viro struct elv_fs_entry *attr = e->elevator_type->elevator_attrs; 8833d1ab40fSAl Viro if (attr) { 884e572ec7eSAl Viro while (attr->attr.name) { 885e572ec7eSAl Viro if (sysfs_create_file(&e->kobj, &attr->attr)) 8863d1ab40fSAl Viro break; 887e572ec7eSAl Viro attr++; 8883d1ab40fSAl Viro } 8893d1ab40fSAl Viro } 8903d1ab40fSAl Viro kobject_uevent(&e->kobj, KOBJ_ADD); 891430c62fbSJens Axboe e->registered = 1; 8923d1ab40fSAl Viro } 8933d1ab40fSAl Viro return error; 8941da177e4SLinus Torvalds } 89501effb0dSMike Snitzer EXPORT_SYMBOL(elv_register_queue); 8961da177e4SLinus Torvalds 897b374d18aSJens Axboe static void __elv_unregister_queue(struct elevator_queue *e) 8981da177e4SLinus Torvalds { 8993d1ab40fSAl Viro kobject_uevent(&e->kobj, KOBJ_REMOVE); 9003d1ab40fSAl Viro kobject_del(&e->kobj); 901430c62fbSJens Axboe e->registered = 0; 9021da177e4SLinus Torvalds } 903bc1c1169SJens Axboe 904bc1c1169SJens Axboe void elv_unregister_queue(struct request_queue *q) 905bc1c1169SJens Axboe { 906bc1c1169SJens Axboe if (q) 907bc1c1169SJens Axboe __elv_unregister_queue(q->elevator); 9081da177e4SLinus Torvalds } 90901effb0dSMike Snitzer EXPORT_SYMBOL(elv_unregister_queue); 9101da177e4SLinus Torvalds 9112fdd82bdSAdrian Bunk void elv_register(struct elevator_type *e) 9121da177e4SLinus Torvalds { 9131ffb96c5SThibaut VARENE char *def = ""; 9142a12dcd7SJens Axboe 9152a12dcd7SJens Axboe spin_lock(&elv_list_lock); 916ce524497SEric Sesterhenn BUG_ON(elevator_find(e->elevator_name)); 9171da177e4SLinus Torvalds list_add_tail(&e->list, &elv_list); 9182a12dcd7SJens Axboe spin_unlock(&elv_list_lock); 9191da177e4SLinus Torvalds 9205f003976SNate Diller if (!strcmp(e->elevator_name, chosen_elevator) || 9215f003976SNate Diller (!*chosen_elevator && 9225f003976SNate Diller !strcmp(e->elevator_name, CONFIG_DEFAULT_IOSCHED))) 9231ffb96c5SThibaut VARENE def = " (default)"; 9241ffb96c5SThibaut VARENE 9254eb166d9SJens Axboe printk(KERN_INFO "io scheduler %s registered%s\n", e->elevator_name, 9264eb166d9SJens Axboe def); 9271da177e4SLinus Torvalds } 9281da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(elv_register); 9291da177e4SLinus Torvalds 9301da177e4SLinus Torvalds void elv_unregister(struct elevator_type *e) 9311da177e4SLinus Torvalds { 93283521d3eSChristoph Hellwig struct task_struct *g, *p; 93383521d3eSChristoph Hellwig 93483521d3eSChristoph Hellwig /* 93583521d3eSChristoph Hellwig * Iterate every thread in the process to remove the io contexts. 93683521d3eSChristoph Hellwig */ 937e17a9489SAl Viro if (e->ops.trim) { 93883521d3eSChristoph Hellwig read_lock(&tasklist_lock); 93983521d3eSChristoph Hellwig do_each_thread(g, p) { 940e17a9489SAl Viro task_lock(p); 9412d8f6131SOleg Nesterov if (p->io_context) 942e17a9489SAl Viro e->ops.trim(p->io_context); 943e17a9489SAl Viro task_unlock(p); 94483521d3eSChristoph Hellwig } while_each_thread(g, p); 94583521d3eSChristoph Hellwig read_unlock(&tasklist_lock); 946e17a9489SAl Viro } 94783521d3eSChristoph Hellwig 9482a12dcd7SJens Axboe spin_lock(&elv_list_lock); 9491da177e4SLinus Torvalds list_del_init(&e->list); 9502a12dcd7SJens Axboe spin_unlock(&elv_list_lock); 9511da177e4SLinus Torvalds } 9521da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(elv_unregister); 9531da177e4SLinus Torvalds 9541da177e4SLinus Torvalds /* 9551da177e4SLinus Torvalds * switch to new_e io scheduler. be careful not to introduce deadlocks - 9561da177e4SLinus Torvalds * we don't free the old io scheduler, before we have allocated what we 9571da177e4SLinus Torvalds * need for the new one. this way we have a chance of going back to the old 958cb98fc8bSTejun Heo * one, if the new one fails init for some reason. 9591da177e4SLinus Torvalds */ 960165125e1SJens Axboe static int elevator_switch(struct request_queue *q, struct elevator_type *new_e) 9611da177e4SLinus Torvalds { 962b374d18aSJens Axboe struct elevator_queue *old_elevator, *e; 963bc1c1169SJens Axboe void *data; 9645dd531a0SJens Axboe int err; 9651da177e4SLinus Torvalds 966cb98fc8bSTejun Heo /* 967cb98fc8bSTejun Heo * Allocate new elevator 968cb98fc8bSTejun Heo */ 969b5deef90SJens Axboe e = elevator_alloc(q, new_e); 9701da177e4SLinus Torvalds if (!e) 9715dd531a0SJens Axboe return -ENOMEM; 9721da177e4SLinus Torvalds 973bc1c1169SJens Axboe data = elevator_init_queue(q, e); 974bc1c1169SJens Axboe if (!data) { 975bc1c1169SJens Axboe kobject_put(&e->kobj); 9765dd531a0SJens Axboe return -ENOMEM; 977bc1c1169SJens Axboe } 978bc1c1169SJens Axboe 9791da177e4SLinus Torvalds /* 980cb98fc8bSTejun Heo * Turn on BYPASS and drain all requests w/ elevator private data 9811da177e4SLinus Torvalds */ 982cb98fc8bSTejun Heo spin_lock_irq(q->queue_lock); 983f600abe2SJens Axboe elv_quiesce_start(q); 984cb98fc8bSTejun Heo 9851da177e4SLinus Torvalds /* 986bc1c1169SJens Axboe * Remember old elevator. 9871da177e4SLinus Torvalds */ 9881da177e4SLinus Torvalds old_elevator = q->elevator; 9891da177e4SLinus Torvalds 9901da177e4SLinus Torvalds /* 9911da177e4SLinus Torvalds * attach and start new elevator 9921da177e4SLinus Torvalds */ 993bc1c1169SJens Axboe elevator_attach(q, e, data); 994bc1c1169SJens Axboe 995bc1c1169SJens Axboe spin_unlock_irq(q->queue_lock); 996bc1c1169SJens Axboe 997430c62fbSJens Axboe if (old_elevator->registered) { 998bc1c1169SJens Axboe __elv_unregister_queue(old_elevator); 9991da177e4SLinus Torvalds 10005dd531a0SJens Axboe err = elv_register_queue(q); 10015dd531a0SJens Axboe if (err) 10021da177e4SLinus Torvalds goto fail_register; 1003430c62fbSJens Axboe } 10041da177e4SLinus Torvalds 10051da177e4SLinus Torvalds /* 1006cb98fc8bSTejun Heo * finally exit old elevator and turn off BYPASS. 10071da177e4SLinus Torvalds */ 10081da177e4SLinus Torvalds elevator_exit(old_elevator); 100975ad23bcSNick Piggin spin_lock_irq(q->queue_lock); 1010f600abe2SJens Axboe elv_quiesce_end(q); 101175ad23bcSNick Piggin spin_unlock_irq(q->queue_lock); 101275ad23bcSNick Piggin 10134722dc52SAlan D. Brunelle blk_add_trace_msg(q, "elv switch: %s", e->elevator_type->elevator_name); 10144722dc52SAlan D. Brunelle 10155dd531a0SJens Axboe return 0; 10161da177e4SLinus Torvalds 10171da177e4SLinus Torvalds fail_register: 10181da177e4SLinus Torvalds /* 10191da177e4SLinus Torvalds * switch failed, exit the new io scheduler and reattach the old 10201da177e4SLinus Torvalds * one again (along with re-adding the sysfs dir) 10211da177e4SLinus Torvalds */ 10221da177e4SLinus Torvalds elevator_exit(e); 10231da177e4SLinus Torvalds q->elevator = old_elevator; 10241da177e4SLinus Torvalds elv_register_queue(q); 102575ad23bcSNick Piggin 102675ad23bcSNick Piggin spin_lock_irq(q->queue_lock); 102775ad23bcSNick Piggin queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q); 102875ad23bcSNick Piggin spin_unlock_irq(q->queue_lock); 102975ad23bcSNick Piggin 10305dd531a0SJens Axboe return err; 10311da177e4SLinus Torvalds } 10321da177e4SLinus Torvalds 10335dd531a0SJens Axboe /* 10345dd531a0SJens Axboe * Switch this queue to the given IO scheduler. 10355dd531a0SJens Axboe */ 10365dd531a0SJens Axboe int elevator_change(struct request_queue *q, const char *name) 10371da177e4SLinus Torvalds { 10381da177e4SLinus Torvalds char elevator_name[ELV_NAME_MAX]; 10391da177e4SLinus Torvalds struct elevator_type *e; 10401da177e4SLinus Torvalds 1041cd43e26fSMartin K. Petersen if (!q->elevator) 10425dd531a0SJens Axboe return -ENXIO; 1043cd43e26fSMartin K. Petersen 1044ee2e992cSLi Zefan strlcpy(elevator_name, name, sizeof(elevator_name)); 10458c279598SKOSAKI Motohiro e = elevator_get(strstrip(elevator_name)); 10461da177e4SLinus Torvalds if (!e) { 10471da177e4SLinus Torvalds printk(KERN_ERR "elevator: type %s not found\n", elevator_name); 10481da177e4SLinus Torvalds return -EINVAL; 10491da177e4SLinus Torvalds } 10501da177e4SLinus Torvalds 10512ca7d93bSNate Diller if (!strcmp(elevator_name, q->elevator->elevator_type->elevator_name)) { 10522ca7d93bSNate Diller elevator_put(e); 10535dd531a0SJens Axboe return 0; 10542ca7d93bSNate Diller } 10551da177e4SLinus Torvalds 10565dd531a0SJens Axboe return elevator_switch(q, e); 10575dd531a0SJens Axboe } 10585dd531a0SJens Axboe EXPORT_SYMBOL(elevator_change); 10595dd531a0SJens Axboe 10605dd531a0SJens Axboe ssize_t elv_iosched_store(struct request_queue *q, const char *name, 10615dd531a0SJens Axboe size_t count) 10625dd531a0SJens Axboe { 10635dd531a0SJens Axboe int ret; 10645dd531a0SJens Axboe 10655dd531a0SJens Axboe if (!q->elevator) 10661da177e4SLinus Torvalds return count; 10675dd531a0SJens Axboe 10685dd531a0SJens Axboe ret = elevator_change(q, name); 10695dd531a0SJens Axboe if (!ret) 10705dd531a0SJens Axboe return count; 10715dd531a0SJens Axboe 10725dd531a0SJens Axboe printk(KERN_ERR "elevator: switch to %s failed\n", name); 10735dd531a0SJens Axboe return ret; 10741da177e4SLinus Torvalds } 10751da177e4SLinus Torvalds 1076165125e1SJens Axboe ssize_t elv_iosched_show(struct request_queue *q, char *name) 10771da177e4SLinus Torvalds { 1078b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 1079cd43e26fSMartin K. Petersen struct elevator_type *elv; 108070cee26eSMatthias Kaehlcke struct elevator_type *__e; 10811da177e4SLinus Torvalds int len = 0; 10821da177e4SLinus Torvalds 1083e36f724bSMike Snitzer if (!q->elevator || !blk_queue_stackable(q)) 1084cd43e26fSMartin K. Petersen return sprintf(name, "none\n"); 1085cd43e26fSMartin K. Petersen 1086cd43e26fSMartin K. Petersen elv = e->elevator_type; 1087cd43e26fSMartin K. Petersen 10882a12dcd7SJens Axboe spin_lock(&elv_list_lock); 108970cee26eSMatthias Kaehlcke list_for_each_entry(__e, &elv_list, list) { 10901da177e4SLinus Torvalds if (!strcmp(elv->elevator_name, __e->elevator_name)) 10911da177e4SLinus Torvalds len += sprintf(name+len, "[%s] ", elv->elevator_name); 10921da177e4SLinus Torvalds else 10931da177e4SLinus Torvalds len += sprintf(name+len, "%s ", __e->elevator_name); 10941da177e4SLinus Torvalds } 10952a12dcd7SJens Axboe spin_unlock(&elv_list_lock); 10961da177e4SLinus Torvalds 10971da177e4SLinus Torvalds len += sprintf(len+name, "\n"); 10981da177e4SLinus Torvalds return len; 10991da177e4SLinus Torvalds } 11001da177e4SLinus Torvalds 1101165125e1SJens Axboe struct request *elv_rb_former_request(struct request_queue *q, 1102165125e1SJens Axboe struct request *rq) 11032e662b65SJens Axboe { 11042e662b65SJens Axboe struct rb_node *rbprev = rb_prev(&rq->rb_node); 11052e662b65SJens Axboe 11062e662b65SJens Axboe if (rbprev) 11072e662b65SJens Axboe return rb_entry_rq(rbprev); 11082e662b65SJens Axboe 11092e662b65SJens Axboe return NULL; 11102e662b65SJens Axboe } 11112e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_former_request); 11122e662b65SJens Axboe 1113165125e1SJens Axboe struct request *elv_rb_latter_request(struct request_queue *q, 1114165125e1SJens Axboe struct request *rq) 11152e662b65SJens Axboe { 11162e662b65SJens Axboe struct rb_node *rbnext = rb_next(&rq->rb_node); 11172e662b65SJens Axboe 11182e662b65SJens Axboe if (rbnext) 11192e662b65SJens Axboe return rb_entry_rq(rbnext); 11202e662b65SJens Axboe 11212e662b65SJens Axboe return NULL; 11222e662b65SJens Axboe } 11232e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_latter_request); 1124