Skip to content

Commit

Permalink
Merge branch 'for-4.2/core' into for-4.2/drivers
Browse files Browse the repository at this point in the history
  • Loading branch information
Jens Axboe committed Jun 1, 2015
2 parents 75619bf + f26cdc8 commit 843e8dd
Show file tree
Hide file tree
Showing 24 changed files with 157 additions and 302 deletions.
4 changes: 2 additions & 2 deletions block/bio-integrity.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ static void bio_integrity_verify_fn(struct work_struct *work)

/* Restore original bio completion handler */
bio->bi_end_io = bip->bip_end_io;
bio_endio_nodec(bio, error);
bio_endio(bio, error);
}

/**
Expand All @@ -388,7 +388,7 @@ void bio_integrity_endio(struct bio *bio, int error)
*/
if (error) {
bio->bi_end_io = bip->bip_end_io;
bio_endio_nodec(bio, error);
bio_endio(bio, error);

return;
}
Expand Down
35 changes: 14 additions & 21 deletions block/bio.c
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,17 @@ static void bio_chain_endio(struct bio *bio, int error)
bio_put(bio);
}

/*
* Increment chain count for the bio. Make sure the CHAIN flag update
* is visible before the raised count.
*/
static inline void bio_inc_remaining(struct bio *bio)
{
bio->bi_flags |= (1 << BIO_CHAIN);
smp_mb__before_atomic();
atomic_inc(&bio->__bi_remaining);
}

/**
* bio_chain - chain bio completions
* @bio: the target bio
Expand Down Expand Up @@ -1756,8 +1767,10 @@ static inline bool bio_remaining_done(struct bio *bio)

BUG_ON(atomic_read(&bio->__bi_remaining) <= 0);

if (atomic_dec_and_test(&bio->__bi_remaining))
if (atomic_dec_and_test(&bio->__bi_remaining)) {
clear_bit(BIO_CHAIN, &bio->bi_flags);
return true;
}

return false;
}
Expand Down Expand Up @@ -1808,26 +1821,6 @@ void bio_endio(struct bio *bio, int error)
}
EXPORT_SYMBOL(bio_endio);

/**
* bio_endio_nodec - end I/O on a bio, without decrementing bi_remaining
* @bio: bio
* @error: error, if any
*
* For code that has saved and restored bi_end_io; thing hard before using this
* function, probably you should've cloned the entire bio.
**/
void bio_endio_nodec(struct bio *bio, int error)
{
/*
* If it's not flagged as a chain, we are not going to dec the count
*/
if (bio_flagged(bio, BIO_CHAIN))
bio_inc_remaining(bio);

bio_endio(bio, error);
}
EXPORT_SYMBOL(bio_endio_nodec);

/**
* bio_split - split a bio
* @bio: bio to split
Expand Down
94 changes: 11 additions & 83 deletions block/blk-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ EXPORT_SYMBOL(blk_rq_init);
static void req_bio_endio(struct request *rq, struct bio *bio,
unsigned int nbytes, int error)
{
if (error)
if (error && !(rq->cmd_flags & REQ_CLONE))
clear_bit(BIO_UPTODATE, &bio->bi_flags);
else if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
error = -EIO;
Expand All @@ -128,7 +128,8 @@ static void req_bio_endio(struct request *rq, struct bio *bio,
bio_advance(bio, nbytes);

/* don't actually finish bio if it's part of flush sequence */
if (bio->bi_iter.bi_size == 0 && !(rq->cmd_flags & REQ_FLUSH_SEQ))
if (bio->bi_iter.bi_size == 0 &&
!(rq->cmd_flags & (REQ_FLUSH_SEQ|REQ_CLONE)))
bio_endio(bio, error);
}

Expand Down Expand Up @@ -2909,95 +2910,22 @@ int blk_lld_busy(struct request_queue *q)
}
EXPORT_SYMBOL_GPL(blk_lld_busy);

/**
* blk_rq_unprep_clone - Helper function to free all bios in a cloned request
* @rq: the clone request to be cleaned up
*
* Description:
* Free all bios in @rq for a cloned request.
*/
void blk_rq_unprep_clone(struct request *rq)
{
struct bio *bio;

while ((bio = rq->bio) != NULL) {
rq->bio = bio->bi_next;

bio_put(bio);
}
}
EXPORT_SYMBOL_GPL(blk_rq_unprep_clone);

/*
* Copy attributes of the original request to the clone request.
* The actual data parts (e.g. ->cmd, ->sense) are not copied.
*/
static void __blk_rq_prep_clone(struct request *dst, struct request *src)
void blk_rq_prep_clone(struct request *dst, struct request *src)
{
dst->cpu = src->cpu;
dst->cmd_flags |= (src->cmd_flags & REQ_CLONE_MASK) | REQ_NOMERGE;
dst->cmd_flags |= (src->cmd_flags & REQ_CLONE_MASK);
dst->cmd_flags |= REQ_NOMERGE | REQ_CLONE;
dst->cmd_type = src->cmd_type;
dst->__sector = blk_rq_pos(src);
dst->__data_len = blk_rq_bytes(src);
dst->nr_phys_segments = src->nr_phys_segments;
dst->ioprio = src->ioprio;
dst->extra_len = src->extra_len;
}

