}
}
+int64_t AvlAllocator::_allocate(
+ uint64_t want,
+ uint64_t unit,
+ uint64_t max_alloc_size,
+ int64_t hint, // unused, for now!
+ PExtentVector* extents)
+{
+ uint64_t allocated = 0;
+ while (allocated < want) {
+ uint64_t offset, length;
+ int r = _allocate(std::min(max_alloc_size, want - allocated),
+ unit, &offset, &length);
+ if (r < 0) {
+ // Allocation failed.
+ break;
+ }
+ extents->emplace_back(offset, length);
+ allocated += length;
+ }
+ return allocated ? allocated : -ENOSPC;
+}
+
int AvlAllocator::_allocate(
uint64_t size,
uint64_t unit,
uint64_t *offset,
uint64_t *length)
{
- std::lock_guard l(lock);
uint64_t max_size = 0;
if (auto p = range_size_tree.rbegin(); p != range_size_tree.rend()) {
max_size = p->end - p->start;
return 0;
}
+void AvlAllocator::_release(const interval_set<uint64_t>& release_set)
+{
+ for (auto p = release_set.begin(); p != release_set.end(); ++p) {
+ const auto offset = p.get_start();
+ const auto length = p.get_len();
+ ldout(cct, 10) << __func__ << std::hex
+ << " offset 0x" << offset
+ << " length 0x" << length
+ << std::dec << dendl;
+ _add_to_tree(offset, length);
+ }
+}
+
+void AvlAllocator::_shutdown()
+{
+ range_size_tree.clear();
+ range_tree.clear_and_dispose(dispose_rs{});
+}
+
AvlAllocator::AvlAllocator(CephContext* cct,
int64_t device_size,
int64_t block_size,
max_alloc_size >= cap) {
max_alloc_size = cap;
}
-
- uint64_t allocated = 0;
- while (allocated < want) {
- uint64_t offset, length;
- int r = _allocate(std::min(max_alloc_size, want - allocated),
- unit, &offset, &length);
- if (r < 0) {
- // Allocation failed.
- break;
- }
- extents->emplace_back(offset, length);
- allocated += length;
- }
- return allocated ? allocated : -ENOSPC;
+ std::lock_guard l(lock);
+ return _allocate(want, unit, max_alloc_size, hint, extents);
}
-void AvlAllocator::release(const interval_set<uint64_t>& release_set)
-{
+void AvlAllocator::release(const interval_set<uint64_t>& release_set) {
std::lock_guard l(lock);
- for (auto p = release_set.begin(); p != release_set.end(); ++p) {
- const auto offset = p.get_start();
- const auto length = p.get_len();
- ldout(cct, 10) << __func__ << std::hex
- << " offset 0x" << offset
- << " length 0x" << length
- << std::dec << dendl;
- _add_to_tree(offset, length);
- }
+ _release(release_set);
}
uint64_t AvlAllocator::get_free()
double AvlAllocator::get_fragmentation()
{
std::lock_guard l(lock);
- auto free_blocks = p2align(num_free, block_size) / block_size;
- if (free_blocks <= 1) {
- return .0;
- }
- return (static_cast<double>(range_tree.size() - 1) / (free_blocks - 1));
+ return _get_fragmentation();
}
void AvlAllocator::dump()
{
std::lock_guard l(lock);
+ _dump();
+}
+
+void AvlAllocator::_dump() const
+{
ldout(cct, 0) << __func__ << " range_tree: " << dendl;
for (auto& rs : range_tree) {
ldout(cct, 0) << std::hex
- << "0x" << rs.start << "~" << rs.end
- << std::dec
- << dendl;
+ << "0x" << rs.start << "~" << rs.end
+ << std::dec
+ << dendl;
}
ldout(cct, 0) << __func__ << " range_size_tree: " << dendl;
for (auto& rs : range_size_tree) {
ldout(cct, 0) << std::hex
- << "0x" << rs.start << "~" << rs.end
- << std::dec
- << dendl;
+ << "0x" << rs.start << "~" << rs.end
+ << std::dec
+ << dendl;
}
}
void AvlAllocator::shutdown()
{
std::lock_guard l(lock);
- range_size_tree.clear();
- range_tree.clear_and_dispose(dispose_rs{});
+ _shutdown();
}
boost::intrusive::avl_set_member_hook<> size_hook;
};
-class AvlAllocator final : public Allocator {
+class AvlAllocator : public Allocator {
struct dispose_rs {
void operator()(range_seg_t* p)
{
protected:
/*
* ctor intended for the usage from descendant class(es) which
- * provides handlig for spilled over entries
+ * provides handling for spilled over entries
* (when entry count >= max_entries)
*/
AvlAllocator(CephContext* cct, int64_t device_size, int64_t block_size,
uint64_t unit,
uint64_t max_alloc_size,
int64_t hint,
- PExtentVector *extents) final;
- void release(const interval_set<uint64_t>& release_set) final;
- uint64_t get_free() final;
- double get_fragmentation() final;
+ PExtentVector *extents) override;
+ void release(const interval_set<uint64_t>& release_set) override;
+ uint64_t get_free() override;
+ double get_fragmentation() override;
- void dump() final;
- void dump(std::function<void(uint64_t offset, uint64_t length)> notify) final;
- void init_add_free(uint64_t offset, uint64_t length) final;
- void init_rm_free(uint64_t offset, uint64_t length) final;
- void shutdown() final;
+ void dump() override;
+ void dump(std::function<void(uint64_t offset, uint64_t length)> notify) override;
+ void init_add_free(uint64_t offset, uint64_t length) override;
+ void init_rm_free(uint64_t offset, uint64_t length) override;
+ void shutdown() override;
private:
template<class Tree>
uint64_t _block_picker(const Tree& t, uint64_t *cursor, uint64_t size,
uint64_t align);
- void _add_to_tree(uint64_t start, uint64_t size);
- void _remove_from_tree(uint64_t start, uint64_t size);
int _allocate(
uint64_t size,
uint64_t unit,
*/
uint64_t range_count_cap = 0;
- CephContext* cct;
- std::mutex lock;
-
- uint64_t _lowest_size_available() {
- auto rs = range_size_tree.begin();
- return rs != range_size_tree.end() ? rs->length() : 0;
- }
void _range_size_tree_rm(range_seg_t& r) {
ceph_assert(num_free >= r.length());
num_free -= r.length();
// i.e. (range_count_cap > 0)
ceph_assert(false);
}
+protected:
+ CephContext* cct;
+ std::mutex lock;
+
+ double _get_fragmentation() const {
+ auto free_blocks = p2align(num_free, block_size) / block_size;
+ if (free_blocks <= 1) {
+ return .0;
+ }
+ return (static_cast<double>(range_tree.size() - 1) / (free_blocks - 1));
+ }
+ void _dump() const;
+
+ uint64_t _lowest_size_available() {
+ auto rs = range_size_tree.begin();
+ return rs != range_size_tree.end() ? rs->length() : 0;
+ }
+
+ int64_t _allocate(
+ uint64_t want,
+ uint64_t unit,
+ uint64_t max_alloc_size,
+ int64_t hint,
+ PExtentVector *extents);
+
+ void _release(const interval_set<uint64_t>& release_set);
+ void _shutdown();
+
+ void _add_to_tree(uint64_t start, uint64_t size);
+ void _remove_from_tree(uint64_t start, uint64_t size);
};