Loading block/bio-integrity.c +2 −2 Original line number Diff line number Diff line Loading @@ -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); } /** Loading @@ -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; } Loading block/bio.c +14 −21 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; } Loading Loading @@ -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 Loading block/blk-core.c +11 −83 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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); } Loading Loading @@ -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); Loading block/blk-merge.c +2 −1 Original line number Diff line number Diff line Loading @@ -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]; Loading block/blk-mq-tag.c +38 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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; Loading Loading
block/bio-integrity.c +2 −2 Original line number Diff line number Diff line Loading @@ -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); } /** Loading @@ -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; } Loading
block/bio.c +14 −21 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; } Loading Loading @@ -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 Loading
block/blk-core.c +11 −83 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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); } Loading Loading @@ -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); Loading
block/blk-merge.c +2 −1 Original line number Diff line number Diff line Loading @@ -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]; Loading
block/blk-mq-tag.c +38 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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; Loading