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 */ 821f98a13fSJens Axboe if (bio_rw_flagged(bio, BIO_RW_DISCARD) != 831f98a13fSJens Axboe bio_rw_flagged(rq->bio, BIO_RW_DISCARD)) 84e17fc0a1SDavid Woodhouse return 0; 85e17fc0a1SDavid Woodhouse 86e17fc0a1SDavid Woodhouse /* 871da177e4SLinus Torvalds * different data direction or already started, don't merge 881da177e4SLinus Torvalds */ 891da177e4SLinus Torvalds if (bio_data_dir(bio) != rq_data_dir(rq)) 901da177e4SLinus Torvalds return 0; 911da177e4SLinus Torvalds 921da177e4SLinus Torvalds /* 93da775265SJens Axboe * must be same device and not a special request 941da177e4SLinus Torvalds */ 95bb4067e3SJens Axboe if (rq->rq_disk != bio->bi_bdev->bd_disk || rq->special) 961da177e4SLinus Torvalds return 0; 97da775265SJens Axboe 987ba1ba12SMartin K. Petersen /* 997ba1ba12SMartin K. Petersen * only merge integrity protected bio into ditto rq 1007ba1ba12SMartin K. Petersen */ 1017ba1ba12SMartin K. Petersen if (bio_integrity(bio) != blk_integrity_rq(rq)) 1027ba1ba12SMartin K. Petersen return 0; 1037ba1ba12SMartin K. Petersen 104da775265SJens Axboe if (!elv_iosched_allow_merge(rq, bio)) 105da775265SJens Axboe return 0; 106da775265SJens Axboe 107da775265SJens Axboe return 1; 1081da177e4SLinus Torvalds } 1091da177e4SLinus Torvalds EXPORT_SYMBOL(elv_rq_merge_ok); 1101da177e4SLinus Torvalds 111769db45bSCoywolf Qi Hunt static inline int elv_try_merge(struct request *__rq, struct bio *bio) 1121da177e4SLinus Torvalds { 1131da177e4SLinus Torvalds int ret = ELEVATOR_NO_MERGE; 1141da177e4SLinus Torvalds 1151da177e4SLinus Torvalds /* 1161da177e4SLinus Torvalds * we can merge and sequence is ok, check if it's possible 1171da177e4SLinus Torvalds */ 1181da177e4SLinus Torvalds if (elv_rq_merge_ok(__rq, bio)) { 11983096ebfSTejun Heo if (blk_rq_pos(__rq) + blk_rq_sectors(__rq) == bio->bi_sector) 1201da177e4SLinus Torvalds ret = ELEVATOR_BACK_MERGE; 12183096ebfSTejun Heo else if (blk_rq_pos(__rq) - bio_sectors(bio) == bio->bi_sector) 1221da177e4SLinus Torvalds ret = ELEVATOR_FRONT_MERGE; 1231da177e4SLinus Torvalds } 1241da177e4SLinus Torvalds 1251da177e4SLinus Torvalds return ret; 1261da177e4SLinus Torvalds } 1271da177e4SLinus Torvalds 1281da177e4SLinus Torvalds static struct elevator_type *elevator_find(const char *name) 1291da177e4SLinus Torvalds { 130a22b169dSVasily Tarasov struct elevator_type *e; 1311da177e4SLinus Torvalds 13270cee26eSMatthias Kaehlcke list_for_each_entry(e, &elv_list, list) { 133a22b169dSVasily Tarasov if (!strcmp(e->elevator_name, name)) 1341da177e4SLinus Torvalds return e; 1351da177e4SLinus Torvalds } 1361da177e4SLinus Torvalds 137a22b169dSVasily Tarasov return NULL; 138a22b169dSVasily Tarasov } 139a22b169dSVasily Tarasov 1401da177e4SLinus Torvalds static void elevator_put(struct elevator_type *e) 1411da177e4SLinus Torvalds { 1421da177e4SLinus Torvalds module_put(e->elevator_owner); 1431da177e4SLinus Torvalds } 1441da177e4SLinus Torvalds 1451da177e4SLinus Torvalds static struct elevator_type *elevator_get(const char *name) 1461da177e4SLinus Torvalds { 1472824bc93STejun Heo struct elevator_type *e; 1481da177e4SLinus Torvalds 1492a12dcd7SJens Axboe spin_lock(&elv_list_lock); 1502824bc93STejun Heo 1512824bc93STejun Heo e = elevator_find(name); 152e1640949SJens Axboe if (!e) { 153e1640949SJens Axboe char elv[ELV_NAME_MAX + strlen("-iosched")]; 154e1640949SJens Axboe 155e1640949SJens Axboe spin_unlock(&elv_list_lock); 156e1640949SJens Axboe 157a506aedcSwzt.wzt@gmail.com snprintf(elv, sizeof(elv), "%s-iosched", name); 158e1640949SJens Axboe 159e180f594Smaximilian attems request_module("%s", elv); 160e1640949SJens Axboe spin_lock(&elv_list_lock); 161e1640949SJens Axboe e = elevator_find(name); 162e1640949SJens Axboe } 163e1640949SJens Axboe 1642824bc93STejun Heo if (e && !try_module_get(e->elevator_owner)) 1652824bc93STejun Heo e = NULL; 1662824bc93STejun Heo 1672a12dcd7SJens Axboe spin_unlock(&elv_list_lock); 1681da177e4SLinus Torvalds 1691da177e4SLinus Torvalds return e; 1701da177e4SLinus Torvalds } 1711da177e4SLinus Torvalds 172165125e1SJens Axboe static void *elevator_init_queue(struct request_queue *q, 173165125e1SJens Axboe struct elevator_queue *eq) 1741da177e4SLinus Torvalds { 175bb37b94cSJens Axboe return eq->ops->elevator_init_fn(q); 176bc1c1169SJens Axboe } 1771da177e4SLinus Torvalds 178165125e1SJens Axboe static void elevator_attach(struct request_queue *q, struct elevator_queue *eq, 179bc1c1169SJens Axboe void *data) 180bc1c1169SJens Axboe { 1811da177e4SLinus Torvalds q->elevator = eq; 182bc1c1169SJens Axboe eq->elevator_data = data; 1831da177e4SLinus Torvalds } 1841da177e4SLinus Torvalds 1851da177e4SLinus Torvalds static char chosen_elevator[16]; 1861da177e4SLinus Torvalds 1875f003976SNate Diller static int __init elevator_setup(char *str) 1881da177e4SLinus Torvalds { 189752a3b79SChuck Ebbert /* 190752a3b79SChuck Ebbert * Be backwards-compatible with previous kernels, so users 191752a3b79SChuck Ebbert * won't get the wrong elevator. 192752a3b79SChuck Ebbert */ 1931da177e4SLinus Torvalds strncpy(chosen_elevator, str, sizeof(chosen_elevator) - 1); 1949b41046cSOGAWA Hirofumi return 1; 1951da177e4SLinus Torvalds } 1961da177e4SLinus Torvalds 1971da177e4SLinus Torvalds __setup("elevator=", elevator_setup); 1981da177e4SLinus Torvalds 1993d1ab40fSAl Viro static struct kobj_type elv_ktype; 2003d1ab40fSAl Viro 201b374d18aSJens Axboe static struct elevator_queue *elevator_alloc(struct request_queue *q, 202165125e1SJens Axboe struct elevator_type *e) 2033d1ab40fSAl Viro { 204b374d18aSJens Axboe struct elevator_queue *eq; 2059817064bSJens Axboe int i; 2069817064bSJens Axboe 207b374d18aSJens Axboe eq = kmalloc_node(sizeof(*eq), GFP_KERNEL | __GFP_ZERO, q->node); 2089817064bSJens Axboe if (unlikely(!eq)) 2099817064bSJens Axboe goto err; 2109817064bSJens Axboe 2113d1ab40fSAl Viro eq->ops = &e->ops; 2123d1ab40fSAl Viro eq->elevator_type = e; 213f9cb074bSGreg Kroah-Hartman kobject_init(&eq->kobj, &elv_ktype); 2143d1ab40fSAl Viro mutex_init(&eq->sysfs_lock); 2159817064bSJens Axboe 216b5deef90SJens Axboe eq->hash = kmalloc_node(sizeof(struct hlist_head) * ELV_HASH_ENTRIES, 217b5deef90SJens Axboe GFP_KERNEL, q->node); 2189817064bSJens Axboe if (!eq->hash) 2199817064bSJens Axboe goto err; 2209817064bSJens Axboe 2219817064bSJens Axboe for (i = 0; i < ELV_HASH_ENTRIES; i++) 2229817064bSJens Axboe INIT_HLIST_HEAD(&eq->hash[i]); 2239817064bSJens Axboe 2243d1ab40fSAl Viro return eq; 2259817064bSJens Axboe err: 2269817064bSJens Axboe kfree(eq); 2279817064bSJens Axboe elevator_put(e); 2289817064bSJens Axboe return NULL; 2293d1ab40fSAl Viro } 2303d1ab40fSAl Viro 2313d1ab40fSAl Viro static void elevator_release(struct kobject *kobj) 2323d1ab40fSAl Viro { 233b374d18aSJens Axboe struct elevator_queue *e; 2349817064bSJens Axboe 235b374d18aSJens Axboe e = container_of(kobj, struct elevator_queue, kobj); 2363d1ab40fSAl Viro elevator_put(e->elevator_type); 2379817064bSJens Axboe kfree(e->hash); 2383d1ab40fSAl Viro kfree(e); 2393d1ab40fSAl Viro } 2403d1ab40fSAl Viro 241165125e1SJens Axboe int elevator_init(struct request_queue *q, char *name) 2421da177e4SLinus Torvalds { 2431da177e4SLinus Torvalds struct elevator_type *e = NULL; 2441da177e4SLinus Torvalds struct elevator_queue *eq; 2451da177e4SLinus Torvalds int ret = 0; 246bc1c1169SJens Axboe void *data; 2471da177e4SLinus Torvalds 248cb98fc8bSTejun Heo INIT_LIST_HEAD(&q->queue_head); 249cb98fc8bSTejun Heo q->last_merge = NULL; 250cb98fc8bSTejun Heo q->end_sector = 0; 251cb98fc8bSTejun Heo q->boundary_rq = NULL; 252cb98fc8bSTejun Heo 2534eb166d9SJens Axboe if (name) { 2544eb166d9SJens Axboe e = elevator_get(name); 2554eb166d9SJens Axboe if (!e) 2561da177e4SLinus Torvalds return -EINVAL; 2574eb166d9SJens Axboe } 2581da177e4SLinus Torvalds 2594eb166d9SJens Axboe if (!e && *chosen_elevator) { 2604eb166d9SJens Axboe e = elevator_get(chosen_elevator); 2614eb166d9SJens Axboe if (!e) 2624eb166d9SJens Axboe printk(KERN_ERR "I/O scheduler %s not found\n", 2634eb166d9SJens Axboe chosen_elevator); 2644eb166d9SJens Axboe } 265248d5ca5SNate Diller 2664eb166d9SJens Axboe if (!e) { 2674eb166d9SJens Axboe e = elevator_get(CONFIG_DEFAULT_IOSCHED); 2684eb166d9SJens Axboe if (!e) { 2694eb166d9SJens Axboe printk(KERN_ERR 2704eb166d9SJens Axboe "Default I/O scheduler not found. " \ 2714eb166d9SJens Axboe "Using noop.\n"); 272248d5ca5SNate Diller e = elevator_get("noop"); 2735f003976SNate Diller } 2744eb166d9SJens Axboe } 2755f003976SNate Diller 276b5deef90SJens Axboe eq = elevator_alloc(q, e); 2773d1ab40fSAl Viro if (!eq) 2781da177e4SLinus Torvalds return -ENOMEM; 2791da177e4SLinus Torvalds 280bc1c1169SJens Axboe data = elevator_init_queue(q, eq); 281bc1c1169SJens Axboe if (!data) { 2823d1ab40fSAl Viro kobject_put(&eq->kobj); 283bc1c1169SJens Axboe return -ENOMEM; 284bc1c1169SJens Axboe } 2851da177e4SLinus Torvalds 286bc1c1169SJens Axboe elevator_attach(q, eq, data); 2871da177e4SLinus Torvalds return ret; 2881da177e4SLinus Torvalds } 2892e662b65SJens Axboe EXPORT_SYMBOL(elevator_init); 2902e662b65SJens Axboe 291b374d18aSJens Axboe void elevator_exit(struct elevator_queue *e) 2921da177e4SLinus Torvalds { 2933d1ab40fSAl Viro mutex_lock(&e->sysfs_lock); 2941da177e4SLinus Torvalds if (e->ops->elevator_exit_fn) 2951da177e4SLinus Torvalds e->ops->elevator_exit_fn(e); 2963d1ab40fSAl Viro e->ops = NULL; 2973d1ab40fSAl Viro mutex_unlock(&e->sysfs_lock); 2981da177e4SLinus Torvalds 2993d1ab40fSAl Viro kobject_put(&e->kobj); 3001da177e4SLinus Torvalds } 3012e662b65SJens Axboe EXPORT_SYMBOL(elevator_exit); 3022e662b65SJens Axboe 3039817064bSJens Axboe static inline void __elv_rqhash_del(struct request *rq) 3049817064bSJens Axboe { 3059817064bSJens Axboe hlist_del_init(&rq->hash); 3069817064bSJens Axboe } 3079817064bSJens Axboe 308165125e1SJens Axboe static void elv_rqhash_del(struct request_queue *q, struct request *rq) 3099817064bSJens Axboe { 3109817064bSJens Axboe if (ELV_ON_HASH(rq)) 3119817064bSJens Axboe __elv_rqhash_del(rq); 3129817064bSJens Axboe } 3139817064bSJens Axboe 314165125e1SJens Axboe static void elv_rqhash_add(struct request_queue *q, struct request *rq) 3159817064bSJens Axboe { 316b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 3179817064bSJens Axboe 3189817064bSJens Axboe BUG_ON(ELV_ON_HASH(rq)); 3199817064bSJens Axboe hlist_add_head(&rq->hash, &e->hash[ELV_HASH_FN(rq_hash_key(rq))]); 3209817064bSJens Axboe } 3219817064bSJens Axboe 322165125e1SJens Axboe static void elv_rqhash_reposition(struct request_queue *q, struct request *rq) 3239817064bSJens Axboe { 3249817064bSJens Axboe __elv_rqhash_del(rq); 3259817064bSJens Axboe elv_rqhash_add(q, rq); 3269817064bSJens Axboe } 3279817064bSJens Axboe 328165125e1SJens Axboe static struct request *elv_rqhash_find(struct request_queue *q, sector_t offset) 3299817064bSJens Axboe { 330b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 3319817064bSJens Axboe struct hlist_head *hash_list = &e->hash[ELV_HASH_FN(offset)]; 3329817064bSJens Axboe struct hlist_node *entry, *next; 3339817064bSJens Axboe struct request *rq; 3349817064bSJens Axboe 3359817064bSJens Axboe hlist_for_each_entry_safe(rq, entry, next, hash_list, hash) { 3369817064bSJens Axboe BUG_ON(!ELV_ON_HASH(rq)); 3379817064bSJens Axboe 3389817064bSJens Axboe if (unlikely(!rq_mergeable(rq))) { 3399817064bSJens Axboe __elv_rqhash_del(rq); 3409817064bSJens Axboe continue; 3419817064bSJens Axboe } 3429817064bSJens Axboe 3439817064bSJens Axboe if (rq_hash_key(rq) == offset) 3449817064bSJens Axboe return rq; 3459817064bSJens Axboe } 3469817064bSJens Axboe 3479817064bSJens Axboe return NULL; 3489817064bSJens Axboe } 3499817064bSJens Axboe 3508922e16cSTejun Heo /* 3512e662b65SJens Axboe * RB-tree support functions for inserting/lookup/removal of requests 3522e662b65SJens Axboe * in a sorted RB tree. 3532e662b65SJens Axboe */ 3542e662b65SJens Axboe struct request *elv_rb_add(struct rb_root *root, struct request *rq) 3552e662b65SJens Axboe { 3562e662b65SJens Axboe struct rb_node **p = &root->rb_node; 3572e662b65SJens Axboe struct rb_node *parent = NULL; 3582e662b65SJens Axboe struct request *__rq; 3592e662b65SJens Axboe 3602e662b65SJens Axboe while (*p) { 3612e662b65SJens Axboe parent = *p; 3622e662b65SJens Axboe __rq = rb_entry(parent, struct request, rb_node); 3632e662b65SJens Axboe 36483096ebfSTejun Heo if (blk_rq_pos(rq) < blk_rq_pos(__rq)) 3652e662b65SJens Axboe p = &(*p)->rb_left; 36683096ebfSTejun Heo else if (blk_rq_pos(rq) > blk_rq_pos(__rq)) 3672e662b65SJens Axboe p = &(*p)->rb_right; 3682e662b65SJens Axboe else 3692e662b65SJens Axboe return __rq; 3702e662b65SJens Axboe } 3712e662b65SJens Axboe 3722e662b65SJens Axboe rb_link_node(&rq->rb_node, parent, p); 3732e662b65SJens Axboe rb_insert_color(&rq->rb_node, root); 3742e662b65SJens Axboe return NULL; 3752e662b65SJens Axboe } 3762e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_add); 3772e662b65SJens Axboe 3782e662b65SJens Axboe void elv_rb_del(struct rb_root *root, struct request *rq) 3792e662b65SJens Axboe { 3802e662b65SJens Axboe BUG_ON(RB_EMPTY_NODE(&rq->rb_node)); 3812e662b65SJens Axboe rb_erase(&rq->rb_node, root); 3822e662b65SJens Axboe RB_CLEAR_NODE(&rq->rb_node); 3832e662b65SJens Axboe } 3842e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_del); 3852e662b65SJens Axboe 3862e662b65SJens Axboe struct request *elv_rb_find(struct rb_root *root, sector_t sector) 3872e662b65SJens Axboe { 3882e662b65SJens Axboe struct rb_node *n = root->rb_node; 3892e662b65SJens Axboe struct request *rq; 3902e662b65SJens Axboe 3912e662b65SJens Axboe while (n) { 3922e662b65SJens Axboe rq = rb_entry(n, struct request, rb_node); 3932e662b65SJens Axboe 39483096ebfSTejun Heo if (sector < blk_rq_pos(rq)) 3952e662b65SJens Axboe n = n->rb_left; 39683096ebfSTejun Heo else if (sector > blk_rq_pos(rq)) 3972e662b65SJens Axboe n = n->rb_right; 3982e662b65SJens Axboe else 3992e662b65SJens Axboe return rq; 4002e662b65SJens Axboe } 4012e662b65SJens Axboe 4022e662b65SJens Axboe return NULL; 4032e662b65SJens Axboe } 4042e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_find); 4052e662b65SJens Axboe 4062e662b65SJens Axboe /* 4078922e16cSTejun Heo * Insert rq into dispatch queue of q. Queue lock must be held on 408dbe7f76dSUwe Kleine-König * entry. rq is sort instead into the dispatch queue. To be used by 4092e662b65SJens Axboe * specific elevators. 4108922e16cSTejun Heo */ 411165125e1SJens Axboe void elv_dispatch_sort(struct request_queue *q, struct request *rq) 4128922e16cSTejun Heo { 4138922e16cSTejun Heo sector_t boundary; 4148922e16cSTejun Heo struct list_head *entry; 4154eb166d9SJens Axboe int stop_flags; 4168922e16cSTejun Heo 41706b86245STejun Heo if (q->last_merge == rq) 41806b86245STejun Heo q->last_merge = NULL; 4199817064bSJens Axboe 4209817064bSJens Axboe elv_rqhash_del(q, rq); 4219817064bSJens Axboe 42215853af9STejun Heo q->nr_sorted--; 42306b86245STejun Heo 4241b47f531SJens Axboe boundary = q->end_sector; 4254eb166d9SJens Axboe stop_flags = REQ_SOFTBARRIER | REQ_HARDBARRIER | REQ_STARTED; 4268922e16cSTejun Heo list_for_each_prev(entry, &q->queue_head) { 4278922e16cSTejun Heo struct request *pos = list_entry_rq(entry); 4288922e16cSTejun Heo 429e17fc0a1SDavid Woodhouse if (blk_discard_rq(rq) != blk_discard_rq(pos)) 430e17fc0a1SDavid Woodhouse break; 431783660b2SJens Axboe if (rq_data_dir(rq) != rq_data_dir(pos)) 432783660b2SJens Axboe break; 4334eb166d9SJens Axboe if (pos->cmd_flags & stop_flags) 4348922e16cSTejun Heo break; 43583096ebfSTejun Heo if (blk_rq_pos(rq) >= boundary) { 43683096ebfSTejun Heo if (blk_rq_pos(pos) < boundary) 4378922e16cSTejun Heo continue; 4388922e16cSTejun Heo } else { 43983096ebfSTejun Heo if (blk_rq_pos(pos) >= boundary) 4408922e16cSTejun Heo break; 4418922e16cSTejun Heo } 44283096ebfSTejun Heo if (blk_rq_pos(rq) >= blk_rq_pos(pos)) 4438922e16cSTejun Heo break; 4448922e16cSTejun Heo } 4458922e16cSTejun Heo 4468922e16cSTejun Heo list_add(&rq->queuelist, entry); 4478922e16cSTejun Heo } 4482e662b65SJens Axboe EXPORT_SYMBOL(elv_dispatch_sort); 4492e662b65SJens Axboe 4509817064bSJens Axboe /* 4512e662b65SJens Axboe * Insert rq into dispatch queue of q. Queue lock must be held on 4522e662b65SJens Axboe * entry. rq is added to the back of the dispatch queue. To be used by 4532e662b65SJens Axboe * specific elevators. 4549817064bSJens Axboe */ 4559817064bSJens Axboe void elv_dispatch_add_tail(struct request_queue *q, struct request *rq) 4569817064bSJens Axboe { 4579817064bSJens Axboe if (q->last_merge == rq) 4589817064bSJens Axboe q->last_merge = NULL; 4599817064bSJens Axboe 4609817064bSJens Axboe elv_rqhash_del(q, rq); 4619817064bSJens Axboe 4629817064bSJens Axboe q->nr_sorted--; 4639817064bSJens Axboe 4649817064bSJens Axboe q->end_sector = rq_end_sector(rq); 4659817064bSJens Axboe q->boundary_rq = rq; 4669817064bSJens Axboe list_add_tail(&rq->queuelist, &q->queue_head); 4679817064bSJens Axboe } 4682e662b65SJens Axboe EXPORT_SYMBOL(elv_dispatch_add_tail); 4692e662b65SJens Axboe 470165125e1SJens Axboe int elv_merge(struct request_queue *q, struct request **req, struct bio *bio) 4711da177e4SLinus Torvalds { 472b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 4739817064bSJens Axboe struct request *__rq; 47406b86245STejun Heo int ret; 47506b86245STejun Heo 4769817064bSJens Axboe /* 477488991e2SAlan D. Brunelle * Levels of merges: 478488991e2SAlan D. Brunelle * nomerges: No merges at all attempted 479488991e2SAlan D. Brunelle * noxmerges: Only simple one-hit cache try 480488991e2SAlan D. Brunelle * merges: All merge tries attempted 481488991e2SAlan D. Brunelle */ 482488991e2SAlan D. Brunelle if (blk_queue_nomerges(q)) 483488991e2SAlan D. Brunelle return ELEVATOR_NO_MERGE; 484488991e2SAlan D. Brunelle 485488991e2SAlan D. Brunelle /* 4869817064bSJens Axboe * First try one-hit cache. 4879817064bSJens Axboe */ 48806b86245STejun Heo if (q->last_merge) { 48906b86245STejun Heo ret = elv_try_merge(q->last_merge, bio); 49006b86245STejun Heo if (ret != ELEVATOR_NO_MERGE) { 49106b86245STejun Heo *req = q->last_merge; 49206b86245STejun Heo return ret; 49306b86245STejun Heo } 49406b86245STejun Heo } 4951da177e4SLinus Torvalds 496488991e2SAlan D. Brunelle if (blk_queue_noxmerges(q)) 497ac9fafa1SAlan D. Brunelle return ELEVATOR_NO_MERGE; 498ac9fafa1SAlan D. Brunelle 4999817064bSJens Axboe /* 5009817064bSJens Axboe * See if our hash lookup can find a potential backmerge. 5019817064bSJens Axboe */ 5029817064bSJens Axboe __rq = elv_rqhash_find(q, bio->bi_sector); 5039817064bSJens Axboe if (__rq && elv_rq_merge_ok(__rq, bio)) { 5049817064bSJens Axboe *req = __rq; 5059817064bSJens Axboe return ELEVATOR_BACK_MERGE; 5069817064bSJens Axboe } 5079817064bSJens Axboe 5081da177e4SLinus Torvalds if (e->ops->elevator_merge_fn) 5091da177e4SLinus Torvalds return e->ops->elevator_merge_fn(q, req, bio); 5101da177e4SLinus Torvalds 5111da177e4SLinus Torvalds return ELEVATOR_NO_MERGE; 5121da177e4SLinus Torvalds } 5131da177e4SLinus Torvalds 514165125e1SJens Axboe void elv_merged_request(struct request_queue *q, struct request *rq, int type) 5151da177e4SLinus Torvalds { 516b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 5171da177e4SLinus Torvalds 5181da177e4SLinus Torvalds if (e->ops->elevator_merged_fn) 5192e662b65SJens Axboe e->ops->elevator_merged_fn(q, rq, type); 52006b86245STejun Heo 5212e662b65SJens Axboe if (type == ELEVATOR_BACK_MERGE) 5229817064bSJens Axboe elv_rqhash_reposition(q, rq); 5239817064bSJens Axboe 52406b86245STejun Heo q->last_merge = rq; 5251da177e4SLinus Torvalds } 5261da177e4SLinus Torvalds 527165125e1SJens Axboe void elv_merge_requests(struct request_queue *q, struct request *rq, 5281da177e4SLinus Torvalds struct request *next) 5291da177e4SLinus Torvalds { 530b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 5311da177e4SLinus Torvalds 5321da177e4SLinus Torvalds if (e->ops->elevator_merge_req_fn) 5331da177e4SLinus Torvalds e->ops->elevator_merge_req_fn(q, rq, next); 53406b86245STejun Heo 5359817064bSJens Axboe elv_rqhash_reposition(q, rq); 5369817064bSJens Axboe elv_rqhash_del(q, next); 5379817064bSJens Axboe 5389817064bSJens Axboe q->nr_sorted--; 53906b86245STejun Heo q->last_merge = rq; 5401da177e4SLinus Torvalds } 5411da177e4SLinus Torvalds 542812d4026SDivyesh Shah void elv_bio_merged(struct request_queue *q, struct request *rq, 543812d4026SDivyesh Shah struct bio *bio) 544812d4026SDivyesh Shah { 545812d4026SDivyesh Shah struct elevator_queue *e = q->elevator; 546812d4026SDivyesh Shah 547812d4026SDivyesh Shah if (e->ops->elevator_bio_merged_fn) 548812d4026SDivyesh Shah e->ops->elevator_bio_merged_fn(q, rq, bio); 549812d4026SDivyesh Shah } 550812d4026SDivyesh Shah 551165125e1SJens Axboe void elv_requeue_request(struct request_queue *q, struct request *rq) 5521da177e4SLinus Torvalds { 5531da177e4SLinus Torvalds /* 5541da177e4SLinus Torvalds * it already went through dequeue, we need to decrement the 5551da177e4SLinus Torvalds * in_flight count again 5561da177e4SLinus Torvalds */ 5578922e16cSTejun Heo if (blk_account_rq(rq)) { 5580a7ae2ffSJens Axboe q->in_flight[rq_is_sync(rq)]--; 559cad97516SJens Axboe if (blk_sorted_rq(rq)) 560cad97516SJens Axboe elv_deactivate_rq(q, rq); 5611da177e4SLinus Torvalds } 5621da177e4SLinus Torvalds 5634aff5e23SJens Axboe rq->cmd_flags &= ~REQ_STARTED; 5641da177e4SLinus Torvalds 56530e9656cSTejun Heo elv_insert(q, rq, ELEVATOR_INSERT_REQUEUE); 5661da177e4SLinus Torvalds } 5671da177e4SLinus Torvalds 56826308eabSJerome Marchand void elv_drain_elevator(struct request_queue *q) 56915853af9STejun Heo { 57015853af9STejun Heo static int printed; 57115853af9STejun Heo while (q->elevator->ops->elevator_dispatch_fn(q, 1)) 57215853af9STejun Heo ; 57315853af9STejun Heo if (q->nr_sorted == 0) 57415853af9STejun Heo return; 57515853af9STejun Heo if (printed++ < 10) { 57615853af9STejun Heo printk(KERN_ERR "%s: forced dispatching is broken " 57715853af9STejun Heo "(nr_sorted=%u), please report this\n", 57815853af9STejun Heo q->elevator->elevator_type->elevator_name, q->nr_sorted); 57915853af9STejun Heo } 58015853af9STejun Heo } 58115853af9STejun Heo 5826c7e8ceeSJens Axboe /* 5836c7e8ceeSJens Axboe * Call with queue lock held, interrupts disabled 5846c7e8ceeSJens Axboe */ 585f600abe2SJens Axboe void elv_quiesce_start(struct request_queue *q) 5866c7e8ceeSJens Axboe { 587cd43e26fSMartin K. Petersen if (!q->elevator) 588cd43e26fSMartin K. Petersen return; 589cd43e26fSMartin K. Petersen 5906c7e8ceeSJens Axboe queue_flag_set(QUEUE_FLAG_ELVSWITCH, q); 5916c7e8ceeSJens Axboe 5926c7e8ceeSJens Axboe /* 5936c7e8ceeSJens Axboe * make sure we don't have any requests in flight 5946c7e8ceeSJens Axboe */ 5956c7e8ceeSJens Axboe elv_drain_elevator(q); 5966c7e8ceeSJens Axboe while (q->rq.elvpriv) { 597a7f55792STejun Heo __blk_run_queue(q); 5986c7e8ceeSJens Axboe spin_unlock_irq(q->queue_lock); 5996c7e8ceeSJens Axboe msleep(10); 6006c7e8ceeSJens Axboe spin_lock_irq(q->queue_lock); 6016c7e8ceeSJens Axboe elv_drain_elevator(q); 6026c7e8ceeSJens Axboe } 6036c7e8ceeSJens Axboe } 6046c7e8ceeSJens Axboe 605f600abe2SJens Axboe void elv_quiesce_end(struct request_queue *q) 6066c7e8ceeSJens Axboe { 6076c7e8ceeSJens Axboe queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q); 6086c7e8ceeSJens Axboe } 6096c7e8ceeSJens Axboe 610165125e1SJens Axboe void elv_insert(struct request_queue *q, struct request *rq, int where) 6111da177e4SLinus Torvalds { 612797e7dbbSTejun Heo struct list_head *pos; 613797e7dbbSTejun Heo unsigned ordseq; 614dac07ec1SJens Axboe int unplug_it = 1; 615797e7dbbSTejun Heo 6165f3ea37cSArnaldo Carvalho de Melo trace_block_rq_insert(q, rq); 6172056a782SJens Axboe 6181da177e4SLinus Torvalds rq->q = q; 6191da177e4SLinus Torvalds 6208922e16cSTejun Heo switch (where) { 6218922e16cSTejun Heo case ELEVATOR_INSERT_FRONT: 6224aff5e23SJens Axboe rq->cmd_flags |= REQ_SOFTBARRIER; 6238922e16cSTejun Heo 6248922e16cSTejun Heo list_add(&rq->queuelist, &q->queue_head); 6258922e16cSTejun Heo break; 6268922e16cSTejun Heo 6278922e16cSTejun Heo case ELEVATOR_INSERT_BACK: 6284aff5e23SJens Axboe rq->cmd_flags |= REQ_SOFTBARRIER; 62915853af9STejun Heo elv_drain_elevator(q); 6308922e16cSTejun Heo list_add_tail(&rq->queuelist, &q->queue_head); 6318922e16cSTejun Heo /* 6328922e16cSTejun Heo * We kick the queue here for the following reasons. 6338922e16cSTejun Heo * - The elevator might have returned NULL previously 6348922e16cSTejun Heo * to delay requests and returned them now. As the 6358922e16cSTejun Heo * queue wasn't empty before this request, ll_rw_blk 6368922e16cSTejun Heo * won't run the queue on return, resulting in hang. 6378922e16cSTejun Heo * - Usually, back inserted requests won't be merged 6388922e16cSTejun Heo * with anything. There's no point in delaying queue 6398922e16cSTejun Heo * processing. 6408922e16cSTejun Heo */ 641a7f55792STejun Heo __blk_run_queue(q); 6428922e16cSTejun Heo break; 6438922e16cSTejun Heo 6448922e16cSTejun Heo case ELEVATOR_INSERT_SORT: 645e17fc0a1SDavid Woodhouse BUG_ON(!blk_fs_request(rq) && !blk_discard_rq(rq)); 6464aff5e23SJens Axboe rq->cmd_flags |= REQ_SORTED; 64715853af9STejun Heo q->nr_sorted++; 6489817064bSJens Axboe if (rq_mergeable(rq)) { 6499817064bSJens Axboe elv_rqhash_add(q, rq); 6509817064bSJens Axboe if (!q->last_merge) 65106b86245STejun Heo q->last_merge = rq; 6529817064bSJens Axboe } 6539817064bSJens Axboe 654ca23509fSTejun Heo /* 655ca23509fSTejun Heo * Some ioscheds (cfq) run q->request_fn directly, so 656ca23509fSTejun Heo * rq cannot be accessed after calling 657ca23509fSTejun Heo * elevator_add_req_fn. 658ca23509fSTejun Heo */ 659ca23509fSTejun Heo q->elevator->ops->elevator_add_req_fn(q, rq); 6608922e16cSTejun Heo break; 6618922e16cSTejun Heo 662797e7dbbSTejun Heo case ELEVATOR_INSERT_REQUEUE: 663797e7dbbSTejun Heo /* 664797e7dbbSTejun Heo * If ordered flush isn't in progress, we do front 665797e7dbbSTejun Heo * insertion; otherwise, requests should be requeued 666797e7dbbSTejun Heo * in ordseq order. 667797e7dbbSTejun Heo */ 6684aff5e23SJens Axboe rq->cmd_flags |= REQ_SOFTBARRIER; 669797e7dbbSTejun Heo 67095543179SLinas Vepstas /* 67195543179SLinas Vepstas * Most requeues happen because of a busy condition, 67295543179SLinas Vepstas * don't force unplug of the queue for that case. 67395543179SLinas Vepstas */ 67495543179SLinas Vepstas unplug_it = 0; 67595543179SLinas Vepstas 676797e7dbbSTejun Heo if (q->ordseq == 0) { 677797e7dbbSTejun Heo list_add(&rq->queuelist, &q->queue_head); 678797e7dbbSTejun Heo break; 679797e7dbbSTejun Heo } 680797e7dbbSTejun Heo 681797e7dbbSTejun Heo ordseq = blk_ordered_req_seq(rq); 682797e7dbbSTejun Heo 683797e7dbbSTejun Heo list_for_each(pos, &q->queue_head) { 684797e7dbbSTejun Heo struct request *pos_rq = list_entry_rq(pos); 685797e7dbbSTejun Heo if (ordseq <= blk_ordered_req_seq(pos_rq)) 686797e7dbbSTejun Heo break; 687797e7dbbSTejun Heo } 688797e7dbbSTejun Heo 689797e7dbbSTejun Heo list_add_tail(&rq->queuelist, pos); 690797e7dbbSTejun Heo break; 691797e7dbbSTejun Heo 6928922e16cSTejun Heo default: 6938922e16cSTejun Heo printk(KERN_ERR "%s: bad insertion point %d\n", 69424c03d47SHarvey Harrison __func__, where); 6958922e16cSTejun Heo BUG(); 6968922e16cSTejun Heo } 6971da177e4SLinus Torvalds 698dac07ec1SJens Axboe if (unplug_it && blk_queue_plugged(q)) { 6991faa16d2SJens Axboe int nrq = q->rq.count[BLK_RW_SYNC] + q->rq.count[BLK_RW_ASYNC] 7000a7ae2ffSJens Axboe - queue_in_flight(q); 7011da177e4SLinus Torvalds 702c374f127STejun Heo if (nrq >= q->unplug_thresh) 7031da177e4SLinus Torvalds __generic_unplug_device(q); 7041da177e4SLinus Torvalds } 7051da177e4SLinus Torvalds } 7061da177e4SLinus Torvalds 707165125e1SJens Axboe void __elv_add_request(struct request_queue *q, struct request *rq, int where, 70830e9656cSTejun Heo int plug) 70930e9656cSTejun Heo { 71030e9656cSTejun Heo if (q->ordcolor) 7114aff5e23SJens Axboe rq->cmd_flags |= REQ_ORDERED_COLOR; 71230e9656cSTejun Heo 7134aff5e23SJens Axboe if (rq->cmd_flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)) { 71430e9656cSTejun Heo /* 71530e9656cSTejun Heo * toggle ordered color 71630e9656cSTejun Heo */ 71730e9656cSTejun Heo if (blk_barrier_rq(rq)) 71830e9656cSTejun Heo q->ordcolor ^= 1; 71930e9656cSTejun Heo 72030e9656cSTejun Heo /* 72130e9656cSTejun Heo * barriers implicitly indicate back insertion 72230e9656cSTejun Heo */ 72330e9656cSTejun Heo if (where == ELEVATOR_INSERT_SORT) 72430e9656cSTejun Heo where = ELEVATOR_INSERT_BACK; 72530e9656cSTejun Heo 72630e9656cSTejun Heo /* 72730e9656cSTejun Heo * this request is scheduling boundary, update 72830e9656cSTejun Heo * end_sector 72930e9656cSTejun Heo */ 730e17fc0a1SDavid Woodhouse if (blk_fs_request(rq) || blk_discard_rq(rq)) { 73130e9656cSTejun Heo q->end_sector = rq_end_sector(rq); 73230e9656cSTejun Heo q->boundary_rq = rq; 73330e9656cSTejun Heo } 7344eb166d9SJens Axboe } else if (!(rq->cmd_flags & REQ_ELVPRIV) && 7354eb166d9SJens Axboe where == ELEVATOR_INSERT_SORT) 73630e9656cSTejun Heo where = ELEVATOR_INSERT_BACK; 73730e9656cSTejun Heo 73830e9656cSTejun Heo if (plug) 73930e9656cSTejun Heo blk_plug_device(q); 74030e9656cSTejun Heo 74130e9656cSTejun Heo elv_insert(q, rq, where); 74230e9656cSTejun Heo } 7432e662b65SJens Axboe EXPORT_SYMBOL(__elv_add_request); 7442e662b65SJens Axboe 745165125e1SJens Axboe void elv_add_request(struct request_queue *q, struct request *rq, int where, 7461da177e4SLinus Torvalds int plug) 7471da177e4SLinus Torvalds { 7481da177e4SLinus Torvalds unsigned long flags; 7491da177e4SLinus Torvalds 7501da177e4SLinus Torvalds spin_lock_irqsave(q->queue_lock, flags); 7511da177e4SLinus Torvalds __elv_add_request(q, rq, where, plug); 7521da177e4SLinus Torvalds spin_unlock_irqrestore(q->queue_lock, flags); 7531da177e4SLinus Torvalds } 7542e662b65SJens Axboe EXPORT_SYMBOL(elv_add_request); 7552e662b65SJens Axboe 756165125e1SJens Axboe int elv_queue_empty(struct request_queue *q) 7571da177e4SLinus Torvalds { 758b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 7591da177e4SLinus Torvalds 7608922e16cSTejun Heo if (!list_empty(&q->queue_head)) 7618922e16cSTejun Heo return 0; 7628922e16cSTejun Heo 7631da177e4SLinus Torvalds if (e->ops->elevator_queue_empty_fn) 7641da177e4SLinus Torvalds return e->ops->elevator_queue_empty_fn(q); 7651da177e4SLinus Torvalds 7668922e16cSTejun Heo return 1; 7671da177e4SLinus Torvalds } 7682e662b65SJens Axboe EXPORT_SYMBOL(elv_queue_empty); 7692e662b65SJens Axboe 770165125e1SJens Axboe struct request *elv_latter_request(struct request_queue *q, struct request *rq) 7711da177e4SLinus Torvalds { 772b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 7731da177e4SLinus Torvalds 7741da177e4SLinus Torvalds if (e->ops->elevator_latter_req_fn) 7751da177e4SLinus Torvalds return e->ops->elevator_latter_req_fn(q, rq); 7761da177e4SLinus Torvalds return NULL; 7771da177e4SLinus Torvalds } 7781da177e4SLinus Torvalds 779165125e1SJens Axboe struct request *elv_former_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_former_req_fn) 7841da177e4SLinus Torvalds return e->ops->elevator_former_req_fn(q, rq); 7851da177e4SLinus Torvalds return NULL; 7861da177e4SLinus Torvalds } 7871da177e4SLinus Torvalds 788165125e1SJens Axboe int elv_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask) 7891da177e4SLinus Torvalds { 790b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 7911da177e4SLinus Torvalds 7921da177e4SLinus Torvalds if (e->ops->elevator_set_req_fn) 793cb78b285SJens Axboe return e->ops->elevator_set_req_fn(q, rq, gfp_mask); 7941da177e4SLinus Torvalds 7951da177e4SLinus Torvalds rq->elevator_private = NULL; 7961da177e4SLinus Torvalds return 0; 7971da177e4SLinus Torvalds } 7981da177e4SLinus Torvalds 799165125e1SJens Axboe void elv_put_request(struct request_queue *q, struct request *rq) 8001da177e4SLinus Torvalds { 801b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 8021da177e4SLinus Torvalds 8031da177e4SLinus Torvalds if (e->ops->elevator_put_req_fn) 804bb37b94cSJens Axboe e->ops->elevator_put_req_fn(rq); 8051da177e4SLinus Torvalds } 8061da177e4SLinus Torvalds 807165125e1SJens Axboe int elv_may_queue(struct request_queue *q, int rw) 8081da177e4SLinus Torvalds { 809b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 8101da177e4SLinus Torvalds 8111da177e4SLinus Torvalds if (e->ops->elevator_may_queue_fn) 812cb78b285SJens Axboe return e->ops->elevator_may_queue_fn(q, rw); 8131da177e4SLinus Torvalds 8141da177e4SLinus Torvalds return ELV_MQUEUE_MAY; 8151da177e4SLinus Torvalds } 8161da177e4SLinus Torvalds 81711914a53SMike Anderson void elv_abort_queue(struct request_queue *q) 81811914a53SMike Anderson { 81911914a53SMike Anderson struct request *rq; 82011914a53SMike Anderson 82111914a53SMike Anderson while (!list_empty(&q->queue_head)) { 82211914a53SMike Anderson rq = list_entry_rq(q->queue_head.next); 82311914a53SMike Anderson rq->cmd_flags |= REQ_QUIET; 8245f3ea37cSArnaldo Carvalho de Melo trace_block_rq_abort(q, rq); 82553c663ceSKiyoshi Ueda /* 82653c663ceSKiyoshi Ueda * Mark this request as started so we don't trigger 82753c663ceSKiyoshi Ueda * any debug logic in the end I/O path. 82853c663ceSKiyoshi Ueda */ 82953c663ceSKiyoshi Ueda blk_start_request(rq); 83040cbbb78STejun Heo __blk_end_request_all(rq, -EIO); 83111914a53SMike Anderson } 83211914a53SMike Anderson } 83311914a53SMike Anderson EXPORT_SYMBOL(elv_abort_queue); 83411914a53SMike Anderson 835165125e1SJens Axboe void elv_completed_request(struct request_queue *q, struct request *rq) 8361da177e4SLinus Torvalds { 837b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 8381da177e4SLinus Torvalds 8391da177e4SLinus Torvalds /* 8401da177e4SLinus Torvalds * request is released from the driver, io must be done 8411da177e4SLinus Torvalds */ 8428922e16cSTejun Heo if (blk_account_rq(rq)) { 8430a7ae2ffSJens Axboe q->in_flight[rq_is_sync(rq)]--; 8441bc691d3STejun Heo if (blk_sorted_rq(rq) && e->ops->elevator_completed_req_fn) 8451bc691d3STejun Heo e->ops->elevator_completed_req_fn(q, rq); 8461bc691d3STejun Heo } 847797e7dbbSTejun Heo 848797e7dbbSTejun Heo /* 849797e7dbbSTejun Heo * Check if the queue is waiting for fs requests to be 850797e7dbbSTejun Heo * drained for flush sequence. 851797e7dbbSTejun Heo */ 8521bc691d3STejun Heo if (unlikely(q->ordseq)) { 8538f11b3e9STejun Heo struct request *next = NULL; 8548f11b3e9STejun Heo 8558f11b3e9STejun Heo if (!list_empty(&q->queue_head)) 8568f11b3e9STejun Heo next = list_entry_rq(q->queue_head.next); 8578f11b3e9STejun Heo 8580a7ae2ffSJens Axboe if (!queue_in_flight(q) && 859797e7dbbSTejun Heo blk_ordered_cur_seq(q) == QUEUE_ORDSEQ_DRAIN && 8608f11b3e9STejun Heo (!next || blk_ordered_req_seq(next) > QUEUE_ORDSEQ_DRAIN)) { 861797e7dbbSTejun Heo blk_ordered_complete_seq(q, QUEUE_ORDSEQ_DRAIN, 0); 862a7f55792STejun Heo __blk_run_queue(q); 863797e7dbbSTejun Heo } 8641da177e4SLinus Torvalds } 8658922e16cSTejun Heo } 8661da177e4SLinus Torvalds 8673d1ab40fSAl Viro #define to_elv(atr) container_of((atr), struct elv_fs_entry, attr) 8683d1ab40fSAl Viro 8693d1ab40fSAl Viro static ssize_t 8703d1ab40fSAl Viro elv_attr_show(struct kobject *kobj, struct attribute *attr, char *page) 8713d1ab40fSAl Viro { 8723d1ab40fSAl Viro struct elv_fs_entry *entry = to_elv(attr); 873b374d18aSJens Axboe struct elevator_queue *e; 8743d1ab40fSAl Viro ssize_t error; 8753d1ab40fSAl Viro 8763d1ab40fSAl Viro if (!entry->show) 8773d1ab40fSAl Viro return -EIO; 8783d1ab40fSAl Viro 879b374d18aSJens Axboe e = container_of(kobj, struct elevator_queue, kobj); 8803d1ab40fSAl Viro mutex_lock(&e->sysfs_lock); 8813d1ab40fSAl Viro error = e->ops ? entry->show(e, page) : -ENOENT; 8823d1ab40fSAl Viro mutex_unlock(&e->sysfs_lock); 8833d1ab40fSAl Viro return error; 8843d1ab40fSAl Viro } 8853d1ab40fSAl Viro 8863d1ab40fSAl Viro static ssize_t 8873d1ab40fSAl Viro elv_attr_store(struct kobject *kobj, struct attribute *attr, 8883d1ab40fSAl Viro const char *page, size_t length) 8893d1ab40fSAl Viro { 8903d1ab40fSAl Viro struct elv_fs_entry *entry = to_elv(attr); 891b374d18aSJens Axboe struct elevator_queue *e; 8923d1ab40fSAl Viro ssize_t error; 8933d1ab40fSAl Viro 8943d1ab40fSAl Viro if (!entry->store) 8953d1ab40fSAl Viro return -EIO; 8963d1ab40fSAl Viro 897b374d18aSJens Axboe e = container_of(kobj, struct elevator_queue, kobj); 8983d1ab40fSAl Viro mutex_lock(&e->sysfs_lock); 8993d1ab40fSAl Viro error = e->ops ? entry->store(e, page, length) : -ENOENT; 9003d1ab40fSAl Viro mutex_unlock(&e->sysfs_lock); 9013d1ab40fSAl Viro return error; 9023d1ab40fSAl Viro } 9033d1ab40fSAl Viro 90452cf25d0SEmese Revfy static const struct sysfs_ops elv_sysfs_ops = { 9053d1ab40fSAl Viro .show = elv_attr_show, 9063d1ab40fSAl Viro .store = elv_attr_store, 9073d1ab40fSAl Viro }; 9083d1ab40fSAl Viro 9093d1ab40fSAl Viro static struct kobj_type elv_ktype = { 9103d1ab40fSAl Viro .sysfs_ops = &elv_sysfs_ops, 9113d1ab40fSAl Viro .release = elevator_release, 9123d1ab40fSAl Viro }; 9133d1ab40fSAl Viro 9141da177e4SLinus Torvalds int elv_register_queue(struct request_queue *q) 9151da177e4SLinus Torvalds { 916b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 9173d1ab40fSAl Viro int error; 9181da177e4SLinus Torvalds 919b2d6db58SGreg Kroah-Hartman error = kobject_add(&e->kobj, &q->kobj, "%s", "iosched"); 9203d1ab40fSAl Viro if (!error) { 921e572ec7eSAl Viro struct elv_fs_entry *attr = e->elevator_type->elevator_attrs; 9223d1ab40fSAl Viro if (attr) { 923e572ec7eSAl Viro while (attr->attr.name) { 924e572ec7eSAl Viro if (sysfs_create_file(&e->kobj, &attr->attr)) 9253d1ab40fSAl Viro break; 926e572ec7eSAl Viro attr++; 9273d1ab40fSAl Viro } 9283d1ab40fSAl Viro } 9293d1ab40fSAl Viro kobject_uevent(&e->kobj, KOBJ_ADD); 9303d1ab40fSAl Viro } 9313d1ab40fSAl Viro return error; 9321da177e4SLinus Torvalds } 933*01effb0dSMike Snitzer EXPORT_SYMBOL(elv_register_queue); 9341da177e4SLinus Torvalds 935b374d18aSJens Axboe static void __elv_unregister_queue(struct elevator_queue *e) 9361da177e4SLinus Torvalds { 9373d1ab40fSAl Viro kobject_uevent(&e->kobj, KOBJ_REMOVE); 9383d1ab40fSAl Viro kobject_del(&e->kobj); 9391da177e4SLinus Torvalds } 940bc1c1169SJens Axboe 941bc1c1169SJens Axboe void elv_unregister_queue(struct request_queue *q) 942bc1c1169SJens Axboe { 943bc1c1169SJens Axboe if (q) 944bc1c1169SJens Axboe __elv_unregister_queue(q->elevator); 9451da177e4SLinus Torvalds } 946*01effb0dSMike Snitzer EXPORT_SYMBOL(elv_unregister_queue); 9471da177e4SLinus Torvalds 9482fdd82bdSAdrian Bunk void elv_register(struct elevator_type *e) 9491da177e4SLinus Torvalds { 9501ffb96c5SThibaut VARENE char *def = ""; 9512a12dcd7SJens Axboe 9522a12dcd7SJens Axboe spin_lock(&elv_list_lock); 953ce524497SEric Sesterhenn BUG_ON(elevator_find(e->elevator_name)); 9541da177e4SLinus Torvalds list_add_tail(&e->list, &elv_list); 9552a12dcd7SJens Axboe spin_unlock(&elv_list_lock); 9561da177e4SLinus Torvalds 9575f003976SNate Diller if (!strcmp(e->elevator_name, chosen_elevator) || 9585f003976SNate Diller (!*chosen_elevator && 9595f003976SNate Diller !strcmp(e->elevator_name, CONFIG_DEFAULT_IOSCHED))) 9601ffb96c5SThibaut VARENE def = " (default)"; 9611ffb96c5SThibaut VARENE 9624eb166d9SJens Axboe printk(KERN_INFO "io scheduler %s registered%s\n", e->elevator_name, 9634eb166d9SJens Axboe def); 9641da177e4SLinus Torvalds } 9651da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(elv_register); 9661da177e4SLinus Torvalds 9671da177e4SLinus Torvalds void elv_unregister(struct elevator_type *e) 9681da177e4SLinus Torvalds { 96983521d3eSChristoph Hellwig struct task_struct *g, *p; 97083521d3eSChristoph Hellwig 97183521d3eSChristoph Hellwig /* 97283521d3eSChristoph Hellwig * Iterate every thread in the process to remove the io contexts. 97383521d3eSChristoph Hellwig */ 974e17a9489SAl Viro if (e->ops.trim) { 97583521d3eSChristoph Hellwig read_lock(&tasklist_lock); 97683521d3eSChristoph Hellwig do_each_thread(g, p) { 977e17a9489SAl Viro task_lock(p); 9782d8f6131SOleg Nesterov if (p->io_context) 979e17a9489SAl Viro e->ops.trim(p->io_context); 980e17a9489SAl Viro task_unlock(p); 98183521d3eSChristoph Hellwig } while_each_thread(g, p); 98283521d3eSChristoph Hellwig read_unlock(&tasklist_lock); 983e17a9489SAl Viro } 98483521d3eSChristoph Hellwig 9852a12dcd7SJens Axboe spin_lock(&elv_list_lock); 9861da177e4SLinus Torvalds list_del_init(&e->list); 9872a12dcd7SJens Axboe spin_unlock(&elv_list_lock); 9881da177e4SLinus Torvalds } 9891da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(elv_unregister); 9901da177e4SLinus Torvalds 9911da177e4SLinus Torvalds /* 9921da177e4SLinus Torvalds * switch to new_e io scheduler. be careful not to introduce deadlocks - 9931da177e4SLinus Torvalds * we don't free the old io scheduler, before we have allocated what we 9941da177e4SLinus Torvalds * need for the new one. this way we have a chance of going back to the old 995cb98fc8bSTejun Heo * one, if the new one fails init for some reason. 9961da177e4SLinus Torvalds */ 997165125e1SJens Axboe static int elevator_switch(struct request_queue *q, struct elevator_type *new_e) 9981da177e4SLinus Torvalds { 999b374d18aSJens Axboe struct elevator_queue *old_elevator, *e; 1000bc1c1169SJens Axboe void *data; 10011da177e4SLinus Torvalds 1002cb98fc8bSTejun Heo /* 1003cb98fc8bSTejun Heo * Allocate new elevator 1004cb98fc8bSTejun Heo */ 1005b5deef90SJens Axboe e = elevator_alloc(q, new_e); 10061da177e4SLinus Torvalds if (!e) 10073d1ab40fSAl Viro return 0; 10081da177e4SLinus Torvalds 1009bc1c1169SJens Axboe data = elevator_init_queue(q, e); 1010bc1c1169SJens Axboe if (!data) { 1011bc1c1169SJens Axboe kobject_put(&e->kobj); 1012bc1c1169SJens Axboe return 0; 1013bc1c1169SJens Axboe } 1014bc1c1169SJens Axboe 10151da177e4SLinus Torvalds /* 1016cb98fc8bSTejun Heo * Turn on BYPASS and drain all requests w/ elevator private data 10171da177e4SLinus Torvalds */ 1018cb98fc8bSTejun Heo spin_lock_irq(q->queue_lock); 1019f600abe2SJens Axboe elv_quiesce_start(q); 1020cb98fc8bSTejun Heo 10211da177e4SLinus Torvalds /* 1022bc1c1169SJens Axboe * Remember old elevator. 10231da177e4SLinus Torvalds */ 10241da177e4SLinus Torvalds old_elevator = q->elevator; 10251da177e4SLinus Torvalds 10261da177e4SLinus Torvalds /* 10271da177e4SLinus Torvalds * attach and start new elevator 10281da177e4SLinus Torvalds */ 1029bc1c1169SJens Axboe elevator_attach(q, e, data); 1030bc1c1169SJens Axboe 1031bc1c1169SJens Axboe spin_unlock_irq(q->queue_lock); 1032bc1c1169SJens Axboe 1033bc1c1169SJens Axboe __elv_unregister_queue(old_elevator); 10341da177e4SLinus Torvalds 10351da177e4SLinus Torvalds if (elv_register_queue(q)) 10361da177e4SLinus Torvalds goto fail_register; 10371da177e4SLinus Torvalds 10381da177e4SLinus Torvalds /* 1039cb98fc8bSTejun Heo * finally exit old elevator and turn off BYPASS. 10401da177e4SLinus Torvalds */ 10411da177e4SLinus Torvalds elevator_exit(old_elevator); 104275ad23bcSNick Piggin spin_lock_irq(q->queue_lock); 1043f600abe2SJens Axboe elv_quiesce_end(q); 104475ad23bcSNick Piggin spin_unlock_irq(q->queue_lock); 104575ad23bcSNick Piggin 10464722dc52SAlan D. Brunelle blk_add_trace_msg(q, "elv switch: %s", e->elevator_type->elevator_name); 10474722dc52SAlan D. Brunelle 10483d1ab40fSAl Viro return 1; 10491da177e4SLinus Torvalds 10501da177e4SLinus Torvalds fail_register: 10511da177e4SLinus Torvalds /* 10521da177e4SLinus Torvalds * switch failed, exit the new io scheduler and reattach the old 10531da177e4SLinus Torvalds * one again (along with re-adding the sysfs dir) 10541da177e4SLinus Torvalds */ 10551da177e4SLinus Torvalds elevator_exit(e); 10561da177e4SLinus Torvalds q->elevator = old_elevator; 10571da177e4SLinus Torvalds elv_register_queue(q); 105875ad23bcSNick Piggin 105975ad23bcSNick Piggin spin_lock_irq(q->queue_lock); 106075ad23bcSNick Piggin queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q); 106175ad23bcSNick Piggin spin_unlock_irq(q->queue_lock); 106275ad23bcSNick Piggin 10633d1ab40fSAl Viro return 0; 10641da177e4SLinus Torvalds } 10651da177e4SLinus Torvalds 1066165125e1SJens Axboe ssize_t elv_iosched_store(struct request_queue *q, const char *name, 1067165125e1SJens Axboe size_t count) 10681da177e4SLinus Torvalds { 10691da177e4SLinus Torvalds char elevator_name[ELV_NAME_MAX]; 10701da177e4SLinus Torvalds struct elevator_type *e; 10711da177e4SLinus Torvalds 1072cd43e26fSMartin K. Petersen if (!q->elevator) 1073cd43e26fSMartin K. Petersen return count; 1074cd43e26fSMartin K. Petersen 1075ee2e992cSLi Zefan strlcpy(elevator_name, name, sizeof(elevator_name)); 10768c279598SKOSAKI Motohiro e = elevator_get(strstrip(elevator_name)); 10771da177e4SLinus Torvalds if (!e) { 10781da177e4SLinus Torvalds printk(KERN_ERR "elevator: type %s not found\n", elevator_name); 10791da177e4SLinus Torvalds return -EINVAL; 10801da177e4SLinus Torvalds } 10811da177e4SLinus Torvalds 10822ca7d93bSNate Diller if (!strcmp(elevator_name, q->elevator->elevator_type->elevator_name)) { 10832ca7d93bSNate Diller elevator_put(e); 10841da177e4SLinus Torvalds return count; 10852ca7d93bSNate Diller } 10861da177e4SLinus Torvalds 10873d1ab40fSAl Viro if (!elevator_switch(q, e)) 10884eb166d9SJens Axboe printk(KERN_ERR "elevator: switch to %s failed\n", 10894eb166d9SJens Axboe elevator_name); 10901da177e4SLinus Torvalds return count; 10911da177e4SLinus Torvalds } 10921da177e4SLinus Torvalds 1093165125e1SJens Axboe ssize_t elv_iosched_show(struct request_queue *q, char *name) 10941da177e4SLinus Torvalds { 1095b374d18aSJens Axboe struct elevator_queue *e = q->elevator; 1096cd43e26fSMartin K. Petersen struct elevator_type *elv; 109770cee26eSMatthias Kaehlcke struct elevator_type *__e; 10981da177e4SLinus Torvalds int len = 0; 10991da177e4SLinus Torvalds 1100cd43e26fSMartin K. Petersen if (!q->elevator) 1101cd43e26fSMartin K. Petersen return sprintf(name, "none\n"); 1102cd43e26fSMartin K. Petersen 1103cd43e26fSMartin K. Petersen elv = e->elevator_type; 1104cd43e26fSMartin K. Petersen 11052a12dcd7SJens Axboe spin_lock(&elv_list_lock); 110670cee26eSMatthias Kaehlcke list_for_each_entry(__e, &elv_list, list) { 11071da177e4SLinus Torvalds if (!strcmp(elv->elevator_name, __e->elevator_name)) 11081da177e4SLinus Torvalds len += sprintf(name+len, "[%s] ", elv->elevator_name); 11091da177e4SLinus Torvalds else 11101da177e4SLinus Torvalds len += sprintf(name+len, "%s ", __e->elevator_name); 11111da177e4SLinus Torvalds } 11122a12dcd7SJens Axboe spin_unlock(&elv_list_lock); 11131da177e4SLinus Torvalds 11141da177e4SLinus Torvalds len += sprintf(len+name, "\n"); 11151da177e4SLinus Torvalds return len; 11161da177e4SLinus Torvalds } 11171da177e4SLinus Torvalds 1118165125e1SJens Axboe struct request *elv_rb_former_request(struct request_queue *q, 1119165125e1SJens Axboe struct request *rq) 11202e662b65SJens Axboe { 11212e662b65SJens Axboe struct rb_node *rbprev = rb_prev(&rq->rb_node); 11222e662b65SJens Axboe 11232e662b65SJens Axboe if (rbprev) 11242e662b65SJens Axboe return rb_entry_rq(rbprev); 11252e662b65SJens Axboe 11262e662b65SJens Axboe return NULL; 11272e662b65SJens Axboe } 11282e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_former_request); 11292e662b65SJens Axboe 1130165125e1SJens Axboe struct request *elv_rb_latter_request(struct request_queue *q, 1131165125e1SJens Axboe struct request *rq) 11322e662b65SJens Axboe { 11332e662b65SJens Axboe struct rb_node *rbnext = rb_next(&rq->rb_node); 11342e662b65SJens Axboe 11352e662b65SJens Axboe if (rbnext) 11362e662b65SJens Axboe return rb_entry_rq(rbnext); 11372e662b65SJens Axboe 11382e662b65SJens Axboe return NULL; 11392e662b65SJens Axboe } 11402e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_latter_request); 1141