]>
git.proxmox.com Git - ceph.git/blob - ceph/src/osd/ExtentCache.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2016 Red Hat
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
15 #include "ExtentCache.h"
17 void ExtentCache::extent::_link_pin_state(pin_state
&pin_state
)
19 assert(parent_extent_set
);
20 assert(!parent_pin_state
);
21 parent_pin_state
= &pin_state
;
22 pin_state
.pin_list
.push_back(*this);
25 void ExtentCache::extent::_unlink_pin_state()
27 assert(parent_extent_set
);
28 assert(parent_pin_state
);
29 auto liter
= pin_state::list::s_iterator_to(*this);
30 parent_pin_state
->pin_list
.erase(liter
);
31 parent_pin_state
= nullptr;
34 void ExtentCache::extent::unlink()
36 assert(parent_extent_set
);
37 assert(parent_pin_state
);
41 // remove from extent set
43 auto siter
= object_extent_set::set::s_iterator_to(*this);
44 auto &set
= object_extent_set::set::container_from_iterator(siter
);
45 assert(&set
== &(parent_extent_set
->extent_set
));
49 parent_extent_set
= nullptr;
50 assert(!parent_pin_state
);
53 void ExtentCache::extent::link(
54 object_extent_set
&extent_set
,
57 assert(!parent_extent_set
);
58 parent_extent_set
= &extent_set
;
59 extent_set
.extent_set
.insert(*this);
61 _link_pin_state(pin_state
);
64 void ExtentCache::extent::move(
71 void ExtentCache::remove_and_destroy_if_empty(object_extent_set
&eset
)
73 if (eset
.extent_set
.empty()) {
74 auto siter
= cache_set::s_iterator_to(eset
);
75 auto &set
= cache_set::container_from_iterator(siter
);
76 assert(&set
== &per_object_caches
);
78 // per_object_caches owns eset
79 per_object_caches
.erase(eset
);
84 ExtentCache::object_extent_set
&ExtentCache::get_or_create(
87 cache_set::insert_commit_data data
;
88 auto p
= per_object_caches
.insert_check(oid
, Cmp(), data
);
90 auto *eset
= new object_extent_set(oid
);
91 per_object_caches
.insert_commit(*eset
, data
);
98 ExtentCache::object_extent_set
*ExtentCache::get_if_exists(
101 cache_set::insert_commit_data data
;
102 auto p
= per_object_caches
.insert_check(oid
, Cmp(), data
);
111 ExtentCache::object_extent_set::set::iterator
,
112 ExtentCache::object_extent_set::set::iterator
113 > ExtentCache::object_extent_set::get_containing_range(
114 uint64_t off
, uint64_t len
)
116 // fst is first iterator with end after off (may be end)
117 auto fst
= extent_set
.upper_bound(off
, uint_cmp());
118 if (fst
!= extent_set
.begin())
120 if (fst
!= extent_set
.end() && off
>= (fst
->offset
+ fst
->get_length()))
123 // lst is first iterator with start >= off + len (may be end)
124 auto lst
= extent_set
.lower_bound(off
+ len
, uint_cmp());
125 return std::make_pair(fst
, lst
);
128 extent_set
ExtentCache::reserve_extents_for_rmw(
129 const hobject_t
&oid
,
131 const extent_set
&to_write
,
132 const extent_set
&to_read
)
134 if (to_write
.empty() && to_read
.empty()) {
137 extent_set must_read
;
138 auto &eset
= get_or_create(oid
);
140 for (auto &&res
: to_write
) {
141 eset
.traverse_update(
145 [&](uint64_t off
, uint64_t len
,
146 extent
*ext
, object_extent_set::update_action
*action
) {
147 action
->action
= object_extent_set::update_action::UPDATE_PIN
;
149 missing
.insert(off
, len
);
153 must_read
.intersection_of(
159 extent_map
ExtentCache::get_remaining_extents_for_rmw(
160 const hobject_t
&oid
,
162 const extent_set
&to_get
)
164 if (to_get
.empty()) {
168 auto &eset
= get_or_create(oid
);
169 for (auto &&res
: to_get
) {
171 uint64_t cur
= res
.first
;
172 eset
.traverse_update(
176 [&](uint64_t off
, uint64_t len
,
177 extent
*ext
, object_extent_set::update_action
*action
) {
180 action
->action
= object_extent_set::update_action::NONE
;
181 assert(ext
&& ext
->bl
&& ext
->pinned_by_write());
186 ret
.insert(off
, len
, bl
);
192 void ExtentCache::present_rmw_update(
193 const hobject_t
&oid
,
195 const extent_map
&extents
)
197 if (extents
.empty()) {
200 auto &eset
= get_or_create(oid
);
201 for (auto &&res
: extents
) {
202 eset
.traverse_update(
206 [&](uint64_t off
, uint64_t len
,
207 extent
*ext
, object_extent_set::update_action
*action
) {
208 action
->action
= object_extent_set::update_action::NONE
;
209 assert(ext
&& ext
->pinned_by_write());
210 action
->bl
= bufferlist();
211 action
->bl
->substr_of(
219 ostream
&ExtentCache::print(ostream
&out
) const
221 out
<< "ExtentCache(" << std::endl
;
222 for (auto esiter
= per_object_caches
.begin();
223 esiter
!= per_object_caches
.end();
225 out
<< " Extents(" << esiter
->oid
<< ")[" << std::endl
;
226 for (auto exiter
= esiter
->extent_set
.begin();
227 exiter
!= esiter
->extent_set
.end();
229 out
<< " Extent(" << exiter
->offset
230 << "~" << exiter
->get_length()
231 << ":" << exiter
->pin_tid()
235 return out
<< ")" << std::endl
;
238 ostream
&operator<<(ostream
&lhs
, const ExtentCache
&cache
)
240 return cache
.print(lhs
);