xref: /linux/block/elevator.c (revision 53c663ce0f39ba8e8ef652e400b317bc60ac7f19)
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>
365f3ea37cSArnaldo Carvalho de Melo #include <trace/block.h>
379817064bSJens Axboe #include <linux/hash.h>
380835da67SJens Axboe #include <linux/uaccess.h>
391da177e4SLinus Torvalds 
40242f9dcbSJens Axboe #include "blk.h"
41242f9dcbSJens Axboe 
421da177e4SLinus Torvalds static DEFINE_SPINLOCK(elv_list_lock);
431da177e4SLinus Torvalds static LIST_HEAD(elv_list);
441da177e4SLinus Torvalds 
450bfc2455SIngo Molnar DEFINE_TRACE(block_rq_abort);
460bfc2455SIngo Molnar 
471da177e4SLinus Torvalds /*
489817064bSJens Axboe  * Merge hash stuff.
499817064bSJens Axboe  */
509817064bSJens Axboe static const int elv_hash_shift = 6;
519817064bSJens Axboe #define ELV_HASH_BLOCK(sec)	((sec) >> 3)
524eb166d9SJens Axboe #define ELV_HASH_FN(sec)	\
534eb166d9SJens Axboe 		(hash_long(ELV_HASH_BLOCK((sec)), elv_hash_shift))
549817064bSJens Axboe #define ELV_HASH_ENTRIES	(1 << elv_hash_shift)
5583096ebfSTejun Heo #define rq_hash_key(rq)		(blk_rq_pos(rq) + blk_rq_sectors(rq))
569817064bSJens Axboe 
570bfc2455SIngo Molnar DEFINE_TRACE(block_rq_insert);
580bfc2455SIngo Molnar DEFINE_TRACE(block_rq_issue);
590bfc2455SIngo Molnar 
609817064bSJens Axboe /*
61da775265SJens Axboe  * Query io scheduler to see if the current process issuing bio may be
62da775265SJens Axboe  * merged with rq.
63da775265SJens Axboe  */
64da775265SJens Axboe static int elv_iosched_allow_merge(struct request *rq, struct bio *bio)
65da775265SJens Axboe {
66165125e1SJens Axboe 	struct request_queue *q = rq->q;
67b374d18aSJens Axboe 	struct elevator_queue *e = q->elevator;
68da775265SJens Axboe 
69da775265SJens Axboe 	if (e->ops->elevator_allow_merge_fn)
70da775265SJens Axboe 		return e->ops->elevator_allow_merge_fn(q, rq, bio);
71da775265SJens Axboe 
72da775265SJens Axboe 	return 1;
73da775265SJens Axboe }
74da775265SJens Axboe 
75da775265SJens Axboe /*
761da177e4SLinus Torvalds  * can we safely merge with this request?
771da177e4SLinus Torvalds  */
7872ed0bf6SAdrian Bunk int elv_rq_merge_ok(struct request *rq, struct bio *bio)
791da177e4SLinus Torvalds {
801da177e4SLinus Torvalds 	if (!rq_mergeable(rq))
811da177e4SLinus Torvalds 		return 0;
821da177e4SLinus Torvalds 
831da177e4SLinus Torvalds 	/*
84e17fc0a1SDavid Woodhouse 	 * Don't merge file system requests and discard requests
85e17fc0a1SDavid Woodhouse 	 */
86e17fc0a1SDavid Woodhouse 	if (bio_discard(bio) != bio_discard(rq->bio))
87e17fc0a1SDavid Woodhouse 		return 0;
88e17fc0a1SDavid Woodhouse 
89e17fc0a1SDavid Woodhouse 	/*
901da177e4SLinus Torvalds 	 * different data direction or already started, don't merge
911da177e4SLinus Torvalds 	 */
921da177e4SLinus Torvalds 	if (bio_data_dir(bio) != rq_data_dir(rq))
931da177e4SLinus Torvalds 		return 0;
941da177e4SLinus Torvalds 
951da177e4SLinus Torvalds 	/*
96da775265SJens Axboe 	 * must be same device and not a special request
971da177e4SLinus Torvalds 	 */
98bb4067e3SJens Axboe 	if (rq->rq_disk != bio->bi_bdev->bd_disk || rq->special)
991da177e4SLinus Torvalds 		return 0;
100da775265SJens Axboe 
1017ba1ba12SMartin K. Petersen 	/*
1027ba1ba12SMartin K. Petersen 	 * only merge integrity protected bio into ditto rq
1037ba1ba12SMartin K. Petersen 	 */
1047ba1ba12SMartin K. Petersen 	if (bio_integrity(bio) != blk_integrity_rq(rq))
1057ba1ba12SMartin K. Petersen 		return 0;
1067ba1ba12SMartin K. Petersen 
107da775265SJens Axboe 	if (!elv_iosched_allow_merge(rq, bio))
108da775265SJens Axboe 		return 0;
109da775265SJens Axboe 
110da775265SJens Axboe 	return 1;
1111da177e4SLinus Torvalds }
1121da177e4SLinus Torvalds EXPORT_SYMBOL(elv_rq_merge_ok);
1131da177e4SLinus Torvalds 
114769db45bSCoywolf Qi Hunt static inline int elv_try_merge(struct request *__rq, struct bio *bio)
1151da177e4SLinus Torvalds {
1161da177e4SLinus Torvalds 	int ret = ELEVATOR_NO_MERGE;
1171da177e4SLinus Torvalds 
1181da177e4SLinus Torvalds 	/*
1191da177e4SLinus Torvalds 	 * we can merge and sequence is ok, check if it's possible
1201da177e4SLinus Torvalds 	 */
1211da177e4SLinus Torvalds 	if (elv_rq_merge_ok(__rq, bio)) {
12283096ebfSTejun Heo 		if (blk_rq_pos(__rq) + blk_rq_sectors(__rq) == bio->bi_sector)
1231da177e4SLinus Torvalds 			ret = ELEVATOR_BACK_MERGE;
12483096ebfSTejun Heo 		else if (blk_rq_pos(__rq) - bio_sectors(bio) == bio->bi_sector)
1251da177e4SLinus Torvalds 			ret = ELEVATOR_FRONT_MERGE;
1261da177e4SLinus Torvalds 	}
1271da177e4SLinus Torvalds 
1281da177e4SLinus Torvalds 	return ret;
1291da177e4SLinus Torvalds }
1301da177e4SLinus Torvalds 
1311da177e4SLinus Torvalds static struct elevator_type *elevator_find(const char *name)
1321da177e4SLinus Torvalds {
133a22b169dSVasily Tarasov 	struct elevator_type *e;
1341da177e4SLinus Torvalds 
13570cee26eSMatthias Kaehlcke 	list_for_each_entry(e, &elv_list, list) {
136a22b169dSVasily Tarasov 		if (!strcmp(e->elevator_name, name))
1371da177e4SLinus Torvalds 			return e;
1381da177e4SLinus Torvalds 	}
1391da177e4SLinus Torvalds 
140a22b169dSVasily Tarasov 	return NULL;
141a22b169dSVasily Tarasov }
142a22b169dSVasily Tarasov 
1431da177e4SLinus Torvalds static void elevator_put(struct elevator_type *e)
1441da177e4SLinus Torvalds {
1451da177e4SLinus Torvalds 	module_put(e->elevator_owner);
1461da177e4SLinus Torvalds }
1471da177e4SLinus Torvalds 
1481da177e4SLinus Torvalds static struct elevator_type *elevator_get(const char *name)
1491da177e4SLinus Torvalds {
1502824bc93STejun Heo 	struct elevator_type *e;
1511da177e4SLinus Torvalds 
1522a12dcd7SJens Axboe 	spin_lock(&elv_list_lock);
1532824bc93STejun Heo 
1542824bc93STejun Heo 	e = elevator_find(name);
155e1640949SJens Axboe 	if (!e) {
156e1640949SJens Axboe 		char elv[ELV_NAME_MAX + strlen("-iosched")];
157e1640949SJens Axboe 
158e1640949SJens Axboe 		spin_unlock(&elv_list_lock);
159e1640949SJens Axboe 
160e1640949SJens Axboe 		if (!strcmp(name, "anticipatory"))
161e1640949SJens Axboe 			sprintf(elv, "as-iosched");
162e1640949SJens Axboe 		else
163e1640949SJens Axboe 			sprintf(elv, "%s-iosched", name);
164e1640949SJens Axboe 
165e180f594Smaximilian attems 		request_module("%s", elv);
166e1640949SJens Axboe 		spin_lock(&elv_list_lock);
167e1640949SJens Axboe 		e = elevator_find(name);
168e1640949SJens Axboe 	}
169e1640949SJens Axboe 
1702824bc93STejun Heo 	if (e && !try_module_get(e->elevator_owner))
1712824bc93STejun Heo 		e = NULL;
1722824bc93STejun Heo 
1732a12dcd7SJens Axboe 	spin_unlock(&elv_list_lock);
1741da177e4SLinus Torvalds 
1751da177e4SLinus Torvalds 	return e;
1761da177e4SLinus Torvalds }
1771da177e4SLinus Torvalds 
178165125e1SJens Axboe static void *elevator_init_queue(struct request_queue *q,
179165125e1SJens Axboe 				 struct elevator_queue *eq)
1801da177e4SLinus Torvalds {
181bb37b94cSJens Axboe 	return eq->ops->elevator_init_fn(q);
182bc1c1169SJens Axboe }
1831da177e4SLinus Torvalds 
184165125e1SJens Axboe static void elevator_attach(struct request_queue *q, struct elevator_queue *eq,
185bc1c1169SJens Axboe 			   void *data)
186bc1c1169SJens Axboe {
1871da177e4SLinus Torvalds 	q->elevator = eq;
188bc1c1169SJens Axboe 	eq->elevator_data = data;
1891da177e4SLinus Torvalds }
1901da177e4SLinus Torvalds 
1911da177e4SLinus Torvalds static char chosen_elevator[16];
1921da177e4SLinus Torvalds 
1935f003976SNate Diller static int __init elevator_setup(char *str)
1941da177e4SLinus Torvalds {
195752a3b79SChuck Ebbert 	/*
196752a3b79SChuck Ebbert 	 * Be backwards-compatible with previous kernels, so users
197752a3b79SChuck Ebbert 	 * won't get the wrong elevator.
198752a3b79SChuck Ebbert 	 */
1995f003976SNate Diller 	if (!strcmp(str, "as"))
200752a3b79SChuck Ebbert 		strcpy(chosen_elevator, "anticipatory");
201cff3ba22SZachary Amsden 	else
2021da177e4SLinus Torvalds 		strncpy(chosen_elevator, str, sizeof(chosen_elevator) - 1);
2039b41046cSOGAWA Hirofumi 	return 1;
2041da177e4SLinus Torvalds }
2051da177e4SLinus Torvalds 
2061da177e4SLinus Torvalds __setup("elevator=", elevator_setup);
2071da177e4SLinus Torvalds 
2083d1ab40fSAl Viro static struct kobj_type elv_ktype;
2093d1ab40fSAl Viro 
210b374d18aSJens Axboe static struct elevator_queue *elevator_alloc(struct request_queue *q,
211165125e1SJens Axboe 				  struct elevator_type *e)
2123d1ab40fSAl Viro {
213b374d18aSJens Axboe 	struct elevator_queue *eq;
2149817064bSJens Axboe 	int i;
2159817064bSJens Axboe 
216b374d18aSJens Axboe 	eq = kmalloc_node(sizeof(*eq), GFP_KERNEL | __GFP_ZERO, q->node);
2179817064bSJens Axboe 	if (unlikely(!eq))
2189817064bSJens Axboe 		goto err;
2199817064bSJens Axboe 
2203d1ab40fSAl Viro 	eq->ops = &e->ops;
2213d1ab40fSAl Viro 	eq->elevator_type = e;
222f9cb074bSGreg Kroah-Hartman 	kobject_init(&eq->kobj, &elv_ktype);
2233d1ab40fSAl Viro 	mutex_init(&eq->sysfs_lock);
2249817064bSJens Axboe 
225b5deef90SJens Axboe 	eq->hash = kmalloc_node(sizeof(struct hlist_head) * ELV_HASH_ENTRIES,
226b5deef90SJens Axboe 					GFP_KERNEL, q->node);
2279817064bSJens Axboe 	if (!eq->hash)
2289817064bSJens Axboe 		goto err;
2299817064bSJens Axboe 
2309817064bSJens Axboe 	for (i = 0; i < ELV_HASH_ENTRIES; i++)
2319817064bSJens Axboe 		INIT_HLIST_HEAD(&eq->hash[i]);
2329817064bSJens Axboe 
2333d1ab40fSAl Viro 	return eq;
2349817064bSJens Axboe err:
2359817064bSJens Axboe 	kfree(eq);
2369817064bSJens Axboe 	elevator_put(e);
2379817064bSJens Axboe 	return NULL;
2383d1ab40fSAl Viro }
2393d1ab40fSAl Viro 
2403d1ab40fSAl Viro static void elevator_release(struct kobject *kobj)
2413d1ab40fSAl Viro {
242b374d18aSJens Axboe 	struct elevator_queue *e;
2439817064bSJens Axboe 
244b374d18aSJens Axboe 	e = container_of(kobj, struct elevator_queue, kobj);
2453d1ab40fSAl Viro 	elevator_put(e->elevator_type);
2469817064bSJens Axboe 	kfree(e->hash);
2473d1ab40fSAl Viro 	kfree(e);
2483d1ab40fSAl Viro }
2493d1ab40fSAl Viro 
250165125e1SJens Axboe int elevator_init(struct request_queue *q, char *name)
2511da177e4SLinus Torvalds {
2521da177e4SLinus Torvalds 	struct elevator_type *e = NULL;
2531da177e4SLinus Torvalds 	struct elevator_queue *eq;
2541da177e4SLinus Torvalds 	int ret = 0;
255bc1c1169SJens Axboe 	void *data;
2561da177e4SLinus Torvalds 
257cb98fc8bSTejun Heo 	INIT_LIST_HEAD(&q->queue_head);
258cb98fc8bSTejun Heo 	q->last_merge = NULL;
259cb98fc8bSTejun Heo 	q->end_sector = 0;
260cb98fc8bSTejun Heo 	q->boundary_rq = NULL;
261cb98fc8bSTejun Heo 
2624eb166d9SJens Axboe 	if (name) {
2634eb166d9SJens Axboe 		e = elevator_get(name);
2644eb166d9SJens Axboe 		if (!e)
2651da177e4SLinus Torvalds 			return -EINVAL;
2664eb166d9SJens Axboe 	}
2671da177e4SLinus Torvalds 
2684eb166d9SJens Axboe 	if (!e && *chosen_elevator) {
2694eb166d9SJens Axboe 		e = elevator_get(chosen_elevator);
2704eb166d9SJens Axboe 		if (!e)
2714eb166d9SJens Axboe 			printk(KERN_ERR "I/O scheduler %s not found\n",
2724eb166d9SJens Axboe 							chosen_elevator);
2734eb166d9SJens Axboe 	}
274248d5ca5SNate Diller 
2754eb166d9SJens Axboe 	if (!e) {
2764eb166d9SJens Axboe 		e = elevator_get(CONFIG_DEFAULT_IOSCHED);
2774eb166d9SJens Axboe 		if (!e) {
2784eb166d9SJens Axboe 			printk(KERN_ERR
2794eb166d9SJens Axboe 				"Default I/O scheduler not found. " \
2804eb166d9SJens Axboe 				"Using noop.\n");
281248d5ca5SNate Diller 			e = elevator_get("noop");
2825f003976SNate Diller 		}
2834eb166d9SJens Axboe 	}
2845f003976SNate Diller 
285b5deef90SJens Axboe 	eq = elevator_alloc(q, e);
2863d1ab40fSAl Viro 	if (!eq)
2871da177e4SLinus Torvalds 		return -ENOMEM;
2881da177e4SLinus Torvalds 
289bc1c1169SJens Axboe 	data = elevator_init_queue(q, eq);
290bc1c1169SJens Axboe 	if (!data) {
2913d1ab40fSAl Viro 		kobject_put(&eq->kobj);
292bc1c1169SJens Axboe 		return -ENOMEM;
293bc1c1169SJens Axboe 	}
2941da177e4SLinus Torvalds 
295bc1c1169SJens Axboe 	elevator_attach(q, eq, data);
2961da177e4SLinus Torvalds 	return ret;
2971da177e4SLinus Torvalds }
2982e662b65SJens Axboe EXPORT_SYMBOL(elevator_init);
2992e662b65SJens Axboe 
300b374d18aSJens Axboe void elevator_exit(struct elevator_queue *e)
3011da177e4SLinus Torvalds {
3023d1ab40fSAl Viro 	mutex_lock(&e->sysfs_lock);
3031da177e4SLinus Torvalds 	if (e->ops->elevator_exit_fn)
3041da177e4SLinus Torvalds 		e->ops->elevator_exit_fn(e);
3053d1ab40fSAl Viro 	e->ops = NULL;
3063d1ab40fSAl Viro 	mutex_unlock(&e->sysfs_lock);
3071da177e4SLinus Torvalds 
3083d1ab40fSAl Viro 	kobject_put(&e->kobj);
3091da177e4SLinus Torvalds }
3102e662b65SJens Axboe EXPORT_SYMBOL(elevator_exit);
3112e662b65SJens Axboe 
3129817064bSJens Axboe static inline void __elv_rqhash_del(struct request *rq)
3139817064bSJens Axboe {
3149817064bSJens Axboe 	hlist_del_init(&rq->hash);
3159817064bSJens Axboe }
3169817064bSJens Axboe 
317165125e1SJens Axboe static void elv_rqhash_del(struct request_queue *q, struct request *rq)
3189817064bSJens Axboe {
3199817064bSJens Axboe 	if (ELV_ON_HASH(rq))
3209817064bSJens Axboe 		__elv_rqhash_del(rq);
3219817064bSJens Axboe }
3229817064bSJens Axboe 
323165125e1SJens Axboe static void elv_rqhash_add(struct request_queue *q, struct request *rq)
3249817064bSJens Axboe {
325b374d18aSJens Axboe 	struct elevator_queue *e = q->elevator;
3269817064bSJens Axboe 
3279817064bSJens Axboe 	BUG_ON(ELV_ON_HASH(rq));
3289817064bSJens Axboe 	hlist_add_head(&rq->hash, &e->hash[ELV_HASH_FN(rq_hash_key(rq))]);
3299817064bSJens Axboe }
3309817064bSJens Axboe 
331165125e1SJens Axboe static void elv_rqhash_reposition(struct request_queue *q, struct request *rq)
3329817064bSJens Axboe {
3339817064bSJens Axboe 	__elv_rqhash_del(rq);
3349817064bSJens Axboe 	elv_rqhash_add(q, rq);
3359817064bSJens Axboe }
3369817064bSJens Axboe 
337165125e1SJens Axboe static struct request *elv_rqhash_find(struct request_queue *q, sector_t offset)
3389817064bSJens Axboe {
339b374d18aSJens Axboe 	struct elevator_queue *e = q->elevator;
3409817064bSJens Axboe 	struct hlist_head *hash_list = &e->hash[ELV_HASH_FN(offset)];
3419817064bSJens Axboe 	struct hlist_node *entry, *next;
3429817064bSJens Axboe 	struct request *rq;
3439817064bSJens Axboe 
3449817064bSJens Axboe 	hlist_for_each_entry_safe(rq, entry, next, hash_list, hash) {
3459817064bSJens Axboe 		BUG_ON(!ELV_ON_HASH(rq));
3469817064bSJens Axboe 
3479817064bSJens Axboe 		if (unlikely(!rq_mergeable(rq))) {
3489817064bSJens Axboe 			__elv_rqhash_del(rq);
3499817064bSJens Axboe 			continue;
3509817064bSJens Axboe 		}
3519817064bSJens Axboe 
3529817064bSJens Axboe 		if (rq_hash_key(rq) == offset)
3539817064bSJens Axboe 			return rq;
3549817064bSJens Axboe 	}
3559817064bSJens Axboe 
3569817064bSJens Axboe 	return NULL;
3579817064bSJens Axboe }
3589817064bSJens Axboe 
3598922e16cSTejun Heo /*
3602e662b65SJens Axboe  * RB-tree support functions for inserting/lookup/removal of requests
3612e662b65SJens Axboe  * in a sorted RB tree.
3622e662b65SJens Axboe  */
3632e662b65SJens Axboe struct request *elv_rb_add(struct rb_root *root, struct request *rq)
3642e662b65SJens Axboe {
3652e662b65SJens Axboe 	struct rb_node **p = &root->rb_node;
3662e662b65SJens Axboe 	struct rb_node *parent = NULL;
3672e662b65SJens Axboe 	struct request *__rq;
3682e662b65SJens Axboe 
3692e662b65SJens Axboe 	while (*p) {
3702e662b65SJens Axboe 		parent = *p;
3712e662b65SJens Axboe 		__rq = rb_entry(parent, struct request, rb_node);
3722e662b65SJens Axboe 
37383096ebfSTejun Heo 		if (blk_rq_pos(rq) < blk_rq_pos(__rq))
3742e662b65SJens Axboe 			p = &(*p)->rb_left;
37583096ebfSTejun Heo 		else if (blk_rq_pos(rq) > blk_rq_pos(__rq))
3762e662b65SJens Axboe 			p = &(*p)->rb_right;
3772e662b65SJens Axboe 		else
3782e662b65SJens Axboe 			return __rq;
3792e662b65SJens Axboe 	}
3802e662b65SJens Axboe 
3812e662b65SJens Axboe 	rb_link_node(&rq->rb_node, parent, p);
3822e662b65SJens Axboe 	rb_insert_color(&rq->rb_node, root);
3832e662b65SJens Axboe 	return NULL;
3842e662b65SJens Axboe }
3852e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_add);
3862e662b65SJens Axboe 
3872e662b65SJens Axboe void elv_rb_del(struct rb_root *root, struct request *rq)
3882e662b65SJens Axboe {
3892e662b65SJens Axboe 	BUG_ON(RB_EMPTY_NODE(&rq->rb_node));
3902e662b65SJens Axboe 	rb_erase(&rq->rb_node, root);
3912e662b65SJens Axboe 	RB_CLEAR_NODE(&rq->rb_node);
3922e662b65SJens Axboe }
3932e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_del);
3942e662b65SJens Axboe 
3952e662b65SJens Axboe struct request *elv_rb_find(struct rb_root *root, sector_t sector)
3962e662b65SJens Axboe {
3972e662b65SJens Axboe 	struct rb_node *n = root->rb_node;
3982e662b65SJens Axboe 	struct request *rq;
3992e662b65SJens Axboe 
4002e662b65SJens Axboe 	while (n) {
4012e662b65SJens Axboe 		rq = rb_entry(n, struct request, rb_node);
4022e662b65SJens Axboe 
40383096ebfSTejun Heo 		if (sector < blk_rq_pos(rq))
4042e662b65SJens Axboe 			n = n->rb_left;
40583096ebfSTejun Heo 		else if (sector > blk_rq_pos(rq))
4062e662b65SJens Axboe 			n = n->rb_right;
4072e662b65SJens Axboe 		else
4082e662b65SJens Axboe 			return rq;
4092e662b65SJens Axboe 	}
4102e662b65SJens Axboe 
4112e662b65SJens Axboe 	return NULL;
4122e662b65SJens Axboe }
4132e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_find);
4142e662b65SJens Axboe 
4152e662b65SJens Axboe /*
4168922e16cSTejun Heo  * Insert rq into dispatch queue of q.  Queue lock must be held on
417dbe7f76dSUwe Kleine-König  * entry.  rq is sort instead into the dispatch queue. To be used by
4182e662b65SJens Axboe  * specific elevators.
4198922e16cSTejun Heo  */
420165125e1SJens Axboe void elv_dispatch_sort(struct request_queue *q, struct request *rq)
4218922e16cSTejun Heo {
4228922e16cSTejun Heo 	sector_t boundary;
4238922e16cSTejun Heo 	struct list_head *entry;
4244eb166d9SJens Axboe 	int stop_flags;
4258922e16cSTejun Heo 
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;
4344eb166d9SJens Axboe 	stop_flags = REQ_SOFTBARRIER | REQ_HARDBARRIER | REQ_STARTED;
4358922e16cSTejun Heo 	list_for_each_prev(entry, &q->queue_head) {
4368922e16cSTejun Heo 		struct request *pos = list_entry_rq(entry);
4378922e16cSTejun Heo 
438e17fc0a1SDavid Woodhouse 		if (blk_discard_rq(rq) != blk_discard_rq(pos))
439e17fc0a1SDavid Woodhouse 			break;
440783660b2SJens Axboe 		if (rq_data_dir(rq) != rq_data_dir(pos))
441783660b2SJens Axboe 			break;
4424eb166d9SJens Axboe 		if (pos->cmd_flags & stop_flags)
4438922e16cSTejun Heo 			break;
44483096ebfSTejun Heo 		if (blk_rq_pos(rq) >= boundary) {
44583096ebfSTejun Heo 			if (blk_rq_pos(pos) < boundary)
4468922e16cSTejun Heo 				continue;
4478922e16cSTejun Heo 		} else {
44883096ebfSTejun Heo 			if (blk_rq_pos(pos) >= boundary)
4498922e16cSTejun Heo 				break;
4508922e16cSTejun Heo 		}
45183096ebfSTejun Heo 		if (blk_rq_pos(rq) >= blk_rq_pos(pos))
4528922e16cSTejun Heo 			break;
4538922e16cSTejun Heo 	}
4548922e16cSTejun Heo 
4558922e16cSTejun Heo 	list_add(&rq->queuelist, entry);
4568922e16cSTejun Heo }
4572e662b65SJens Axboe EXPORT_SYMBOL(elv_dispatch_sort);
4582e662b65SJens Axboe 
4599817064bSJens Axboe /*
4602e662b65SJens Axboe  * Insert rq into dispatch queue of q.  Queue lock must be held on
4612e662b65SJens Axboe  * entry.  rq is added to the back of the dispatch queue. To be used by
4622e662b65SJens Axboe  * specific elevators.
4639817064bSJens Axboe  */
4649817064bSJens Axboe void elv_dispatch_add_tail(struct request_queue *q, struct request *rq)
4659817064bSJens Axboe {
4669817064bSJens Axboe 	if (q->last_merge == rq)
4679817064bSJens Axboe 		q->last_merge = NULL;
4689817064bSJens Axboe 
4699817064bSJens Axboe 	elv_rqhash_del(q, rq);
4709817064bSJens Axboe 
4719817064bSJens Axboe 	q->nr_sorted--;
4729817064bSJens Axboe 
4739817064bSJens Axboe 	q->end_sector = rq_end_sector(rq);
4749817064bSJens Axboe 	q->boundary_rq = rq;
4759817064bSJens Axboe 	list_add_tail(&rq->queuelist, &q->queue_head);
4769817064bSJens Axboe }
4772e662b65SJens Axboe EXPORT_SYMBOL(elv_dispatch_add_tail);
4782e662b65SJens Axboe 
479165125e1SJens Axboe int elv_merge(struct request_queue *q, struct request **req, struct bio *bio)
4801da177e4SLinus Torvalds {
481b374d18aSJens Axboe 	struct elevator_queue *e = q->elevator;
4829817064bSJens Axboe 	struct request *__rq;
48306b86245STejun Heo 	int ret;
48406b86245STejun Heo 
4859817064bSJens Axboe 	/*
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 
496ac9fafa1SAlan D. Brunelle 	if (blk_queue_nomerges(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 
542165125e1SJens Axboe void elv_requeue_request(struct request_queue *q, struct request *rq)
5431da177e4SLinus Torvalds {
5441da177e4SLinus Torvalds 	/*
5451da177e4SLinus Torvalds 	 * it already went through dequeue, we need to decrement the
5461da177e4SLinus Torvalds 	 * in_flight count again
5471da177e4SLinus Torvalds 	 */
5488922e16cSTejun Heo 	if (blk_account_rq(rq)) {
5490a7ae2ffSJens Axboe 		q->in_flight[rq_is_sync(rq)]--;
550cad97516SJens Axboe 		if (blk_sorted_rq(rq))
551cad97516SJens Axboe 			elv_deactivate_rq(q, rq);
5521da177e4SLinus Torvalds 	}
5531da177e4SLinus Torvalds 
5544aff5e23SJens Axboe 	rq->cmd_flags &= ~REQ_STARTED;
5551da177e4SLinus Torvalds 
55630e9656cSTejun Heo 	elv_insert(q, rq, ELEVATOR_INSERT_REQUEUE);
5571da177e4SLinus Torvalds }
5581da177e4SLinus Torvalds 
55926308eabSJerome Marchand void elv_drain_elevator(struct request_queue *q)
56015853af9STejun Heo {
56115853af9STejun Heo 	static int printed;
56215853af9STejun Heo 	while (q->elevator->ops->elevator_dispatch_fn(q, 1))
56315853af9STejun Heo 		;
56415853af9STejun Heo 	if (q->nr_sorted == 0)
56515853af9STejun Heo 		return;
56615853af9STejun Heo 	if (printed++ < 10) {
56715853af9STejun Heo 		printk(KERN_ERR "%s: forced dispatching is broken "
56815853af9STejun Heo 		       "(nr_sorted=%u), please report this\n",
56915853af9STejun Heo 		       q->elevator->elevator_type->elevator_name, q->nr_sorted);
57015853af9STejun Heo 	}
57115853af9STejun Heo }
57215853af9STejun Heo 
5736c7e8ceeSJens Axboe /*
5746c7e8ceeSJens Axboe  * Call with queue lock held, interrupts disabled
5756c7e8ceeSJens Axboe  */
576f600abe2SJens Axboe void elv_quiesce_start(struct request_queue *q)
5776c7e8ceeSJens Axboe {
578cd43e26fSMartin K. Petersen 	if (!q->elevator)
579cd43e26fSMartin K. Petersen 		return;
580cd43e26fSMartin K. Petersen 
5816c7e8ceeSJens Axboe 	queue_flag_set(QUEUE_FLAG_ELVSWITCH, q);
5826c7e8ceeSJens Axboe 
5836c7e8ceeSJens Axboe 	/*
5846c7e8ceeSJens Axboe 	 * make sure we don't have any requests in flight
5856c7e8ceeSJens Axboe 	 */
5866c7e8ceeSJens Axboe 	elv_drain_elevator(q);
5876c7e8ceeSJens Axboe 	while (q->rq.elvpriv) {
588a7f55792STejun Heo 		__blk_run_queue(q);
5896c7e8ceeSJens Axboe 		spin_unlock_irq(q->queue_lock);
5906c7e8ceeSJens Axboe 		msleep(10);
5916c7e8ceeSJens Axboe 		spin_lock_irq(q->queue_lock);
5926c7e8ceeSJens Axboe 		elv_drain_elevator(q);
5936c7e8ceeSJens Axboe 	}
5946c7e8ceeSJens Axboe }
5956c7e8ceeSJens Axboe 
596f600abe2SJens Axboe void elv_quiesce_end(struct request_queue *q)
5976c7e8ceeSJens Axboe {
5986c7e8ceeSJens Axboe 	queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q);
5996c7e8ceeSJens Axboe }
6006c7e8ceeSJens Axboe 
601165125e1SJens Axboe void elv_insert(struct request_queue *q, struct request *rq, int where)
6021da177e4SLinus Torvalds {
603797e7dbbSTejun Heo 	struct list_head *pos;
604797e7dbbSTejun Heo 	unsigned ordseq;
605dac07ec1SJens Axboe 	int unplug_it = 1;
606797e7dbbSTejun Heo 
6075f3ea37cSArnaldo Carvalho de Melo 	trace_block_rq_insert(q, rq);
6082056a782SJens Axboe 
6091da177e4SLinus Torvalds 	rq->q = q;
6101da177e4SLinus Torvalds 
6118922e16cSTejun Heo 	switch (where) {
6128922e16cSTejun Heo 	case ELEVATOR_INSERT_FRONT:
6134aff5e23SJens Axboe 		rq->cmd_flags |= REQ_SOFTBARRIER;
6148922e16cSTejun Heo 
6158922e16cSTejun Heo 		list_add(&rq->queuelist, &q->queue_head);
6168922e16cSTejun Heo 		break;
6178922e16cSTejun Heo 
6188922e16cSTejun Heo 	case ELEVATOR_INSERT_BACK:
6194aff5e23SJens Axboe 		rq->cmd_flags |= REQ_SOFTBARRIER;
62015853af9STejun Heo 		elv_drain_elevator(q);
6218922e16cSTejun Heo 		list_add_tail(&rq->queuelist, &q->queue_head);
6228922e16cSTejun Heo 		/*
6238922e16cSTejun Heo 		 * We kick the queue here for the following reasons.
6248922e16cSTejun Heo 		 * - The elevator might have returned NULL previously
6258922e16cSTejun Heo 		 *   to delay requests and returned them now.  As the
6268922e16cSTejun Heo 		 *   queue wasn't empty before this request, ll_rw_blk
6278922e16cSTejun Heo 		 *   won't run the queue on return, resulting in hang.
6288922e16cSTejun Heo 		 * - Usually, back inserted requests won't be merged
6298922e16cSTejun Heo 		 *   with anything.  There's no point in delaying queue
6308922e16cSTejun Heo 		 *   processing.
6318922e16cSTejun Heo 		 */
632a7f55792STejun Heo 		__blk_run_queue(q);
6338922e16cSTejun Heo 		break;
6348922e16cSTejun Heo 
6358922e16cSTejun Heo 	case ELEVATOR_INSERT_SORT:
636e17fc0a1SDavid Woodhouse 		BUG_ON(!blk_fs_request(rq) && !blk_discard_rq(rq));
6374aff5e23SJens Axboe 		rq->cmd_flags |= REQ_SORTED;
63815853af9STejun Heo 		q->nr_sorted++;
6399817064bSJens Axboe 		if (rq_mergeable(rq)) {
6409817064bSJens Axboe 			elv_rqhash_add(q, rq);
6419817064bSJens Axboe 			if (!q->last_merge)
64206b86245STejun Heo 				q->last_merge = rq;
6439817064bSJens Axboe 		}
6449817064bSJens Axboe 
645ca23509fSTejun Heo 		/*
646ca23509fSTejun Heo 		 * Some ioscheds (cfq) run q->request_fn directly, so
647ca23509fSTejun Heo 		 * rq cannot be accessed after calling
648ca23509fSTejun Heo 		 * elevator_add_req_fn.
649ca23509fSTejun Heo 		 */
650ca23509fSTejun Heo 		q->elevator->ops->elevator_add_req_fn(q, rq);
6518922e16cSTejun Heo 		break;
6528922e16cSTejun Heo 
653797e7dbbSTejun Heo 	case ELEVATOR_INSERT_REQUEUE:
654797e7dbbSTejun Heo 		/*
655797e7dbbSTejun Heo 		 * If ordered flush isn't in progress, we do front
656797e7dbbSTejun Heo 		 * insertion; otherwise, requests should be requeued
657797e7dbbSTejun Heo 		 * in ordseq order.
658797e7dbbSTejun Heo 		 */
6594aff5e23SJens Axboe 		rq->cmd_flags |= REQ_SOFTBARRIER;
660797e7dbbSTejun Heo 
66195543179SLinas Vepstas 		/*
66295543179SLinas Vepstas 		 * Most requeues happen because of a busy condition,
66395543179SLinas Vepstas 		 * don't force unplug of the queue for that case.
66495543179SLinas Vepstas 		 */
66595543179SLinas Vepstas 		unplug_it = 0;
66695543179SLinas Vepstas 
667797e7dbbSTejun Heo 		if (q->ordseq == 0) {
668797e7dbbSTejun Heo 			list_add(&rq->queuelist, &q->queue_head);
669797e7dbbSTejun Heo 			break;
670797e7dbbSTejun Heo 		}
671797e7dbbSTejun Heo 
672797e7dbbSTejun Heo 		ordseq = blk_ordered_req_seq(rq);
673797e7dbbSTejun Heo 
674797e7dbbSTejun Heo 		list_for_each(pos, &q->queue_head) {
675797e7dbbSTejun Heo 			struct request *pos_rq = list_entry_rq(pos);
676797e7dbbSTejun Heo 			if (ordseq <= blk_ordered_req_seq(pos_rq))
677797e7dbbSTejun Heo 				break;
678797e7dbbSTejun Heo 		}
679797e7dbbSTejun Heo 
680797e7dbbSTejun Heo 		list_add_tail(&rq->queuelist, pos);
681797e7dbbSTejun Heo 		break;
682797e7dbbSTejun Heo 
6838922e16cSTejun Heo 	default:
6848922e16cSTejun Heo 		printk(KERN_ERR "%s: bad insertion point %d\n",
68524c03d47SHarvey Harrison 		       __func__, where);
6868922e16cSTejun Heo 		BUG();
6878922e16cSTejun Heo 	}
6881da177e4SLinus Torvalds 
689dac07ec1SJens Axboe 	if (unplug_it && blk_queue_plugged(q)) {
6901faa16d2SJens Axboe 		int nrq = q->rq.count[BLK_RW_SYNC] + q->rq.count[BLK_RW_ASYNC]
6910a7ae2ffSJens Axboe 				- queue_in_flight(q);
6921da177e4SLinus Torvalds 
693c374f127STejun Heo  		if (nrq >= q->unplug_thresh)
6941da177e4SLinus Torvalds 			__generic_unplug_device(q);
6951da177e4SLinus Torvalds 	}
6961da177e4SLinus Torvalds }
6971da177e4SLinus Torvalds 
698165125e1SJens Axboe void __elv_add_request(struct request_queue *q, struct request *rq, int where,
69930e9656cSTejun Heo 		       int plug)
70030e9656cSTejun Heo {
70130e9656cSTejun Heo 	if (q->ordcolor)
7024aff5e23SJens Axboe 		rq->cmd_flags |= REQ_ORDERED_COLOR;
70330e9656cSTejun Heo 
7044aff5e23SJens Axboe 	if (rq->cmd_flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)) {
70530e9656cSTejun Heo 		/*
70630e9656cSTejun Heo 		 * toggle ordered color
70730e9656cSTejun Heo 		 */
70830e9656cSTejun Heo 		if (blk_barrier_rq(rq))
70930e9656cSTejun Heo 			q->ordcolor ^= 1;
71030e9656cSTejun Heo 
71130e9656cSTejun Heo 		/*
71230e9656cSTejun Heo 		 * barriers implicitly indicate back insertion
71330e9656cSTejun Heo 		 */
71430e9656cSTejun Heo 		if (where == ELEVATOR_INSERT_SORT)
71530e9656cSTejun Heo 			where = ELEVATOR_INSERT_BACK;
71630e9656cSTejun Heo 
71730e9656cSTejun Heo 		/*
71830e9656cSTejun Heo 		 * this request is scheduling boundary, update
71930e9656cSTejun Heo 		 * end_sector
72030e9656cSTejun Heo 		 */
721e17fc0a1SDavid Woodhouse 		if (blk_fs_request(rq) || blk_discard_rq(rq)) {
72230e9656cSTejun Heo 			q->end_sector = rq_end_sector(rq);
72330e9656cSTejun Heo 			q->boundary_rq = rq;
72430e9656cSTejun Heo 		}
7254eb166d9SJens Axboe 	} else if (!(rq->cmd_flags & REQ_ELVPRIV) &&
7264eb166d9SJens Axboe 		    where == ELEVATOR_INSERT_SORT)
72730e9656cSTejun Heo 		where = ELEVATOR_INSERT_BACK;
72830e9656cSTejun Heo 
72930e9656cSTejun Heo 	if (plug)
73030e9656cSTejun Heo 		blk_plug_device(q);
73130e9656cSTejun Heo 
73230e9656cSTejun Heo 	elv_insert(q, rq, where);
73330e9656cSTejun Heo }
7342e662b65SJens Axboe EXPORT_SYMBOL(__elv_add_request);
7352e662b65SJens Axboe 
736165125e1SJens Axboe void elv_add_request(struct request_queue *q, struct request *rq, int where,
7371da177e4SLinus Torvalds 		     int plug)
7381da177e4SLinus Torvalds {
7391da177e4SLinus Torvalds 	unsigned long flags;
7401da177e4SLinus Torvalds 
7411da177e4SLinus Torvalds 	spin_lock_irqsave(q->queue_lock, flags);
7421da177e4SLinus Torvalds 	__elv_add_request(q, rq, where, plug);
7431da177e4SLinus Torvalds 	spin_unlock_irqrestore(q->queue_lock, flags);
7441da177e4SLinus Torvalds }
7452e662b65SJens Axboe EXPORT_SYMBOL(elv_add_request);
7462e662b65SJens Axboe 
747165125e1SJens Axboe int elv_queue_empty(struct request_queue *q)
7481da177e4SLinus Torvalds {
749b374d18aSJens Axboe 	struct elevator_queue *e = q->elevator;
7501da177e4SLinus Torvalds 
7518922e16cSTejun Heo 	if (!list_empty(&q->queue_head))
7528922e16cSTejun Heo 		return 0;
7538922e16cSTejun Heo 
7541da177e4SLinus Torvalds 	if (e->ops->elevator_queue_empty_fn)
7551da177e4SLinus Torvalds 		return e->ops->elevator_queue_empty_fn(q);
7561da177e4SLinus Torvalds 
7578922e16cSTejun Heo 	return 1;
7581da177e4SLinus Torvalds }
7592e662b65SJens Axboe EXPORT_SYMBOL(elv_queue_empty);
7602e662b65SJens Axboe 
761165125e1SJens Axboe struct request *elv_latter_request(struct request_queue *q, struct request *rq)
7621da177e4SLinus Torvalds {
763b374d18aSJens Axboe 	struct elevator_queue *e = q->elevator;
7641da177e4SLinus Torvalds 
7651da177e4SLinus Torvalds 	if (e->ops->elevator_latter_req_fn)
7661da177e4SLinus Torvalds 		return e->ops->elevator_latter_req_fn(q, rq);
7671da177e4SLinus Torvalds 	return NULL;
7681da177e4SLinus Torvalds }
7691da177e4SLinus Torvalds 
770165125e1SJens Axboe struct request *elv_former_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_former_req_fn)
7751da177e4SLinus Torvalds 		return e->ops->elevator_former_req_fn(q, rq);
7761da177e4SLinus Torvalds 	return NULL;
7771da177e4SLinus Torvalds }
7781da177e4SLinus Torvalds 
779165125e1SJens Axboe int elv_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask)
7801da177e4SLinus Torvalds {
781b374d18aSJens Axboe 	struct elevator_queue *e = q->elevator;
7821da177e4SLinus Torvalds 
7831da177e4SLinus Torvalds 	if (e->ops->elevator_set_req_fn)
784cb78b285SJens Axboe 		return e->ops->elevator_set_req_fn(q, rq, gfp_mask);
7851da177e4SLinus Torvalds 
7861da177e4SLinus Torvalds 	rq->elevator_private = NULL;
7871da177e4SLinus Torvalds 	return 0;
7881da177e4SLinus Torvalds }
7891da177e4SLinus Torvalds 
790165125e1SJens Axboe void elv_put_request(struct request_queue *q, struct request *rq)
7911da177e4SLinus Torvalds {
792b374d18aSJens Axboe 	struct elevator_queue *e = q->elevator;
7931da177e4SLinus Torvalds 
7941da177e4SLinus Torvalds 	if (e->ops->elevator_put_req_fn)
795bb37b94cSJens Axboe 		e->ops->elevator_put_req_fn(rq);
7961da177e4SLinus Torvalds }
7971da177e4SLinus Torvalds 
798165125e1SJens Axboe int elv_may_queue(struct request_queue *q, int rw)
7991da177e4SLinus Torvalds {
800b374d18aSJens Axboe 	struct elevator_queue *e = q->elevator;
8011da177e4SLinus Torvalds 
8021da177e4SLinus Torvalds 	if (e->ops->elevator_may_queue_fn)
803cb78b285SJens Axboe 		return e->ops->elevator_may_queue_fn(q, rw);
8041da177e4SLinus Torvalds 
8051da177e4SLinus Torvalds 	return ELV_MQUEUE_MAY;
8061da177e4SLinus Torvalds }
8071da177e4SLinus Torvalds 
80811914a53SMike Anderson void elv_abort_queue(struct request_queue *q)
80911914a53SMike Anderson {
81011914a53SMike Anderson 	struct request *rq;
81111914a53SMike Anderson 
81211914a53SMike Anderson 	while (!list_empty(&q->queue_head)) {
81311914a53SMike Anderson 		rq = list_entry_rq(q->queue_head.next);
81411914a53SMike Anderson 		rq->cmd_flags |= REQ_QUIET;
8155f3ea37cSArnaldo Carvalho de Melo 		trace_block_rq_abort(q, rq);
816*53c663ceSKiyoshi Ueda 		/*
817*53c663ceSKiyoshi Ueda 		 * Mark this request as started so we don't trigger
818*53c663ceSKiyoshi Ueda 		 * any debug logic in the end I/O path.
819*53c663ceSKiyoshi Ueda 		 */
820*53c663ceSKiyoshi Ueda 		blk_start_request(rq);
82140cbbb78STejun Heo 		__blk_end_request_all(rq, -EIO);
82211914a53SMike Anderson 	}
82311914a53SMike Anderson }
82411914a53SMike Anderson EXPORT_SYMBOL(elv_abort_queue);
82511914a53SMike Anderson 
826165125e1SJens Axboe void elv_completed_request(struct request_queue *q, struct request *rq)
8271da177e4SLinus Torvalds {
828b374d18aSJens Axboe 	struct elevator_queue *e = q->elevator;
8291da177e4SLinus Torvalds 
8301da177e4SLinus Torvalds 	/*
8311da177e4SLinus Torvalds 	 * request is released from the driver, io must be done
8321da177e4SLinus Torvalds 	 */
8338922e16cSTejun Heo 	if (blk_account_rq(rq)) {
8340a7ae2ffSJens Axboe 		q->in_flight[rq_is_sync(rq)]--;
8351bc691d3STejun Heo 		if (blk_sorted_rq(rq) && e->ops->elevator_completed_req_fn)
8361bc691d3STejun Heo 			e->ops->elevator_completed_req_fn(q, rq);
8371bc691d3STejun Heo 	}
838797e7dbbSTejun Heo 
839797e7dbbSTejun Heo 	/*
840797e7dbbSTejun Heo 	 * Check if the queue is waiting for fs requests to be
841797e7dbbSTejun Heo 	 * drained for flush sequence.
842797e7dbbSTejun Heo 	 */
8431bc691d3STejun Heo 	if (unlikely(q->ordseq)) {
8448f11b3e9STejun Heo 		struct request *next = NULL;
8458f11b3e9STejun Heo 
8468f11b3e9STejun Heo 		if (!list_empty(&q->queue_head))
8478f11b3e9STejun Heo 			next = list_entry_rq(q->queue_head.next);
8488f11b3e9STejun Heo 
8490a7ae2ffSJens Axboe 		if (!queue_in_flight(q) &&
850797e7dbbSTejun Heo 		    blk_ordered_cur_seq(q) == QUEUE_ORDSEQ_DRAIN &&
8518f11b3e9STejun Heo 		    (!next || blk_ordered_req_seq(next) > QUEUE_ORDSEQ_DRAIN)) {
852797e7dbbSTejun Heo 			blk_ordered_complete_seq(q, QUEUE_ORDSEQ_DRAIN, 0);
853a7f55792STejun Heo 			__blk_run_queue(q);
854797e7dbbSTejun Heo 		}
8551da177e4SLinus Torvalds 	}
8568922e16cSTejun Heo }
8571da177e4SLinus Torvalds 
8583d1ab40fSAl Viro #define to_elv(atr) container_of((atr), struct elv_fs_entry, attr)
8593d1ab40fSAl Viro 
8603d1ab40fSAl Viro static ssize_t
8613d1ab40fSAl Viro elv_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
8623d1ab40fSAl Viro {
8633d1ab40fSAl Viro 	struct elv_fs_entry *entry = to_elv(attr);
864b374d18aSJens Axboe 	struct elevator_queue *e;
8653d1ab40fSAl Viro 	ssize_t error;
8663d1ab40fSAl Viro 
8673d1ab40fSAl Viro 	if (!entry->show)
8683d1ab40fSAl Viro 		return -EIO;
8693d1ab40fSAl Viro 
870b374d18aSJens Axboe 	e = container_of(kobj, struct elevator_queue, kobj);
8713d1ab40fSAl Viro 	mutex_lock(&e->sysfs_lock);
8723d1ab40fSAl Viro 	error = e->ops ? entry->show(e, page) : -ENOENT;
8733d1ab40fSAl Viro 	mutex_unlock(&e->sysfs_lock);
8743d1ab40fSAl Viro 	return error;
8753d1ab40fSAl Viro }
8763d1ab40fSAl Viro 
8773d1ab40fSAl Viro static ssize_t
8783d1ab40fSAl Viro elv_attr_store(struct kobject *kobj, struct attribute *attr,
8793d1ab40fSAl Viro 	       const char *page, size_t length)
8803d1ab40fSAl Viro {
8813d1ab40fSAl Viro 	struct elv_fs_entry *entry = to_elv(attr);
882b374d18aSJens Axboe 	struct elevator_queue *e;
8833d1ab40fSAl Viro 	ssize_t error;
8843d1ab40fSAl Viro 
8853d1ab40fSAl Viro 	if (!entry->store)
8863d1ab40fSAl Viro 		return -EIO;
8873d1ab40fSAl Viro 
888b374d18aSJens Axboe 	e = container_of(kobj, struct elevator_queue, kobj);
8893d1ab40fSAl Viro 	mutex_lock(&e->sysfs_lock);
8903d1ab40fSAl Viro 	error = e->ops ? entry->store(e, page, length) : -ENOENT;
8913d1ab40fSAl Viro 	mutex_unlock(&e->sysfs_lock);
8923d1ab40fSAl Viro 	return error;
8933d1ab40fSAl Viro }
8943d1ab40fSAl Viro 
8953d1ab40fSAl Viro static struct sysfs_ops elv_sysfs_ops = {
8963d1ab40fSAl Viro 	.show	= elv_attr_show,
8973d1ab40fSAl Viro 	.store	= elv_attr_store,
8983d1ab40fSAl Viro };
8993d1ab40fSAl Viro 
9003d1ab40fSAl Viro static struct kobj_type elv_ktype = {
9013d1ab40fSAl Viro 	.sysfs_ops	= &elv_sysfs_ops,
9023d1ab40fSAl Viro 	.release	= elevator_release,
9033d1ab40fSAl Viro };
9043d1ab40fSAl Viro 
9051da177e4SLinus Torvalds int elv_register_queue(struct request_queue *q)
9061da177e4SLinus Torvalds {
907b374d18aSJens Axboe 	struct elevator_queue *e = q->elevator;
9083d1ab40fSAl Viro 	int error;
9091da177e4SLinus Torvalds 
910b2d6db58SGreg Kroah-Hartman 	error = kobject_add(&e->kobj, &q->kobj, "%s", "iosched");
9113d1ab40fSAl Viro 	if (!error) {
912e572ec7eSAl Viro 		struct elv_fs_entry *attr = e->elevator_type->elevator_attrs;
9133d1ab40fSAl Viro 		if (attr) {
914e572ec7eSAl Viro 			while (attr->attr.name) {
915e572ec7eSAl Viro 				if (sysfs_create_file(&e->kobj, &attr->attr))
9163d1ab40fSAl Viro 					break;
917e572ec7eSAl Viro 				attr++;
9183d1ab40fSAl Viro 			}
9193d1ab40fSAl Viro 		}
9203d1ab40fSAl Viro 		kobject_uevent(&e->kobj, KOBJ_ADD);
9213d1ab40fSAl Viro 	}
9223d1ab40fSAl Viro 	return error;
9231da177e4SLinus Torvalds }
9241da177e4SLinus Torvalds 
925b374d18aSJens Axboe static void __elv_unregister_queue(struct elevator_queue *e)
9261da177e4SLinus Torvalds {
9273d1ab40fSAl Viro 	kobject_uevent(&e->kobj, KOBJ_REMOVE);
9283d1ab40fSAl Viro 	kobject_del(&e->kobj);
9291da177e4SLinus Torvalds }
930bc1c1169SJens Axboe 
931bc1c1169SJens Axboe void elv_unregister_queue(struct request_queue *q)
932bc1c1169SJens Axboe {
933bc1c1169SJens Axboe 	if (q)
934bc1c1169SJens Axboe 		__elv_unregister_queue(q->elevator);
9351da177e4SLinus Torvalds }
9361da177e4SLinus Torvalds 
9372fdd82bdSAdrian Bunk void elv_register(struct elevator_type *e)
9381da177e4SLinus Torvalds {
9391ffb96c5SThibaut VARENE 	char *def = "";
9402a12dcd7SJens Axboe 
9412a12dcd7SJens Axboe 	spin_lock(&elv_list_lock);
942ce524497SEric Sesterhenn 	BUG_ON(elevator_find(e->elevator_name));
9431da177e4SLinus Torvalds 	list_add_tail(&e->list, &elv_list);
9442a12dcd7SJens Axboe 	spin_unlock(&elv_list_lock);
9451da177e4SLinus Torvalds 
9465f003976SNate Diller 	if (!strcmp(e->elevator_name, chosen_elevator) ||
9475f003976SNate Diller 			(!*chosen_elevator &&
9485f003976SNate Diller 			 !strcmp(e->elevator_name, CONFIG_DEFAULT_IOSCHED)))
9491ffb96c5SThibaut VARENE 				def = " (default)";
9501ffb96c5SThibaut VARENE 
9514eb166d9SJens Axboe 	printk(KERN_INFO "io scheduler %s registered%s\n", e->elevator_name,
9524eb166d9SJens Axboe 								def);
9531da177e4SLinus Torvalds }
9541da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(elv_register);
9551da177e4SLinus Torvalds 
9561da177e4SLinus Torvalds void elv_unregister(struct elevator_type *e)
9571da177e4SLinus Torvalds {
95883521d3eSChristoph Hellwig 	struct task_struct *g, *p;
95983521d3eSChristoph Hellwig 
96083521d3eSChristoph Hellwig 	/*
96183521d3eSChristoph Hellwig 	 * Iterate every thread in the process to remove the io contexts.
96283521d3eSChristoph Hellwig 	 */
963e17a9489SAl Viro 	if (e->ops.trim) {
96483521d3eSChristoph Hellwig 		read_lock(&tasklist_lock);
96583521d3eSChristoph Hellwig 		do_each_thread(g, p) {
966e17a9489SAl Viro 			task_lock(p);
9672d8f6131SOleg Nesterov 			if (p->io_context)
968e17a9489SAl Viro 				e->ops.trim(p->io_context);
969e17a9489SAl Viro 			task_unlock(p);
97083521d3eSChristoph Hellwig 		} while_each_thread(g, p);
97183521d3eSChristoph Hellwig 		read_unlock(&tasklist_lock);
972e17a9489SAl Viro 	}
97383521d3eSChristoph Hellwig 
9742a12dcd7SJens Axboe 	spin_lock(&elv_list_lock);
9751da177e4SLinus Torvalds 	list_del_init(&e->list);
9762a12dcd7SJens Axboe 	spin_unlock(&elv_list_lock);
9771da177e4SLinus Torvalds }
9781da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(elv_unregister);
9791da177e4SLinus Torvalds 
9801da177e4SLinus Torvalds /*
9811da177e4SLinus Torvalds  * switch to new_e io scheduler. be careful not to introduce deadlocks -
9821da177e4SLinus Torvalds  * we don't free the old io scheduler, before we have allocated what we
9831da177e4SLinus Torvalds  * need for the new one. this way we have a chance of going back to the old
984cb98fc8bSTejun Heo  * one, if the new one fails init for some reason.
9851da177e4SLinus Torvalds  */
986165125e1SJens Axboe static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
9871da177e4SLinus Torvalds {
988b374d18aSJens Axboe 	struct elevator_queue *old_elevator, *e;
989bc1c1169SJens Axboe 	void *data;
9901da177e4SLinus Torvalds 
991cb98fc8bSTejun Heo 	/*
992cb98fc8bSTejun Heo 	 * Allocate new elevator
993cb98fc8bSTejun Heo 	 */
994b5deef90SJens Axboe 	e = elevator_alloc(q, new_e);
9951da177e4SLinus Torvalds 	if (!e)
9963d1ab40fSAl Viro 		return 0;
9971da177e4SLinus Torvalds 
998bc1c1169SJens Axboe 	data = elevator_init_queue(q, e);
999bc1c1169SJens Axboe 	if (!data) {
1000bc1c1169SJens Axboe 		kobject_put(&e->kobj);
1001bc1c1169SJens Axboe 		return 0;
1002bc1c1169SJens Axboe 	}
1003bc1c1169SJens Axboe 
10041da177e4SLinus Torvalds 	/*
1005cb98fc8bSTejun Heo 	 * Turn on BYPASS and drain all requests w/ elevator private data
10061da177e4SLinus Torvalds 	 */
1007cb98fc8bSTejun Heo 	spin_lock_irq(q->queue_lock);
1008f600abe2SJens Axboe 	elv_quiesce_start(q);
1009cb98fc8bSTejun Heo 
10101da177e4SLinus Torvalds 	/*
1011bc1c1169SJens Axboe 	 * Remember old elevator.
10121da177e4SLinus Torvalds 	 */
10131da177e4SLinus Torvalds 	old_elevator = q->elevator;
10141da177e4SLinus Torvalds 
10151da177e4SLinus Torvalds 	/*
10161da177e4SLinus Torvalds 	 * attach and start new elevator
10171da177e4SLinus Torvalds 	 */
1018bc1c1169SJens Axboe 	elevator_attach(q, e, data);
1019bc1c1169SJens Axboe 
1020bc1c1169SJens Axboe 	spin_unlock_irq(q->queue_lock);
1021bc1c1169SJens Axboe 
1022bc1c1169SJens Axboe 	__elv_unregister_queue(old_elevator);
10231da177e4SLinus Torvalds 
10241da177e4SLinus Torvalds 	if (elv_register_queue(q))
10251da177e4SLinus Torvalds 		goto fail_register;
10261da177e4SLinus Torvalds 
10271da177e4SLinus Torvalds 	/*
1028cb98fc8bSTejun Heo 	 * finally exit old elevator and turn off BYPASS.
10291da177e4SLinus Torvalds 	 */
10301da177e4SLinus Torvalds 	elevator_exit(old_elevator);
103175ad23bcSNick Piggin 	spin_lock_irq(q->queue_lock);
1032f600abe2SJens Axboe 	elv_quiesce_end(q);
103375ad23bcSNick Piggin 	spin_unlock_irq(q->queue_lock);
103475ad23bcSNick Piggin 
10354722dc52SAlan D. Brunelle 	blk_add_trace_msg(q, "elv switch: %s", e->elevator_type->elevator_name);
10364722dc52SAlan D. Brunelle 
10373d1ab40fSAl Viro 	return 1;
10381da177e4SLinus Torvalds 
10391da177e4SLinus Torvalds fail_register:
10401da177e4SLinus Torvalds 	/*
10411da177e4SLinus Torvalds 	 * switch failed, exit the new io scheduler and reattach the old
10421da177e4SLinus Torvalds 	 * one again (along with re-adding the sysfs dir)
10431da177e4SLinus Torvalds 	 */
10441da177e4SLinus Torvalds 	elevator_exit(e);
10451da177e4SLinus Torvalds 	q->elevator = old_elevator;
10461da177e4SLinus Torvalds 	elv_register_queue(q);
104775ad23bcSNick Piggin 
104875ad23bcSNick Piggin 	spin_lock_irq(q->queue_lock);
104975ad23bcSNick Piggin 	queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q);
105075ad23bcSNick Piggin 	spin_unlock_irq(q->queue_lock);
105175ad23bcSNick Piggin 
10523d1ab40fSAl Viro 	return 0;
10531da177e4SLinus Torvalds }
10541da177e4SLinus Torvalds 
1055165125e1SJens Axboe ssize_t elv_iosched_store(struct request_queue *q, const char *name,
1056165125e1SJens Axboe 			  size_t count)
10571da177e4SLinus Torvalds {
10581da177e4SLinus Torvalds 	char elevator_name[ELV_NAME_MAX];
10591da177e4SLinus Torvalds 	struct elevator_type *e;
10601da177e4SLinus Torvalds 
1061cd43e26fSMartin K. Petersen 	if (!q->elevator)
1062cd43e26fSMartin K. Petersen 		return count;
1063cd43e26fSMartin K. Petersen 
1064ee2e992cSLi Zefan 	strlcpy(elevator_name, name, sizeof(elevator_name));
1065ee2e992cSLi Zefan 	strstrip(elevator_name);
10661da177e4SLinus Torvalds 
10671da177e4SLinus Torvalds 	e = elevator_get(elevator_name);
10681da177e4SLinus Torvalds 	if (!e) {
10691da177e4SLinus Torvalds 		printk(KERN_ERR "elevator: type %s not found\n", elevator_name);
10701da177e4SLinus Torvalds 		return -EINVAL;
10711da177e4SLinus Torvalds 	}
10721da177e4SLinus Torvalds 
10732ca7d93bSNate Diller 	if (!strcmp(elevator_name, q->elevator->elevator_type->elevator_name)) {
10742ca7d93bSNate Diller 		elevator_put(e);
10751da177e4SLinus Torvalds 		return count;
10762ca7d93bSNate Diller 	}
10771da177e4SLinus Torvalds 
10783d1ab40fSAl Viro 	if (!elevator_switch(q, e))
10794eb166d9SJens Axboe 		printk(KERN_ERR "elevator: switch to %s failed\n",
10804eb166d9SJens Axboe 							elevator_name);
10811da177e4SLinus Torvalds 	return count;
10821da177e4SLinus Torvalds }
10831da177e4SLinus Torvalds 
1084165125e1SJens Axboe ssize_t elv_iosched_show(struct request_queue *q, char *name)
10851da177e4SLinus Torvalds {
1086b374d18aSJens Axboe 	struct elevator_queue *e = q->elevator;
1087cd43e26fSMartin K. Petersen 	struct elevator_type *elv;
108870cee26eSMatthias Kaehlcke 	struct elevator_type *__e;
10891da177e4SLinus Torvalds 	int len = 0;
10901da177e4SLinus Torvalds 
1091cd43e26fSMartin K. Petersen 	if (!q->elevator)
1092cd43e26fSMartin K. Petersen 		return sprintf(name, "none\n");
1093cd43e26fSMartin K. Petersen 
1094cd43e26fSMartin K. Petersen 	elv = e->elevator_type;
1095cd43e26fSMartin K. Petersen 
10962a12dcd7SJens Axboe 	spin_lock(&elv_list_lock);
109770cee26eSMatthias Kaehlcke 	list_for_each_entry(__e, &elv_list, list) {
10981da177e4SLinus Torvalds 		if (!strcmp(elv->elevator_name, __e->elevator_name))
10991da177e4SLinus Torvalds 			len += sprintf(name+len, "[%s] ", elv->elevator_name);
11001da177e4SLinus Torvalds 		else
11011da177e4SLinus Torvalds 			len += sprintf(name+len, "%s ", __e->elevator_name);
11021da177e4SLinus Torvalds 	}
11032a12dcd7SJens Axboe 	spin_unlock(&elv_list_lock);
11041da177e4SLinus Torvalds 
11051da177e4SLinus Torvalds 	len += sprintf(len+name, "\n");
11061da177e4SLinus Torvalds 	return len;
11071da177e4SLinus Torvalds }
11081da177e4SLinus Torvalds 
1109165125e1SJens Axboe struct request *elv_rb_former_request(struct request_queue *q,
1110165125e1SJens Axboe 				      struct request *rq)
11112e662b65SJens Axboe {
11122e662b65SJens Axboe 	struct rb_node *rbprev = rb_prev(&rq->rb_node);
11132e662b65SJens Axboe 
11142e662b65SJens Axboe 	if (rbprev)
11152e662b65SJens Axboe 		return rb_entry_rq(rbprev);
11162e662b65SJens Axboe 
11172e662b65SJens Axboe 	return NULL;
11182e662b65SJens Axboe }
11192e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_former_request);
11202e662b65SJens Axboe 
1121165125e1SJens Axboe struct request *elv_rb_latter_request(struct request_queue *q,
1122165125e1SJens Axboe 				      struct request *rq)
11232e662b65SJens Axboe {
11242e662b65SJens Axboe 	struct rb_node *rbnext = rb_next(&rq->rb_node);
11252e662b65SJens Axboe 
11262e662b65SJens Axboe 	if (rbnext)
11272e662b65SJens Axboe 		return rb_entry_rq(rbnext);
11282e662b65SJens Axboe 
11292e662b65SJens Axboe 	return NULL;
11302e662b65SJens Axboe }
11312e662b65SJens Axboe EXPORT_SYMBOL(elv_rb_latter_request);
1132