/**
* blk_rq_prep_clone - Helper function to setup clone request
* @rq: the request to be setup
* @rq_src: original request to be cloned
* @bs: bio_set that bios for clone are allocated from
* @gfp_mask: memory allocation mask for bio
* @bio_ctr: setup function to be called for each clone bio.
* Returns %0 for success, non %0 for failure.
* @data: private data to be passed to @bio_ctr
*
* Description:
* Clones bios in @rq_src to @rq, and copies attributes of @rq_src to @rq.
* The actual data parts of @rq_src (e.g. ->cmd, ->sense)
* are not copied, and copying such parts is the caller's responsibility.
* Also, pages which the original bios are pointing to are not copied
* and the cloned bios just point same pages.
* So cloned bios must be completed before original bios, which means
* the caller must complete @rq before @rq_src.
*/
int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
struct bio_set *bs, gfp_t gfp_mask,
int (*bio_ctr)(struct bio *, struct bio *, void *),
void *data)
{
struct bio *bio, *bio_src;

if (!bs)
bs = fs_bio_set;

__rq_for_each_bio(bio_src, rq_src) {
bio = bio_clone_fast(bio_src, gfp_mask, bs);
if (!bio)
goto free_and_out;

if (bio_ctr && bio_ctr(bio, bio_src, data))
goto free_and_out;

if (rq->bio) {
rq->biotail->bi_next = bio;
rq->biotail = bio;
} else
rq->bio = rq->biotail = bio;
}

__blk_rq_prep_clone(rq, rq_src);

return 0;

free_and_out:
if (bio)
bio_put(bio);
blk_rq_unprep_clone(rq);

return -ENOMEM;
dst->bio = src->bio;
dst->biotail = src->biotail;
dst->cmd = src->cmd;
dst->cmd_len = src->cmd_len;
dst->sense = src->sense;
}
EXPORT_SYMBOL_GPL(blk_rq_prep_clone);

Expand Down
3 changes: 2 additions & 1 deletion block/blk-merge.c
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,8 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio)
!blk_write_same_mergeable(rq->bio, bio))
return false;

if (q->queue_flags & (1 << QUEUE_FLAG_SG_GAPS)) {
/* Only check gaps if the bio carries data */
if (q->queue_flags & (1 << QUEUE_FLAG_SG_GAPS) && bio_has_data(bio)) {
struct bio_vec *bprev;

bprev = &rq->biotail->bi_io_vec[rq->biotail->bi_vcnt - 1];
Expand Down
38 changes: 38 additions & 0 deletions block/blk-mq-tag.c
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,39 @@ static void bt_for_each(struct blk_mq_hw_ctx *hctx,
}
}

static void bt_tags_for_each(struct blk_mq_tags *tags,
struct blk_mq_bitmap_tags *bt, unsigned int off,
busy_tag_iter_fn *fn, void *data, bool reserved)
{
struct request *rq;
int bit, i;

if (!tags->rqs)
return;
for (i = 0; i < bt->map_nr; i++) {
struct blk_align_bitmap *bm = &bt->map[i];

for (bit = find_first_bit(&bm->word, bm->depth);
bit < bm->depth;
bit = find_next_bit(&bm->word, bm->depth, bit + 1)) {
rq = blk_mq_tag_to_rq(tags, off + bit);
fn(rq, data, reserved);
}

off += (1 << bt->bits_per_word);
}
}

void blk_mq_all_tag_busy_iter(struct blk_mq_tags *tags, busy_tag_iter_fn *fn,
void *priv)
{
if (tags->nr_reserved_tags)
bt_tags_for_each(tags, &tags->breserved_tags, 0, fn, priv, true);
bt_tags_for_each(tags, &tags->bitmap_tags, tags->nr_reserved_tags, fn, priv,
false);
}
EXPORT_SYMBOL(blk_mq_all_tag_busy_iter);

void blk_mq_tag_busy_iter(struct blk_mq_hw_ctx *hctx, busy_iter_fn *fn,
void *priv)
{
Expand Down Expand Up @@ -580,6 +613,11 @@ struct blk_mq_tags *blk_mq_init_tags(unsigned int total_tags,
if (!tags)
return NULL;

if (!zalloc_cpumask_var(&tags->cpumask, GFP_KERNEL)) {
kfree(tags);
return NULL;
}

tags->nr_tags = total_tags;
tags->nr_reserved_tags = reserved_tags;

Expand Down
1 change: 1 addition & 0 deletions block/blk-mq-tag.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ struct blk_mq_tags {
struct list_head page_list;

int alloc_policy;
cpumask_var_t cpumask;
};


Expand Down
12 changes: 10 additions & 2 deletions block/blk-mq.c
Original file line number Diff line number Diff line change
Expand Up @@ -1525,7 +1525,6 @@ static struct blk_mq_tags *blk_mq_init_rq_map(struct blk_mq_tag_set *set,
i++;
}
}

return tags;

fail:
Expand Down Expand Up @@ -1821,6 +1820,7 @@ static void blk_mq_map_swqueue(struct request_queue *q)

hctx = q->mq_ops->map_queue(q, i);
cpumask_set_cpu(i, hctx->cpumask);
cpumask_set_cpu(i, hctx->tags->cpumask);
ctx->index_hw = hctx->nr_ctx;
hctx->ctxs[hctx->nr_ctx++] = ctx;
}
Expand Down Expand Up @@ -2187,6 +2187,12 @@ static int blk_mq_alloc_rq_maps(struct blk_mq_tag_set *set)
return 0;
}

