diff --git a/module/bdev/raid/bdev_raid.c b/module/bdev/raid/bdev_raid.c index 5eb4da557..90c2d8fba 100644 --- a/module/bdev/raid/bdev_raid.c +++ b/module/bdev/raid/bdev_raid.c @@ -317,28 +317,37 @@ raid_bdev_io_complete(struct raid_bdev_io *raid_io, enum spdk_bdev_io_status sta /* * brief: - * raid_bdev_base_io_completion is the completion callback for member disk requests + * raid_bdev_io_complete_part - signal the completion of a part of the expected + * base bdev IOs and complete the raid_io if this is the final expected IO. + * The caller should first set raid_io->base_bdev_io_remaining. This function + * will decrement this counter by the value of the 'completed' parameter and + * complete the raid_io if the counter reaches 0. The caller is free to + * interpret the 'base_bdev_io_remaining' and 'completed' values as needed, + * it can represent e.g. blocks or IOs. * params: - * bdev_io - pointer to member disk requested bdev_io - * success - true if successful, false if unsuccessful - * cb_arg - callback argument (parent raid_bdev_io) + * raid_io - pointer to raid_bdev_io + * completed - the part of the raid_io that has been completed + * status - status of the base IO * returns: - * none + * true - if the raid_io is completed + * false - otherwise */ -void -raid_bdev_base_io_completion(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) +bool +raid_bdev_io_complete_part(struct raid_bdev_io *raid_io, uint64_t completed, + enum spdk_bdev_io_status status) { - struct raid_bdev_io *raid_io = cb_arg; + assert(raid_io->base_bdev_io_remaining >= completed); + raid_io->base_bdev_io_remaining -= completed; - spdk_bdev_free_io(bdev_io); - - if (!success) { - raid_io->base_bdev_io_status = SPDK_BDEV_IO_STATUS_FAILED; + if (status != SPDK_BDEV_IO_STATUS_SUCCESS) { + raid_io->base_bdev_io_status = status; } - raid_io->base_bdev_io_completed++; - if (raid_io->base_bdev_io_completed == raid_io->base_bdev_io_expected) { + if (raid_io->base_bdev_io_remaining == 0) { raid_bdev_io_complete(raid_io, raid_io->base_bdev_io_status); + return true; + } else { + return false; } } @@ -364,6 +373,18 @@ raid_bdev_queue_io_wait(struct raid_bdev_io *raid_io, struct spdk_bdev *bdev, spdk_bdev_queue_io_wait(bdev, ch, &raid_io->waitq_entry); } +static void +raid_base_bdev_reset_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) +{ + struct raid_bdev_io *raid_io = cb_arg; + + spdk_bdev_free_io(bdev_io); + + raid_bdev_io_complete_part(raid_io, 1, success ? + SPDK_BDEV_IO_STATUS_SUCCESS : + SPDK_BDEV_IO_STATUS_FAILED); +} + static void raid_bdev_submit_reset_request(struct raid_bdev_io *raid_io); @@ -396,14 +417,16 @@ raid_bdev_submit_reset_request(struct raid_bdev_io *raid_io) raid_bdev = raid_io->raid_bdev; - raid_io->base_bdev_io_expected = raid_bdev->num_base_bdevs; + if (raid_io->base_bdev_io_remaining == 0) { + raid_io->base_bdev_io_remaining = raid_bdev->num_base_bdevs; + } while (raid_io->base_bdev_io_submitted < raid_bdev->num_base_bdevs) { i = raid_io->base_bdev_io_submitted; base_info = &raid_bdev->base_bdev_info[i]; base_ch = raid_io->raid_ch->base_channel[i]; ret = spdk_bdev_reset(base_info->desc, base_ch, - raid_bdev_base_io_completion, raid_io); + raid_base_bdev_reset_complete, raid_io); if (ret == 0) { raid_io->base_bdev_io_submitted++; } else if (ret == -ENOMEM) { @@ -461,8 +484,8 @@ raid_bdev_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_i raid_io->raid_bdev = bdev_io->bdev->ctxt; raid_io->raid_ch = spdk_io_channel_get_ctx(ch); + raid_io->base_bdev_io_remaining = 0; raid_io->base_bdev_io_submitted = 0; - raid_io->base_bdev_io_completed = 0; raid_io->base_bdev_io_status = SPDK_BDEV_IO_STATUS_SUCCESS; switch (bdev_io->type) { diff --git a/module/bdev/raid/bdev_raid.h b/module/bdev/raid/bdev_raid.h index a55092cd7..4acca1da6 100644 --- a/module/bdev/raid/bdev_raid.h +++ b/module/bdev/raid/bdev_raid.h @@ -104,9 +104,8 @@ struct raid_bdev_io { struct raid_bdev_io_channel *raid_ch; /* Used for tracking progress on io requests sent to member disks. */ + uint64_t base_bdev_io_remaining; uint8_t base_bdev_io_submitted; - uint8_t base_bdev_io_completed; - uint8_t base_bdev_io_expected; uint8_t base_bdev_io_status; }; @@ -308,8 +307,9 @@ __RAID_MODULE_REGISTER(__LINE__)(void) \ raid_bdev_module_list_add(_module); \ } -void -raid_bdev_base_io_completion(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg); +bool +raid_bdev_io_complete_part(struct raid_bdev_io *raid_io, uint64_t completed, + enum spdk_bdev_io_status status); void raid_bdev_queue_io_wait(struct raid_bdev_io *raid_io, struct spdk_bdev *bdev, struct spdk_io_channel *ch, spdk_bdev_io_wait_cb cb_fn); diff --git a/module/bdev/raid/raid0.c b/module/bdev/raid/raid0.c index 7ed26c5ed..21ec8c569 100644 --- a/module/bdev/raid/raid0.c +++ b/module/bdev/raid/raid0.c @@ -262,6 +262,18 @@ _raid0_submit_null_payload_request(void *_raid_io) raid0_submit_null_payload_request(raid_io); } +static void +raid0_base_io_complete(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) +{ + struct raid_bdev_io *raid_io = cb_arg; + + raid_bdev_io_complete_part(raid_io, 1, success ? + SPDK_BDEV_IO_STATUS_SUCCESS : + SPDK_BDEV_IO_STATUS_FAILED); + + spdk_bdev_free_io(bdev_io); +} + /* * brief: * raid0_submit_null_payload_request function submits the next batch of @@ -290,9 +302,11 @@ raid0_submit_null_payload_request(struct raid_bdev_io *raid_io) raid_bdev->strip_size, raid_bdev->strip_size_shift, bdev_io->u.bdev.offset_blocks, bdev_io->u.bdev.num_blocks); - raid_io->base_bdev_io_expected = io_range.n_disks_involved; + if (raid_io->base_bdev_io_remaining == 0) { + raid_io->base_bdev_io_remaining = io_range.n_disks_involved; + } - while (raid_io->base_bdev_io_submitted < raid_io->base_bdev_io_expected) { + while (raid_io->base_bdev_io_submitted < io_range.n_disks_involved) { uint8_t disk_idx; uint64_t offset_in_disk; uint64_t nblocks_in_disk; @@ -310,13 +324,13 @@ raid0_submit_null_payload_request(struct raid_bdev_io *raid_io) case SPDK_BDEV_IO_TYPE_UNMAP: ret = spdk_bdev_unmap_blocks(base_info->desc, base_ch, offset_in_disk, nblocks_in_disk, - raid_bdev_base_io_completion, raid_io); + raid0_base_io_complete, raid_io); break; case SPDK_BDEV_IO_TYPE_FLUSH: ret = spdk_bdev_flush_blocks(base_info->desc, base_ch, offset_in_disk, nblocks_in_disk, - raid_bdev_base_io_completion, raid_io); + raid0_base_io_complete, raid_io); break; default: