logger().debug("open");
// Get SSD's features from identify_controller and namespace command.
// Do identify_controller first, and then identify_namespace.
- return identify_controller().safe_then([this, in_path, mode](
+ return identify_controller(device).safe_then([this, in_path, mode](
auto id_controller_data) {
support_multistream = id_controller_data.oacs.support_directives;
if (support_multistream) {
stream_id_count = WRITE_LIFE_MAX;
}
awupf = id_controller_data.awupf + 1;
- return identify_namespace().safe_then([this, in_path, mode] (
+ return identify_namespace(device).safe_then([this, in_path, mode] (
auto id_namespace_data) {
- // LBA format provides LBA size which is power of 2. LBA is the
- // minimum size of read and write.
- super.block_size = (1 << id_namespace_data.lbaf0.lbads);
atomic_write_unit = awupf * super.block_size;
data_protection_type = id_namespace_data.dps.protection_type;
data_protection_enabled = (data_protection_type > 0);
}
nvme_command_ertr::future<nvme_identify_controller_data_t>
-NVMeBlockDevice::identify_controller() {
+NVMeBlockDevice::identify_controller(seastar::file f) {
return seastar::do_with(
nvme_admin_command_t(),
nvme_identify_controller_data_t(),
- [this](auto &admin_command, auto &data) {
+ [this, f](auto &admin_command, auto &data) {
admin_command.common.opcode = nvme_admin_command_t::OPCODE_IDENTIFY;
admin_command.common.addr = (uint64_t)&data;
admin_command.common.data_len = sizeof(data);
admin_command.identify.cns = nvme_identify_command_t::CNS_CONTROLLER;
- return pass_admin(admin_command).safe_then([&data](auto status) {
+ return pass_admin(admin_command, f).safe_then([&data](auto status) {
return seastar::make_ready_future<nvme_identify_controller_data_t>(
std::move(data));
});
}
nvme_command_ertr::future<nvme_identify_namespace_data_t>
-NVMeBlockDevice::identify_namespace() {
- return get_nsid().safe_then([this](auto nsid) {
+NVMeBlockDevice::identify_namespace(seastar::file f) {
+ return get_nsid(f).safe_then([this, f](auto nsid) {
return seastar::do_with(
nvme_admin_command_t(),
nvme_identify_namespace_data_t(),
- [this, nsid](auto &admin_command, auto &data) {
+ [this, nsid, f](auto &admin_command, auto &data) {
admin_command.common.opcode = nvme_admin_command_t::OPCODE_IDENTIFY;
admin_command.common.addr = (uint64_t)&data;
admin_command.common.data_len = sizeof(data);
admin_command.common.nsid = nsid;
admin_command.identify.cns = nvme_identify_command_t::CNS_NAMESPACE;
- return pass_admin(admin_command).safe_then([&data](auto status){
+ return pass_admin(admin_command, f).safe_then([&data](auto status){
return seastar::make_ready_future<nvme_identify_namespace_data_t>(
std::move(data));
});
});
}
-nvme_command_ertr::future<int> NVMeBlockDevice::get_nsid() {
- return device.ioctl(NVME_IOCTL_ID, nullptr);
+nvme_command_ertr::future<int> NVMeBlockDevice::get_nsid(seastar::file f) {
+ return f.ioctl(NVME_IOCTL_ID, nullptr).handle_exception(
+ [](auto e)->nvme_command_ertr::future<int> {
+ logger().error("pass_admin: ioctl failed");
+ return crimson::ct_error::input_output_error::make();
+ });
}
nvme_command_ertr::future<int> NVMeBlockDevice::pass_admin(
- nvme_admin_command_t& admin_cmd) {
- return device.ioctl(NVME_IOCTL_ADMIN_CMD, &admin_cmd).handle_exception(
+ nvme_admin_command_t& admin_cmd, seastar::file f) {
+ return f.ioctl(NVME_IOCTL_ADMIN_CMD, &admin_cmd).handle_exception(
[](auto e)->nvme_command_ertr::future<int> {
logger().error("pass_admin: ioctl failed");
return crimson::ct_error::input_output_error::make();
return seastar::open_file_dma(
device_path,
seastar::open_flags::rw | seastar::open_flags::dsync
- ).then([stat](auto file) mutable {
- return file.size().then([stat, file](auto size) mutable {
+ ).then([this, stat](auto file) mutable {
+ return file.size().then([this, stat, file](auto size) mutable {
stat.size = size;
- return file.close(
- ).then([stat] {
+ return identify_namespace(file
+ ).safe_then([stat] (auto id_namespace_data) mutable {
+ // LBA format provides LBA size which is power of 2. LBA is the
+ // minimum size of read and write.
+ stat.block_size = (1 << id_namespace_data.lbaf0.lbads);
+ if (stat.block_size < RBM_SUPERBLOCK_SIZE) {
+ stat.block_size = RBM_SUPERBLOCK_SIZE;
+ }
+ return stat_device_ret(
+ read_ertr::ready_future_marker{},
+ stat
+ );
+ }).handle_error(crimson::ct_error::input_output_error::handle(
+ [stat]{
return stat_device_ret(
read_ertr::ready_future_marker{},
stat
);
+ }), crimson::ct_error::pass_further_all{});
+ }).safe_then([file](auto st) mutable {
+ return file.close(
+ ).then([st] {
+ return stat_device_ret(
+ read_ertr::ready_future_marker{},
+ st
+ );
});
});
});
* Caller can construct and execute its own nvme command
*/
nvme_command_ertr::future<int> pass_admin(
- nvme_admin_command_t& admin_cmd);
+ nvme_admin_command_t& admin_cmd, seastar::file f);
nvme_command_ertr::future<int> pass_through_io(
nvme_io_command_t& io_cmd);
private:
// identify_controller/namespace are used to get SSD internal information such
// as supported features, NPWG and NPWA
- nvme_command_ertr::future<nvme_identify_controller_data_t> identify_controller();
- nvme_command_ertr::future<nvme_identify_namespace_data_t> identify_namespace();
- nvme_command_ertr::future<int> get_nsid();
+ nvme_command_ertr::future<nvme_identify_controller_data_t>
+ identify_controller(seastar::file f);
+ nvme_command_ertr::future<nvme_identify_namespace_data_t>
+ identify_namespace(seastar::file f);
+ nvme_command_ertr::future<int> get_nsid(seastar::file f);
open_ertr::future<> open_for_io(
const std::string& in_path,
seastar::open_flags mode);