提交 56f29d7f 编写于 作者: L Linus Torvalds

Merge branch 'block' of git://brick.kernel.dk/data/git/linux-2.6-block

* 'block' of git://brick.kernel.dk/data/git/linux-2.6-block: (67 commits)
  [PATCH] blk_queue_start_tag() shared map race fix
  [PATCH] Update axboe@suse.de email address
  [PATCH] fix creating zero sized bio mempools in low memory system
  [PATCH] CONFIG_BLOCK: blk_congestion_wait() fix
  [PATCH] CONFIG_BLOCK internal.h cleanups
  [PATCH] BLOCK: Make USB storage depend on SCSI rather than selecting it [try #6]
  [PATCH] BLOCK: Make it possible to disable the block layer [try #6]
  [PATCH] BLOCK: Remove no-longer necessary linux/buffer_head.h inclusions [try #6]
  [PATCH] BLOCK: Remove no-longer necessary linux/mpage.h inclusions [try #6]
  [PATCH] BLOCK: Move the msdos device ioctl compat stuff to the msdos driver [try #6]
  [PATCH] BLOCK: Move the Ext3 device ioctl compat stuff to the Ext3 driver [try #6]
  [PATCH] BLOCK: Move the Ext2 device ioctl compat stuff to the Ext2 driver [try #6]
  [PATCH] BLOCK: Move the ReiserFS device ioctl compat stuff to the ReiserFS driver [try #6]
  [PATCH] BLOCK: Move common FS-specific ioctls to linux/fs.h [try #6]
  [PATCH] BLOCK: Move the loop device ioctl compat stuff to the loop driver [try #6]
  [PATCH] BLOCK: Move __invalidate_device() to block_dev.c [try #6]
  [PATCH] BLOCK: Dissociate generic_writepages() from mpage stuff [try #6]
  [PATCH] BLOCK: Remove dependence on existence of blockdev_superblock [try #6]
  [PATCH] BLOCK: Move extern declarations out of fs/*.c into header files [try #6]
  [PATCH] BLOCK: Don't call block_sync_page() from AFS [try #6]
  ...
......@@ -501,7 +501,7 @@ S: Maintained
BLOCK LAYER
P: Jens Axboe
M: axboe@suse.de
M: axboe@kernel.dk
L: linux-kernel@vger.kernel.org
T: git kernel.org:/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git
S: Maintained
......@@ -1380,7 +1380,7 @@ S: Maintained
IDE/ATAPI CDROM DRIVER
P: Jens Axboe
M: axboe@suse.de
M: axboe@kernel.dk
L: linux-kernel@vger.kernel.org
W: http://www.kernel.dk
S: Maintained
......@@ -2531,7 +2531,7 @@ S: Maintained
SCSI CDROM DRIVER
P: Jens Axboe
M: axboe@suse.de
M: axboe@kernel.dk
L: linux-scsi@vger.kernel.org
W: http://www.kernel.dk
S: Maintained
......@@ -2976,7 +2976,7 @@ S: Maintained
UNIFORM CDROM DRIVER
P: Jens Axboe
M: axboe@suse.de
M: axboe@kernel.dk
L: linux-kernel@vger.kernel.org
W: http://www.kernel.dk
S: Maintained
......
......@@ -42,6 +42,8 @@
#include "signal-common.h"
extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat);
/*
* Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
*/
......@@ -81,8 +83,6 @@ struct rt_sigframe_n32 {
#endif
};
extern void sigset_from_compat (sigset_t *set, compat_sigset_t *compat);
save_static_function(sysn32_rt_sigsuspend);
__attribute_used__ noinline static int
_sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
......
......@@ -981,8 +981,6 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req)
__u64 offset;
int len;
if(req->rq_status == RQ_INACTIVE) return(1);
/* This should be impossible now */
if((rq_data_dir(req) == WRITE) && !dev->openflags.w){
printk("Write attempted on readonly ubd device %s\n",
......
#
# Block layer core configuration
#
config BLOCK
bool "Enable the block layer"
default y
help
This permits the block layer to be removed from the kernel if it's not
needed (on some embedded devices for example). If this option is
disabled, then blockdev files will become unusable and some
filesystems (such as ext3) will become unavailable.
This option will also disable SCSI character devices and USB storage
since they make use of various block layer definitions and
facilities.
Say Y here unless you know you really don't want to mount disks and
suchlike.
if BLOCK
#XXX - it makes sense to enable this only for 32-bit subarch's, not for x86_64
#for instance.
config LBD
......@@ -33,4 +51,6 @@ config LSF
If unsure, say Y.
endif
source block/Kconfig.iosched
if BLOCK
menu "IO Schedulers"
......@@ -67,3 +68,5 @@ config DEFAULT_IOSCHED
default "noop" if DEFAULT_NOOP
endmenu
endif
......@@ -2,7 +2,7 @@
# Makefile for the kernel block layer
#
obj-y := elevator.o ll_rw_blk.o ioctl.o genhd.o scsi_ioctl.o
obj-$(CONFIG_BLOCK) := elevator.o ll_rw_blk.o ioctl.o genhd.o scsi_ioctl.o
obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o
obj-$(CONFIG_IOSCHED_AS) += as-iosched.o
......
此差异已折叠。
/*
* Copyright (C) 2006 Jens Axboe <axboe@suse.de>
* Copyright (C) 2006 Jens Axboe <axboe@kernel.dk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
......@@ -69,7 +69,7 @@ static u32 ddir_act[2] __read_mostly = { BLK_TC_ACT(BLK_TC_READ), BLK_TC_ACT(BLK
/*
* Bio action bits of interest
*/
static u32 bio_act[5] __read_mostly = { 0, BLK_TC_ACT(BLK_TC_BARRIER), BLK_TC_ACT(BLK_TC_SYNC), 0, BLK_TC_ACT(BLK_TC_AHEAD) };
static u32 bio_act[9] __read_mostly = { 0, BLK_TC_ACT(BLK_TC_BARRIER), BLK_TC_ACT(BLK_TC_SYNC), 0, BLK_TC_ACT(BLK_TC_AHEAD), 0, 0, 0, BLK_TC_ACT(BLK_TC_META) };
/*
* More could be added as needed, taking care to increment the decrementer
......@@ -81,6 +81,8 @@ static u32 bio_act[5] __read_mostly = { 0, BLK_TC_ACT(BLK_TC_BARRIER), BLK_TC_AC
(((rw) & (1 << BIO_RW_SYNC)) >> (BIO_RW_SYNC - 1))
#define trace_ahead_bit(rw) \
(((rw) & (1 << BIO_RW_AHEAD)) << (2 - BIO_RW_AHEAD))
#define trace_meta_bit(rw) \
(((rw) & (1 << BIO_RW_META)) >> (BIO_RW_META - 3))
/*
* The worker for the various blk_add_trace*() types. Fills out a
......@@ -103,6 +105,7 @@ void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes,
what |= bio_act[trace_barrier_bit(rw)];
what |= bio_act[trace_sync_bit(rw)];
what |= bio_act[trace_ahead_bit(rw)];
what |= bio_act[trace_meta_bit(rw)];
pid = tsk->pid;
if (unlikely(act_log_check(bt, what, sector, pid)))
......@@ -473,6 +476,9 @@ static void blk_check_time(unsigned long long *t)
*t -= (a + b) / 2;
}
/*
* calibrate our inter-CPU timings
*/
static void blk_trace_check_cpu_time(void *data)
{
unsigned long long *t;
......@@ -490,20 +496,6 @@ static void blk_trace_check_cpu_time(void *data)
put_cpu();
}
/*
* Call blk_trace_check_cpu_time() on each CPU to calibrate our inter-CPU
* timings
*/
static void blk_trace_calibrate_offsets(void)
{
unsigned long flags;
smp_call_function(blk_trace_check_cpu_time, NULL, 1, 1);
local_irq_save(flags);
blk_trace_check_cpu_time(NULL);
local_irq_restore(flags);
}
static void blk_trace_set_ht_offsets(void)
{
#if defined(CONFIG_SCHED_SMT)
......@@ -532,7 +524,7 @@ static void blk_trace_set_ht_offsets(void)
static __init int blk_trace_init(void)
{
mutex_init(&blk_tree_mutex);
blk_trace_calibrate_offsets();
on_each_cpu(blk_trace_check_cpu_time, NULL, 1, 1);
blk_trace_set_ht_offsets();
return 0;
......
此差异已折叠。
/*
* Deadline i/o scheduler.
*
* Copyright (C) 2002 Jens Axboe <axboe@suse.de>
* Copyright (C) 2002 Jens Axboe <axboe@kernel.dk>
*/
#include <linux/kernel.h>
#include <linux/fs.h>
......@@ -12,7 +12,6 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/compiler.h>
#include <linux/hash.h>
#include <linux/rbtree.h>
/*
......@@ -24,13 +23,6 @@ static const int writes_starved = 2; /* max times reads can starve a write */
static const int fifo_batch = 16; /* # of sequential requests treated as one
by the above parameters. For throughput. */
static const int deadline_hash_shift = 5;
#define DL_HASH_BLOCK(sec) ((sec) >> 3)
#define DL_HASH_FN(sec) (hash_long(DL_HASH_BLOCK((sec)), deadline_hash_shift))
#define DL_HASH_ENTRIES (1 << deadline_hash_shift)
#define rq_hash_key(rq) ((rq)->sector + (rq)->nr_sectors)
#define ON_HASH(drq) (!hlist_unhashed(&(drq)->hash))
struct deadline_data {
/*
* run time data
......@@ -45,8 +37,7 @@ struct deadline_data {
/*
* next in sort order. read, write or both are NULL
*/
struct deadline_rq *next_drq[2];
struct hlist_head *hash; /* request hash */
struct request *next_rq[2];
unsigned int batching; /* number of sequential requests made */
sector_t last_sector; /* head position */
unsigned int starved; /* times reads have starved writes */
......@@ -58,240 +49,69 @@ struct deadline_data {
int fifo_batch;
int writes_starved;
int front_merges;
mempool_t *drq_pool;
};
/*
* pre-request data.
*/
struct deadline_rq {
/*
* rbtree index, key is the starting offset
*/
struct rb_node rb_node;
sector_t rb_key;
struct request *request;
/*
* request hash, key is the ending offset (for back merge lookup)
*/
struct hlist_node hash;
/*
* expire fifo
*/
struct list_head fifo;
unsigned long expires;
};
static void deadline_move_request(struct deadline_data *dd, struct deadline_rq *drq);
static kmem_cache_t *drq_pool;
#define RQ_DATA(rq) ((struct deadline_rq *) (rq)->elevator_private)
static void deadline_move_request(struct deadline_data *, struct request *);
/*
* the back merge hash support functions
*/
static inline void __deadline_del_drq_hash(struct deadline_rq *drq)
{
hlist_del_init(&drq->hash);
}
static inline void deadline_del_drq_hash(struct deadline_rq *drq)
{
if (ON_HASH(drq))
__deadline_del_drq_hash(drq);
}
static inline void
deadline_add_drq_hash(struct deadline_data *dd, struct deadline_rq *drq)
{
struct request *rq = drq->request;
BUG_ON(ON_HASH(drq));
hlist_add_head(&drq->hash, &dd->hash[DL_HASH_FN(rq_hash_key(rq))]);
}
/*
* move hot entry to front of chain
*/
static inline void
deadline_hot_drq_hash(struct deadline_data *dd, struct deadline_rq *drq)
{
struct request *rq = drq->request;
struct hlist_head *head = &dd->hash[DL_HASH_FN(rq_hash_key(rq))];
if (ON_HASH(drq) && &drq->hash != head->first) {
hlist_del(&drq->hash);
hlist_add_head(&drq->hash, head);
}
}
static struct request *
deadline_find_drq_hash(struct deadline_data *dd, sector_t offset)
{
struct hlist_head *hash_list = &dd->hash[DL_HASH_FN(offset)];
struct hlist_node *entry, *next;
struct deadline_rq *drq;
hlist_for_each_entry_safe(drq, entry, next, hash_list, hash) {
struct request *__rq = drq->request;
BUG_ON(!ON_HASH(drq));
if (!rq_mergeable(__rq)) {
__deadline_del_drq_hash(drq);
continue;
}
if (rq_hash_key(__rq) == offset)
return __rq;
}
return NULL;
}
/*
* rb tree support functions
*/
#define rb_entry_drq(node) rb_entry((node), struct deadline_rq, rb_node)
#define DRQ_RB_ROOT(dd, drq) (&(dd)->sort_list[rq_data_dir((drq)->request)])
#define rq_rb_key(rq) (rq)->sector
static struct deadline_rq *
__deadline_add_drq_rb(struct deadline_data *dd, struct deadline_rq *drq)
{
struct rb_node **p = &DRQ_RB_ROOT(dd, drq)->rb_node;
struct rb_node *parent = NULL;
struct deadline_rq *__drq;
while (*p) {
parent = *p;
__drq = rb_entry_drq(parent);
if (drq->rb_key < __drq->rb_key)
p = &(*p)->rb_left;
else if (drq->rb_key > __drq->rb_key)
p = &(*p)->rb_right;
else
return __drq;
}
rb_link_node(&drq->rb_node, parent, p);
return NULL;
}
#define RQ_RB_ROOT(dd, rq) (&(dd)->sort_list[rq_data_dir((rq))])
static void
deadline_add_drq_rb(struct deadline_data *dd, struct deadline_rq *drq)
deadline_add_rq_rb(struct deadline_data *dd, struct request *rq)
{
struct deadline_rq *__alias;
drq->rb_key = rq_rb_key(drq->request);
struct rb_root *root = RQ_RB_ROOT(dd, rq);
struct request *__alias;
retry:
__alias = __deadline_add_drq_rb(dd, drq);
if (!__alias) {
rb_insert_color(&drq->rb_node, DRQ_RB_ROOT(dd, drq));
return;
__alias = elv_rb_add(root, rq);
if (unlikely(__alias)) {
deadline_move_request(dd, __alias);
goto retry;
}
deadline_move_request(dd, __alias);
goto retry;
}
static inline void
deadline_del_drq_rb(struct deadline_data *dd, struct deadline_rq *drq)
deadline_del_rq_rb(struct deadline_data *dd, struct request *rq)
{
const int data_dir = rq_data_dir(drq->request);
const int data_dir = rq_data_dir(rq);
if (dd->next_drq[data_dir] == drq) {
struct rb_node *rbnext = rb_next(&drq->rb_node);
if (dd->next_rq[data_dir] == rq) {
struct rb_node *rbnext = rb_next(&rq->rb_node);
dd->next_drq[data_dir] = NULL;
dd->next_rq[data_dir] = NULL;
if (rbnext)
dd->next_drq[data_dir] = rb_entry_drq(rbnext);
}
BUG_ON(!RB_EMPTY_NODE(&drq->rb_node));
rb_erase(&drq->rb_node, DRQ_RB_ROOT(dd, drq));
RB_CLEAR_NODE(&drq->rb_node);
}
static struct request *
deadline_find_drq_rb(struct deadline_data *dd, sector_t sector, int data_dir)
{
struct rb_node *n = dd->sort_list[data_dir].rb_node;
struct deadline_rq *drq;
while (n) {
drq = rb_entry_drq(n);
if (sector < drq->rb_key)
n = n->rb_left;
else if (sector > drq->rb_key)
n = n->rb_right;
else
return drq->request;
dd->next_rq[data_dir] = rb_entry_rq(rbnext);
}
return NULL;
elv_rb_del(RQ_RB_ROOT(dd, rq), rq);
}
/*
* deadline_find_first_drq finds the first (lowest sector numbered) request
* for the specified data_dir. Used to sweep back to the start of the disk
* (1-way elevator) after we process the last (highest sector) request.
*/
static struct deadline_rq *
deadline_find_first_drq(struct deadline_data *dd, int data_dir)
{
struct rb_node *n = dd->sort_list[data_dir].rb_node;
for (;;) {
if (n->rb_left == NULL)
return rb_entry_drq(n);
n = n->rb_left;
}
}
/*
* add drq to rbtree and fifo
* add rq to rbtree and fifo
*/
static void
deadline_add_request(struct request_queue *q, struct request *rq)
{
struct deadline_data *dd = q->elevator->elevator_data;
struct deadline_rq *drq = RQ_DATA(rq);
const int data_dir = rq_data_dir(rq);
const int data_dir = rq_data_dir(drq->request);
deadline_add_rq_rb(dd, rq);
deadline_add_drq_rb(dd, drq);
/*
* set expire time (only used for reads) and add to fifo list
*/
drq->expires = jiffies + dd->fifo_expire[data_dir];
list_add_tail(&drq->fifo, &dd->fifo_list[data_dir]);
if (rq_mergeable(rq))
deadline_add_drq_hash(dd, drq);
rq_set_fifo_time(rq, jiffies + dd->fifo_expire[data_dir]);
list_add_tail(&rq->queuelist, &dd->fifo_list[data_dir]);
}
/*
* remove rq from rbtree, fifo, and hash
* remove rq from rbtree and fifo.
*/
static void deadline_remove_request(request_queue_t *q, struct request *rq)
{
struct deadline_rq *drq = RQ_DATA(rq);
struct deadline_data *dd = q->elevator->elevator_data;
list_del_init(&drq->fifo);
deadline_del_drq_rb(dd, drq);
deadline_del_drq_hash(drq);
rq_fifo_clear(rq);
deadline_del_rq_rb(dd, rq);
}
static int
......@@ -301,28 +121,15 @@ deadline_merge(request_queue_t *q, struct request **req, struct bio *bio)
struct request *__rq;
int ret;
/*
* see if the merge hash can satisfy a back merge
*/
__rq = deadline_find_drq_hash(dd, bio->bi_sector);
if (__rq) {
BUG_ON(__rq->sector + __rq->nr_sectors != bio->bi_sector);
if (elv_rq_merge_ok(__rq, bio)) {
ret = ELEVATOR_BACK_MERGE;
goto out;
}
}
/*
* check for front merge
*/
if (dd->front_merges) {
sector_t rb_key = bio->bi_sector + bio_sectors(bio);
sector_t sector = bio->bi_sector + bio_sectors(bio);
__rq = deadline_find_drq_rb(dd, rb_key, bio_data_dir(bio));
__rq = elv_rb_find(&dd->sort_list[bio_data_dir(bio)], sector);
if (__rq) {
BUG_ON(rb_key != rq_rb_key(__rq));
BUG_ON(sector != __rq->sector);
if (elv_rq_merge_ok(__rq, bio)) {
ret = ELEVATOR_FRONT_MERGE;
......@@ -333,29 +140,21 @@ deadline_merge(request_queue_t *q, struct request **req, struct bio *bio)
return ELEVATOR_NO_MERGE;
out:
if (ret)
deadline_hot_drq_hash(dd, RQ_DATA(__rq));
*req = __rq;
return ret;
}
static void deadline_merged_request(request_queue_t *q, struct request *req)
static void deadline_merged_request(request_queue_t *q, struct request *req,
int type)
{
struct deadline_data *dd = q->elevator->elevator_data;
struct deadline_rq *drq = RQ_DATA(req);
/*
* hash always needs to be repositioned, key is end sector
*/
deadline_del_drq_hash(drq);
deadline_add_drq_hash(dd, drq);
/*
* if the merge was a front merge, we need to reposition request
*/
if (rq_rb_key(req) != drq->rb_key) {
deadline_del_drq_rb(dd, drq);
deadline_add_drq_rb(dd, drq);
if (type == ELEVATOR_FRONT_MERGE) {
elv_rb_del(RQ_RB_ROOT(dd, req), req);
deadline_add_rq_rb(dd, req);
}
}
......@@ -363,33 +162,14 @@ static void
deadline_merged_requests(request_queue_t *q, struct request *req,
struct request *next)
{
struct deadline_data *dd = q->elevator->elevator_data;
struct deadline_rq *drq = RQ_DATA(req);
struct deadline_rq *dnext = RQ_DATA(next);
BUG_ON(!drq);
BUG_ON(!dnext);
/*
* reposition drq (this is the merged request) in hash, and in rbtree
* in case of a front merge
* if next expires before rq, assign its expire time to rq
* and move into next position (next will be deleted) in fifo
*/
deadline_del_drq_hash(drq);
deadline_add_drq_hash(dd, drq);
if (rq_rb_key(req) != drq->rb_key) {
deadline_del_drq_rb(dd, drq);
deadline_add_drq_rb(dd, drq);
}
/*
* if dnext expires before drq, assign its expire time to drq
* and move into dnext position (dnext will be deleted) in fifo
*/
if (!list_empty(&drq->fifo) && !list_empty(&dnext->fifo)) {
if (time_before(dnext->expires, drq->expires)) {
list_move(&drq->fifo, &dnext->fifo);
drq->expires = dnext->expires;
if (!list_empty(&req->queuelist) && !list_empty(&next->queuelist)) {
if (time_before(rq_fifo_time(next), rq_fifo_time(req))) {
list_move(&req->queuelist, &next->queuelist);
rq_set_fifo_time(req, rq_fifo_time(next));
}
}
......@@ -403,52 +183,50 @@ deadline_merged_requests(request_queue_t *q, struct request *req,
* move request from sort list to dispatch queue.
*/
static inline void
deadline_move_to_dispatch(struct deadline_data *dd, struct deadline_rq *drq)
deadline_move_to_dispatch(struct deadline_data *dd, struct request *rq)
{
request_queue_t *q = drq->request->q;
request_queue_t *q = rq->q;
deadline_remove_request(q, drq->request);
elv_dispatch_add_tail(q, drq->request);
deadline_remove_request(q, rq);
elv_dispatch_add_tail(q, rq);
}
/*
* move an entry to dispatch queue
*/
static void
deadline_move_request(struct deadline_data *dd, struct deadline_rq *drq)
deadline_move_request(struct deadline_data *dd, struct request *rq)
{
const int data_dir = rq_data_dir(drq->request);
struct rb_node *rbnext = rb_next(&drq->rb_node);
const int data_dir = rq_data_dir(rq);
struct rb_node *rbnext = rb_next(&rq->rb_node);
dd->next_drq[READ] = NULL;
dd->next_drq[WRITE] = NULL;
dd->next_rq[READ] = NULL;
dd->next_rq[WRITE] = NULL;
if (rbnext)
dd->next_drq[data_dir] = rb_entry_drq(rbnext);
dd->next_rq[data_dir] = rb_entry_rq(rbnext);
dd->last_sector = drq->request->sector + drq->request->nr_sectors;
dd->last_sector = rq->sector + rq->nr_sectors;
/*
* take it off the sort and fifo list, move
* to dispatch queue
*/
deadline_move_to_dispatch(dd, drq);
deadline_move_to_dispatch(dd, rq);
}
#define list_entry_fifo(ptr) list_entry((ptr), struct deadline_rq, fifo)
/*
* deadline_check_fifo returns 0 if there are no expired reads on the fifo,
* 1 otherwise. Requires !list_empty(&dd->fifo_list[data_dir])
*/
static inline int deadline_check_fifo(struct deadline_data *dd, int ddir)
{
struct deadline_rq *drq = list_entry_fifo(dd->fifo_list[ddir].next);
struct request *rq = rq_entry_fifo(dd->fifo_list[ddir].next);
/*
* drq is expired!
* rq is expired!
*/
if (time_after(jiffies, drq->expires))
if (time_after(jiffies, rq_fifo_time(rq)))
return 1;
return 0;
......@@ -463,21 +241,21 @@ static int deadline_dispatch_requests(request_queue_t *q, int force)
struct deadline_data *dd = q->elevator->elevator_data;
const int reads = !list_empty(&dd->fifo_list[READ]);
const int writes = !list_empty(&dd->fifo_list[WRITE]);
struct deadline_rq *drq;
struct request *rq;
int data_dir;
/*
* batches are currently reads XOR writes
*/
if (dd->next_drq[WRITE])
drq = dd->next_drq[WRITE];
if (dd->next_rq[WRITE])
rq = dd->next_rq[WRITE];
else
drq = dd->next_drq[READ];
rq = dd->next_rq[READ];
if (drq) {
if (rq) {
/* we have a "next request" */
if (dd->last_sector != drq->request->sector)
if (dd->last_sector != rq->sector)
/* end the batch on a non sequential request */
dd->batching += dd->fifo_batch;
......@@ -526,30 +304,33 @@ static int deadline_dispatch_requests(request_queue_t *q, int force)
if (deadline_check_fifo(dd, data_dir)) {
/* An expired request exists - satisfy it */
dd->batching = 0;
drq = list_entry_fifo(dd->fifo_list[data_dir].next);
rq = rq_entry_fifo(dd->fifo_list[data_dir].next);
} else if (dd->next_drq[data_dir]) {
} else if (dd->next_rq[data_dir]) {
/*
* The last req was the same dir and we have a next request in
* sort order. No expired requests so continue on from here.
*/
drq = dd->next_drq[data_dir];
rq = dd->next_rq[data_dir];
} else {
struct rb_node *node;
/*
* The last req was the other direction or we have run out of
* higher-sectored requests. Go back to the lowest sectored
* request (1 way elevator) and start a new batch.
*/
dd->batching = 0;
drq = deadline_find_first_drq(dd, data_dir);
node = rb_first(&dd->sort_list[data_dir]);
if (node)
rq = rb_entry_rq(node);
}
dispatch_request:
/*
* drq is the selected appropriate request.
* rq is the selected appropriate request.
*/
dd->batching++;
deadline_move_request(dd, drq);
deadline_move_request(dd, rq);
return 1;
}
......@@ -562,30 +343,6 @@ static int deadline_queue_empty(request_queue_t *q)
&& list_empty(&dd->fifo_list[READ]);
}
static struct request *
deadline_former_request(request_queue_t *q, struct request *rq)
{
struct deadline_rq *drq = RQ_DATA(rq);
struct rb_node *rbprev = rb_prev(&drq->rb_node);
if (rbprev)
return rb_entry_drq(rbprev)->request;
return NULL;
}
static struct request *
deadline_latter_request(request_queue_t *q, struct request *rq)
{
struct deadline_rq *drq = RQ_DATA(rq);
struct rb_node *rbnext = rb_next(&drq->rb_node);
if (rbnext)
return rb_entry_drq(rbnext)->request;
return NULL;
}
static void deadline_exit_queue(elevator_t *e)
{
struct deadline_data *dd = e->elevator_data;
......@@ -593,46 +350,21 @@ static void deadline_exit_queue(elevator_t *e)
BUG_ON(!list_empty(&dd->fifo_list[READ]));
BUG_ON(!list_empty(&dd->fifo_list[WRITE]));
mempool_destroy(dd->drq_pool);
kfree(dd->hash);
kfree(dd);
}
/*
* initialize elevator private data (deadline_data), and alloc a drq for
* each request on the free lists
* initialize elevator private data (deadline_data).
*/
static void *deadline_init_queue(request_queue_t *q, elevator_t *e)
{
struct deadline_data *dd;
int i;
if (!drq_pool)
return NULL;
dd = kmalloc_node(sizeof(*dd), GFP_KERNEL, q->node);
if (!dd)
return NULL;
memset(dd, 0, sizeof(*dd));
dd->hash = kmalloc_node(sizeof(struct hlist_head)*DL_HASH_ENTRIES,
GFP_KERNEL, q->node);
if (!dd->hash) {
kfree(dd);
return NULL;
}
dd->drq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
mempool_free_slab, drq_pool, q->node);
if (!dd->drq_pool) {
kfree(dd->hash);
kfree(dd);
return NULL;
}
for (i = 0; i < DL_HASH_ENTRIES; i++)
INIT_HLIST_HEAD(&dd->hash[i]);
INIT_LIST_HEAD(&dd->fifo_list[READ]);
INIT_LIST_HEAD(&dd->fifo_list[WRITE]);
dd->sort_list[READ] = RB_ROOT;
......@@ -645,39 +377,6 @@ static void *deadline_init_queue(request_queue_t *q, elevator_t *e)
return dd;
}
static void deadline_put_request(request_queue_t *q, struct request *rq)
{
struct deadline_data *dd = q->elevator->elevator_data;
struct deadline_rq *drq = RQ_DATA(rq);
mempool_free(drq, dd->drq_pool);
rq->elevator_private = NULL;
}
static int
deadline_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
gfp_t gfp_mask)
{
struct deadline_data *dd = q->elevator->elevator_data;
struct deadline_rq *drq;
drq = mempool_alloc(dd->drq_pool, gfp_mask);
if (drq) {
memset(drq, 0, sizeof(*drq));
RB_CLEAR_NODE(&drq->rb_node);
drq->request = rq;
INIT_HLIST_NODE(&drq->hash);
INIT_LIST_HEAD(&drq->fifo);
rq->elevator_private = drq;
return 0;
}
return 1;
}
/*
* sysfs parts below
*/
......@@ -757,10 +456,8 @@ static struct elevator_type iosched_deadline = {
.elevator_dispatch_fn = deadline_dispatch_requests,
.elevator_add_req_fn = deadline_add_request,
.elevator_queue_empty_fn = deadline_queue_empty,
.elevator_former_req_fn = deadline_former_request,
.elevator_latter_req_fn = deadline_latter_request,
.elevator_set_req_fn = deadline_set_request,
.elevator_put_req_fn = deadline_put_request,
.elevator_former_req_fn = elv_rb_former_request,
.elevator_latter_req_fn = elv_rb_latter_request,
.elevator_init_fn = deadline_init_queue,
.elevator_exit_fn = deadline_exit_queue,
},
......@@ -772,24 +469,11 @@ static struct elevator_type iosched_deadline = {
static int __init deadline_init(void)
{
int ret;
drq_pool = kmem_cache_create("deadline_drq", sizeof(struct deadline_rq),
0, 0, NULL, NULL);
if (!drq_pool)
return -ENOMEM;
ret = elv_register(&iosched_deadline);
if (ret)
kmem_cache_destroy(drq_pool);
return ret;
return elv_register(&iosched_deadline);
}
static void __exit deadline_exit(void)
{
kmem_cache_destroy(drq_pool);
elv_unregister(&iosched_deadline);
}
......
......@@ -3,7 +3,7 @@
*
* Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
*
* 30042000 Jens Axboe <axboe@suse.de> :
* 30042000 Jens Axboe <axboe@kernel.dk> :
*
* Split the elevator a bit so that it is possible to choose a different
* one or even write a new "plug in". There are three pieces:
......@@ -33,12 +33,23 @@
#include <linux/compiler.h>
#include <linux/delay.h>
#include <linux/blktrace_api.h>
#include <linux/hash.h>
#include <asm/uaccess.h>
static DEFINE_SPINLOCK(elv_list_lock);
static LIST_HEAD(elv_list);
/*
* Merge hash stuff.
*/
static const int elv_hash_shift = 6;
#define ELV_HASH_BLOCK(sec) ((sec) >> 3)
#define ELV_HASH_FN(sec) (hash_long(ELV_HASH_BLOCK((sec)), elv_hash_shift))
#define ELV_HASH_ENTRIES (1 << elv_hash_shift)
#define rq_hash_key(rq) ((rq)->sector + (rq)->nr_sectors)
#define ELV_ON_HASH(rq) (!hlist_unhashed(&(rq)->hash))
/*
* can we safely merge with this request?
*/
......@@ -56,8 +67,7 @@ inline int elv_rq_merge_ok(struct request *rq, struct bio *bio)
/*
* same device and no special stuff set, merge is ok
*/
if (rq->rq_disk == bio->bi_bdev->bd_disk &&
!rq->waiting && !rq->special)
if (rq->rq_disk == bio->bi_bdev->bd_disk && !rq->special)
return 1;
return 0;
......@@ -151,27 +161,44 @@ __setup("elevator=", elevator_setup);
static struct kobj_type elv_ktype;
static elevator_t *elevator_alloc(struct elevator_type *e)
{
elevator_t *eq = kmalloc(sizeof(elevator_t), GFP_KERNEL);
if (eq) {
memset(eq, 0, sizeof(*eq));
eq->ops = &e->ops;
eq->elevator_type = e;
kobject_init(&eq->kobj);
snprintf(eq->kobj.name, KOBJ_NAME_LEN, "%s", "iosched");
eq->kobj.ktype = &elv_ktype;
mutex_init(&eq->sysfs_lock);
} else {
elevator_put(e);
}
static elevator_t *elevator_alloc(request_queue_t *q, struct elevator_type *e)
{
elevator_t *eq;
int i;
eq = kmalloc_node(sizeof(elevator_t), GFP_KERNEL, q->node);
if (unlikely(!eq))
goto err;
memset(eq, 0, sizeof(*eq));
eq->ops = &e->ops;
eq->elevator_type = e;
kobject_init(&eq->kobj);
snprintf(eq->kobj.name, KOBJ_NAME_LEN, "%s", "iosched");
eq->kobj.ktype = &elv_ktype;
mutex_init(&eq->sysfs_lock);
eq->hash = kmalloc_node(sizeof(struct hlist_head) * ELV_HASH_ENTRIES,
GFP_KERNEL, q->node);
if (!eq->hash)
goto err;
for (i = 0; i < ELV_HASH_ENTRIES; i++)
INIT_HLIST_HEAD(&eq->hash[i]);
return eq;
err:
kfree(eq);
elevator_put(e);
return NULL;
}
static void elevator_release(struct kobject *kobj)
{
elevator_t *e = container_of(kobj, elevator_t, kobj);
elevator_put(e->elevator_type);
kfree(e->hash);
kfree(e);
}
......@@ -198,7 +225,7 @@ int elevator_init(request_queue_t *q, char *name)
e = elevator_get("noop");
}
eq = elevator_alloc(e);
eq = elevator_alloc(q, e);
if (!eq)
return -ENOMEM;
......@@ -212,6 +239,8 @@ int elevator_init(request_queue_t *q, char *name)
return ret;
}
EXPORT_SYMBOL(elevator_init);
void elevator_exit(elevator_t *e)
{
mutex_lock(&e->sysfs_lock);
......@@ -223,10 +252,118 @@ void elevator_exit(elevator_t *e)
kobject_put(&e->kobj);
}
EXPORT_SYMBOL(elevator_exit);
static inline void __elv_rqhash_del(struct request *rq)
{
hlist_del_init(&rq->hash);
}
static void elv_rqhash_del(request_queue_t *q, struct request *rq)
{
if (ELV_ON_HASH(rq))
__elv_rqhash_del(rq);
}
static void elv_rqhash_add(request_queue_t *q, struct request *rq)
{
elevator_t *e = q->elevator;
BUG_ON(ELV_ON_HASH(rq));
hlist_add_head(&rq->hash, &e->hash[ELV_HASH_FN(rq_hash_key(rq))]);
}
static void elv_rqhash_reposition(request_queue_t *q, struct request *rq)
{
__elv_rqhash_del(rq);
elv_rqhash_add(q, rq);
}
static struct request *elv_rqhash_find(request_queue_t *q, sector_t offset)
{
elevator_t *e = q->elevator;
struct hlist_head *hash_list = &e->hash[ELV_HASH_FN(offset)];
struct hlist_node *entry, *next;
struct request *rq;
hlist_for_each_entry_safe(rq, entry, next, hash_list, hash) {
BUG_ON(!ELV_ON_HASH(rq));
if (unlikely(!rq_mergeable(rq))) {
__elv_rqhash_del(rq);
continue;
}
if (rq_hash_key(rq) == offset)
return rq;
}
return NULL;
}
/*
* RB-tree support functions for inserting/lookup/removal of requests
* in a sorted RB tree.
*/
struct request *elv_rb_add(struct rb_root *root, struct request *rq)
{
struct rb_node **p = &root->rb_node;
struct rb_node *parent = NULL;
struct request *__rq;
while (*p) {
parent = *p;
__rq = rb_entry(parent, struct request, rb_node);
if (rq->sector < __rq->sector)
p = &(*p)->rb_left;
else if (rq->sector > __rq->sector)
p = &(*p)->rb_right;
else
return __rq;
}
rb_link_node(&rq->rb_node, parent, p);
rb_insert_color(&rq->rb_node, root);
return NULL;
}
EXPORT_SYMBOL(elv_rb_add);
void elv_rb_del(struct rb_root *root, struct request *rq)
{
BUG_ON(RB_EMPTY_NODE(&rq->rb_node));
rb_erase(&rq->rb_node, root);
RB_CLEAR_NODE(&rq->rb_node);
}
EXPORT_SYMBOL(elv_rb_del);
struct request *elv_rb_find(struct rb_root *root, sector_t sector)
{
struct rb_node *n = root->rb_node;
struct request *rq;
while (n) {
rq = rb_entry(n, struct request, rb_node);
if (sector < rq->sector)
n = n->rb_left;
else if (sector > rq->sector)
n = n->rb_right;
else
return rq;
}
return NULL;
}
EXPORT_SYMBOL(elv_rb_find);
/*
* Insert rq into dispatch queue of q. Queue lock must be held on
* entry. If sort != 0, rq is sort-inserted; otherwise, rq will be
* appended to the dispatch queue. To be used by specific elevators.
* entry. rq is sort insted into the dispatch queue. To be used by
* specific elevators.
*/
void elv_dispatch_sort(request_queue_t *q, struct request *rq)
{
......@@ -235,6 +372,9 @@ void elv_dispatch_sort(request_queue_t *q, struct request *rq)
if (q->last_merge == rq)
q->last_merge = NULL;
elv_rqhash_del(q, rq);
q->nr_sorted--;
boundary = q->end_sector;
......@@ -242,7 +382,7 @@ void elv_dispatch_sort(request_queue_t *q, struct request *rq)
list_for_each_prev(entry, &q->queue_head) {
struct request *pos = list_entry_rq(entry);
if (pos->flags & (REQ_SOFTBARRIER|REQ_HARDBARRIER|REQ_STARTED))
if (pos->cmd_flags & (REQ_SOFTBARRIER|REQ_HARDBARRIER|REQ_STARTED))
break;
if (rq->sector >= boundary) {
if (pos->sector < boundary)
......@@ -258,11 +398,38 @@ void elv_dispatch_sort(request_queue_t *q, struct request *rq)
list_add(&rq->queuelist, entry);
}
EXPORT_SYMBOL(elv_dispatch_sort);
/*
* Insert rq into dispatch queue of q. Queue lock must be held on
* entry. rq is added to the back of the dispatch queue. To be used by
* specific elevators.
*/
void elv_dispatch_add_tail(struct request_queue *q, struct request *rq)
{
if (q->last_merge == rq)
q->last_merge = NULL;
elv_rqhash_del(q, rq);
q->nr_sorted--;
q->end_sector = rq_end_sector(rq);
q->boundary_rq = rq;
list_add_tail(&rq->queuelist, &q->queue_head);
}
EXPORT_SYMBOL(elv_dispatch_add_tail);
int elv_merge(request_queue_t *q, struct request **req, struct bio *bio)
{
elevator_t *e = q->elevator;
struct request *__rq;
int ret;
/*
* First try one-hit cache.
*/
if (q->last_merge) {
ret = elv_try_merge(q->last_merge, bio);
if (ret != ELEVATOR_NO_MERGE) {
......@@ -271,18 +438,30 @@ int elv_merge(request_queue_t *q, struct request **req, struct bio *bio)
}
}
/*
* See if our hash lookup can find a potential backmerge.
*/
__rq = elv_rqhash_find(q, bio->bi_sector);
if (__rq && elv_rq_merge_ok(__rq, bio)) {
*req = __rq;
return ELEVATOR_BACK_MERGE;
}
if (e->ops->elevator_merge_fn)
return e->ops->elevator_merge_fn(q, req, bio);
return ELEVATOR_NO_MERGE;
}
void elv_merged_request(request_queue_t *q, struct request *rq)
void elv_merged_request(request_queue_t *q, struct request *rq, int type)
{
elevator_t *e = q->elevator;
if (e->ops->elevator_merged_fn)
e->ops->elevator_merged_fn(q, rq);
e->ops->elevator_merged_fn(q, rq, type);
if (type == ELEVATOR_BACK_MERGE)
elv_rqhash_reposition(q, rq);
q->last_merge = rq;
}
......@@ -294,8 +473,11 @@ void elv_merge_requests(request_queue_t *q, struct request *rq,
if (e->ops->elevator_merge_req_fn)
e->ops->elevator_merge_req_fn(q, rq, next);
q->nr_sorted--;
elv_rqhash_reposition(q, rq);
elv_rqhash_del(q, next);
q->nr_sorted--;
q->last_merge = rq;
}
......@@ -313,7 +495,7 @@ void elv_requeue_request(request_queue_t *q, struct request *rq)
e->ops->elevator_deactivate_req_fn(q, rq);
}
rq->flags &= ~REQ_STARTED;
rq->cmd_flags &= ~REQ_STARTED;
elv_insert(q, rq, ELEVATOR_INSERT_REQUEUE);
}
......@@ -344,13 +526,13 @@ void elv_insert(request_queue_t *q, struct request *rq, int where)
switch (where) {
case ELEVATOR_INSERT_FRONT:
rq->flags |= REQ_SOFTBARRIER;
rq->cmd_flags |= REQ_SOFTBARRIER;
list_add(&rq->queuelist, &q->queue_head);
break;
case ELEVATOR_INSERT_BACK:
rq->flags |= REQ_SOFTBARRIER;
rq->cmd_flags |= REQ_SOFTBARRIER;
elv_drain_elevator(q);
list_add_tail(&rq->queuelist, &q->queue_head);
/*
......@@ -369,10 +551,14 @@ void elv_insert(request_queue_t *q, struct request *rq, int where)
case ELEVATOR_INSERT_SORT:
BUG_ON(!blk_fs_request(rq));
rq->flags |= REQ_SORTED;
rq->cmd_flags |= REQ_SORTED;
q->nr_sorted++;
if (q->last_merge == NULL && rq_mergeable(rq))
q->last_merge = rq;
if (rq_mergeable(rq)) {
elv_rqhash_add(q, rq);
if (!q->last_merge)
q->last_merge = rq;
}
/*
* Some ioscheds (cfq) run q->request_fn directly, so
* rq cannot be accessed after calling
......@@ -387,7 +573,7 @@ void elv_insert(request_queue_t *q, struct request *rq, int where)
* insertion; otherwise, requests should be requeued
* in ordseq order.
*/
rq->flags |= REQ_SOFTBARRIER;
rq->cmd_flags |= REQ_SOFTBARRIER;
if (q->ordseq == 0) {
list_add(&rq->queuelist, &q->queue_head);
......@@ -429,9 +615,9 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where,
int plug)
{
if (q->ordcolor)
rq->flags |= REQ_ORDERED_COLOR;
rq->cmd_flags |= REQ_ORDERED_COLOR;
if (rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)) {
if (rq->cmd_flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)) {
/*
* toggle ordered color
*/
......@@ -452,7 +638,7 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where,
q->end_sector = rq_end_sector(rq);
q->boundary_rq = rq;
}
} else if (!(rq->flags & REQ_ELVPRIV) && where == ELEVATOR_INSERT_SORT)
} else if (!(rq->cmd_flags & REQ_ELVPRIV) && where == ELEVATOR_INSERT_SORT)
where = ELEVATOR_INSERT_BACK;
if (plug)
......@@ -461,6 +647,8 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where,
elv_insert(q, rq, where);
}
EXPORT_SYMBOL(__elv_add_request);
void elv_add_request(request_queue_t *q, struct request *rq, int where,
int plug)
{
......@@ -471,6 +659,8 @@ void elv_add_request(request_queue_t *q, struct request *rq, int where,
spin_unlock_irqrestore(q->queue_lock, flags);
}
EXPORT_SYMBOL(elv_add_request);
static inline struct request *__elv_next_request(request_queue_t *q)
{
struct request *rq;
......@@ -493,7 +683,7 @@ struct request *elv_next_request(request_queue_t *q)
int ret;
while ((rq = __elv_next_request(q)) != NULL) {
if (!(rq->flags & REQ_STARTED)) {
if (!(rq->cmd_flags & REQ_STARTED)) {
elevator_t *e = q->elevator;
/*
......@@ -510,7 +700,7 @@ struct request *elv_next_request(request_queue_t *q)
* it, a request that has been delayed should
* not be passed by new incoming requests
*/
rq->flags |= REQ_STARTED;
rq->cmd_flags |= REQ_STARTED;
blk_add_trace_rq(q, rq, BLK_TA_ISSUE);
}
......@@ -519,7 +709,7 @@ struct request *elv_next_request(request_queue_t *q)
q->boundary_rq = NULL;
}
if ((rq->flags & REQ_DONTPREP) || !q->prep_rq_fn)
if ((rq->cmd_flags & REQ_DONTPREP) || !q->prep_rq_fn)
break;
ret = q->prep_rq_fn(q, rq);
......@@ -541,7 +731,7 @@ struct request *elv_next_request(request_queue_t *q)
nr_bytes = rq->data_len;
blkdev_dequeue_request(rq);
rq->flags |= REQ_QUIET;
rq->cmd_flags |= REQ_QUIET;
end_that_request_chunk(rq, 0, nr_bytes);
end_that_request_last(rq, 0);
} else {
......@@ -554,9 +744,12 @@ struct request *elv_next_request(request_queue_t *q)
return rq;
}
EXPORT_SYMBOL(elv_next_request);
void elv_dequeue_request(request_queue_t *q, struct request *rq)
{
BUG_ON(list_empty(&rq->queuelist));
BUG_ON(ELV_ON_HASH(rq));
list_del_init(&rq->queuelist);
......@@ -569,6 +762,8 @@ void elv_dequeue_request(request_queue_t *q, struct request *rq)
q->in_flight++;
}
EXPORT_SYMBOL(elv_dequeue_request);
int elv_queue_empty(request_queue_t *q)
{
elevator_t *e = q->elevator;
......@@ -582,6 +777,8 @@ int elv_queue_empty(request_queue_t *q)
return 1;
}
EXPORT_SYMBOL(elv_queue_empty);
struct request *elv_latter_request(request_queue_t *q, struct request *rq)
{
elevator_t *e = q->elevator;
......@@ -600,13 +797,12 @@ struct request *elv_former_request(request_queue_t *q, struct request *rq)
return NULL;
}
int elv_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
gfp_t gfp_mask)
int elv_set_request(request_queue_t *q, struct request *rq, gfp_t gfp_mask)
{
elevator_t *e = q->elevator;
if (e->ops->elevator_set_req_fn)
return e->ops->elevator_set_req_fn(q, rq, bio, gfp_mask);
return e->ops->elevator_set_req_fn(q, rq, gfp_mask);
rq->elevator_private = NULL;
return 0;
......@@ -620,12 +816,12 @@ void elv_put_request(request_queue_t *q, struct request *rq)
e->ops->elevator_put_req_fn(q, rq);
}
int elv_may_queue(request_queue_t *q, int rw, struct bio *bio)
int elv_may_queue(request_queue_t *q, int rw)
{
elevator_t *e = q->elevator;
if (e->ops->elevator_may_queue_fn)
return e->ops->elevator_may_queue_fn(q, rw, bio);
return e->ops->elevator_may_queue_fn(q, rw);
return ELV_MQUEUE_MAY;
}
......@@ -792,7 +988,7 @@ static int elevator_switch(request_queue_t *q, struct elevator_type *new_e)
/*
* Allocate new elevator
*/
e = elevator_alloc(new_e);
e = elevator_alloc(q, new_e);
if (!e)
return 0;
......@@ -908,11 +1104,26 @@ ssize_t elv_iosched_show(request_queue_t *q, char *name)
return len;
}
EXPORT_SYMBOL(elv_dispatch_sort);
EXPORT_SYMBOL(elv_add_request);
EXPORT_SYMBOL(__elv_add_request);
EXPORT_SYMBOL(elv_next_request);
EXPORT_SYMBOL(elv_dequeue_request);
EXPORT_SYMBOL(elv_queue_empty);
EXPORT_SYMBOL(elevator_exit);
EXPORT_SYMBOL(elevator_init);
struct request *elv_rb_former_request(request_queue_t *q, struct request *rq)
{
struct rb_node *rbprev = rb_prev(&rq->rb_node);
if (rbprev)
return rb_entry_rq(rbprev);
return NULL;
}
EXPORT_SYMBOL(elv_rb_former_request);
struct request *elv_rb_latter_request(request_queue_t *q, struct request *rq)
{
struct rb_node *rbnext = rb_next(&rq->rb_node);
if (rbnext)
return rb_entry_rq(rbnext);
return NULL;
}
EXPORT_SYMBOL(elv_rb_latter_request);
......@@ -39,6 +39,7 @@ static void blk_unplug_timeout(unsigned long data);
static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io);
static void init_request_from_bio(struct request *req, struct bio *bio);
static int __make_request(request_queue_t *q, struct bio *bio);
static struct io_context *current_io_context(gfp_t gfp_flags, int node);
/*
* For the allocated request tables
......@@ -277,19 +278,19 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
EXPORT_SYMBOL(blk_queue_make_request);
static inline void rq_init(request_queue_t *q, struct request *rq)
static void rq_init(request_queue_t *q, struct request *rq)
{
INIT_LIST_HEAD(&rq->queuelist);
INIT_LIST_HEAD(&rq->donelist);
rq->errors = 0;
rq->rq_status = RQ_ACTIVE;
rq->bio = rq->biotail = NULL;
INIT_HLIST_NODE(&rq->hash);
RB_CLEAR_NODE(&rq->rb_node);
rq->ioprio = 0;
rq->buffer = NULL;
rq->ref_count = 1;
rq->q = q;
rq->waiting = NULL;
rq->special = NULL;
rq->data_len = 0;
rq->data = NULL;
......@@ -382,8 +383,8 @@ unsigned blk_ordered_req_seq(struct request *rq)
if (rq == &q->post_flush_rq)
return QUEUE_ORDSEQ_POSTFLUSH;
if ((rq->flags & REQ_ORDERED_COLOR) ==
(q->orig_bar_rq->flags & REQ_ORDERED_COLOR))
if ((rq->cmd_flags & REQ_ORDERED_COLOR) ==
(q->orig_bar_rq->cmd_flags & REQ_ORDERED_COLOR))
return QUEUE_ORDSEQ_DRAIN;
else
return QUEUE_ORDSEQ_DONE;
......@@ -446,11 +447,11 @@ static void queue_flush(request_queue_t *q, unsigned which)
end_io = post_flush_end_io;
}
rq->cmd_flags = REQ_HARDBARRIER;
rq_init(q, rq);
rq->flags = REQ_HARDBARRIER;
rq->elevator_private = NULL;
rq->elevator_private2 = NULL;
rq->rq_disk = q->bar_rq.rq_disk;
rq->rl = NULL;
rq->end_io = end_io;
q->prepare_flush_fn(q, rq);
......@@ -471,11 +472,13 @@ static inline struct request *start_ordered(request_queue_t *q,
blkdev_dequeue_request(rq);
q->orig_bar_rq = rq;
rq = &q->bar_rq;
rq->cmd_flags = 0;
rq_init(q, rq);
rq->flags = bio_data_dir(q->orig_bar_rq->bio);
rq->flags |= q->ordered & QUEUE_ORDERED_FUA ? REQ_FUA : 0;
if (bio_data_dir(q->orig_bar_rq->bio) == WRITE)
rq->cmd_flags |= REQ_RW;
rq->cmd_flags |= q->ordered & QUEUE_ORDERED_FUA ? REQ_FUA : 0;
rq->elevator_private = NULL;
rq->rl = NULL;
rq->elevator_private2 = NULL;
init_request_from_bio(rq, q->orig_bar_rq->bio);
rq->end_io = bar_end_io;
......@@ -587,8 +590,8 @@ static int flush_dry_bio_endio(struct bio *bio, unsigned int bytes, int error)
return 0;
}
static inline int ordered_bio_endio(struct request *rq, struct bio *bio,
unsigned int nbytes, int error)
static int ordered_bio_endio(struct request *rq, struct bio *bio,
unsigned int nbytes, int error)
{
request_queue_t *q = rq->q;
bio_end_io_t *endio;
......@@ -1124,7 +1127,7 @@ void blk_queue_end_tag(request_queue_t *q, struct request *rq)
}
list_del_init(&rq->queuelist);
rq->flags &= ~REQ_QUEUED;
rq->cmd_flags &= ~REQ_QUEUED;
rq->tag = -1;
if (unlikely(bqt->tag_index[tag] == NULL))
......@@ -1160,7 +1163,7 @@ int blk_queue_start_tag(request_queue_t *q, struct request *rq)
struct blk_queue_tag *bqt = q->queue_tags;
int tag;
if (unlikely((rq->flags & REQ_QUEUED))) {
if (unlikely((rq->cmd_flags & REQ_QUEUED))) {
printk(KERN_ERR
"%s: request %p for device [%s] already tagged %d",
__FUNCTION__, rq,
......@@ -1168,13 +1171,18 @@ int blk_queue_start_tag(request_queue_t *q, struct request *rq)
BUG();
}
tag = find_first_zero_bit(bqt->tag_map, bqt->max_depth);
if (tag >= bqt->max_depth)
return 1;
/*
* Protect against shared tag maps, as we may not have exclusive
* access to the tag map.
*/
do {
tag = find_first_zero_bit(bqt->tag_map, bqt->max_depth);
if (tag >= bqt->max_depth)
return 1;
__set_bit(tag, bqt->tag_map);
} while (test_and_set_bit(tag, bqt->tag_map));
rq->flags |= REQ_QUEUED;
rq->cmd_flags |= REQ_QUEUED;
rq->tag = tag;
bqt->tag_index[tag] = rq;
blkdev_dequeue_request(rq);
......@@ -1210,65 +1218,31 @@ void blk_queue_invalidate_tags(request_queue_t *q)
printk(KERN_ERR
"%s: bad tag found on list\n", __FUNCTION__);
list_del_init(&rq->queuelist);
rq->flags &= ~REQ_QUEUED;
rq->cmd_flags &= ~REQ_QUEUED;
} else
blk_queue_end_tag(q, rq);
rq->flags &= ~REQ_STARTED;
rq->cmd_flags &= ~REQ_STARTED;
__elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 0);
}
}
EXPORT_SYMBOL(blk_queue_invalidate_tags);
static const char * const rq_flags[] = {
"REQ_RW",
"REQ_FAILFAST",
"REQ_SORTED",
"REQ_SOFTBARRIER",
"REQ_HARDBARRIER",
"REQ_FUA",
"REQ_CMD",
"REQ_NOMERGE",
"REQ_STARTED",
"REQ_DONTPREP",
"REQ_QUEUED",
"REQ_ELVPRIV",
"REQ_PC",
"REQ_BLOCK_PC",
"REQ_SENSE",
"REQ_FAILED",
"REQ_QUIET",
"REQ_SPECIAL",
"REQ_DRIVE_CMD",
"REQ_DRIVE_TASK",
"REQ_DRIVE_TASKFILE",
"REQ_PREEMPT",
"REQ_PM_SUSPEND",
"REQ_PM_RESUME",
"REQ_PM_SHUTDOWN",
"REQ_ORDERED_COLOR",
};
void blk_dump_rq_flags(struct request *rq, char *msg)
{
int bit;
printk("%s: dev %s: flags = ", msg,
rq->rq_disk ? rq->rq_disk->disk_name : "?");
bit = 0;
do {
if (rq->flags & (1 << bit))
printk("%s ", rq_flags[bit]);
bit++;
} while (bit < __REQ_NR_BITS);
printk("%s: dev %s: type=%x, flags=%x\n", msg,
rq->rq_disk ? rq->rq_disk->disk_name : "?", rq->cmd_type,
rq->cmd_flags);
printk("\nsector %llu, nr/cnr %lu/%u\n", (unsigned long long)rq->sector,
rq->nr_sectors,
rq->current_nr_sectors);
printk("bio %p, biotail %p, buffer %p, data %p, len %u\n", rq->bio, rq->biotail, rq->buffer, rq->data, rq->data_len);
if (rq->flags & (REQ_BLOCK_PC | REQ_PC)) {
if (blk_pc_request(rq)) {
printk("cdb: ");
for (bit = 0; bit < sizeof(rq->cmd); bit++)
printk("%02x ", rq->cmd[bit]);
......@@ -1441,7 +1415,7 @@ static inline int ll_new_mergeable(request_queue_t *q,
int nr_phys_segs = bio_phys_segments(q, bio);
if (req->nr_phys_segments + nr_phys_segs > q->max_phys_segments) {
req->flags |= REQ_NOMERGE;
req->cmd_flags |= REQ_NOMERGE;
if (req == q->last_merge)
q->last_merge = NULL;
return 0;
......@@ -1464,7 +1438,7 @@ static inline int ll_new_hw_segment(request_queue_t *q,
if (req->nr_hw_segments + nr_hw_segs > q->max_hw_segments
|| req->nr_phys_segments + nr_phys_segs > q->max_phys_segments) {
req->flags |= REQ_NOMERGE;
req->cmd_flags |= REQ_NOMERGE;
if (req == q->last_merge)
q->last_merge = NULL;
return 0;
......@@ -1491,7 +1465,7 @@ static int ll_back_merge_fn(request_queue_t *q, struct request *req,
max_sectors = q->max_sectors;
if (req->nr_sectors + bio_sectors(bio) > max_sectors) {
req->flags |= REQ_NOMERGE;
req->cmd_flags |= REQ_NOMERGE;
if (req == q->last_merge)
q->last_merge = NULL;
return 0;
......@@ -1530,7 +1504,7 @@ static int ll_front_merge_fn(request_queue_t *q, struct request *req,
if (req->nr_sectors + bio_sectors(bio) > max_sectors) {
req->flags |= REQ_NOMERGE;
req->cmd_flags |= REQ_NOMERGE;
if (req == q->last_merge)
q->last_merge = NULL;
return 0;
......@@ -2029,14 +2003,13 @@ EXPORT_SYMBOL(blk_get_queue);
static inline void blk_free_request(request_queue_t *q, struct request *rq)
{
if (rq->flags & REQ_ELVPRIV)
if (rq->cmd_flags & REQ_ELVPRIV)
elv_put_request(q, rq);
mempool_free(rq, q->rq.rq_pool);
}
static inline struct request *
blk_alloc_request(request_queue_t *q, int rw, struct bio *bio,
int priv, gfp_t gfp_mask)
static struct request *
blk_alloc_request(request_queue_t *q, int rw, int priv, gfp_t gfp_mask)
{
struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask);
......@@ -2044,17 +2017,17 @@ blk_alloc_request(request_queue_t *q, int rw, struct bio *bio,
return NULL;
/*
* first three bits are identical in rq->flags and bio->bi_rw,
* first three bits are identical in rq->cmd_flags and bio->bi_rw,
* see bio.h and blkdev.h
*/
rq->flags = rw;
rq->cmd_flags = rw | REQ_ALLOCED;
if (priv) {
if (unlikely(elv_set_request(q, rq, bio, gfp_mask))) {
if (unlikely(elv_set_request(q, rq, gfp_mask))) {
mempool_free(rq, q->rq.rq_pool);
return NULL;
}
rq->flags |= REQ_ELVPRIV;
rq->cmd_flags |= REQ_ELVPRIV;
}
return rq;
......@@ -2141,13 +2114,13 @@ static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
struct io_context *ioc = NULL;
int may_queue, priv;
may_queue = elv_may_queue(q, rw, bio);
may_queue = elv_may_queue(q, rw);
if (may_queue == ELV_MQUEUE_NO)
goto rq_starved;
if (rl->count[rw]+1 >= queue_congestion_on_threshold(q)) {
if (rl->count[rw]+1 >= q->nr_requests) {
ioc = current_io_context(GFP_ATOMIC);
ioc = current_io_context(GFP_ATOMIC, q->node);
/*
* The queue will fill after this allocation, so set
* it as full, and mark this process as "batching".
......@@ -2189,7 +2162,7 @@ static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
spin_unlock_irq(q->queue_lock);
rq = blk_alloc_request(q, rw, bio, priv, gfp_mask);
rq = blk_alloc_request(q, rw, priv, gfp_mask);
if (unlikely(!rq)) {
/*
* Allocation failed presumably due to memory. Undo anything
......@@ -2225,7 +2198,6 @@ static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
ioc->nr_batch_requests--;
rq_init(q, rq);
rq->rl = rl;
blk_add_trace_generic(q, bio, rw, BLK_TA_GETRQ);
out:
......@@ -2268,7 +2240,7 @@ static struct request *get_request_wait(request_queue_t *q, int rw,
* up to a big batch of them for a small period time.
* See ioc_batching, ioc_set_batching
*/
ioc = current_io_context(GFP_NOIO);
ioc = current_io_context(GFP_NOIO, q->node);
ioc_set_batching(q, ioc);
spin_lock_irq(q->queue_lock);
......@@ -2299,6 +2271,25 @@ struct request *blk_get_request(request_queue_t *q, int rw, gfp_t gfp_mask)
}
EXPORT_SYMBOL(blk_get_request);
/**
* blk_start_queueing - initiate dispatch of requests to device
* @q: request queue to kick into gear
*
* This is basically a helper to remove the need to know whether a queue
* is plugged or not if someone just wants to initiate dispatch of requests
* for this queue.
*
* The queue lock must be held with interrupts disabled.
*/
void blk_start_queueing(request_queue_t *q)
{
if (!blk_queue_plugged(q))
q->request_fn(q);
else
__generic_unplug_device(q);
}
EXPORT_SYMBOL(blk_start_queueing);
/**
* blk_requeue_request - put a request back on queue
* @q: request queue where request should be inserted
......@@ -2351,7 +2342,8 @@ void blk_insert_request(request_queue_t *q, struct request *rq,
* must not attempt merges on this) and that it acts as a soft
* barrier
*/
rq->flags |= REQ_SPECIAL | REQ_SOFTBARRIER;
rq->cmd_type = REQ_TYPE_SPECIAL;
rq->cmd_flags |= REQ_SOFTBARRIER;
rq->special = data;
......@@ -2365,11 +2357,7 @@ void blk_insert_request(request_queue_t *q, struct request *rq,
drive_stat_acct(rq, rq->nr_sectors, 1);
__elv_add_request(q, rq, where, 0);
if (blk_queue_plugged(q))
__generic_unplug_device(q);
else
q->request_fn(q);
blk_start_queueing(q);
spin_unlock_irqrestore(q->queue_lock, flags);
}
......@@ -2558,7 +2546,7 @@ void blk_execute_rq_nowait(request_queue_t *q, struct gendisk *bd_disk,
int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
rq->rq_disk = bd_disk;
rq->flags |= REQ_NOMERGE;
rq->cmd_flags |= REQ_NOMERGE;
rq->end_io = done;
WARN_ON(irqs_disabled());
spin_lock_irq(q->queue_lock);
......@@ -2598,10 +2586,9 @@ int blk_execute_rq(request_queue_t *q, struct gendisk *bd_disk,
rq->sense_len = 0;
}
rq->waiting = &wait;
rq->end_io_data = &wait;
blk_execute_rq_nowait(q, bd_disk, rq, at_head, blk_end_sync_rq);
wait_for_completion(&wait);
rq->waiting = NULL;
if (rq->errors)
err = -EIO;
......@@ -2710,8 +2697,6 @@ EXPORT_SYMBOL_GPL(disk_round_stats);
*/
void __blk_put_request(request_queue_t *q, struct request *req)
{
struct request_list *rl = req->rl;
if (unlikely(!q))
return;
if (unlikely(--req->ref_count))
......@@ -2719,18 +2704,16 @@ void __blk_put_request(request_queue_t *q, struct request *req)
elv_completed_request(q, req);
req->rq_status = RQ_INACTIVE;
req->rl = NULL;
/*
* Request may not have originated from ll_rw_blk. if not,
* it didn't come out of our reserved rq pools
*/
if (rl) {
if (req->cmd_flags & REQ_ALLOCED) {
int rw = rq_data_dir(req);
int priv = req->flags & REQ_ELVPRIV;
int priv = req->cmd_flags & REQ_ELVPRIV;
BUG_ON(!list_empty(&req->queuelist));
BUG_ON(!hlist_unhashed(&req->hash));
blk_free_request(q, req);
freed_request(q, rw, priv);
......@@ -2764,9 +2747,9 @@ EXPORT_SYMBOL(blk_put_request);
*/
void blk_end_sync_rq(struct request *rq, int error)
{
struct completion *waiting = rq->waiting;
struct completion *waiting = rq->end_io_data;
rq->waiting = NULL;
rq->end_io_data = NULL;
__blk_put_request(rq->q, rq);
/*
......@@ -2829,7 +2812,7 @@ static int attempt_merge(request_queue_t *q, struct request *req,
if (rq_data_dir(req) != rq_data_dir(next)
|| req->rq_disk != next->rq_disk
|| next->waiting || next->special)
|| next->special)
return 0;
/*
......@@ -2890,22 +2873,24 @@ static inline int attempt_front_merge(request_queue_t *q, struct request *rq)
static void init_request_from_bio(struct request *req, struct bio *bio)
{
req->flags |= REQ_CMD;
req->cmd_type = REQ_TYPE_FS;
/*
* inherit FAILFAST from bio (for read-ahead, and explicit FAILFAST)
*/
if (bio_rw_ahead(bio) || bio_failfast(bio))
req->flags |= REQ_FAILFAST;
req->cmd_flags |= REQ_FAILFAST;
/*
* REQ_BARRIER implies no merging, but lets make it explicit
*/
if (unlikely(bio_barrier(bio)))
req->flags |= (REQ_HARDBARRIER | REQ_NOMERGE);
req->cmd_flags |= (REQ_HARDBARRIER | REQ_NOMERGE);
if (bio_sync(bio))
req->flags |= REQ_RW_SYNC;
req->cmd_flags |= REQ_RW_SYNC;
if (bio_rw_meta(bio))
req->cmd_flags |= REQ_RW_META;
req->errors = 0;
req->hard_sector = req->sector = bio->bi_sector;
......@@ -2914,7 +2899,6 @@ static void init_request_from_bio(struct request *req, struct bio *bio)
req->nr_phys_segments = bio_phys_segments(req->q, bio);
req->nr_hw_segments = bio_hw_segments(req->q, bio);
req->buffer = bio_data(bio); /* see ->buffer comment above */
req->waiting = NULL;
req->bio = req->biotail = bio;
req->ioprio = bio_prio(bio);
req->rq_disk = bio->bi_bdev->bd_disk;
......@@ -2924,17 +2908,11 @@ static void init_request_from_bio(struct request *req, struct bio *bio)
static int __make_request(request_queue_t *q, struct bio *bio)
{
struct request *req;
int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, err, sync;
unsigned short prio;
sector_t sector;
int el_ret, nr_sectors, barrier, err;
const unsigned short prio = bio_prio(bio);
const int sync = bio_sync(bio);
sector = bio->bi_sector;
nr_sectors = bio_sectors(bio);
cur_nr_sectors = bio_cur_sectors(bio);
prio = bio_prio(bio);
rw = bio_data_dir(bio);
sync = bio_sync(bio);
/*
* low level driver can indicate that it wants pages above a
......@@ -2943,8 +2921,6 @@ static int __make_request(request_queue_t *q, struct bio *bio)
*/
blk_queue_bounce(q, &bio);
spin_lock_prefetch(q->queue_lock);
barrier = bio_barrier(bio);
if (unlikely(barrier) && (q->next_ordered == QUEUE_ORDERED_NONE)) {
err = -EOPNOTSUPP;
......@@ -2972,7 +2948,7 @@ static int __make_request(request_queue_t *q, struct bio *bio)
req->ioprio = ioprio_best(req->ioprio, prio);
drive_stat_acct(req, nr_sectors, 0);
if (!attempt_back_merge(q, req))
elv_merged_request(q, req);
elv_merged_request(q, req, el_ret);
goto out;
case ELEVATOR_FRONT_MERGE:
......@@ -2992,14 +2968,14 @@ static int __make_request(request_queue_t *q, struct bio *bio)
* not touch req->buffer either...
*/
req->buffer = bio_data(bio);
req->current_nr_sectors = cur_nr_sectors;
req->hard_cur_sectors = cur_nr_sectors;
req->sector = req->hard_sector = sector;
req->current_nr_sectors = bio_cur_sectors(bio);
req->hard_cur_sectors = req->current_nr_sectors;
req->sector = req->hard_sector = bio->bi_sector;
req->nr_sectors = req->hard_nr_sectors += nr_sectors;
req->ioprio = ioprio_best(req->ioprio, prio);
drive_stat_acct(req, nr_sectors, 0);
if (!attempt_front_merge(q, req))
elv_merged_request(q, req);
elv_merged_request(q, req, el_ret);
goto out;
/* ELV_NO_MERGE: elevator says don't/can't merge. */
......@@ -3012,7 +2988,7 @@ static int __make_request(request_queue_t *q, struct bio *bio)
* Grab a free request. This is might sleep but can not fail.
* Returns with the queue unlocked.
*/
req = get_request_wait(q, rw, bio);
req = get_request_wait(q, bio_data_dir(bio), bio);
/*
* After dropping the lock and possibly sleeping here, our request
......@@ -3306,7 +3282,7 @@ static int __end_that_request_first(struct request *req, int uptodate,
req->errors = 0;
if (!uptodate) {
if (blk_fs_request(req) && !(req->flags & REQ_QUIET))
if (blk_fs_request(req) && !(req->cmd_flags & REQ_QUIET))
printk("end_request: I/O error, dev %s, sector %llu\n",
req->rq_disk ? req->rq_disk->disk_name : "?",
(unsigned long long)req->sector);
......@@ -3569,8 +3545,8 @@ EXPORT_SYMBOL(end_request);
void blk_rq_bio_prep(request_queue_t *q, struct request *rq, struct bio *bio)
{
/* first two bits are identical in rq->flags and bio->bi_rw */
rq->flags |= (bio->bi_rw & 3);
/* first two bits are identical in rq->cmd_flags and bio->bi_rw */
rq->cmd_flags |= (bio->bi_rw & 3);
rq->nr_phys_segments = bio_phys_segments(q, bio);
rq->nr_hw_segments = bio_hw_segments(q, bio);
......@@ -3658,25 +3634,22 @@ EXPORT_SYMBOL(put_io_context);
/* Called by the exitting task */
void exit_io_context(void)
{
unsigned long flags;
struct io_context *ioc;
struct cfq_io_context *cic;
local_irq_save(flags);
task_lock(current);
ioc = current->io_context;
current->io_context = NULL;
ioc->task = NULL;
task_unlock(current);
local_irq_restore(flags);
ioc->task = NULL;
if (ioc->aic && ioc->aic->exit)
ioc->aic->exit(ioc->aic);
if (ioc->cic_root.rb_node != NULL) {
cic = rb_entry(rb_first(&ioc->cic_root), struct cfq_io_context, rb_node);
cic->exit(ioc);
}
put_io_context(ioc);
}
......@@ -3688,7 +3661,7 @@ void exit_io_context(void)
* but since the current task itself holds a reference, the context can be
* used in general code, so long as it stays within `current` context.
*/
struct io_context *current_io_context(gfp_t gfp_flags)
static struct io_context *current_io_context(gfp_t gfp_flags, int node)
{
struct task_struct *tsk = current;
struct io_context *ret;
......@@ -3697,11 +3670,11 @@ struct io_context *current_io_context(gfp_t gfp_flags)
if (likely(ret))
return ret;
ret = kmem_cache_alloc(iocontext_cachep, gfp_flags);
ret = kmem_cache_alloc_node(iocontext_cachep, gfp_flags, node);
if (ret) {
atomic_set(&ret->refcount, 1);
ret->task = current;
ret->set_ioprio = NULL;
ret->ioprio_changed = 0;
ret->last_waited = jiffies; /* doesn't matter... */
ret->nr_batch_requests = 0; /* because this is 0 */
ret->aic = NULL;
......@@ -3721,10 +3694,10 @@ EXPORT_SYMBOL(current_io_context);
*
* This is always called in the context of the task which submitted the I/O.
*/
struct io_context *get_io_context(gfp_t gfp_flags)
struct io_context *get_io_context(gfp_t gfp_flags, int node)
{
struct io_context *ret;
ret = current_io_context(gfp_flags);
ret = current_io_context(gfp_flags, node);
if (likely(ret))
atomic_inc(&ret->refcount);
return ret;
......@@ -3837,9 +3810,6 @@ queue_ra_store(struct request_queue *q, const char *page, size_t count)
ssize_t ret = queue_var_store(&ra_kb, page, count);
spin_lock_irq(q->queue_lock);
if (ra_kb > (q->max_sectors >> 1))
ra_kb = (q->max_sectors >> 1);
q->backing_dev_info.ra_pages = ra_kb >> (PAGE_CACHE_SHIFT - 10);
spin_unlock_irq(q->queue_lock);
......
......@@ -69,7 +69,7 @@ static void *noop_init_queue(request_queue_t *q, elevator_t *e)
{
struct noop_data *nd;
nd = kmalloc(sizeof(*nd), GFP_KERNEL);
nd = kmalloc_node(sizeof(*nd), GFP_KERNEL, q->node);
if (!nd)
return NULL;
INIT_LIST_HEAD(&nd->queue);
......
......@@ -294,7 +294,7 @@ static int sg_io(struct file *file, request_queue_t *q,
rq->sense = sense;
rq->sense_len = 0;
rq->flags |= REQ_BLOCK_PC;
rq->cmd_type = REQ_TYPE_BLOCK_PC;
bio = rq->bio;
/*
......@@ -470,7 +470,7 @@ int sg_scsi_ioctl(struct file *file, struct request_queue *q,
memset(sense, 0, sizeof(sense));
rq->sense = sense;
rq->sense_len = 0;
rq->flags |= REQ_BLOCK_PC;
rq->cmd_type = REQ_TYPE_BLOCK_PC;
blk_execute_rq(q, disk, rq, 0);
......@@ -502,7 +502,7 @@ static int __blk_send_generic(request_queue_t *q, struct gendisk *bd_disk, int c
int err;
rq = blk_get_request(q, WRITE, __GFP_WAIT);
rq->flags |= REQ_BLOCK_PC;
rq->cmd_type = REQ_TYPE_BLOCK_PC;
rq->data = NULL;
rq->data_len = 0;
rq->timeout = BLK_DEFAULT_TIMEOUT;
......
......@@ -3331,7 +3331,7 @@ static int DAC960_process_queue(DAC960_Controller_T *Controller, struct request_
Command->DmaDirection = PCI_DMA_TODEVICE;
Command->CommandType = DAC960_WriteCommand;
}
Command->Completion = Request->waiting;
Command->Completion = Request->end_io_data;
Command->LogicalDriveNumber = (long)Request->rq_disk->private_data;
Command->BlockNumber = Request->sector;
Command->BlockCount = Request->nr_sectors;
......
......@@ -2,6 +2,8 @@
# Block device driver configuration
#
if BLOCK
menu "Block devices"
config BLK_DEV_FD
......@@ -468,3 +470,5 @@ config ATA_OVER_ETH
devices like the Coraid EtherDrive (R) Storage Blade.
endmenu
endif
......@@ -1229,7 +1229,6 @@ static inline void complete_buffers(struct bio *bio, int status)
int nr_sectors = bio_sectors(bio);
bio->bi_next = NULL;
blk_finished_io(len);
bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO);
bio = xbh;
}
......
......@@ -989,7 +989,6 @@ static inline void complete_buffers(struct bio *bio, int ok)
xbh = bio->bi_next;
bio->bi_next = NULL;
blk_finished_io(nr_sectors);
bio_endio(bio, nr_sectors << 9, ok ? 0 : -EIO);
bio = xbh;
......
......@@ -2991,8 +2991,8 @@ static void do_fd_request(request_queue_t * q)
if (usage_count == 0) {
printk("warning: usage count=0, current_req=%p exiting\n",
current_req);
printk("sect=%ld flags=%lx\n", (long)current_req->sector,
current_req->flags);
printk("sect=%ld type=%x flags=%x\n", (long)current_req->sector,
current_req->cmd_type, current_req->cmd_flags);
return;
}
if (test_bit(0, &fdc_busy)) {
......
此差异已折叠。
......@@ -407,10 +407,10 @@ static void do_nbd_request(request_queue_t * q)
struct nbd_device *lo;
blkdev_dequeue_request(req);
dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%lx)\n",
req->rq_disk->disk_name, req, req->flags);
dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%x)\n",
req->rq_disk->disk_name, req, req->cmd_type);
if (!(req->flags & REQ_CMD))
if (!blk_fs_request(req))
goto error_out;
lo = req->rq_disk->private_data;
......@@ -489,7 +489,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
switch (cmd) {
case NBD_DISCONNECT:
printk(KERN_INFO "%s: NBD_DISCONNECT\n", lo->disk->disk_name);
sreq.flags = REQ_SPECIAL;
sreq.cmd_type = REQ_TYPE_SPECIAL;
nbd_cmd(&sreq) = NBD_CMD_DISC;
/*
* Set these to sane values in case server implementation
......
......@@ -437,7 +437,7 @@ static char *pd_buf; /* buffer for request in progress */
static enum action do_pd_io_start(void)
{
if (pd_req->flags & REQ_SPECIAL) {
if (blk_special_request(pd_req)) {
phase = pd_special;
return pd_special();
}
......@@ -719,14 +719,12 @@ static int pd_special_command(struct pd_unit *disk,
memset(&rq, 0, sizeof(rq));
rq.errors = 0;
rq.rq_status = RQ_ACTIVE;
rq.rq_disk = disk->gd;
rq.ref_count = 1;
rq.waiting = &wait;
rq.end_io_data = &wait;
rq.end_io = blk_end_sync_rq;
blk_insert_request(disk->gd->queue, &rq, 0, func);
wait_for_completion(&wait);
rq.waiting = NULL;
if (rq.errors)
err = -EIO;
blk_put_request(&rq);
......
......@@ -365,17 +365,17 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
rq->sense = sense;
memset(sense, 0, sizeof(sense));
rq->sense_len = 0;
rq->flags |= REQ_BLOCK_PC | REQ_HARDBARRIER;
rq->cmd_type = REQ_TYPE_BLOCK_PC;
rq->cmd_flags |= REQ_HARDBARRIER;
if (cgc->quiet)
rq->flags |= REQ_QUIET;
rq->cmd_flags |= REQ_QUIET;
memcpy(rq->cmd, cgc->cmd, CDROM_PACKET_SIZE);
if (sizeof(rq->cmd) > CDROM_PACKET_SIZE)
memset(rq->cmd + CDROM_PACKET_SIZE, 0, sizeof(rq->cmd) - CDROM_PACKET_SIZE);
rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
rq->ref_count++;
rq->flags |= REQ_NOMERGE;
rq->waiting = &wait;
rq->end_io_data = &wait;
rq->end_io = blk_end_sync_rq;
elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1);
generic_unplug_device(q);
......
......@@ -319,8 +319,8 @@ static void start_request(struct floppy_state *fs)
printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%ld buf=%p\n",
req->rq_disk->disk_name, req->cmd,
(long)req->sector, req->nr_sectors, req->buffer);
printk(" rq_status=%d errors=%d current_nr_sectors=%ld\n",
req->rq_status, req->errors, req->current_nr_sectors);
printk(" errors=%d current_nr_sectors=%ld\n",
req->errors, req->current_nr_sectors);
#endif
if (req->sector < 0 || req->sector >= fs->total_secs) {
......
......@@ -529,8 +529,8 @@ static void start_request(struct floppy_state *fs)
printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%ld buf=%p\n",
CURRENT->rq_disk->disk_name, CURRENT->cmd,
CURRENT->sector, CURRENT->nr_sectors, CURRENT->buffer);
printk(" rq_status=%d errors=%d current_nr_sectors=%ld\n",
CURRENT->rq_status, CURRENT->errors, CURRENT->current_nr_sectors);
printk(" errors=%d current_nr_sectors=%ld\n",
CURRENT->errors, CURRENT->current_nr_sectors);
#endif
if (CURRENT->sector < 0 || CURRENT->sector >= fs->total_secs) {
......
......@@ -313,7 +313,7 @@ static void do_xd_request (request_queue_t * q)
int res = 0;
int retry;
if (!(req->flags & REQ_CMD)) {
if (!blk_fs_request(req)) {
end_request(req, 0);
continue;
}
......
......@@ -3,7 +3,7 @@
#
menu "Old CD-ROM drivers (not SCSI, not IDE)"
depends on ISA
depends on ISA && BLOCK
config CD_NO_IDESCSI
bool "Support non-SCSI/IDE/ATAPI CDROM drives"
......
......@@ -2129,7 +2129,7 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
rq->cmd[9] = 0xf8;
rq->cmd_len = 12;
rq->flags |= REQ_BLOCK_PC;
rq->cmd_type = REQ_TYPE_BLOCK_PC;
rq->timeout = 60 * HZ;
bio = rq->bio;
......
......@@ -1338,8 +1338,10 @@ static void do_cdu31a_request(request_queue_t * q)
}
/* WTF??? */
if (!(req->flags & REQ_CMD))
if (!blk_fs_request(req)) {
end_request(req, 0);
continue;
}
if (rq_data_dir(req) == WRITE) {
end_request(req, 0);
continue;
......
......@@ -1006,6 +1006,7 @@ config GPIO_VR41XX
config RAW_DRIVER
tristate "RAW driver (/dev/raw/rawN) (OBSOLETE)"
depends on BLOCK
help
The raw driver permits block devices to be bound to /dev/raw/rawN.
Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O.
......
......@@ -655,6 +655,7 @@ void add_interrupt_randomness(int irq)
add_timer_randomness(irq_timer_state[irq], 0x100 + irq);
}
#ifdef CONFIG_BLOCK
void add_disk_randomness(struct gendisk *disk)
{
if (!disk || !disk->random)
......@@ -667,6 +668,7 @@ void add_disk_randomness(struct gendisk *disk)
}
EXPORT_SYMBOL(add_disk_randomness);
#endif
#define EXTRACT_SIZE 10
......@@ -918,6 +920,7 @@ void rand_initialize_irq(int irq)
}
}
#ifdef CONFIG_BLOCK
void rand_initialize_disk(struct gendisk *disk)
{
struct timer_rand_state *state;
......@@ -932,6 +935,7 @@ void rand_initialize_disk(struct gendisk *disk)
disk->random = state;
}
}
#endif
static ssize_t
random_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos)
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
if S390
if S390 && BLOCK
comment "S/390 block device drivers"
depends on S390
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册