struct cpumask *blk_mq_tags_cpumask(struct blk_mq_tags *tags)
{
return tags->cpumask;
}
EXPORT_SYMBOL_GPL(blk_mq_tags_cpumask);

/*
* Alloc a tag set to be associated with one or more request queues.
* May fail with EINVAL for various error conditions. May adjust the
Expand Down Expand Up @@ -2248,8 +2254,10 @@ void blk_mq_free_tag_set(struct blk_mq_tag_set *set)
int i;

for (i = 0; i < set->nr_hw_queues; i++) {
if (set->tags[i])
if (set->tags[i]) {
blk_mq_free_rq_map(set, set->tags[i], i);
free_cpumask_var(set->tags[i]->cpumask);
}
}

kfree(set->tags);
Expand Down
2 changes: 1 addition & 1 deletion drivers/md/bcache/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ static void bch_bio_submit_split_done(struct closure *cl)

s->bio->bi_end_io = s->bi_end_io;
s->bio->bi_private = s->bi_private;
bio_endio_nodec(s->bio, 0);
bio_endio(s->bio, 0);

closure_debug_destroy(&s->cl);
mempool_free(s, s->p->bio_split_hook);
Expand Down
6 changes: 0 additions & 6 deletions drivers/md/dm-cache-target.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,6 @@ static void dm_unhook_bio(struct dm_hook_info *h, struct bio *bio)
{
bio->bi_end_io = h->bi_end_io;
bio->bi_private = h->bi_private;

/*
* Must bump bi_remaining to allow bio to complete with
* restored bi_end_io.
*/
bio_inc_remaining(bio);
}

/*----------------------------------------------------------------*/
Expand Down
2 changes: 0 additions & 2 deletions drivers/md/dm-raid1.c
Original file line number Diff line number Diff line change
Expand Up @@ -1254,8 +1254,6 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
dm_bio_restore(bd, bio);
bio_record->details.bi_bdev = NULL;

bio_inc_remaining(bio);

queue_bio(ms, bio, rw);
return DM_ENDIO_INCOMPLETE;
}
Expand Down
1 change: 0 additions & 1 deletion drivers/md/dm-snap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1478,7 +1478,6 @@ static void pending_complete(struct dm_snap_pending_exception *pe, int success)
if (full_bio) {
full_bio->bi_end_io = pe->full_bio_end_io;
full_bio->bi_private = pe->full_bio_private;
bio_inc_remaining(full_bio);
}
increment_pending_exceptions_done_count();

Expand Down
25 changes: 16 additions & 9 deletions drivers/md/dm-table.c
Original file line number Diff line number Diff line change
Expand Up @@ -940,21 +940,28 @@ static int dm_table_alloc_md_mempools(struct dm_table *t, struct mapped_device *
{
unsigned type = dm_table_get_type(t);
unsigned per_bio_data_size = 0;
struct dm_target *tgt;
unsigned i;

if (unlikely(type == DM_TYPE_NONE)) {
switch (type) {
case DM_TYPE_BIO_BASED:
for (i = 0; i < t->num_targets; i++) {
struct dm_target *tgt = t->targets + i;

per_bio_data_size = max(per_bio_data_size,
tgt->per_bio_data_size);
}
t->mempools = dm_alloc_bio_mempools(t->integrity_supported,
per_bio_data_size);
break;
case DM_TYPE_REQUEST_BASED:
case DM_TYPE_MQ_REQUEST_BASED:
t->mempools = dm_alloc_rq_mempools(md, type);
break;
default:
DMWARN("no table type is set, can't allocate mempools");
return -EINVAL;
}

if (type == DM_TYPE_BIO_BASED)
for (i = 0; i < t->num_targets; i++) {
tgt = t->targets + i;
per_bio_data_size = max(per_bio_data_size, tgt->per_bio_data_size);
}

t->mempools = dm_alloc_md_mempools(md, type, t->integrity_supported, per_bio_data_size);
if (!t->mempools)
return -ENOMEM;

Expand Down
Loading

0 comments on commit 843e8dd

Please sign in to comment.