1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "MissingLoc.h"
6 #define dout_context cct
8 #define dout_prefix (gen_prefix(*_dout))
9 #define dout_subsys ceph_subsys_osd
11 bool MissingLoc::readable_with_acting(
12 const hobject_t
&hoid
,
13 const set
<pg_shard_t
> &acting
) const {
14 if (!needs_recovery(hoid
))
18 auto missing_loc_entry
= missing_loc
.find(hoid
);
19 if (missing_loc_entry
== missing_loc
.end())
21 const set
<pg_shard_t
> &locs
= missing_loc_entry
->second
;
22 ldout(cct
, 10) << __func__
<< ": locs:" << locs
<< dendl
;
23 set
<pg_shard_t
> have_acting
;
24 for (set
<pg_shard_t
>::const_iterator i
= locs
.begin();
28 have_acting
.insert(*i
);
30 return (*is_readable
)(have_acting
);
33 void MissingLoc::add_batch_sources_info(
34 const set
<pg_shard_t
> &sources
,
37 ldout(cct
, 10) << __func__
<< ": adding sources in batch "
38 << sources
.size() << dendl
;
40 bool sources_updated
= false;
41 for (map
<hobject_t
, pg_missing_item
>::const_iterator i
= needs_recovery_map
.begin();
42 i
!= needs_recovery_map
.end();
44 if (handle
&& ++loop
>= cct
->_conf
->osd_loop_before_reset_tphandle
) {
45 handle
->reset_tp_timeout();
48 if (i
->second
.is_delete())
51 auto p
= missing_loc
.find(i
->first
);
52 if (p
== missing_loc
.end()) {
53 p
= missing_loc
.emplace(i
->first
, set
<pg_shard_t
>()).first
;
55 _dec_count(p
->second
);
57 missing_loc
[i
->first
].insert(sources
.begin(), sources
.end());
58 _inc_count(p
->second
);
60 if (!sources_updated
) {
61 missing_loc_sources
.insert(sources
.begin(), sources
.end());
62 sources_updated
= true;
67 bool MissingLoc::add_source_info(
69 const pg_info_t
&oinfo
,
70 const pg_missing_t
&omissing
,
73 bool found_missing
= false;
75 bool sources_updated
= false;
77 for (map
<hobject_t
,pg_missing_item
>::const_iterator p
= needs_recovery_map
.begin();
78 p
!= needs_recovery_map
.end();
80 const hobject_t
&soid(p
->first
);
81 eversion_t need
= p
->second
.need
;
82 if (handle
&& ++loop
>= cct
->_conf
->osd_loop_before_reset_tphandle
) {
83 handle
->reset_tp_timeout();
86 if (p
->second
.is_delete()) {
87 ldout(cct
, 10) << __func__
<< " " << soid
88 << " delete, ignoring source" << dendl
;
91 if (oinfo
.last_update
< need
) {
92 ldout(cct
, 10) << "search_for_missing " << soid
<< " " << need
93 << " also missing on osd." << fromosd
94 << " (last_update " << oinfo
.last_update
95 << " < needed " << need
<< ")" << dendl
;
98 if (p
->first
>= oinfo
.last_backfill
) {
99 // FIXME: this is _probably_ true, although it could conceivably
100 // be in the undefined region! Hmm!
101 ldout(cct
, 10) << "search_for_missing " << soid
<< " " << need
102 << " also missing on osd." << fromosd
103 << " (past last_backfill " << oinfo
.last_backfill
107 if (omissing
.is_missing(soid
)) {
108 ldout(cct
, 10) << "search_for_missing " << soid
<< " " << need
109 << " also missing on osd." << fromosd
<< dendl
;
113 ldout(cct
, 10) << "search_for_missing " << soid
<< " " << need
114 << " is on osd." << fromosd
<< dendl
;
117 auto p
= missing_loc
.find(soid
);
118 if (p
== missing_loc
.end()) {
119 p
= missing_loc
.emplace(soid
, set
<pg_shard_t
>()).first
;
121 _dec_count(p
->second
);
123 p
->second
.insert(fromosd
);
124 _inc_count(p
->second
);
127 if (!sources_updated
) {
128 missing_loc_sources
.insert(fromosd
);
129 sources_updated
= true;
131 found_missing
= true;
134 ldout(cct
, 20) << "needs_recovery_map missing " << needs_recovery_map
136 return found_missing
;
139 void MissingLoc::check_recovery_sources(const OSDMapRef
& osdmap
)
141 set
<pg_shard_t
> now_down
;
142 for (set
<pg_shard_t
>::iterator p
= missing_loc_sources
.begin();
143 p
!= missing_loc_sources
.end();
145 if (osdmap
->is_up(p
->osd
)) {
149 ldout(cct
, 10) << __func__
<< " source osd." << *p
<< " now down" << dendl
;
151 missing_loc_sources
.erase(p
++);
154 if (now_down
.empty()) {
155 ldout(cct
, 10) << __func__
<< " no source osds (" << missing_loc_sources
<< ") went down" << dendl
;
157 ldout(cct
, 10) << __func__
<< " sources osds " << now_down
<< " now down, remaining sources are "
158 << missing_loc_sources
<< dendl
;
160 // filter missing_loc
161 map
<hobject_t
, set
<pg_shard_t
>>::iterator p
= missing_loc
.begin();
162 while (p
!= missing_loc
.end()) {
163 set
<pg_shard_t
>::iterator q
= p
->second
.begin();
164 bool changed
= false;
165 while (q
!= p
->second
.end()) {
166 if (now_down
.count(*q
)) {
169 _dec_count(p
->second
);
171 p
->second
.erase(q
++);
176 if (p
->second
.empty()) {
177 missing_loc
.erase(p
++);
180 _inc_count(p
->second
);
188 void MissingLoc::remove_stray_recovery_sources(pg_shard_t stray
)
190 ldout(cct
, 10) << __func__
<< " remove osd " << stray
<< " from missing_loc" << dendl
;
191 // filter missing_loc
192 map
<hobject_t
, set
<pg_shard_t
>>::iterator p
= missing_loc
.begin();
193 while (p
!= missing_loc
.end()) {
194 set
<pg_shard_t
>::iterator q
= p
->second
.begin();
195 bool changed
= false;
196 while (q
!= p
->second
.end()) {
200 _dec_count(p
->second
);
202 p
->second
.erase(q
++);
207 if (p
->second
.empty()) {
208 missing_loc
.erase(p
++);
211 _inc_count(p
->second
);
216 // filter missing_loc_sources
217 for (set
<pg_shard_t
>::iterator p
= missing_loc_sources
.begin();
218 p
!= missing_loc_sources
.end();
224 ldout(cct
, 10) << __func__
<< " remove osd" << stray
<< " from missing_loc_sources" << dendl
;
225 missing_loc_sources
.erase(p
++);