From: myoungwon oh Date: Mon, 24 May 2021 14:19:49 +0000 (+0900) Subject: seastore: introduce rbm_sync_block_bitmap_by_range() X-Git-Tag: v17.1.0~1638^2~26 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=0f287e0834a455d7c8c9efc178adb1e30aefc8ae;p=ceph-ci.git seastore: introduce rbm_sync_block_bitmap_by_range() To set continous range of block id at once, this commit adds rbm_sync_block_bitmap_by_range(). Signed-off-by: Myoungwon Oh --- diff --git a/src/crimson/os/seastore/randomblock_manager.cc b/src/crimson/os/seastore/randomblock_manager.cc index cbaf50b673b..0db316ac8fa 100644 --- a/src/crimson/os/seastore/randomblock_manager.cc +++ b/src/crimson/os/seastore/randomblock_manager.cc @@ -309,6 +309,105 @@ RandomBlockManager::free_extent(Transaction &t, blk_paddr_t blk_paddr) ); } +RandomBlockManager::write_ertr::future<> +RandomBlockManager::rbm_sync_block_bitmap_by_range(blk_id_t start, blk_id_t end, bitmap_op_types_t op) +{ + auto addr = super.start_alloc_area + + (start / max_block_by_bitmap_block()) + * super.block_size; + // aligned write + if (start % max_block_by_bitmap_block() == 0 && + end % (max_block_by_bitmap_block() - 1) == 0) { + auto num_block = num_block_between_blk_ids(start, end); + bufferlist bl_bitmap_block; + add_cont_bitmap_blocks_to_buf(bl_bitmap_block, num_block, op); + return write( + addr, + bl_bitmap_block); + } + auto bp = bufferptr(ceph::buffer::create_page_aligned(super.block_size)); + // try to read first block, then check the block is aligned + return device->read( + addr, + bp).safe_then([bp, start, end, op, addr, this]() { + rbm_bitmap_block_t b_block(super.block_size); + bufferlist bl_bitmap_block; + bl_bitmap_block.append(bp); + decode(b_block, bl_bitmap_block); + auto max = max_block_by_bitmap_block(); + auto loop_end = end < (start / max + 1) * max ? + end % max : max - 1; + for (uint64_t i = (start % max); i <= loop_end; i++) { + if (op == bitmap_op_types_t::ALL_SET) { + b_block.set_bit(i); + } else { + b_block.clear_bit(i); + } + } + auto num_block = num_block_between_blk_ids(start, end); + logger().debug("rbm_sync_block_bitmap_by_range: start {}, end {}, loop_end {}, num_block {}", + start, end, loop_end, num_block); + + bl_bitmap_block.clear(); + encode(b_block, bl_bitmap_block); + if (num_block == 1) { + // | front (unaligned) | + return write( + addr, + bl_bitmap_block); + } else if (!((end + 1) % max)) { + // | front (unaligned) | middle (aligned) | + add_cont_bitmap_blocks_to_buf(bl_bitmap_block, num_block - 1, op); + logger().debug("partially aligned write: addr {} length {}", + addr, bl_bitmap_block.length()); + return write( + addr, + bl_bitmap_block); + } else if (num_block > 2) { + // | front (unaligned) | middle | end (unaligned) | + // fill up the middle + add_cont_bitmap_blocks_to_buf(bl_bitmap_block, num_block - 2, op); + } + + auto next_addr = super.start_alloc_area + + (end / max_block_by_bitmap_block()) + * super.block_size; + auto bptr = bufferptr(ceph::buffer::create_page_aligned(super.block_size)); + // | front (unaligned) | middle | end (unaligned) | or | front (unaligned) | end (unaligned) | + return device->read( + next_addr, + bptr).safe_then([bptr, bl_bitmap_block, start, end, op, addr, this]() mutable { + rbm_bitmap_block_t b_block(super.block_size); + bufferlist block; + block.append(bptr); + decode(b_block, block); + auto max = max_block_by_bitmap_block(); + for (uint64_t i = (end - (end % max)) % max; i <= (end % max); i++) { + if (op == bitmap_op_types_t::ALL_SET) { + b_block.set_bit(i); + } else { + b_block.clear_bit(i); + } + } + logger().debug("start {} end {} ", end - (end % max), end); + bl_bitmap_block.claim_append(block); + return write( + addr, + bl_bitmap_block); + }).handle_error( + write_ertr::pass_further{}, + crimson::ct_error::assert_all{ + "Invalid error in RandomBlockManager::rbm_sync_block_bitmap_by_range" + } + ); + }).handle_error( + write_ertr::pass_further{}, + crimson::ct_error::assert_all{ + "Invalid error in RandomBlockManager::rbm_sync_block_bitmap_by_range" + } + ); +} + RandomBlockManager::write_ertr::future<> RandomBlockManager::complete_allocation(Transaction &t) { @@ -480,6 +579,30 @@ RandomBlockManager::read_rbm_header(blk_paddr_t addr) ); } +RandomBlockManager::write_ertr::future<> +RandomBlockManager::write( + blk_paddr_t addr, + bufferlist &bl) +{ + ceph_assert(device); + bufferptr bptr; + try { + bptr = bufferptr(ceph::buffer::create_page_aligned(bl.length())); + auto iter = bl.cbegin(); + iter.copy(bl.length(), bptr.c_str()); + } catch (const std::exception &e) { + logger().error( + "write: " + "exception creating aligned buffer {}", + e + ); + ceph_assert(0 == "unhandled exception"); + } + return device->write( + addr, + bptr); +} + std::ostream &operator<<(std::ostream &out, const rbm_metadata_header_t &header) { out << " rbm_metadata_header_t(size=" << header.size diff --git a/src/crimson/os/seastore/randomblock_manager.h b/src/crimson/os/seastore/randomblock_manager.h index dde04a8ae78..6fb79218728 100644 --- a/src/crimson/os/seastore/randomblock_manager.h +++ b/src/crimson/os/seastore/randomblock_manager.h @@ -90,6 +90,11 @@ struct rbm_bitmap_block_header_t { std::ostream &operator<<(std::ostream &out, const rbm_metadata_header_t &header); std::ostream &operator<<(std::ostream &out, const rbm_bitmap_block_header_t &header); +enum class bitmap_op_types_t : uint8_t { + ALL_CLEAR = 1, + ALL_SET = 2 +}; + struct rbm_bitmap_block_t { rbm_bitmap_block_header_t header; bufferlist buf; @@ -113,6 +118,16 @@ struct rbm_bitmap_block_t { *p |= mask; } + void set_all_bits() { + ceph_assert(buf.length()); + ::memset(buf.c_str(), std::numeric_limits::max(), buf.length()); + } + + void set_clear_bits() { + ceph_assert(buf.length()); + ::memset(buf.c_str(), 0, buf.length()); + } + void clear_bit(uint64_t nr) { ceph_assert(buf.length()); char mask = ~BIT_CHAR_MASK(nr); @@ -351,6 +366,29 @@ public: return (id * super.block_size) + super.start; } + int num_block_between_blk_ids(blk_id_t start, blk_id_t end) { + auto max = max_block_by_bitmap_block(); + auto block_start = start / max; + auto block_end = end / max; + return block_end - block_start + 1; + } + + write_ertr::future<> rbm_sync_block_bitmap_by_range(blk_id_t start, blk_id_t end, bitmap_op_types_t op); + void add_cont_bitmap_blocks_to_buf(bufferlist& buf, int num_block, bitmap_op_types_t op) { + rbm_bitmap_block_t b_block(super.block_size); + alloc_rbm_bitmap_block_buf(b_block); + if (op == bitmap_op_types_t::ALL_SET) { + b_block.set_all_bits(); + } else { + b_block.set_clear_bits(); + } + for (int i = 0; i < num_block; i++) { + encode(b_block, buf); + } + } + + write_ertr::future<> write(blk_paddr_t addr, bufferlist &bl); + private: rbm_metadata_header_t super; // this contains the number of bitmap blocks, free blocks and rbm specific information //FreelistManager free_manager; // TODO: block management