mirror of https://github.com/schoebel/mars
mars_if: fix bio semantics
This commit is contained in:
parent
847f2a416f
commit
ec42130eb5
93
mars_if.c
93
mars_if.c
|
@ -220,30 +220,75 @@ void if_timer(unsigned long data)
|
||||||
*/
|
*/
|
||||||
static int if_make_request(struct request_queue *q, struct bio *bio)
|
static int if_make_request(struct request_queue *q, struct bio *bio)
|
||||||
{
|
{
|
||||||
|
struct if_input *input = q->queuedata;
|
||||||
|
struct if_brick *brick = input->brick;
|
||||||
|
|
||||||
|
/* Original flags of the source bio
|
||||||
|
*/
|
||||||
|
const int rw = bio_data_dir(bio);
|
||||||
|
const int sectors = bio_sectors(bio);
|
||||||
|
const bool ahead = bio_rw_flagged(bio, BIO_RW_AHEAD) && rw == READ;
|
||||||
|
const bool barrier = bio_rw_flagged(bio, BIO_RW_BARRIER);
|
||||||
|
const bool syncio = bio_rw_flagged(bio, BIO_RW_SYNCIO);
|
||||||
|
const bool unplug = bio_rw_flagged(bio, BIO_RW_UNPLUG);
|
||||||
|
const bool meta = bio_rw_flagged(bio, BIO_RW_META);
|
||||||
|
const bool discard = bio_rw_flagged(bio, BIO_RW_DISCARD);
|
||||||
|
const bool noidle = bio_rw_flagged(bio, BIO_RW_NOIDLE);
|
||||||
|
const int prio = bio_prio(bio);
|
||||||
|
|
||||||
|
/* Transform into MARS flags
|
||||||
|
*/
|
||||||
|
const int ref_prio =
|
||||||
|
(prio == IOPRIO_CLASS_RT || (meta | syncio)) ?
|
||||||
|
MARS_PRIO_HIGH :
|
||||||
|
(prio == IOPRIO_CLASS_IDLE) ?
|
||||||
|
MARS_PRIO_LOW :
|
||||||
|
MARS_PRIO_NORMAL;
|
||||||
|
const bool do_unplug = ALWAYS_UNPLUG | unplug | noidle;
|
||||||
|
const bool do_skip_sync = brick->skip_sync && !(barrier | syncio);
|
||||||
|
|
||||||
struct bio_wrapper *biow;
|
struct bio_wrapper *biow;
|
||||||
struct if_input *input;
|
|
||||||
struct if_brick *brick = NULL;
|
|
||||||
struct mref_object *mref = NULL;
|
struct mref_object *mref = NULL;
|
||||||
struct if_mref_aspect *mref_a;
|
struct if_mref_aspect *mref_a;
|
||||||
struct bio_vec *bvec;
|
struct bio_vec *bvec;
|
||||||
int i;
|
int i;
|
||||||
bool assigned = false;
|
bool assigned = false;
|
||||||
const bool unplug = bio_rw_flagged(bio, BIO_RW_UNPLUG) || bio_rw_flagged(bio, BIO_RW_SYNCIO);
|
|
||||||
const bool barrier = ((bio->bi_rw & 1) != READ && bio_rw_flagged(bio, BIO_RW_BARRIER));
|
|
||||||
loff_t pos = ((loff_t)bio->bi_sector) << 9; // TODO: make dynamic
|
loff_t pos = ((loff_t)bio->bi_sector) << 9; // TODO: make dynamic
|
||||||
int rw = bio_data_dir(bio);
|
|
||||||
int total_len = bio->bi_size;
|
int total_len = bio->bi_size;
|
||||||
int error = -ENOSYS;
|
int error = -ENOSYS;
|
||||||
|
|
||||||
MARS_IO("bio %p size = %d rw = %d unplug = %d barrier = %d\n", bio, bio->bi_size, rw, unplug, barrier);
|
MARS_IO("bio %p "
|
||||||
|
"size = %d "
|
||||||
|
"rw = %d "
|
||||||
|
"sectors = %d "
|
||||||
|
"ahead = %d "
|
||||||
|
"barrier = %d "
|
||||||
|
"syncio = %d "
|
||||||
|
"unplug = %d "
|
||||||
|
"meta = %d "
|
||||||
|
"discard = %d "
|
||||||
|
"noidle = %d "
|
||||||
|
"prio = %d "
|
||||||
|
"pos = %lldd "
|
||||||
|
"total_len = %d\n",
|
||||||
|
bio,
|
||||||
|
bio->bi_size,
|
||||||
|
rw,
|
||||||
|
sectors,
|
||||||
|
ahead,
|
||||||
|
barrier,
|
||||||
|
syncio,
|
||||||
|
unplug,
|
||||||
|
meta,
|
||||||
|
discard,
|
||||||
|
noidle,
|
||||||
|
prio,
|
||||||
|
pos,
|
||||||
|
total_len);
|
||||||
|
|
||||||
might_sleep();
|
might_sleep();
|
||||||
|
|
||||||
input = q->queuedata;
|
if (unlikely(!sectors)) {
|
||||||
if (unlikely(!input))
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
if (unlikely(!bio_sectors(bio))) {
|
|
||||||
_if_unplug(input);
|
_if_unplug(input);
|
||||||
/* THINK: usually this happens only at write barriers.
|
/* THINK: usually this happens only at write barriers.
|
||||||
* We have no "barrier" operation in MARS, since
|
* We have no "barrier" operation in MARS, since
|
||||||
|
@ -257,15 +302,18 @@ static int if_make_request(struct request_queue *q, struct bio *bio)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DENY_READA // provisinary -- we should introduce an equivalent of READA also to the MARS infrastructure
|
#ifdef DENY_READA // provisinary -- we should introduce an equivalent of READA also to the MARS infrastructure
|
||||||
if (bio_rw(bio) == READA) {
|
if (ahead) {
|
||||||
atomic_inc(&input->total_reada_count);
|
atomic_inc(&input->total_reada_count);
|
||||||
bio_endio(bio, -EWOULDBLOCK);
|
bio_endio(bio, -EWOULDBLOCK);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
(void)ahead; // shut up gcc
|
||||||
#endif
|
#endif
|
||||||
|
if (unlikely(discard)) { // NYI
|
||||||
brick = input->brick;
|
bio_endio(bio, 0);
|
||||||
CHECK_PTR(brick, err);
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
biow = brick_mem_alloc(sizeof(struct bio_wrapper));
|
biow = brick_mem_alloc(sizeof(struct bio_wrapper));
|
||||||
CHECK_PTR(biow, err);
|
CHECK_PTR(biow, err);
|
||||||
|
@ -289,14 +337,6 @@ static int if_make_request(struct request_queue *q, struct bio *bio)
|
||||||
msleep(100);
|
msleep(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef IO_DEBUGGING
|
|
||||||
{
|
|
||||||
const unsigned short prio = bio_prio(bio);
|
|
||||||
const bool sync = bio_rw_flagged(bio, BIO_RW_SYNCIO);
|
|
||||||
MARS_IO("BIO raw_rw = 0x%016lx len = %d prio = %d sync = %d unplug = %d\n", bio->bi_rw, bio->bi_size, prio, sync, unplug);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
down(&input->kick_sem);
|
down(&input->kick_sem);
|
||||||
|
|
||||||
bio_for_each_segment(bvec, bio, i) {
|
bio_for_each_segment(bvec, bio, i) {
|
||||||
|
@ -357,7 +397,7 @@ static int if_make_request(struct request_queue *q, struct bio *bio)
|
||||||
mref = tmp_mref;
|
mref = tmp_mref;
|
||||||
mref_a = tmp_a;
|
mref_a = tmp_a;
|
||||||
this_len = bv_len;
|
this_len = bv_len;
|
||||||
if (barrier) {
|
if (!do_skip_sync) {
|
||||||
mref->ref_skip_sync = false;
|
mref->ref_skip_sync = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,6 +456,7 @@ static int if_make_request(struct request_queue *q, struct bio *bio)
|
||||||
mref->ref_pos = pos;
|
mref->ref_pos = pos;
|
||||||
mref->ref_len = prefetch_len;
|
mref->ref_len = prefetch_len;
|
||||||
mref->ref_data = data; // direct IO
|
mref->ref_data = data; // direct IO
|
||||||
|
mref->ref_prio = ref_prio;
|
||||||
mref_a->orig_page = page;
|
mref_a->orig_page = page;
|
||||||
mref_a->is_kmapped = true;
|
mref_a->is_kmapped = true;
|
||||||
|
|
||||||
|
@ -445,7 +486,7 @@ static int if_make_request(struct request_queue *q, struct bio *bio)
|
||||||
mref_a->bio_count = 1;
|
mref_a->bio_count = 1;
|
||||||
assigned = true;
|
assigned = true;
|
||||||
|
|
||||||
if (brick->skip_sync && !barrier) {
|
if (do_skip_sync) {
|
||||||
mref->ref_skip_sync = true;
|
mref->ref_skip_sync = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -495,7 +536,7 @@ err:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ALWAYS_UNPLUG || unplug ||
|
if (do_unplug ||
|
||||||
(brick && brick->max_plugged > 0 && atomic_read(&input->plugged_count) > brick->max_plugged)) {
|
(brick && brick->max_plugged > 0 && atomic_read(&input->plugged_count) > brick->max_plugged)) {
|
||||||
_if_unplug(input);
|
_if_unplug(input);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue