From: Xuehan Xu Date: Thu, 14 Oct 2021 09:43:23 +0000 (+0800) Subject: crimson/os/seastore: deal with scenarios in which bufferlist of do_writev has more... X-Git-Tag: v17.1.0~662^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F43537%2Fhead;p=ceph.git crimson/os/seastore: deal with scenarios in which bufferlist of do_writev has more than IOV_MAX buffers Signed-off-by: Xuehan Xu --- diff --git a/src/crimson/os/seastore/segment_manager/block.cc b/src/crimson/os/seastore/segment_manager/block.cc index 5b395fac589b..2fb9e4e41931 100644 --- a/src/crimson/os/seastore/segment_manager/block.cc +++ b/src/crimson/os/seastore/segment_manager/block.cc @@ -5,6 +5,7 @@ #include #include "crimson/common/config_proxy.h" +#include "crimson/common/errorator-loop.h" #include "crimson/common/log.h" #include "include/buffer.h" @@ -53,31 +54,43 @@ static write_ertr::future<> do_writev( size_t block_size) { logger().debug( - "block: do_writev offset {} len {}", + "block: do_writev offset {} len {}, {} buffers", offset, - bl.length()); + bl.length(), + bl.get_num_buffers()); // writev requires each buffer to be aligned to the disks' block // size, we need to rebuild here bl.rebuild_aligned(block_size); - std::vector iov; - bl.prepare_iov(&iov); - return device.dma_write( - offset, - std::move(iov) - ).handle_exception([](auto e) -> write_ertr::future { - logger().error( - "do_writev: dma_write got error {}", - e); - return crimson::ct_error::input_output_error::make(); - }).then( - [bl=std::move(bl)/* hold the buf until the end of io */](size_t written) - -> write_ertr::future<> { - if (written != bl.length()) { - return crimson::ct_error::input_output_error::make(); - } - return write_ertr::now(); + return seastar::do_with( + bl.prepare_iovs(), + std::move(bl), + [&device, offset] (auto& iovs, auto& bl) { + return write_ertr::parallel_for_each( + iovs, + [&device, offset](auto& p) mutable { + auto off = offset + p.first.first; + auto len = p.first.second; + auto& iov = p.second; + logger().debug("do_writev: dma_write to {}, length {}", off, len); + return device.dma_write(off, std::move(iov)) + .handle_exception([](auto e) -> write_ertr::future { + logger().error( + "do_writev: dma_write got error {}", + e); + return crimson::ct_error::input_output_error::make(); + }).then( + [off, len](size_t written) -> write_ertr::future<> { + if (written != len) { + logger().error( + "do_writev: dma_write to {}, failed, written {} != iov len {}", + off, written, len); + return crimson::ct_error::input_output_error::make(); + } + return write_ertr::now(); + }); + }); }); } @@ -96,7 +109,12 @@ static read_ertr::future<> do_read( offset, bptr.c_str(), len - ).handle_exception([](auto e) -> read_ertr::future { + ).handle_exception( + //FIXME: this is a little bit tricky, since seastar::future::handle_exception + // returns seastar::future, to return an crimson::ct_error, we have to create + // a seastar::future holding that crimson::ct_error. This is not necessary + // once seastar::future::handle_exception() returns seastar::futurize_t + [](auto e) -> read_ertr::future { logger().error( "do_read: dma_read got error {}", e);