]>
git.proxmox.com Git - ceph.git/blob - ceph/src/os/bluestore/ZonedAllocator.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
5 // A simple allocator that just hands out space from the next empty zone. This
6 // is temporary, just to get the simplest append-only write workload to work.
8 // Copyright (C) 2020 Abutalib Aghayev
11 #include "ZonedAllocator.h"
12 #include "bluestore_types.h"
13 #include "zoned_types.h"
14 #include "common/debug.h"
16 #define dout_context cct
17 #define dout_subsys ceph_subsys_bluestore
19 #define dout_prefix *_dout << "ZonedAllocator " << this << " "
21 ZonedAllocator::ZonedAllocator(CephContext
* cct
,
24 const std::string
& name
)
25 : Allocator(name
, size
, block_size
),
29 // To avoid interface changes, we piggyback zone size and the first
30 // sequential zone number onto the first 32 bits of 64-bit |block_size|.
31 // The last 32 bits of |block_size| is holding the actual block size.
32 block_size((block_size
& 0x00000000ffffffff)),
33 zone_size(((block_size
& 0x0000ffff00000000) >> 32) * 1024 * 1024),
34 starting_zone_num((block_size
& 0xffff000000000000) >> 48),
35 num_zones(size
/ zone_size
) {
36 ldout(cct
, 10) << __func__
<< " size 0x" << std::hex
<< size
37 << " zone size 0x" << zone_size
<< std::dec
38 << " number of zones " << num_zones
39 << " first sequential zone " << starting_zone_num
41 ceph_assert(size
% zone_size
== 0);
44 ZonedAllocator::~ZonedAllocator() {}
46 int64_t ZonedAllocator::allocate(
49 uint64_t max_alloc_size
,
51 PExtentVector
*extents
) {
52 std::lock_guard
l(lock
);
54 ceph_assert(want_size
% 4096 == 0);
56 ldout(cct
, 10) << __func__
<< " trying to allocate "
57 << std::hex
<< want_size
<< dendl
;
59 uint64_t zone_num
= starting_zone_num
;
60 for ( ; zone_num
< num_zones
; ++zone_num
) {
61 if (fits(want_size
, zone_num
)) {
64 ldout(cct
, 10) << __func__
<< " skipping zone " << zone_num
65 << " because there is not enough space: "
66 << " want_size = " << want_size
67 << " available = " << get_remaining_space(zone_num
)
71 if (zone_num
== num_zones
) {
72 ldout(cct
, 10) << __func__
<< " failed to allocate" << dendl
;
76 uint64_t offset
= get_offset(zone_num
);
78 ldout(cct
, 10) << __func__
<< " advancing zone " << std::hex
79 << zone_num
<< " write pointer from " << offset
80 << " to " << offset
+ want_size
<< dendl
;
82 advance_write_pointer(zone_num
, want_size
);
83 if (get_remaining_space(zone_num
) == 0) {
84 starting_zone_num
= zone_num
+ 1;
87 ldout(cct
, 10) << __func__
<< std::hex
<< " zone " << zone_num
88 << " offset is now " << get_write_pointer(zone_num
) << dendl
;
90 ldout(cct
, 10) << __func__
<< " allocated " << std::hex
<< want_size
91 << " bytes at offset " << offset
92 << " located at zone " << zone_num
93 << " and zone offset " << offset
% zone_size
<< dendl
;
95 extents
->emplace_back(bluestore_pextent_t(offset
, want_size
));
99 void ZonedAllocator::release(const interval_set
<uint64_t>& release_set
) {
100 std::lock_guard
l(lock
);
103 uint64_t ZonedAllocator::get_free() {
107 void ZonedAllocator::dump() {
108 std::lock_guard
l(lock
);
111 void ZonedAllocator::dump(std::function
<void(uint64_t offset
,
112 uint64_t length
)> notify
) {
113 std::lock_guard
l(lock
);
116 // This just increments |num_free|. The actual free space is added by
117 // set_zone_states, as it updates the write pointer for each zone.
118 void ZonedAllocator::init_add_free(uint64_t offset
, uint64_t length
) {
119 ldout(cct
, 40) << __func__
<< " " << std::hex
120 << offset
<< "~" << length
<< dendl
;
125 void ZonedAllocator::init_rm_free(uint64_t offset
, uint64_t length
) {
126 std::lock_guard
l(lock
);
127 ldout(cct
, 40) << __func__
<< " 0x" << std::hex
128 << offset
<< "~" << length
<< dendl
;
131 ceph_assert(num_free
>= 0);
133 uint64_t zone_num
= offset
/ zone_size
;
134 uint64_t write_pointer
= offset
% zone_size
;
135 uint64_t remaining_space
= get_remaining_space(zone_num
);
137 ceph_assert(get_write_pointer(zone_num
) == write_pointer
);
138 ceph_assert(remaining_space
<= length
);
139 advance_write_pointer(zone_num
, remaining_space
);
141 ldout(cct
, 40) << __func__
<< " set zone 0x" << std::hex
142 << zone_num
<< " write pointer to 0x" << zone_size
<< dendl
;
144 length
-= remaining_space
;
145 ceph_assert(length
% zone_size
== 0);
147 for ( ; length
; length
-= zone_size
) {
148 advance_write_pointer(++zone_num
, zone_size
);
149 ldout(cct
, 40) << __func__
<< " set zone 0x" << std::hex
150 << zone_num
<< " write pointer to 0x" << zone_size
<< dendl
;
154 bool ZonedAllocator::zoned_get_zones_to_clean(std::deque
<uint64_t> *zones_to_clean
) {
155 // TODO: make 0.25 tunable
156 if (static_cast<double>(num_free
) / size
> 0.25) {
160 std::lock_guard
l(lock
);
161 // TODO: populate |zones_to_clean| with the numbers of zones that should be
167 void ZonedAllocator::zoned_set_zone_states(std::vector
<zone_state_t
> &&_zone_states
) {
168 std::lock_guard
l(lock
);
169 ldout(cct
, 10) << __func__
<< dendl
;
170 zone_states
= std::move(_zone_states
);
173 void ZonedAllocator::shutdown() {
174 ldout(cct
, 1) << __func__
<< dendl
;