1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Bitmap based in-memory allocator.
5 * Author: Ramesh Chander, Ramesh.Chander@sandisk.com
9 #include "BitAllocator.h"
11 #include "BitMapAllocator.h"
12 #include "bluestore_types.h"
13 #include "common/debug.h"
15 #define dout_context cct
16 #define dout_subsys ceph_subsys_bluestore
18 #define dout_prefix *_dout << "bitmapalloc:"
21 BitMapAllocator::BitMapAllocator(CephContext
* cct
, int64_t device_size
,
25 if (!ISP2(block_size
)) {
26 derr
<< __func__
<< " block_size " << block_size
27 << " not power of 2 aligned!"
29 assert(ISP2(block_size
));
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!"
38 assert(ISP2(zone_size_blks
));
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!"
47 assert(ISP2(span_size
));
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);
56 derr
<< __func__
<< " Unable to intialize Bit Allocator" << dendl
;
59 dout(10) << __func__
<< " instance " << (uint64_t) this
60 << " size 0x" << std::hex
<< device_size
<< std::dec
64 BitMapAllocator::~BitMapAllocator()
69 void BitMapAllocator::insert_free(uint64_t off
, uint64_t len
)
71 dout(20) << __func__
<< " instance " << (uint64_t) this
72 << " off 0x" << std::hex
<< off
73 << " len 0x" << len
<< std::dec
76 assert(!(off
% m_block_size
));
77 assert(!(len
% m_block_size
));
79 m_bit_alloc
->free_blocks(off
/ m_block_size
,
83 int BitMapAllocator::reserve(uint64_t need
)
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()
92 if (!m_bit_alloc
->reserve_blocks(nblks
)) {
98 void BitMapAllocator::unreserve(uint64_t unused
)
100 int nblks
= unused
/ m_block_size
;
101 assert(!(unused
% m_block_size
));
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()
109 m_bit_alloc
->unreserve_blocks(nblks
);
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
)
117 assert(!(alloc_unit
% m_block_size
));
120 assert(!max_alloc_size
|| max_alloc_size
>= alloc_unit
);
122 dout(10) << __func__
<<" instance "<< (uint64_t) this
123 << " want_size " << want_size
124 << " alloc_unit " << alloc_unit
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
);
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
)
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
;
140 num
= m_bit_alloc
->alloc_blocks_dis_res(nblks
, alloc_unit
, hint
, &block_list
);
145 return num
* m_block_size
;
148 void BitMapAllocator::release(
149 uint64_t offset
, uint64_t length
)
151 dout(10) << __func__
<< " 0x"
152 << std::hex
<< offset
<< "~" << length
<< std::dec
154 insert_free(offset
, length
);
157 uint64_t BitMapAllocator::get_free()
159 assert(m_bit_alloc
->total_blocks() >= m_bit_alloc
->get_used_blocks());
161 m_bit_alloc
->total_blocks() - m_bit_alloc
->get_used_blocks()) *
165 void BitMapAllocator::dump()
167 dout(0) << __func__
<< " instance " << this << dendl
;
171 void BitMapAllocator::init_add_free(uint64_t offset
, uint64_t length
)
173 dout(10) << __func__
<< " instance " << (uint64_t) this
174 << " offset 0x" << std::hex
<< offset
175 << " length 0x" << length
<< std::dec
177 uint64_t size
= m_bit_alloc
->size() * m_block_size
;
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
;
183 if ((offset_adj
+ length_adj
) > size
) {
184 assert(((offset_adj
+ length_adj
) - m_block_size
) < size
);
185 length_adj
= size
- offset_adj
;
188 insert_free(offset_adj
, length_adj
);
191 void BitMapAllocator::init_rm_free(uint64_t offset
, uint64_t length
)
193 dout(10) << __func__
<< " instance " << (uint64_t) this
194 << " offset 0x" << std::hex
<< offset
195 << " length 0x" << length
<< std::dec
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
;
204 assert(!(offset_adj
% m_block_size
));
205 assert(!(length_adj
% m_block_size
));
207 int64_t first_blk
= offset_adj
/ m_block_size
;
208 int64_t count
= length_adj
/ m_block_size
;
211 m_bit_alloc
->set_blocks_used(first_blk
, count
);
215 void BitMapAllocator::shutdown()
217 dout(10) << __func__
<< " instance " << (uint64_t) this << dendl
;
218 m_bit_alloc
->shutdown();