1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
8 #include <boost/intrusive_ptr.hpp>
9 #include <boost/smart_ptr/intrusive_ref_counter.hpp>
10 #include <seastar/core/future.hh>
12 #include "include/ceph_assert.h"
13 #include "crimson/os/seastore/seastore_types.h"
14 #include "include/buffer_fwd.h"
15 #include "crimson/osd/exceptions.h"
17 #include "crimson/os/seastore/transaction.h"
19 #include "crimson/common/layout.h"
20 #include "include/buffer.h"
21 #include "crimson/os/seastore/device.h"
23 namespace crimson::os::seastore
{
25 struct rbm_shard_info_t
{
27 uint64_t start_offset
= 0;
29 DENC(rbm_shard_info_t
, v
, p
) {
32 denc(v
.start_offset
, p
);
37 struct rbm_metadata_header_t
{
39 size_t block_size
= 0;
41 uint64_t journal_size
= 0;
43 device_config_t config
;
44 unsigned int shard_num
= 0;
45 std::vector
<rbm_shard_info_t
> shard_infos
;
47 DENC(rbm_metadata_header_t
, v
, p
) {
50 denc(v
.block_size
, p
);
53 denc(v
.journal_size
, p
);
57 denc(v
.shard_infos
, p
);
61 void validate() const {
62 ceph_assert(shard_num
== seastar::smp::count
);
63 ceph_assert(block_size
> 0);
64 for (unsigned int i
= 0; i
< seastar::smp::count
; i
++) {
65 ceph_assert(shard_infos
[i
].size
> block_size
&&
66 shard_infos
[i
].size
% block_size
== 0);
67 ceph_assert_always(shard_infos
[i
].size
<= DEVICE_OFF_MAX
);
68 ceph_assert(journal_size
> 0 &&
69 journal_size
% block_size
== 0);
70 ceph_assert(shard_infos
[i
].start_offset
< size
&&
71 shard_infos
[i
].start_offset
% block_size
== 0);
73 ceph_assert(config
.spec
.magic
!= 0);
74 ceph_assert(get_default_backend_of_device(config
.spec
.dtype
) ==
75 backend_type_t::RANDOM_BLOCK
);
76 ceph_assert(config
.spec
.id
<= DEVICE_ID_MAX_VALID
);
80 enum class rbm_extent_state_t
{
81 FREE
, // not allocated
82 RESERVED
, // extent is reserved by alloc_new_extent, but is not persistent
83 ALLOCATED
, // extent is persistent
87 using rbm_abs_addr
= uint64_t;
88 constexpr rbm_abs_addr RBM_START_ADDRESS
= 0;
89 class RandomBlockManager
{
92 using read_ertr
= crimson::errorator
<
93 crimson::ct_error::input_output_error
,
94 crimson::ct_error::invarg
,
95 crimson::ct_error::enoent
,
96 crimson::ct_error::erange
>;
97 virtual read_ertr::future
<> read(paddr_t addr
, bufferptr
&buffer
) = 0;
99 using write_ertr
= crimson::errorator
<
100 crimson::ct_error::input_output_error
,
101 crimson::ct_error::invarg
,
102 crimson::ct_error::ebadf
,
103 crimson::ct_error::enospc
,
104 crimson::ct_error::erange
106 virtual write_ertr::future
<> write(paddr_t addr
, bufferptr
&buf
) = 0;
108 using open_ertr
= crimson::errorator
<
109 crimson::ct_error::input_output_error
,
110 crimson::ct_error::invarg
,
111 crimson::ct_error::enoent
>;
112 virtual open_ertr::future
<> open() = 0;
114 using close_ertr
= crimson::errorator
<
115 crimson::ct_error::input_output_error
,
116 crimson::ct_error::invarg
>;
117 virtual close_ertr::future
<> close() = 0;
119 using allocate_ertr
= crimson::errorator
<
120 crimson::ct_error::input_output_error
,
121 crimson::ct_error::invarg
,
122 crimson::ct_error::enospc
124 using allocate_ret
= allocate_ertr::future
<paddr_t
>;
125 // allocator, return start addr of allocated blocks
126 virtual paddr_t
alloc_extent(size_t size
) = 0;
128 virtual void mark_space_used(paddr_t paddr
, size_t len
) = 0;
129 virtual void mark_space_free(paddr_t paddr
, size_t len
) = 0;
131 virtual void complete_allocation(paddr_t addr
, size_t size
) = 0;
133 virtual size_t get_size() const = 0;
134 virtual extent_len_t
get_block_size() const = 0;
135 virtual uint64_t get_free_blocks() const = 0;
136 virtual device_id_t
get_device_id() const = 0;
137 virtual const seastore_meta_t
&get_meta() const = 0;
138 virtual Device
* get_device() = 0;
139 virtual paddr_t
get_start() = 0;
140 virtual rbm_extent_state_t
get_extent_state(paddr_t addr
, size_t size
) = 0;
141 virtual size_t get_journal_size() const = 0;
142 virtual ~RandomBlockManager() {}
144 using RandomBlockManagerRef
= std::unique_ptr
<RandomBlockManager
>;
146 inline rbm_abs_addr
convert_paddr_to_abs_addr(const paddr_t
& paddr
) {
147 const blk_paddr_t
& blk_addr
= paddr
.as_blk_paddr();
148 return blk_addr
.get_device_off();
151 inline paddr_t
convert_abs_addr_to_paddr(rbm_abs_addr addr
, device_id_t d_id
) {
152 return paddr_t::make_blk_paddr(d_id
, addr
);
155 namespace random_block_device
{
159 seastar::future
<std::unique_ptr
<random_block_device::RBMDevice
>>
160 get_rb_device(const std::string
&device
);
162 std::ostream
&operator<<(std::ostream
&out
, const rbm_metadata_header_t
&header
);
163 std::ostream
&operator<<(std::ostream
&out
, const rbm_shard_info_t
&shard
);
166 WRITE_CLASS_DENC_BOUNDED(
167 crimson::os::seastore::rbm_shard_info_t
169 WRITE_CLASS_DENC_BOUNDED(
170 crimson::os::seastore::rbm_metadata_header_t
173 #if FMT_VERSION >= 90000
174 template<> struct fmt::formatter
<crimson::os::seastore::rbm_metadata_header_t
> : fmt::ostream_formatter
{};
175 template<> struct fmt::formatter
<crimson::os::seastore::rbm_shard_info_t
> : fmt::ostream_formatter
{};