]> git.proxmox.com Git - ceph.git/blame - ceph/src/osd/ExtentCache.cc
buildsys: switch source download to quincy
[ceph.git] / ceph / src / osd / ExtentCache.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 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2016 Red Hat
7 *
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.
12 *
13 */
14
15#include "ExtentCache.h"
16
f67539c2
TL
17using std::ostream;
18
19using ceph::bufferlist;
20
7c673cae
FG
21void ExtentCache::extent::_link_pin_state(pin_state &pin_state)
22{
11fdf7f2
TL
23 ceph_assert(parent_extent_set);
24 ceph_assert(!parent_pin_state);
7c673cae
FG
25 parent_pin_state = &pin_state;
26 pin_state.pin_list.push_back(*this);
27}
28
29void ExtentCache::extent::_unlink_pin_state()
30{
11fdf7f2
TL
31 ceph_assert(parent_extent_set);
32 ceph_assert(parent_pin_state);
7c673cae
FG
33 auto liter = pin_state::list::s_iterator_to(*this);
34 parent_pin_state->pin_list.erase(liter);
35 parent_pin_state = nullptr;
36}
37
38void ExtentCache::extent::unlink()
39{
11fdf7f2
TL
40 ceph_assert(parent_extent_set);
41 ceph_assert(parent_pin_state);
7c673cae
FG
42
43 _unlink_pin_state();
44
45 // remove from extent set
46 {
47 auto siter = object_extent_set::set::s_iterator_to(*this);
48 auto &set = object_extent_set::set::container_from_iterator(siter);
11fdf7f2 49 ceph_assert(&set == &(parent_extent_set->extent_set));
7c673cae
FG
50 set.erase(siter);
51 }
52
53 parent_extent_set = nullptr;
11fdf7f2 54 ceph_assert(!parent_pin_state);
7c673cae
FG
55}
56
57void ExtentCache::extent::link(
58 object_extent_set &extent_set,
59 pin_state &pin_state)
60{
11fdf7f2 61 ceph_assert(!parent_extent_set);
7c673cae
FG
62 parent_extent_set = &extent_set;
63 extent_set.extent_set.insert(*this);
64
65 _link_pin_state(pin_state);
66}
67
68void ExtentCache::extent::move(
69 pin_state &to)
70{
71 _unlink_pin_state();
72 _link_pin_state(to);
73}
74
75void ExtentCache::remove_and_destroy_if_empty(object_extent_set &eset)
76{
77 if (eset.extent_set.empty()) {
78 auto siter = cache_set::s_iterator_to(eset);
79 auto &set = cache_set::container_from_iterator(siter);
11fdf7f2 80 ceph_assert(&set == &per_object_caches);
7c673cae
FG
81
82 // per_object_caches owns eset
83 per_object_caches.erase(eset);
84 delete &eset;
85 }
86}
87
88ExtentCache::object_extent_set &ExtentCache::get_or_create(
89 const hobject_t &oid)
90{
91 cache_set::insert_commit_data data;
92 auto p = per_object_caches.insert_check(oid, Cmp(), data);
93 if (p.second) {
94 auto *eset = new object_extent_set(oid);
95 per_object_caches.insert_commit(*eset, data);
96 return *eset;
97 } else {
98 return *(p.first);
99 }
100}
101
102ExtentCache::object_extent_set *ExtentCache::get_if_exists(
103 const hobject_t &oid)
104{
105 cache_set::insert_commit_data data;
106 auto p = per_object_caches.insert_check(oid, Cmp(), data);
107 if (p.second) {
108 return nullptr;
109 } else {
110 return &*(p.first);
111 }
112}
113
114std::pair<
115 ExtentCache::object_extent_set::set::iterator,
116 ExtentCache::object_extent_set::set::iterator
117 > ExtentCache::object_extent_set::get_containing_range(
118 uint64_t off, uint64_t len)
119{
120 // fst is first iterator with end after off (may be end)
121 auto fst = extent_set.upper_bound(off, uint_cmp());
122 if (fst != extent_set.begin())
123 --fst;
124 if (fst != extent_set.end() && off >= (fst->offset + fst->get_length()))
125 ++fst;
126
127 // lst is first iterator with start >= off + len (may be end)
128 auto lst = extent_set.lower_bound(off + len, uint_cmp());
129 return std::make_pair(fst, lst);
130}
131
132extent_set ExtentCache::reserve_extents_for_rmw(
133 const hobject_t &oid,
134 write_pin &pin,
135 const extent_set &to_write,
136 const extent_set &to_read)
137{
138 if (to_write.empty() && to_read.empty()) {
139 return extent_set();
140 }
141 extent_set must_read;
142 auto &eset = get_or_create(oid);
143 extent_set missing;
144 for (auto &&res: to_write) {
145 eset.traverse_update(
146 pin,
147 res.first,
148 res.second,
149 [&](uint64_t off, uint64_t len,
150 extent *ext, object_extent_set::update_action *action) {
151 action->action = object_extent_set::update_action::UPDATE_PIN;
152 if (!ext) {
153 missing.insert(off, len);
154 }
155 });
156 }
157 must_read.intersection_of(
158 to_read,
159 missing);
160 return must_read;
161}
162
163extent_map ExtentCache::get_remaining_extents_for_rmw(
164 const hobject_t &oid,
165 write_pin &pin,
166 const extent_set &to_get)
167{
168 if (to_get.empty()) {
169 return extent_map();
170 }
171 extent_map ret;
172 auto &eset = get_or_create(oid);
173 for (auto &&res: to_get) {
174 bufferlist bl;
175 uint64_t cur = res.first;
176 eset.traverse_update(
177 pin,
178 res.first,
179 res.second,
180 [&](uint64_t off, uint64_t len,
181 extent *ext, object_extent_set::update_action *action) {
11fdf7f2 182 ceph_assert(off == cur);
7c673cae
FG
183 cur = off + len;
184 action->action = object_extent_set::update_action::NONE;
11fdf7f2 185 ceph_assert(ext && ext->bl && ext->pinned_by_write());
7c673cae
FG
186 bl.substr_of(
187 *(ext->bl),
188 off - ext->offset,
189 len);
190 ret.insert(off, len, bl);
191 });
192 }
193 return ret;
194}
195
196void ExtentCache::present_rmw_update(
197 const hobject_t &oid,
198 write_pin &pin,
199 const extent_map &extents)
200{
201 if (extents.empty()) {
202 return;
203 }
204 auto &eset = get_or_create(oid);
205 for (auto &&res: extents) {
206 eset.traverse_update(
207 pin,
208 res.get_off(),
209 res.get_len(),
210 [&](uint64_t off, uint64_t len,
211 extent *ext, object_extent_set::update_action *action) {
212 action->action = object_extent_set::update_action::NONE;
11fdf7f2 213 ceph_assert(ext && ext->pinned_by_write());
7c673cae
FG
214 action->bl = bufferlist();
215 action->bl->substr_of(
216 res.get_val(),
217 off - res.get_off(),
218 len);
219 });
220 }
221}
222
223ostream &ExtentCache::print(ostream &out) const
224{
225 out << "ExtentCache(" << std::endl;
226 for (auto esiter = per_object_caches.begin();
227 esiter != per_object_caches.end();
228 ++esiter) {
229 out << " Extents(" << esiter->oid << ")[" << std::endl;
230 for (auto exiter = esiter->extent_set.begin();
231 exiter != esiter->extent_set.end();
232 ++exiter) {
233 out << " Extent(" << exiter->offset
234 << "~" << exiter->get_length()
235 << ":" << exiter->pin_tid()
236 << ")" << std::endl;
237 }
238 }
239 return out << ")" << std::endl;
240}
241
242ostream &operator<<(ostream &lhs, const ExtentCache &cache)
243{
244 return cache.print(lhs);
245}