block: separate priority boosting from REQ_META
Add a new REQ_PRIO to let requests preempt others in the cfq I/O schedule, and lave REQ_META purely for marking requests as metadata in blktrace. All existing callers of REQ_META except for XFS are updated to also set REQ_PRIO for now. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Namhyung Kim <namhyung@gmail.com> Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
This commit is contained in:
parent
5dc06c5a70
commit
65299a3b78
11 changed files with 32 additions and 25 deletions
|
@ -130,8 +130,8 @@ struct cfq_queue {
|
||||||
unsigned long slice_end;
|
unsigned long slice_end;
|
||||||
long slice_resid;
|
long slice_resid;
|
||||||
|
|
||||||
/* pending metadata requests */
|
/* pending priority requests */
|
||||||
int meta_pending;
|
int prio_pending;
|
||||||
/* number of requests that are on the dispatch list or inside driver */
|
/* number of requests that are on the dispatch list or inside driver */
|
||||||
int dispatched;
|
int dispatched;
|
||||||
|
|
||||||
|
@ -684,8 +684,8 @@ cfq_choose_req(struct cfq_data *cfqd, struct request *rq1, struct request *rq2,
|
||||||
if (rq_is_sync(rq1) != rq_is_sync(rq2))
|
if (rq_is_sync(rq1) != rq_is_sync(rq2))
|
||||||
return rq_is_sync(rq1) ? rq1 : rq2;
|
return rq_is_sync(rq1) ? rq1 : rq2;
|
||||||
|
|
||||||
if ((rq1->cmd_flags ^ rq2->cmd_flags) & REQ_META)
|
if ((rq1->cmd_flags ^ rq2->cmd_flags) & REQ_PRIO)
|
||||||
return rq1->cmd_flags & REQ_META ? rq1 : rq2;
|
return rq1->cmd_flags & REQ_PRIO ? rq1 : rq2;
|
||||||
|
|
||||||
s1 = blk_rq_pos(rq1);
|
s1 = blk_rq_pos(rq1);
|
||||||
s2 = blk_rq_pos(rq2);
|
s2 = blk_rq_pos(rq2);
|
||||||
|
@ -1612,9 +1612,9 @@ static void cfq_remove_request(struct request *rq)
|
||||||
cfqq->cfqd->rq_queued--;
|
cfqq->cfqd->rq_queued--;
|
||||||
cfq_blkiocg_update_io_remove_stats(&(RQ_CFQG(rq))->blkg,
|
cfq_blkiocg_update_io_remove_stats(&(RQ_CFQG(rq))->blkg,
|
||||||
rq_data_dir(rq), rq_is_sync(rq));
|
rq_data_dir(rq), rq_is_sync(rq));
|
||||||
if (rq->cmd_flags & REQ_META) {
|
if (rq->cmd_flags & REQ_PRIO) {
|
||||||
WARN_ON(!cfqq->meta_pending);
|
WARN_ON(!cfqq->prio_pending);
|
||||||
cfqq->meta_pending--;
|
cfqq->prio_pending--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3372,7 +3372,7 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
|
||||||
* So both queues are sync. Let the new request get disk time if
|
* So both queues are sync. Let the new request get disk time if
|
||||||
* it's a metadata request and the current queue is doing regular IO.
|
* it's a metadata request and the current queue is doing regular IO.
|
||||||
*/
|
*/
|
||||||
if ((rq->cmd_flags & REQ_META) && !cfqq->meta_pending)
|
if ((rq->cmd_flags & REQ_PRIO) && !cfqq->prio_pending)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3439,8 +3439,8 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
|
||||||
struct cfq_io_context *cic = RQ_CIC(rq);
|
struct cfq_io_context *cic = RQ_CIC(rq);
|
||||||
|
|
||||||
cfqd->rq_queued++;
|
cfqd->rq_queued++;
|
||||||
if (rq->cmd_flags & REQ_META)
|
if (rq->cmd_flags & REQ_PRIO)
|
||||||
cfqq->meta_pending++;
|
cfqq->prio_pending++;
|
||||||
|
|
||||||
cfq_update_io_thinktime(cfqd, cfqq, cic);
|
cfq_update_io_thinktime(cfqd, cfqq, cic);
|
||||||
cfq_update_io_seektime(cfqd, cfqq, rq);
|
cfq_update_io_seektime(cfqd, cfqq, rq);
|
||||||
|
|
|
@ -926,6 +926,9 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
|
||||||
/*
|
/*
|
||||||
* Reliable writes are used to implement Forced Unit Access and
|
* Reliable writes are used to implement Forced Unit Access and
|
||||||
* REQ_META accesses, and are supported only on MMCs.
|
* REQ_META accesses, and are supported only on MMCs.
|
||||||
|
*
|
||||||
|
* XXX: this really needs a good explanation of why REQ_META
|
||||||
|
* is treated special.
|
||||||
*/
|
*/
|
||||||
bool do_rel_wr = ((req->cmd_flags & REQ_FUA) ||
|
bool do_rel_wr = ((req->cmd_flags & REQ_FUA) ||
|
||||||
(req->cmd_flags & REQ_META)) &&
|
(req->cmd_flags & REQ_META)) &&
|
||||||
|
|
|
@ -1134,7 +1134,7 @@ struct buffer_head *ext3_bread(handle_t *handle, struct inode *inode,
|
||||||
return bh;
|
return bh;
|
||||||
if (buffer_uptodate(bh))
|
if (buffer_uptodate(bh))
|
||||||
return bh;
|
return bh;
|
||||||
ll_rw_block(READ | REQ_META, 1, &bh);
|
ll_rw_block(READ | REQ_META | REQ_PRIO, 1, &bh);
|
||||||
wait_on_buffer(bh);
|
wait_on_buffer(bh);
|
||||||
if (buffer_uptodate(bh))
|
if (buffer_uptodate(bh))
|
||||||
return bh;
|
return bh;
|
||||||
|
@ -2807,7 +2807,7 @@ make_io:
|
||||||
trace_ext3_load_inode(inode);
|
trace_ext3_load_inode(inode);
|
||||||
get_bh(bh);
|
get_bh(bh);
|
||||||
bh->b_end_io = end_buffer_read_sync;
|
bh->b_end_io = end_buffer_read_sync;
|
||||||
submit_bh(READ | REQ_META, bh);
|
submit_bh(READ | REQ_META | REQ_PRIO, bh);
|
||||||
wait_on_buffer(bh);
|
wait_on_buffer(bh);
|
||||||
if (!buffer_uptodate(bh)) {
|
if (!buffer_uptodate(bh)) {
|
||||||
ext3_error(inode->i_sb, "ext3_get_inode_loc",
|
ext3_error(inode->i_sb, "ext3_get_inode_loc",
|
||||||
|
|
|
@ -922,7 +922,8 @@ restart:
|
||||||
bh = ext3_getblk(NULL, dir, b++, 0, &err);
|
bh = ext3_getblk(NULL, dir, b++, 0, &err);
|
||||||
bh_use[ra_max] = bh;
|
bh_use[ra_max] = bh;
|
||||||
if (bh)
|
if (bh)
|
||||||
ll_rw_block(READ | REQ_META, 1, &bh);
|
ll_rw_block(READ | REQ_META | REQ_PRIO,
|
||||||
|
1, &bh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((bh = bh_use[ra_ptr++]) == NULL)
|
if ((bh = bh_use[ra_ptr++]) == NULL)
|
||||||
|
|
|
@ -650,7 +650,7 @@ struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode,
|
||||||
return bh;
|
return bh;
|
||||||
if (buffer_uptodate(bh))
|
if (buffer_uptodate(bh))
|
||||||
return bh;
|
return bh;
|
||||||
ll_rw_block(READ | REQ_META, 1, &bh);
|
ll_rw_block(READ | REQ_META | REQ_PRIO, 1, &bh);
|
||||||
wait_on_buffer(bh);
|
wait_on_buffer(bh);
|
||||||
if (buffer_uptodate(bh))
|
if (buffer_uptodate(bh))
|
||||||
return bh;
|
return bh;
|
||||||
|
@ -3301,7 +3301,7 @@ make_io:
|
||||||
trace_ext4_load_inode(inode);
|
trace_ext4_load_inode(inode);
|
||||||
get_bh(bh);
|
get_bh(bh);
|
||||||
bh->b_end_io = end_buffer_read_sync;
|
bh->b_end_io = end_buffer_read_sync;
|
||||||
submit_bh(READ | REQ_META, bh);
|
submit_bh(READ | REQ_META | REQ_PRIO, bh);
|
||||||
wait_on_buffer(bh);
|
wait_on_buffer(bh);
|
||||||
if (!buffer_uptodate(bh)) {
|
if (!buffer_uptodate(bh)) {
|
||||||
EXT4_ERROR_INODE_BLOCK(inode, block,
|
EXT4_ERROR_INODE_BLOCK(inode, block,
|
||||||
|
|
|
@ -922,7 +922,8 @@ restart:
|
||||||
bh = ext4_getblk(NULL, dir, b++, 0, &err);
|
bh = ext4_getblk(NULL, dir, b++, 0, &err);
|
||||||
bh_use[ra_max] = bh;
|
bh_use[ra_max] = bh;
|
||||||
if (bh)
|
if (bh)
|
||||||
ll_rw_block(READ | REQ_META, 1, &bh);
|
ll_rw_block(READ | REQ_META | REQ_PRIO,
|
||||||
|
1, &bh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((bh = bh_use[ra_ptr++]) == NULL)
|
if ((bh = bh_use[ra_ptr++]) == NULL)
|
||||||
|
|
|
@ -624,9 +624,9 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags, int pull)
|
||||||
bh->b_end_io = end_buffer_write_sync;
|
bh->b_end_io = end_buffer_write_sync;
|
||||||
get_bh(bh);
|
get_bh(bh);
|
||||||
if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags))
|
if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags))
|
||||||
submit_bh(WRITE_SYNC | REQ_META, bh);
|
submit_bh(WRITE_SYNC | REQ_META | REQ_PRIO, bh);
|
||||||
else
|
else
|
||||||
submit_bh(WRITE_FLUSH_FUA | REQ_META, bh);
|
submit_bh(WRITE_FLUSH_FUA | REQ_META | REQ_PRIO, bh);
|
||||||
wait_on_buffer(bh);
|
wait_on_buffer(bh);
|
||||||
|
|
||||||
if (!buffer_uptodate(bh))
|
if (!buffer_uptodate(bh))
|
||||||
|
|
|
@ -37,7 +37,7 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb
|
||||||
{
|
{
|
||||||
struct buffer_head *bh, *head;
|
struct buffer_head *bh, *head;
|
||||||
int nr_underway = 0;
|
int nr_underway = 0;
|
||||||
int write_op = REQ_META |
|
int write_op = REQ_META | REQ_PRIO |
|
||||||
(wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE);
|
(wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE);
|
||||||
|
|
||||||
BUG_ON(!PageLocked(page));
|
BUG_ON(!PageLocked(page));
|
||||||
|
@ -225,7 +225,7 @@ int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags,
|
||||||
}
|
}
|
||||||
bh->b_end_io = end_buffer_read_sync;
|
bh->b_end_io = end_buffer_read_sync;
|
||||||
get_bh(bh);
|
get_bh(bh);
|
||||||
submit_bh(READ_SYNC | REQ_META, bh);
|
submit_bh(READ_SYNC | REQ_META | REQ_PRIO, bh);
|
||||||
if (!(flags & DIO_WAIT))
|
if (!(flags & DIO_WAIT))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -435,7 +435,7 @@ struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen)
|
||||||
if (buffer_uptodate(first_bh))
|
if (buffer_uptodate(first_bh))
|
||||||
goto out;
|
goto out;
|
||||||
if (!buffer_locked(first_bh))
|
if (!buffer_locked(first_bh))
|
||||||
ll_rw_block(READ_SYNC | REQ_META, 1, &first_bh);
|
ll_rw_block(READ_SYNC | REQ_META | REQ_PRIO, 1, &first_bh);
|
||||||
|
|
||||||
dblock++;
|
dblock++;
|
||||||
extlen--;
|
extlen--;
|
||||||
|
|
|
@ -224,7 +224,7 @@ static int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector, int silent)
|
||||||
|
|
||||||
bio->bi_end_io = end_bio_io_page;
|
bio->bi_end_io = end_bio_io_page;
|
||||||
bio->bi_private = page;
|
bio->bi_private = page;
|
||||||
submit_bio(READ_SYNC | REQ_META, bio);
|
submit_bio(READ_SYNC | REQ_META | REQ_PRIO, bio);
|
||||||
wait_on_page_locked(page);
|
wait_on_page_locked(page);
|
||||||
bio_put(bio);
|
bio_put(bio);
|
||||||
if (!PageUptodate(page)) {
|
if (!PageUptodate(page)) {
|
||||||
|
|
|
@ -709,7 +709,7 @@ get_a_page:
|
||||||
set_buffer_uptodate(bh);
|
set_buffer_uptodate(bh);
|
||||||
|
|
||||||
if (!buffer_uptodate(bh)) {
|
if (!buffer_uptodate(bh)) {
|
||||||
ll_rw_block(READ | REQ_META, 1, &bh);
|
ll_rw_block(READ | REQ_META | REQ_PRIO, 1, &bh);
|
||||||
wait_on_buffer(bh);
|
wait_on_buffer(bh);
|
||||||
if (!buffer_uptodate(bh))
|
if (!buffer_uptodate(bh))
|
||||||
goto unlock_out;
|
goto unlock_out;
|
||||||
|
|
|
@ -124,6 +124,7 @@ enum rq_flag_bits {
|
||||||
|
|
||||||
__REQ_SYNC, /* request is sync (sync write or read) */
|
__REQ_SYNC, /* request is sync (sync write or read) */
|
||||||
__REQ_META, /* metadata io request */
|
__REQ_META, /* metadata io request */
|
||||||
|
__REQ_PRIO, /* boost priority in cfq */
|
||||||
__REQ_DISCARD, /* request to discard sectors */
|
__REQ_DISCARD, /* request to discard sectors */
|
||||||
__REQ_SECURE, /* secure discard (used with __REQ_DISCARD) */
|
__REQ_SECURE, /* secure discard (used with __REQ_DISCARD) */
|
||||||
|
|
||||||
|
@ -161,14 +162,15 @@ enum rq_flag_bits {
|
||||||
#define REQ_FAILFAST_DRIVER (1 << __REQ_FAILFAST_DRIVER)
|
#define REQ_FAILFAST_DRIVER (1 << __REQ_FAILFAST_DRIVER)
|
||||||
#define REQ_SYNC (1 << __REQ_SYNC)
|
#define REQ_SYNC (1 << __REQ_SYNC)
|
||||||
#define REQ_META (1 << __REQ_META)
|
#define REQ_META (1 << __REQ_META)
|
||||||
|
#define REQ_PRIO (1 << __REQ_PRIO)
|
||||||
#define REQ_DISCARD (1 << __REQ_DISCARD)
|
#define REQ_DISCARD (1 << __REQ_DISCARD)
|
||||||
#define REQ_NOIDLE (1 << __REQ_NOIDLE)
|
#define REQ_NOIDLE (1 << __REQ_NOIDLE)
|
||||||
|
|
||||||
#define REQ_FAILFAST_MASK \
|
#define REQ_FAILFAST_MASK \
|
||||||
(REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER)
|
(REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER)
|
||||||
#define REQ_COMMON_MASK \
|
#define REQ_COMMON_MASK \
|
||||||
(REQ_WRITE | REQ_FAILFAST_MASK | REQ_SYNC | REQ_META | REQ_DISCARD | \
|
(REQ_WRITE | REQ_FAILFAST_MASK | REQ_SYNC | REQ_META | REQ_PRIO | \
|
||||||
REQ_NOIDLE | REQ_FLUSH | REQ_FUA | REQ_SECURE)
|
REQ_DISCARD | REQ_NOIDLE | REQ_FLUSH | REQ_FUA | REQ_SECURE)
|
||||||
#define REQ_CLONE_MASK REQ_COMMON_MASK
|
#define REQ_CLONE_MASK REQ_COMMON_MASK
|
||||||
|
|
||||||
#define REQ_RAHEAD (1 << __REQ_RAHEAD)
|
#define REQ_RAHEAD (1 << __REQ_RAHEAD)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue