/* * Request completion handler for request-based dm */ static void dm_softirq_done(struct request *rq) { bool mapped = true; struct dm_rq_target_io *tio = tio_from_request(rq); struct request *clone = tio->clone; int rw; if (!clone) { struct mapped_device *md = tio->md; rq_end_stats(md, rq); rw = rq_data_dir(rq); if (!rq->q->mq_ops) blk_end_request_all(rq, tio->error); else blk_mq_end_request(rq, tio->error); rq_completed(md, rw, false); return; } if (rq->rq_flags & RQF_FAILED) mapped = false; dm_done(clone, tio->error, mapped); }
/* * Request completion handler for request-based dm */ static void dm_softirq_done(struct request *rq) { bool mapped = true; struct dm_rq_target_io *tio = tio_from_request(rq); struct request *clone = tio->clone; int rw; if (!clone) { rq_end_stats(tio->md, rq); rw = rq_data_dir(rq); if (!rq->q->mq_ops) { blk_end_request_all(rq, tio->error); rq_completed(tio->md, rw, false); free_old_rq_tio(tio); } else { blk_mq_end_request(rq, tio->error); rq_completed(tio->md, rw, false); } return; } if (rq->cmd_flags & REQ_FAILED) mapped = false; dm_done(clone, tio->error, mapped); }
/* * Complete the clone and the original request. * Must be called without clone's queue lock held, * see end_clone_request() for more details. */ static void dm_end_request(struct request *clone, int error) { int rw = rq_data_dir(clone); struct dm_rq_target_io *tio = clone->end_io_data; struct mapped_device *md = tio->md; struct request *rq = tio->orig; if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { rq->errors = clone->errors; rq->resid_len = clone->resid_len; if (rq->sense) /* * We are using the sense buffer of the original * request. * So setting the length of the sense data is enough. */ rq->sense_len = clone->sense_len; } free_rq_clone(clone); rq_end_stats(md, rq); if (!rq->q->mq_ops) blk_end_request_all(rq, error); else blk_mq_end_request(rq, error); rq_completed(md, rw, true); }
static int dm_mq_queue_rq(struct blk_mq_hw_ctx *hctx, const struct blk_mq_queue_data *bd) { struct request *rq = bd->rq; struct dm_rq_target_io *tio = blk_mq_rq_to_pdu(rq); struct mapped_device *md = tio->md; struct dm_target *ti = md->immutable_target; if (unlikely(!ti)) { int srcu_idx; struct dm_table *map = dm_get_live_table(md, &srcu_idx); ti = dm_table_find_target(map, 0); dm_put_live_table(md, srcu_idx); } /* * On suspend dm_stop_queue() handles stopping the blk-mq * request_queue BUT: even though the hw_queues are marked * BLK_MQ_S_STOPPED at that point there is still a race that * is allowing block/blk-mq.c to call ->queue_rq against a * hctx that it really shouldn't. The following check guards * against this rarity (albeit _not_ race-free). */ if (unlikely(test_bit(BLK_MQ_S_STOPPED, &hctx->state))) return BLK_MQ_RQ_QUEUE_BUSY; if (ti->type->busy && ti->type->busy(ti)) return BLK_MQ_RQ_QUEUE_BUSY; dm_start_request(md, rq); /* Init tio using md established in .init_request */ init_tio(tio, rq, md); /* * Establish tio->ti before calling map_request(). */ tio->ti = ti; /* Direct call is fine since .queue_rq allows allocations */ if (map_request(tio, rq, md) == DM_MAPIO_REQUEUE) { /* Undo dm_start_request() before requeuing */ rq_end_stats(md, rq); rq_completed(md, rq_data_dir(rq), false); return BLK_MQ_RQ_QUEUE_BUSY; } return BLK_MQ_RQ_QUEUE_OK; }
static void dm_requeue_original_request(struct mapped_device *md, struct request *rq) { int rw = rq_data_dir(rq); rq_end_stats(md, rq); dm_unprep_request(rq); if (!rq->q->mq_ops) dm_old_requeue_request(rq); else dm_mq_requeue_request(rq); rq_completed(md, rw, false); }
/* * Complete the clone and the original request. * Must be called without clone's queue lock held, * see end_clone_request() for more details. */ static void dm_end_request(struct request *clone, blk_status_t error) { int rw = rq_data_dir(clone); struct dm_rq_target_io *tio = clone->end_io_data; struct mapped_device *md = tio->md; struct request *rq = tio->orig; blk_rq_unprep_clone(clone); tio->ti->type->release_clone_rq(clone); rq_end_stats(md, rq); if (!rq->q->mq_ops) blk_end_request_all(rq, error); else blk_mq_end_request(rq, error); rq_completed(md, rw, true); }
static void dm_requeue_original_request(struct dm_rq_target_io *tio, bool delay_requeue) { struct mapped_device *md = tio->md; struct request *rq = tio->orig; int rw = rq_data_dir(rq); rq_end_stats(md, rq); if (tio->clone) { blk_rq_unprep_clone(tio->clone); tio->ti->type->release_clone_rq(tio->clone); } if (!rq->q->mq_ops) dm_old_requeue_request(rq); else dm_mq_delay_requeue_request(rq, delay_requeue ? 100/*ms*/ : 0); rq_completed(md, rw, false); }
static int dm_mq_queue_rq(struct blk_mq_hw_ctx *hctx, const struct blk_mq_queue_data *bd) { struct request *rq = bd->rq; struct dm_rq_target_io *tio = blk_mq_rq_to_pdu(rq); struct mapped_device *md = tio->md; struct dm_target *ti = md->immutable_target; if (unlikely(!ti)) { int srcu_idx; struct dm_table *map = dm_get_live_table(md, &srcu_idx); ti = dm_table_find_target(map, 0); dm_put_live_table(md, srcu_idx); } if (ti->type->busy && ti->type->busy(ti)) return BLK_MQ_RQ_QUEUE_BUSY; dm_start_request(md, rq); /* Init tio using md established in .init_request */ init_tio(tio, rq, md); /* * Establish tio->ti before calling map_request(). */ tio->ti = ti; /* Direct call is fine since .queue_rq allows allocations */ if (map_request(tio) == DM_MAPIO_REQUEUE) { /* Undo dm_start_request() before requeuing */ rq_end_stats(md, rq); rq_completed(md, rq_data_dir(rq), false); blk_mq_delay_run_hw_queue(hctx, 100/*ms*/); return BLK_MQ_RQ_QUEUE_BUSY; } return BLK_MQ_RQ_QUEUE_OK; }