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 11673c10101SJens 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 42473c10101SJens Axboe BUG_ON(rq->cmd_flags & REQ_ON_PLUG); 42573c10101SJens 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 5245e84ea3aSJens Axboe /* 5255e84ea3aSJens Axboe * Attempt to do an insertion back merge. Only check for the case where 5265e84ea3aSJens Axboe * we can append 'rq' to an existing request, so we can throw 'rq' away 5275e84ea3aSJens Axboe * afterwards. 5285e84ea3aSJens Axboe * 5295e84ea3aSJens Axboe * Returns true if we merged, false otherwise 5305e84ea3aSJens Axboe */ 5315e84ea3aSJens Axboe static bool elv_attempt_insert_merge(struct request_queue *q, 5325e84ea3aSJens Axboe struct request *rq) 5335e84ea3aSJens Axboe { 5345e84ea3aSJens Axboe struct request *__rq; 5355e84ea3aSJens Axboe 5365e84ea3aSJens Axboe if (blk_queue_nomerges(q)) 5375e84ea3aSJens Axboe return false; 5385e84ea3aSJens Axboe 5395e84ea3aSJens Axboe /* 5405e84ea3aSJens Axboe * First try one-hit cache. 5415e84ea3aSJens Axboe */ 5425e84ea3aSJens Axboe if (q->last_merge && blk_attempt_req_merge(q, q->last_merge, rq)) 5435e84ea3aSJens Axboe return true; 5445e84ea3aSJens Axboe 5455e84ea3aSJens Axboe if (blk_queue_noxmerges(q)) 5465e84ea3aSJens Axboe return false; 5475e84ea3aSJens Axboe 5485e84ea3aSJens Axboe /* 5495e84ea3aSJens Axboe * See if our hash lookup can find a potential backmerge. 5505e84ea3aSJens Axboe */ 5515e84ea3aSJens Axboe __rq = elv_rqhash_find(q, blk_rq_pos(rq)); 5525e84ea3aSJens Axboe if (__rq && blk_attempt_req_merge(q, __rq, rq)) 5535e84ea3aSJens Axboe return true; 5545e84ea3aSJens Axboe 5555e84ea3aSJens Axboe return false; 5565e84ea3aSJens Axboe } 5575e84ea3aSJens Axboe 558165125e1SJens Axboe void elv_merged_request(struct request_queue *q, struct request *rq, int type) 5591da177e4SLinus Torvalds { 560b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 5611da177e4SLinus Torvalds 5621da177e4SLinus Torvalds if (e->ops->elevator_merged_fn) 5632e662b65SJens Axboe e->ops->elevator_merged_fn(q, rq, type); 56406b86245STejun Heo 5652e662b65SJens Axboe if (type == ELEVATOR_BACK_MERGE) 5669817064bSJens Axboe elv_rqhash_reposition(q, rq); 5679817064bSJens Axboe 56806b86245STejun Heo q->last_merge = rq; 5691da177e4SLinus Torvalds } 5701da177e4SLinus Torvalds 571165125e1SJens Axboe void elv_merge_requests(struct request_queue *q, struct request *rq, 5721da177e4SLinus Torvalds struct request *next) 5731da177e4SLinus Torvalds { 574b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 5755e84ea3aSJens Axboe const int next_sorted = next->cmd_flags & REQ_SORTED; 5761da177e4SLinus Torvalds 5775e84ea3aSJens Axboe if (next_sorted && e->ops->elevator_merge_req_fn) 5781da177e4SLinus Torvalds e->ops->elevator_merge_req_fn(q, rq, next); 57906b86245STejun Heo 5809817064bSJens Axboe elv_rqhash_reposition(q, rq); 5819817064bSJens Axboe 5825e84ea3aSJens Axboe if (next_sorted) { 5835e84ea3aSJens Axboe elv_rqhash_del(q, next); 5849817064bSJens Axboe q->nr_sorted--; 5855e84ea3aSJens Axboe } 5865e84ea3aSJens Axboe 58706b86245STejun Heo q->last_merge = rq; 5881da177e4SLinus Torvalds } 5891da177e4SLinus Torvalds 590812d4026SDivyesh Shah void elv_bio_merged(struct request_queue *q, struct request *rq, 591812d4026SDivyesh Shah struct bio *bio) 592812d4026SDivyesh Shah { 593812d4026SDivyesh Shah struct elevator_queue *e = q->elevator; 594812d4026SDivyesh Shah 595812d4026SDivyesh Shah if (e->ops->elevator_bio_merged_fn) 596812d4026SDivyesh Shah e->ops->elevator_bio_merged_fn(q, rq, bio); 597812d4026SDivyesh Shah } 598812d4026SDivyesh Shah 599165125e1SJens Axboe void elv_requeue_request(struct request_queue *q, struct request *rq) 6001da177e4SLinus Torvalds { 6011da177e4SLinus Torvalds /* 6021da177e4SLinus Torvalds * it already went through dequeue, we need to decrement the 6031da177e4SLinus Torvalds * in_flight count again 6041da177e4SLinus Torvalds */ 6058922e16cSTejun Heo if (blk_account_rq(rq)) { 6060a7ae2ffSJens Axboe q->in_flight[rq_is_sync(rq)]--; 60733659ebbSChristoph Hellwig if (rq->cmd_flags & REQ_SORTED) 608cad97516SJens Axboe elv_deactivate_rq(q, rq); 6091da177e4SLinus Torvalds } 6101da177e4SLinus Torvalds 6114aff5e23SJens Axboe rq->cmd_flags &= ~REQ_STARTED; 6121da177e4SLinus Torvalds 613b710a480SJens Axboe __elv_add_request(q, rq, ELEVATOR_INSERT_REQUEUE); 6141da177e4SLinus Torvalds } 6151da177e4SLinus Torvalds 61626308eabSJerome Marchand void elv_drain_elevator(struct request_queue *q) 61715853af9STejun Heo { 61815853af9STejun Heo static int printed; 61915853af9STejun Heo while (q->elevator->ops->elevator_dispatch_fn(q, 1)) 62015853af9STejun Heo ; 62115853af9STejun Heo if (q->nr_sorted == 0) 62215853af9STejun Heo return; 62315853af9STejun Heo if (printed++ < 10) { 62415853af9STejun Heo printk(KERN_ERR "%s: forced dispatching is broken " 62515853af9STejun Heo "(nr_sorted=%u), please report this\n", 62615853af9STejun Heo q->elevator->elevator_type->elevator_name, q->nr_sorted); 62715853af9STejun Heo } 62815853af9STejun Heo } 62915853af9STejun Heo 6306c7e8ceeSJens Axboe /* 6316c7e8ceeSJens Axboe * Call with queue lock held, interrupts disabled 6326c7e8ceeSJens Axboe */ 633f600abe2SJens Axboe void elv_quiesce_start(struct request_queue *q) 6346c7e8ceeSJens Axboe { 635cd43e26fSMartin K. Petersen if (!q->elevator) 636cd43e26fSMartin K. Petersen return; 637cd43e26fSMartin K. Petersen 6386c7e8ceeSJens Axboe queue_flag_set(QUEUE_FLAG_ELVSWITCH, q); 6396c7e8ceeSJens Axboe 6406c7e8ceeSJens Axboe /* 6416c7e8ceeSJens Axboe * make sure we don't have any requests in flight 6426c7e8ceeSJens Axboe */ 6436c7e8ceeSJens Axboe elv_drain_elevator(q); 6446c7e8ceeSJens Axboe while (q->rq.elvpriv) { 645*24ecfbe2SChristoph Hellwig __blk_run_queue(q); 6466c7e8ceeSJens Axboe spin_unlock_irq(q->queue_lock); 6476c7e8ceeSJens Axboe msleep(10); 6486c7e8ceeSJens Axboe spin_lock_irq(q->queue_lock); 6496c7e8ceeSJens Axboe elv_drain_elevator(q); 6506c7e8ceeSJens Axboe } 6516c7e8ceeSJens Axboe } 6526c7e8ceeSJens Axboe 653f600abe2SJens Axboe void elv_quiesce_end(struct request_queue *q) 6546c7e8ceeSJens Axboe { 6556c7e8ceeSJens Axboe queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q); 6566c7e8ceeSJens Axboe } 6576c7e8ceeSJens Axboe 658b710a480SJens Axboe void __elv_add_request(struct request_queue *q, struct request *rq, int where) 6591da177e4SLinus Torvalds { 6605f3ea37cSArnaldo Carvalho de Melo trace_block_rq_insert(q, rq); 6612056a782SJens Axboe 6621da177e4SLinus Torvalds rq->q = q; 6631da177e4SLinus Torvalds 664b710a480SJens Axboe BUG_ON(rq->cmd_flags & REQ_ON_PLUG); 665b710a480SJens Axboe 666b710a480SJens Axboe if (rq->cmd_flags & REQ_SOFTBARRIER) { 667b710a480SJens Axboe /* barriers are scheduling boundary, update end_sector */ 668b710a480SJens Axboe if (rq->cmd_type == REQ_TYPE_FS || 669b710a480SJens Axboe (rq->cmd_flags & REQ_DISCARD)) { 670b710a480SJens Axboe q->end_sector = rq_end_sector(rq); 671b710a480SJens Axboe q->boundary_rq = rq; 672b710a480SJens Axboe } 673b710a480SJens Axboe } else if (!(rq->cmd_flags & REQ_ELVPRIV) && 674b710a480SJens Axboe where == ELEVATOR_INSERT_SORT) 675b710a480SJens Axboe where = ELEVATOR_INSERT_BACK; 676b710a480SJens Axboe 6778922e16cSTejun Heo switch (where) { 67828e7d184STejun Heo case ELEVATOR_INSERT_REQUEUE: 6798922e16cSTejun Heo case ELEVATOR_INSERT_FRONT: 6804aff5e23SJens Axboe rq->cmd_flags |= REQ_SOFTBARRIER; 6818922e16cSTejun Heo list_add(&rq->queuelist, &q->queue_head); 6828922e16cSTejun Heo break; 6838922e16cSTejun Heo 6848922e16cSTejun Heo case ELEVATOR_INSERT_BACK: 6854aff5e23SJens Axboe rq->cmd_flags |= REQ_SOFTBARRIER; 68615853af9STejun Heo elv_drain_elevator(q); 6878922e16cSTejun Heo list_add_tail(&rq->queuelist, &q->queue_head); 6888922e16cSTejun Heo /* 6898922e16cSTejun Heo * We kick the queue here for the following reasons. 6908922e16cSTejun Heo * - The elevator might have returned NULL previously 6918922e16cSTejun Heo * to delay requests and returned them now. As the 6928922e16cSTejun Heo * queue wasn't empty before this request, ll_rw_blk 6938922e16cSTejun Heo * won't run the queue on return, resulting in hang. 6948922e16cSTejun Heo * - Usually, back inserted requests won't be merged 6958922e16cSTejun Heo * with anything. There's no point in delaying queue 6968922e16cSTejun Heo * processing. 6978922e16cSTejun Heo */ 698*24ecfbe2SChristoph Hellwig __blk_run_queue(q); 6998922e16cSTejun Heo break; 7008922e16cSTejun Heo 7015e84ea3aSJens Axboe case ELEVATOR_INSERT_SORT_MERGE: 7025e84ea3aSJens Axboe /* 7035e84ea3aSJens Axboe * If we succeed in merging this request with one in the 7045e84ea3aSJens Axboe * queue already, we are done - rq has now been freed, 7055e84ea3aSJens Axboe * so no need to do anything further. 7065e84ea3aSJens Axboe */ 7075e84ea3aSJens Axboe if (elv_attempt_insert_merge(q, rq)) 7085e84ea3aSJens Axboe break; 7098922e16cSTejun Heo case ELEVATOR_INSERT_SORT: 71033659ebbSChristoph Hellwig BUG_ON(rq->cmd_type != REQ_TYPE_FS && 71133659ebbSChristoph Hellwig !(rq->cmd_flags & REQ_DISCARD)); 7124aff5e23SJens Axboe rq->cmd_flags |= REQ_SORTED; 71315853af9STejun Heo q->nr_sorted++; 7149817064bSJens Axboe if (rq_mergeable(rq)) { 7159817064bSJens Axboe elv_rqhash_add(q, rq); 7169817064bSJens Axboe if (!q->last_merge) 71706b86245STejun Heo q->last_merge = rq; 7189817064bSJens Axboe } 7199817064bSJens Axboe 720ca23509fSTejun Heo /* 721ca23509fSTejun Heo * Some ioscheds (cfq) run q->request_fn directly, so 722ca23509fSTejun Heo * rq cannot be accessed after calling 723ca23509fSTejun Heo * elevator_add_req_fn. 724ca23509fSTejun Heo */ 725ca23509fSTejun Heo q->elevator->ops->elevator_add_req_fn(q, rq); 7268922e16cSTejun Heo break; 7278922e16cSTejun Heo 728ae1b1539STejun Heo case ELEVATOR_INSERT_FLUSH: 729ae1b1539STejun Heo rq->cmd_flags |= REQ_SOFTBARRIER; 730ae1b1539STejun Heo blk_insert_flush(rq); 731ae1b1539STejun Heo break; 7328922e16cSTejun Heo default: 7338922e16cSTejun Heo printk(KERN_ERR "%s: bad insertion point %d\n", 73424c03d47SHarvey Harrison __func__, where); 7358922e16cSTejun Heo BUG(); 7368922e16cSTejun Heo } 7371da177e4SLinus Torvalds } 7382e662b65SJens Axboe EXPORT_SYMBOL(__elv_add_request); 7392e662b65SJens Axboe 7407eaceaccSJens Axboe void elv_add_request(struct request_queue *q, struct request *rq, int where) 7411da177e4SLinus Torvalds { 7421da177e4SLinus Torvalds unsigned long flags; 7431da177e4SLinus Torvalds 7441da177e4SLinus Torvalds spin_lock_irqsave(q->queue_lock, flags); 7457eaceaccSJens Axboe __elv_add_request(q, rq, where); 7461da177e4SLinus Torvalds spin_unlock_irqrestore(q->queue_lock, flags); 7471da177e4SLinus Torvalds } 7482e662b65SJens Axboe EXPORT_SYMBOL(elv_add_request); 7492e662b65SJens Axboe 750165125e1SJens Axboe struct request *elv_latter_request(struct request_queue *q, struct request *rq) 7511da177e4SLinus Torvalds { 752b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 7531da177e4SLinus Torvalds 7541da177e4SLinus Torvalds if (e->ops->elevator_latter_req_fn) 7551da177e4SLinus Torvalds return e->ops->elevator_latter_req_fn(q, rq); 7561da177e4SLinus Torvalds return NULL; 7571da177e4SLinus Torvalds } 7581da177e4SLinus Torvalds 759165125e1SJens Axboe struct request *elv_former_request(struct request_queue *q, struct request *rq) 7601da177e4SLinus Torvalds { 761b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 7621da177e4SLinus Torvalds 7631da177e4SLinus Torvalds if (e->ops->elevator_former_req_fn) 7641da177e4SLinus Torvalds return e->ops->elevator_former_req_fn(q, rq); 7651da177e4SLinus Torvalds return NULL; 7661da177e4SLinus Torvalds } 7671da177e4SLinus Torvalds 768165125e1SJens Axboe int elv_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask) 7691da177e4SLinus Torvalds { 770b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 7711da177e4SLinus Torvalds 7721da177e4SLinus Torvalds if (e->ops->elevator_set_req_fn) 773cb78b285SJens Axboe return e->ops->elevator_set_req_fn(q, rq, gfp_mask); 7741da177e4SLinus Torvalds 775c186794dSMike Snitzer rq->elevator_private[0] = NULL; 7761da177e4SLinus Torvalds return 0; 7771da177e4SLinus Torvalds } 7781da177e4SLinus Torvalds 779165125e1SJens Axboe void elv_put_request(struct request_queue *q, struct request *rq) 7801da177e4SLinus Torvalds { 781b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 7821da177e4SLinus Torvalds 7831da177e4SLinus Torvalds if (e->ops->elevator_put_req_fn) 784bb37b94cSJens Axboe e->ops->elevator_put_req_fn(rq); 7851da177e4SLinus Torvalds } 7861da177e4SLinus Torvalds 787165125e1SJens Axboe int elv_may_queue(struct request_queue *q, int rw) 7881da177e4SLinus Torvalds { 789b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 7901da177e4SLinus Torvalds 7911da177e4SLinus Torvalds if (e->ops->elevator_may_queue_fn) 792cb78b285SJens Axboe return e->ops->elevator_may_queue_fn(q, rw); 7931da177e4SLinus Torvalds 7941da177e4SLinus Torvalds return ELV_MQUEUE_MAY; 7951da177e4SLinus Torvalds } 7961da177e4SLinus Torvalds 79711914a53SMike Anderson void elv_abort_queue(struct request_queue *q) 79811914a53SMike Anderson { 79911914a53SMike Anderson struct request *rq; 80011914a53SMike Anderson 801ae1b1539STejun Heo blk_abort_flushes(q); 802ae1b1539STejun Heo 80311914a53SMike Anderson while (!list_empty(&q->queue_head)) { 80411914a53SMike Anderson rq = list_entry_rq(q->queue_head.next); 80511914a53SMike Anderson rq->cmd_flags |= REQ_QUIET; 8065f3ea37cSArnaldo Carvalho de Melo trace_block_rq_abort(q, rq); 80753c663ceSKiyoshi Ueda /* 80853c663ceSKiyoshi Ueda * Mark this request as started so we don't trigger 80953c663ceSKiyoshi Ueda * any debug logic in the end I/O path. 81053c663ceSKiyoshi Ueda */ 81153c663ceSKiyoshi Ueda blk_start_request(rq); 81240cbbb78STejun Heo __blk_end_request_all(rq, -EIO); 81311914a53SMike Anderson } 81411914a53SMike Anderson } 81511914a53SMike Anderson EXPORT_SYMBOL(elv_abort_queue); 81611914a53SMike Anderson 817165125e1SJens Axboe void elv_completed_request(struct request_queue *q, struct request *rq) 8181da177e4SLinus Torvalds { 819b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 8201da177e4SLinus Torvalds 8211da177e4SLinus Torvalds /* 8221da177e4SLinus Torvalds * request is released from the driver, io must be done 8231da177e4SLinus Torvalds */ 8248922e16cSTejun Heo if (blk_account_rq(rq)) { 8250a7ae2ffSJens Axboe q->in_flight[rq_is_sync(rq)]--; 82633659ebbSChristoph Hellwig if ((rq->cmd_flags & REQ_SORTED) && 82733659ebbSChristoph Hellwig e->ops->elevator_completed_req_fn) 8281bc691d3STejun Heo e->ops->elevator_completed_req_fn(q, rq); 8291bc691d3STejun Heo } 8308922e16cSTejun Heo } 8311da177e4SLinus Torvalds 8323d1ab40fSAl Viro #define to_elv(atr) container_of((atr), struct elv_fs_entry, attr) 8333d1ab40fSAl Viro 8343d1ab40fSAl Viro static ssize_t 8353d1ab40fSAl Viro elv_attr_show(struct kobject *kobj, struct attribute *attr, char *page) 8363d1ab40fSAl Viro { 8373d1ab40fSAl Viro struct elv_fs_entry *entry = to_elv(attr); 838b374d18aSJens Axboe struct elevator_queue *e; 8393d1ab40fSAl Viro ssize_t error; 8403d1ab40fSAl Viro 8413d1ab40fSAl Viro if (!entry->show) 8423d1ab40fSAl Viro return -EIO; 8433d1ab40fSAl Viro 844b374d18aSJens Axboe e = container_of(kobj, struct elevator_queue, kobj); 8453d1ab40fSAl Viro mutex_lock(&e->sysfs_lock); 8463d1ab40fSAl Viro error = e->ops ? entry->show(e, page) : -ENOENT; 8473d1ab40fSAl Viro mutex_unlock(&e->sysfs_lock); 8483d1ab40fSAl Viro return error; 8493d1ab40fSAl Viro } 8503d1ab40fSAl Viro 8513d1ab40fSAl Viro static ssize_t 8523d1ab40fSAl Viro elv_attr_store(struct kobject *kobj, struct attribute *attr, 8533d1ab40fSAl Viro const char *page, size_t length) 8543d1ab40fSAl Viro { 8553d1ab40fSAl Viro struct elv_fs_entry *entry = to_elv(attr); 856b374d18aSJens Axboe struct elevator_queue *e; 8573d1ab40fSAl Viro ssize_t error; 8583d1ab40fSAl Viro 8593d1ab40fSAl Viro if (!entry->store) 8603d1ab40fSAl Viro return -EIO; 8613d1ab40fSAl Viro 862b374d18aSJens Axboe e = container_of(kobj, struct elevator_queue, kobj); 8633d1ab40fSAl Viro mutex_lock(&e->sysfs_lock); 8643d1ab40fSAl Viro error = e->ops ? entry->store(e, page, length) : -ENOENT; 8653d1ab40fSAl Viro mutex_unlock(&e->sysfs_lock); 8663d1ab40fSAl Viro return error; 8673d1ab40fSAl Viro } 8683d1ab40fSAl Viro 86952cf25d0SEmese Revfy static const struct sysfs_ops elv_sysfs_ops = { 8703d1ab40fSAl Viro .show = elv_attr_show, 8713d1ab40fSAl Viro .store = elv_attr_store, 8723d1ab40fSAl Viro }; 8733d1ab40fSAl Viro 8743d1ab40fSAl Viro static struct kobj_type elv_ktype = { 8753d1ab40fSAl Viro .sysfs_ops = &elv_sysfs_ops, 8763d1ab40fSAl Viro .release = elevator_release, 8773d1ab40fSAl Viro }; 8783d1ab40fSAl Viro 8791da177e4SLinus Torvalds int elv_register_queue(struct request_queue *q) 8801da177e4SLinus Torvalds { 881b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 8823d1ab40fSAl Viro int error; 8831da177e4SLinus Torvalds 884b2d6db58SGreg Kroah-Hartman error = kobject_add(&e->kobj, &q->kobj, "%s", "iosched"); 8853d1ab40fSAl Viro if (!error) { 886e572ec7eSAl Viro struct elv_fs_entry *attr = e->elevator_type->elevator_attrs; 8873d1ab40fSAl Viro if (attr) { 888e572ec7eSAl Viro while (attr->attr.name) { 889e572ec7eSAl Viro if (sysfs_create_file(&e->kobj, &attr->attr)) 8903d1ab40fSAl Viro break; 891e572ec7eSAl Viro attr++; 8923d1ab40fSAl Viro } 8933d1ab40fSAl Viro } 8943d1ab40fSAl Viro kobject_uevent(&e->kobj, KOBJ_ADD); 895430c62fbSJens Axboe e->registered = 1; 8963d1ab40fSAl Viro } 8973d1ab40fSAl Viro return error; 8981da177e4SLinus Torvalds } 89901effb0dSMike Snitzer EXPORT_SYMBOL(elv_register_queue); 9001da177e4SLinus Torvalds 901b374d18aSJens Axboe static void __elv_unregister_queue(struct elevator_queue *e) 9021da177e4SLinus Torvalds { 9033d1ab40fSAl Viro kobject_uevent(&e->kobj, KOBJ_REMOVE); 9043d1ab40fSAl Viro kobject_del(&e->kobj); 905430c62fbSJens Axboe e->registered = 0; 9061da177e4SLinus Torvalds } 907bc1c1169SJens Axboe 908bc1c1169SJens Axboe void elv_unregister_queue(struct request_queue *q) 909bc1c1169SJens Axboe { 910bc1c1169SJens Axboe if (q) 911bc1c1169SJens Axboe __elv_unregister_queue(q->elevator); 9121da177e4SLinus Torvalds } 91301effb0dSMike Snitzer EXPORT_SYMBOL(elv_unregister_queue); 9141da177e4SLinus Torvalds 9152fdd82bdSAdrian Bunk void elv_register(struct elevator_type *e) 9161da177e4SLinus Torvalds { 9171ffb96c5SThibaut VARENE char *def = ""; 9182a12dcd7SJens Axboe 9192a12dcd7SJens Axboe spin_lock(&elv_list_lock); 920ce524497SEric Sesterhenn BUG_ON(elevator_find(e->elevator_name)); 9211da177e4SLinus Torvalds list_add_tail(&e->list, &elv_list); 9222a12dcd7SJens Axboe spin_unlock(&elv_list_lock); 9231da177e4SLinus Torvalds 9245f003976SNate Diller if (!strcmp(e->elevator_name, chosen_elevator) || 9255f003976SNate Diller (!*chosen_elevator && 9265f003976SNate Diller !strcmp(e->elevator_name, CONFIG_DEFAULT_IOSCHED))) 9271ffb96c5SThibaut VARENE def = " (default)"; 9281ffb96c5SThibaut VARENE 9294eb166d9SJens Axboe printk(KERN_INFO "io scheduler %s registered%s\n", e->elevator_name, 9304eb166d9SJens Axboe def); 9311da177e4SLinus Torvalds } 9321da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(elv_register); 9331da177e4SLinus Torvalds 9341da177e4SLinus Torvalds void elv_unregister(struct elevator_type *e) 9351da177e4SLinus Torvalds { 93683521d3eSChristoph Hellwig struct task_struct *g, *p; 93783521d3eSChristoph Hellwig 93883521d3eSChristoph Hellwig /* 93983521d3eSChristoph Hellwig * Iterate every thread in the process to remove the io contexts. 94083521d3eSChristoph Hellwig */ 941e17a9489SAl Viro if (e->ops.trim) { 94283521d3eSChristoph Hellwig read_lock(&tasklist_lock); 94383521d3eSChristoph Hellwig do_each_thread(g, p) { 944e17a9489SAl Viro task_lock(p); 9452d8f6131SOleg Nesterov if (p->io_context) 946e17a9489SAl Viro e->ops.trim(p->io_context); 947e17a9489SAl Viro task_unlock(p); 94883521d3eSChristoph Hellwig } while_each_thread(g, p); 94983521d3eSChristoph Hellwig read_unlock(&tasklist_lock); 950e17a9489SAl Viro } 95183521d3eSChristoph Hellwig 9522a12dcd7SJens Axboe spin_lock(&elv_list_lock); 9531da177e4SLinus Torvalds list_del_init(&e->list); 9542a12dcd7SJens Axboe spin_unlock(&elv_list_lock); 9551da177e4SLinus Torvalds } 9561da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(elv_unregister); 9571da177e4SLinus Torvalds 9581da177e4SLinus Torvalds /* 9591da177e4SLinus Torvalds * switch to new_e io scheduler. be careful not to introduce deadlocks - 9601da177e4SLinus Torvalds * we don't free the old io scheduler, before we have allocated what we 9611da177e4SLinus Torvalds * need for the new one. this way we have a chance of going back to the old 962cb98fc8bSTejun Heo * one, if the new one fails init for some reason. 9631da177e4SLinus Torvalds */ 964165125e1SJens Axboe static int elevator_switch(struct request_queue *q, struct elevator_type *new_e) 9651da177e4SLinus Torvalds { 966b374d18aSJens Axboe struct elevator_queue *old_elevator, *e; 967bc1c1169SJens Axboe void *data; 9685dd531a0SJens Axboe int err; 9691da177e4SLinus Torvalds 970cb98fc8bSTejun Heo /* 971cb98fc8bSTejun Heo * Allocate new elevator 972cb98fc8bSTejun Heo */ 973b5deef90SJens Axboe e = elevator_alloc(q, new_e); 9741da177e4SLinus Torvalds if (!e) 9755dd531a0SJens Axboe return -ENOMEM; 9761da177e4SLinus Torvalds 977bc1c1169SJens Axboe data = elevator_init_queue(q, e); 978bc1c1169SJens Axboe if (!data) { 979bc1c1169SJens Axboe kobject_put(&e->kobj); 9805dd531a0SJens Axboe return -ENOMEM; 981bc1c1169SJens Axboe } 982bc1c1169SJens Axboe 9831da177e4SLinus Torvalds /* 984cb98fc8bSTejun Heo * Turn on BYPASS and drain all requests w/ elevator private data 9851da177e4SLinus Torvalds */ 986cb98fc8bSTejun Heo spin_lock_irq(q->queue_lock); 987f600abe2SJens Axboe elv_quiesce_start(q); 988cb98fc8bSTejun Heo 9891da177e4SLinus Torvalds /* 990bc1c1169SJens Axboe * Remember old elevator. 9911da177e4SLinus Torvalds */ 9921da177e4SLinus Torvalds old_elevator = q->elevator; 9931da177e4SLinus Torvalds 9941da177e4SLinus Torvalds /* 9951da177e4SLinus Torvalds * attach and start new elevator 9961da177e4SLinus Torvalds */ 997bc1c1169SJens Axboe elevator_attach(q, e, data); 998bc1c1169SJens Axboe 999bc1c1169SJens Axboe spin_unlock_irq(q->queue_lock); 1000bc1c1169SJens Axboe 1001430c62fbSJens Axboe if (old_elevator->registered) { 1002bc1c1169SJens Axboe __elv_unregister_queue(old_elevator); 10031da177e4SLinus Torvalds 10045dd531a0SJens Axboe err = elv_register_queue(q); 10055dd531a0SJens Axboe if (err) 10061da177e4SLinus Torvalds goto fail_register; 1007430c62fbSJens Axboe } 10081da177e4SLinus Torvalds 10091da177e4SLinus Torvalds /* 1010cb98fc8bSTejun Heo * finally exit old elevator and turn off BYPASS. 10111da177e4SLinus Torvalds */ 10121da177e4SLinus Torvalds elevator_exit(old_elevator); 101375ad23bcSNick Piggin spin_lock_irq(q->queue_lock); 1014f600abe2SJens Axboe elv_quiesce_end(q); 101575ad23bcSNick Piggin spin_unlock_irq(q->queue_lock); 101675ad23bcSNick Piggin 10174722dc52SAlan D. Brunelle blk_add_trace_msg(q, "elv switch: %s", e->elevator_type->elevator_name); 10184722dc52SAlan D. Brunelle 10195dd531a0SJens Axboe return 0; 10201da177e4SLinus Torvalds 10211da177e4SLinus Torvalds fail_register: 10221da177e4SLinus Torvalds /* 10231da177e4SLinus Torvalds * switch failed, exit the new io scheduler and reattach the old 10241da177e4SLinus Torvalds * one again (along with re-adding the sysfs dir) 10251da177e4SLinus Torvalds */ 10261da177e4SLinus Torvalds elevator_exit(e); 10271da177e4SLinus Torvalds q->elevator = old_elevator; 10281da177e4SLinus Torvalds elv_register_queue(q); 102975ad23bcSNick Piggin 103075ad23bcSNick Piggin spin_lock_irq(q->queue_lock); 103175ad23bcSNick Piggin queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q); 103275ad23bcSNick Piggin spin_unlock_irq(q->queue_lock); 103375ad23bcSNick Piggin 10345dd531a0SJens Axboe return err; 10351da177e4SLinus Torvalds } 10361da177e4SLinus Torvalds 10375dd531a0SJens Axboe /* 10385dd531a0SJens Axboe * Switch this queue to the given IO scheduler. 10395dd531a0SJens Axboe */ 10405dd531a0SJens Axboe int elevator_change(struct request_queue *q, const char *name) 10411da177e4SLinus Torvalds { 10421da177e4SLinus Torvalds char elevator_name[ELV_NAME_MAX]; 10431da177e4SLinus Torvalds struct elevator_type *e; 10441da177e4SLinus Torvalds 1045cd43e26fSMartin K. Petersen if (!q->elevator) 10465dd531a0SJens Axboe return -ENXIO; 1047cd43e26fSMartin K. Petersen 1048ee2e992cSLi Zefan strlcpy(elevator_name, name, sizeof(elevator_name)); 10498c279598SKOSAKI Motohiro e = elevator_get(strstrip(elevator_name)); 10501da177e4SLinus Torvalds if (!e) { 10511da177e4SLinus Torvalds printk(KERN_ERR "elevator: type %s not found\n", elevator_name); 10521da177e4SLinus Torvalds return -EINVAL; 10531da177e4SLinus Torvalds } 10541da177e4SLinus Torvalds 10552ca7d93bSNate Diller if (!strcmp(elevator_name, q->elevator->elevator_type->elevator_name)) { 10562ca7d93bSNate Diller elevator_put(e); 10575dd531a0SJens Axboe return 0; 10582ca7d93bSNate Diller } 10591da177e4SLinus Torvalds 10605dd531a0SJens Axboe return elevator_switch(q, e); 10615dd531a0SJens Axboe } 10625dd531a0SJens Axboe EXPORT_SYMBOL(elevator_change); 10635dd531a0SJens Axboe 10645dd531a0SJens Axboe ssize_t elv_iosched_store(struct request_queue *q, const char *name, 10655dd531a0SJens Axboe size_t count) 10665dd531a0SJens Axboe { 10675dd531a0SJens Axboe int ret; 10685dd531a0SJens Axboe 10695dd531a0SJens Axboe if (!q->elevator) 10701da177e4SLinus Torvalds return count; 10715dd531a0SJens Axboe 10725dd531a0SJens Axboe ret = elevator_change(q, name); 10735dd531a0SJens Axboe if (!ret) 10745dd531a0SJens Axboe return count; 10755dd531a0SJens Axboe 10765dd531a0SJens Axboe printk(KERN_ERR "elevator: switch to %s failed\n", name); 10775dd531a0SJens Axboe return ret; 10781da177e4SLinus Torvalds } 10791da177e4SLinus Torvalds 1080165125e1SJens Axboe ssize_t elv_iosched_show(struct request_queue *q, char *name) 10811da177e4SLinus Torvalds { 1082b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 1083cd43e26fSMartin K. Petersen struct elevator_type *elv; 108470cee26eSMatthias Kaehlcke struct elevator_type *__e; 10851da177e4SLinus Torvalds int len = 0; 10861da177e4SLinus Torvalds 1087e36f724bSMike Snitzer if (!q->elevator || !blk_queue_stackable(q)) 1088cd43e26fSMartin K. Petersen return sprintf(name, "none\n"); 1089cd43e26fSMartin K. Petersen 1090cd43e26fSMartin K. Petersen elv = e->elevator_type; 1091cd43e26fSMartin K. Petersen 10922a12dcd7SJens Axboe spin_lock(&elv_list_lock); 109370cee26eSMatthias Kaehlcke list_for_each_entry(__e, &elv_list, list) { 10941da177e4SLinus Torvalds if (!strcmp(elv->elevator_name, __e->elevator_name)) 10951da177e4SLinus Torvalds len += sprintf(name+len, "[%s] ", elv->elevator_name); 10961da177e4SLinus Torvalds else 10971da177e4SLinus Torvalds len += sprintf(name+len, "%s ", __e->elevator_name); 10981da177e4SLinus Torvalds } 10992a12dcd7SJens Axboe spin_unlock(&elv_list_lock); 11001da177e4SLinus Torvalds 11011da177e4SLinus Torvalds len += sprintf(len+name, "\n"); 11021da177e4SLinus Torvalds return len; 11031da177e4SLinus Torvalds } 11041da177e4SLinus Torvalds 1105165125e1SJens Axboe struct request *elv_rb_former_request(struct request_queue *q, 1106165125e1SJens Axboe struct request *rq) 11072e662b65SJens Axboe { 11082e662b65SJens Axboe struct rb_node *rbprev = rb_prev(&rq->rb_node); 11092e662b65SJens Axboe 11102e662b65SJens Axboe if (rbprev) 11112e662b65SJens Axboe return rb_entry_rq(rbprev); 11122e662b65SJens Axboe 11132e662b65SJens Axboe return NULL; 11142e662b65SJens Axboe } 11152e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_former_request); 11162e662b65SJens Axboe 1117165125e1SJens Axboe struct request *elv_rb_latter_request(struct request_queue *q, 1118165125e1SJens Axboe struct request *rq) 11192e662b65SJens Axboe { 11202e662b65SJens Axboe struct rb_node *rbnext = rb_next(&rq->rb_node); 11212e662b65SJens Axboe 11222e662b65SJens Axboe if (rbnext) 11232e662b65SJens Axboe return rb_entry_rq(rbnext); 11242e662b65SJens Axboe 11252e662b65SJens Axboe return NULL; 11262e662b65SJens Axboe } 11272e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_latter_request); 1128