1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
5 #include <linux/blkzoned.h>
7 #include <boost/intrusive_ptr.hpp>
8 #include <boost/smart_ptr/intrusive_ref_counter.hpp>
10 #include <seastar/core/file.hh>
11 #include <seastar/core/future.hh>
12 #include <seastar/core/reactor.hh>
14 #include "crimson/common/layout.h"
16 #include "crimson/os/seastore/segment_manager.h"
18 #include "include/uuid.h"
20 namespace crimson::os::seastore::segment_manager::zbd
{
22 struct zbd_shard_info_t
{
25 size_t first_segment_offset
= 0;
27 DENC(zbd_shard_info_t
, v
, p
) {
31 denc(v
.first_segment_offset
, p
);
36 struct zbd_sm_metadata_t
{
37 unsigned int shard_num
= 0;
38 size_t segment_size
= 0;
39 size_t segment_capacity
= 0;
40 size_t zones_per_segment
= 0;
41 size_t zone_capacity
= 0;
42 size_t block_size
= 0;
45 std::vector
<zbd_shard_info_t
> shard_infos
;
49 bool major_dev
= false;
51 device_type_t dtype
= device_type_t::NONE
;
52 device_id_t device_id
= 0;
53 secondary_device_set_t secondary_devices
;
55 DENC(zbd_sm_metadata_t
, v
, p
) {
58 denc(v
.segment_size
, p
);
59 denc(v
.segment_capacity
, p
);
60 denc(v
.zones_per_segment
, p
);
61 denc(v
.zone_capacity
, p
);
62 denc(v
.block_size
, p
);
64 denc(v
.shard_infos
, p
);
70 denc(v
.secondary_devices
, p
);
75 void validate() const {
76 ceph_assert_always(shard_num
== seastar::smp::count
);
77 for (unsigned int i
= 0; i
< seastar::smp::count
; i
++) {
78 ceph_assert_always(shard_infos
[i
].size
> 0);
79 ceph_assert_always(shard_infos
[i
].size
<= DEVICE_OFF_MAX
);
80 ceph_assert_always(shard_infos
[i
].segments
> 0);
81 ceph_assert_always(shard_infos
[i
].segments
<= DEVICE_SEGMENT_ID_MAX
);
83 ceph_assert_always(segment_capacity
> 0);
84 ceph_assert_always(segment_capacity
<= SEGMENT_OFF_MAX
);
88 using write_ertr
= crimson::errorator
<crimson::ct_error::input_output_error
>;
89 using read_ertr
= crimson::errorator
<crimson::ct_error::input_output_error
>;
98 class ZBDSegmentManager
;
100 class ZBDSegment final
: public Segment
{
102 ZBDSegment(ZBDSegmentManager
&man
, segment_id_t i
) : manager(man
), id(i
){};
104 segment_id_t
get_segment_id() const final
{ return id
; }
105 segment_off_t
get_write_capacity() const final
;
106 segment_off_t
get_write_ptr() const final
{ return write_pointer
; }
107 close_ertr::future
<> close() final
;
108 write_ertr::future
<> write(segment_off_t offset
, ceph::bufferlist bl
) final
;
109 write_ertr::future
<> advance_wp(segment_off_t offset
) final
;
113 friend class ZBDSegmentManager
;
114 ZBDSegmentManager
&manager
;
115 const segment_id_t id
;
116 segment_off_t write_pointer
= 0;
117 write_ertr::future
<> write_padding_bytes(size_t padding_bytes
);
120 class ZBDSegmentManager final
: public SegmentManager
{
121 // interfaces used by Device
123 seastar::future
<> start() {
124 return shard_devices
.start(device_path
);
127 seastar::future
<> stop() {
128 return shard_devices
.stop();
131 Device
& get_sharded_device() final
{
132 return shard_devices
.local();
135 mount_ret
mount() final
;
136 mkfs_ret
mkfs(device_config_t meta
) final
;
138 ZBDSegmentManager(const std::string
&path
) : device_path(path
) {}
140 ~ZBDSegmentManager() final
= default;
142 //interfaces used by each shard device
144 open_ertr::future
<SegmentRef
> open(segment_id_t id
) final
;
145 close_ertr::future
<> close() final
;
147 release_ertr::future
<> release(segment_id_t id
) final
;
149 read_ertr::future
<> read(
152 ceph::bufferptr
&out
) final
;
154 device_type_t
get_device_type() const final
{
155 return device_type_t::ZBD
;
158 size_t get_available_size() const final
{
159 return shard_info
.size
;
162 extent_len_t
get_block_size() const final
{
163 return metadata
.block_size
;
166 segment_off_t
get_segment_size() const final
{
167 return metadata
.segment_capacity
;
170 const seastore_meta_t
&get_meta() const {
171 return metadata
.meta
;
174 device_id_t
get_device_id() const final
;
176 secondary_device_set_t
& get_secondary_devices() final
;
178 magic_t
get_magic() const final
;
180 Segment::write_ertr::future
<> segment_write(
183 bool ignore_check
=false);
186 friend class ZBDSegment
;
187 std::string device_path
;
188 zbd_shard_info_t shard_info
;
189 zbd_sm_metadata_t metadata
;
190 seastar::file device
;
196 void increment(uint64_t read_bytes
) {
202 struct zbd_sm_stats
{
203 effort_t data_read
= {};
204 effort_t data_write
= {};
205 effort_t metadata_write
= {};
206 uint64_t opened_segments
= 0;
207 uint64_t closed_segments
= 0;
208 uint64_t closed_segments_unused_bytes
= 0;
209 uint64_t released_segments
= 0;
212 *this = zbd_sm_stats
{};
216 void register_metrics();
217 seastar::metrics::metric_group metrics
;
219 Segment::close_ertr::future
<> segment_close(
220 segment_id_t id
, segment_off_t write_pointer
);
222 uint64_t get_offset(paddr_t addr
) {
223 auto& seg_addr
= addr
.as_seg_paddr();
224 return (shard_info
.first_segment_offset
+
225 (seg_addr
.get_segment_id().device_segment_id() *
226 metadata
.segment_size
)) + seg_addr
.get_segment_off();
230 mkfs_ret
primary_mkfs(device_config_t meta
);
232 mkfs_ret
shard_mkfs();
234 mount_ret
shard_mount();
236 seastar::sharded
<ZBDSegmentManager
> shard_devices
;
241 WRITE_CLASS_DENC_BOUNDED(
242 crimson::os::seastore::segment_manager::zbd::zbd_shard_info_t
244 WRITE_CLASS_DENC_BOUNDED(
245 crimson::os::seastore::segment_manager::zbd::zbd_sm_metadata_t