Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / os / bluestore / BitMapAllocator.cc
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
21 BitMapAllocator::BitMapAllocator(CephContext* cct, int64_t device_size,
22                                  int64_t block_size)
23   : cct(cct)
24 {
25   if (!ISP2(block_size)) {
26     derr << __func__ << " block_size " << block_size
27          << " not power of 2 aligned!"
28          << dendl;
29     assert(ISP2(block_size));
30     return;
31   }
32
33   int64_t zone_size_blks = cct->_conf->bluestore_bitmapallocator_blocks_per_zone;
34   if (!ISP2(zone_size_blks)) {
35     derr << __func__ << " zone_size " << zone_size_blks
36          << " not power of 2 aligned!"
37          << dendl;
38     assert(ISP2(zone_size_blks));
39     return;
40   }
41
42   int64_t span_size = cct->_conf->bluestore_bitmapallocator_span_size;
43   if (!ISP2(span_size)) {
44     derr << __func__ << " span_size " << span_size
45          << " not power of 2 aligned!"
46          << dendl;
47     assert(ISP2(span_size));
48     return;
49   }
50
51   m_block_size = block_size;
52   m_total_size = P2ALIGN(device_size, block_size);
53   m_bit_alloc = new BitAllocator(cct, device_size / block_size,
54                                  zone_size_blks, CONCURRENT, true);
55   if (!m_bit_alloc) {
56     derr << __func__ << " Unable to intialize Bit Allocator" << dendl;
57     assert(m_bit_alloc);
58   }
59   dout(10) << __func__ << " instance " << (uint64_t) this
60            << " size 0x" << std::hex << device_size << std::dec
61            << dendl;
62 }
63
64 BitMapAllocator::~BitMapAllocator()
65 {
66   delete m_bit_alloc;
67 }
68
69 void 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
83 int 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
98 void 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
112 int64_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;
127   hint = hint % m_total_size; // make hint error-tolerant
128   return allocate_dis(want_size, alloc_unit / m_block_size,
129                       max_alloc_size, hint / m_block_size, extents);
130 }
131
132 int64_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
148 void 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
157 uint64_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
165 void BitMapAllocator::dump()
166 {
167   dout(0) << __func__ << " instance " << this << dendl;
168   m_bit_alloc->dump();
169 }
170
171 void 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
191 void 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
215 void BitMapAllocator::shutdown()
216 {
217   dout(10) << __func__ << " instance " << (uint64_t) this << dendl;
218   m_bit_alloc->shutdown();
219 }
220