block: change the request allocation/congestion logic to be sync/async based

This makes sure that we never wait on async IO for sync requests, instead
of doing the split on writes vs reads.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Jens Axboe
2009-04-06 14:48:01 +02:00
committed by Linus Torvalds
parent 0221c81b1b
commit 1faa16d228
6 changed files with 100 additions and 82 deletions

View File

@ -38,6 +38,10 @@ struct request;
typedef void (rq_end_io_fn)(struct request *, int);
struct request_list {
/*
* count[], starved[], and wait[] are indexed by
* BLK_RW_SYNC/BLK_RW_ASYNC
*/
int count[2];
int starved[2];
int elvpriv;
@ -66,6 +70,11 @@ enum rq_cmd_type_bits {
REQ_TYPE_ATA_PC,
};
enum {
BLK_RW_ASYNC = 0,
BLK_RW_SYNC = 1,
};
/*
* For request of type REQ_TYPE_LINUX_BLOCK, rq->cmd[0] is the opcode being
* sent down (similar to how REQ_TYPE_BLOCK_PC means that ->cmd[] holds a
@ -103,7 +112,7 @@ enum rq_flag_bits {
__REQ_QUIET, /* don't worry about errors */
__REQ_PREEMPT, /* set for "ide_preempt" requests */
__REQ_ORDERED_COLOR, /* is before or after barrier */
__REQ_RW_SYNC, /* request is sync (O_DIRECT) */
__REQ_RW_SYNC, /* request is sync (sync write or read) */
__REQ_ALLOCED, /* request came from our alloc pool */
__REQ_RW_META, /* metadata io request */
__REQ_COPY_USER, /* contains copies of user pages */
@ -438,8 +447,8 @@ struct request_queue
#define QUEUE_FLAG_CLUSTER 0 /* cluster several segments into 1 */
#define QUEUE_FLAG_QUEUED 1 /* uses generic tag queueing */
#define QUEUE_FLAG_STOPPED 2 /* queue is stopped */
#define QUEUE_FLAG_READFULL 3 /* read queue has been filled */
#define QUEUE_FLAG_WRITEFULL 4 /* write queue has been filled */
#define QUEUE_FLAG_SYNCFULL 3 /* read queue has been filled */
#define QUEUE_FLAG_ASYNCFULL 4 /* write queue has been filled */
#define QUEUE_FLAG_DEAD 5 /* queue being torn down */
#define QUEUE_FLAG_REENTER 6 /* Re-entrancy avoidance */
#define QUEUE_FLAG_PLUGGED 7 /* queue is plugged */
@ -611,32 +620,41 @@ enum {
#define rq_data_dir(rq) ((rq)->cmd_flags & 1)
/*
* We regard a request as sync, if it's a READ or a SYNC write.
* We regard a request as sync, if either a read or a sync write
*/
#define rq_is_sync(rq) (rq_data_dir((rq)) == READ || (rq)->cmd_flags & REQ_RW_SYNC)
static inline bool rw_is_sync(unsigned int rw_flags)
{
return !(rw_flags & REQ_RW) || (rw_flags & REQ_RW_SYNC);
}
static inline bool rq_is_sync(struct request *rq)
{
return rw_is_sync(rq->cmd_flags);
}
#define rq_is_meta(rq) ((rq)->cmd_flags & REQ_RW_META)
static inline int blk_queue_full(struct request_queue *q, int rw)
static inline int blk_queue_full(struct request_queue *q, int sync)
{
if (rw == READ)
return test_bit(QUEUE_FLAG_READFULL, &q->queue_flags);
return test_bit(QUEUE_FLAG_WRITEFULL, &q->queue_flags);
if (sync)
return test_bit(QUEUE_FLAG_SYNCFULL, &q->queue_flags);
return test_bit(QUEUE_FLAG_ASYNCFULL, &q->queue_flags);
}
static inline void blk_set_queue_full(struct request_queue *q, int rw)
static inline void blk_set_queue_full(struct request_queue *q, int sync)
{
if (rw == READ)
queue_flag_set(QUEUE_FLAG_READFULL, q);
if (sync)
queue_flag_set(QUEUE_FLAG_SYNCFULL, q);
else
queue_flag_set(QUEUE_FLAG_WRITEFULL, q);
queue_flag_set(QUEUE_FLAG_ASYNCFULL, q);
}
static inline void blk_clear_queue_full(struct request_queue *q, int rw)
static inline void blk_clear_queue_full(struct request_queue *q, int sync)
{
if (rw == READ)
queue_flag_clear(QUEUE_FLAG_READFULL, q);
if (sync)
queue_flag_clear(QUEUE_FLAG_SYNCFULL, q);
else
queue_flag_clear(QUEUE_FLAG_WRITEFULL, q);
queue_flag_clear(QUEUE_FLAG_ASYNCFULL, q);
}