]> git.proxmox.com Git - ceph.git/blame - ceph/src/os/bluestore/BitMapAllocator.cc
update sources to v12.1.0
[ceph.git] / ceph / src / os / bluestore / BitMapAllocator.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Bitmap based in-memory allocator.
5 * Author: Ramesh Chander, Ramesh.Chander@sandisk.com
6 *
7 */
8
9#include "BitAllocator.h"
10
11#include "BitMapAllocator.h"
12#include "bluestore_types.h"
13#include "common/debug.h"
14
15#define dout_context cct
16#define dout_subsys ceph_subsys_bluestore
17#undef dout_prefix
18#define dout_prefix *_dout << "bitmapalloc:"
19
20
21BitMapAllocator::BitMapAllocator(CephContext* cct, int64_t device_size,
22 int64_t block_size)
23 : cct(cct)
24{
7c673cae
FG
25 if (!ISP2(block_size)) {
26 derr << __func__ << " block_size " << block_size
27 << " not power of 2 aligned!"
28 << dendl;
31f18b77 29 assert(ISP2(block_size));
7c673cae
FG
30 return;
31 }
32
33 int64_t zone_size_blks = cct->_conf->bluestore_bitmapallocator_blocks_per_zone;
7c673cae
FG
34 if (!ISP2(zone_size_blks)) {
35 derr << __func__ << " zone_size " << zone_size_blks
36 << " not power of 2 aligned!"
37 << dendl;
31f18b77 38 assert(ISP2(zone_size_blks));
7c673cae
FG
39 return;
40 }
41
42 int64_t span_size = cct->_conf->bluestore_bitmapallocator_span_size;
7c673cae
FG
43 if (!ISP2(span_size)) {
44 derr << __func__ << " span_size " << span_size
45 << " not power of 2 aligned!"
46 << dendl;
31f18b77 47 assert(ISP2(span_size));
7c673cae
FG
48 return;
49 }
50
51 m_block_size = block_size;
31f18b77 52 m_total_size = P2ALIGN(device_size, block_size);
7c673cae
FG
53 m_bit_alloc = new BitAllocator(cct, device_size / block_size,
54 zone_size_blks, CONCURRENT, true);
7c673cae
FG
55 if (!m_bit_alloc) {
56 derr << __func__ << " Unable to intialize Bit Allocator" << dendl;
31f18b77 57 assert(m_bit_alloc);
7c673cae
FG
58 }
59 dout(10) << __func__ << " instance " << (uint64_t) this
60 << " size 0x" << std::hex << device_size << std::dec
61 << dendl;
62}
63
64BitMapAllocator::~BitMapAllocator()
65{
66 delete m_bit_alloc;
67}
68
69void BitMapAllocator::insert_free(uint64_t off, uint64_t len)
70{
71 dout(20) << __func__ << " instance " << (uint64_t) this
72 << " off 0x" << std::hex << off
73 << " len 0x" << len << std::dec
74 << dendl;
75
76 assert(!(off % m_block_size));
77 assert(!(len % m_block_size));
78
79 m_bit_alloc->free_blocks(off / m_block_size,
80 len / m_block_size);
81}
82
83int BitMapAllocator::reserve(uint64_t need)
84{
85 int nblks = need / m_block_size; // apply floor
86 assert(!(need % m_block_size));
87 dout(10) << __func__ << " instance " << (uint64_t) this
88 << " num_used " << m_bit_alloc->get_used_blocks()
89 << " total " << m_bit_alloc->total_blocks()
90 << dendl;
91
92 if (!m_bit_alloc->reserve_blocks(nblks)) {
93 return -ENOSPC;
94 }
95 return 0;
96}
97
98void BitMapAllocator::unreserve(uint64_t unused)
99{
100 int nblks = unused / m_block_size;
101 assert(!(unused % m_block_size));
102
103 dout(10) << __func__ << " instance " << (uint64_t) this
104 << " unused " << nblks
105 << " num used " << m_bit_alloc->get_used_blocks()
106 << " total " << m_bit_alloc->total_blocks()
107 << dendl;
108
109 m_bit_alloc->unreserve_blocks(nblks);
110}
111
112int64_t BitMapAllocator::allocate(
113 uint64_t want_size, uint64_t alloc_unit, uint64_t max_alloc_size,
114 int64_t hint, mempool::bluestore_alloc::vector<AllocExtent> *extents)
115{
116
117 assert(!(alloc_unit % m_block_size));
118 assert(alloc_unit);
119
120 assert(!max_alloc_size || max_alloc_size >= alloc_unit);
121
122 dout(10) << __func__ <<" instance "<< (uint64_t) this
123 << " want_size " << want_size
124 << " alloc_unit " << alloc_unit
125 << " hint " << hint
126 << dendl;
31f18b77 127 hint = hint % m_total_size; // make hint error-tolerant
7c673cae
FG
128 return allocate_dis(want_size, alloc_unit / m_block_size,
129 max_alloc_size, hint / m_block_size, extents);
130}
131
132int64_t BitMapAllocator::allocate_dis(
133 uint64_t want_size, uint64_t alloc_unit, uint64_t max_alloc_size,
134 int64_t hint, mempool::bluestore_alloc::vector<AllocExtent> *extents)
135{
136 ExtentList block_list = ExtentList(extents, m_block_size, max_alloc_size);
137 int64_t nblks = (want_size + m_block_size - 1) / m_block_size;
138 int64_t num = 0;
139
140 num = m_bit_alloc->alloc_blocks_dis_res(nblks, alloc_unit, hint, &block_list);
141 if (num == 0) {
142 return -ENOSPC;
143 }
144
145 return num * m_block_size;
146}
147
148void BitMapAllocator::release(
149 uint64_t offset, uint64_t length)
150{
151 dout(10) << __func__ << " 0x"
152 << std::hex << offset << "~" << length << std::dec
153 << dendl;
154 insert_free(offset, length);
155}
156
157uint64_t BitMapAllocator::get_free()
158{
159 assert(m_bit_alloc->total_blocks() >= m_bit_alloc->get_used_blocks());
160 return ((
161 m_bit_alloc->total_blocks() - m_bit_alloc->get_used_blocks()) *
162 m_block_size);
163}
164
165void BitMapAllocator::dump()
166{
167 dout(0) << __func__ << " instance " << this << dendl;
168 m_bit_alloc->dump();
169}
170
171void BitMapAllocator::init_add_free(uint64_t offset, uint64_t length)
172{
173 dout(10) << __func__ << " instance " << (uint64_t) this
174 << " offset 0x" << std::hex << offset
175 << " length 0x" << length << std::dec
176 << dendl;
177 uint64_t size = m_bit_alloc->size() * m_block_size;
178
179 uint64_t offset_adj = ROUND_UP_TO(offset, m_block_size);
180 uint64_t length_adj = ((length - (offset_adj - offset)) /
181 m_block_size) * m_block_size;
182
183 if ((offset_adj + length_adj) > size) {
184 assert(((offset_adj + length_adj) - m_block_size) < size);
185 length_adj = size - offset_adj;
186 }
187
188 insert_free(offset_adj, length_adj);
189}
190
191void BitMapAllocator::init_rm_free(uint64_t offset, uint64_t length)
192{
193 dout(10) << __func__ << " instance " << (uint64_t) this
194 << " offset 0x" << std::hex << offset
195 << " length 0x" << length << std::dec
196 << dendl;
197
198 // we use the same adjustment/alignment that init_add_free does
199 // above so that we can yank back some of the space.
200 uint64_t offset_adj = ROUND_UP_TO(offset, m_block_size);
201 uint64_t length_adj = ((length - (offset_adj - offset)) /
202 m_block_size) * m_block_size;
203
204 assert(!(offset_adj % m_block_size));
205 assert(!(length_adj % m_block_size));
206
207 int64_t first_blk = offset_adj / m_block_size;
208 int64_t count = length_adj / m_block_size;
209
210 if (count)
211 m_bit_alloc->set_blocks_used(first_blk, count);
212}
213
214
215void BitMapAllocator::shutdown()
216{
217 dout(10) << __func__ << " instance " << (uint64_t) this << dendl;
218 m_bit_alloc->shutdown();
219}
220