]>
Commit | Line | Data |
---|---|---|
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) 2004-2006 Sage Weil <sage@newdream.net> | |
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 "InoTable.h" | |
16 | #include "MDSRank.h" | |
17 | ||
18 | #include "include/types.h" | |
19 | ||
20 | #include "common/config.h" | |
21 | ||
22 | #define dout_context g_ceph_context | |
23 | #define dout_subsys ceph_subsys_mds | |
24 | #undef dout_prefix | |
25 | #define dout_prefix *_dout << "mds." << rank << "." << table_name << ": " | |
26 | ||
27 | void InoTable::reset_state() | |
28 | { | |
29 | // use generic range. FIXME THIS IS CRAP | |
30 | free.clear(); | |
31 | //#ifdef __LP64__ | |
32 | uint64_t start = (uint64_t)(rank+1) << 40; | |
33 | uint64_t len = (uint64_t)1 << 40; | |
34 | //#else | |
35 | //# warning this looks like a 32-bit system, using small inode numbers. | |
36 | // uint64_t start = (uint64_t)(mds->get_nodeid()+1) << 25; | |
37 | // uint64_t end = ((uint64_t)(mds->get_nodeid()+2) << 25) - 1; | |
38 | //#endif | |
39 | free.insert(start, len); | |
40 | ||
41 | projected_free = free; | |
42 | } | |
43 | ||
44 | inodeno_t InoTable::project_alloc_id(inodeno_t id) | |
45 | { | |
46 | dout(10) << "project_alloc_id " << id << " to " << projected_free << "/" << free << dendl; | |
47 | assert(is_active()); | |
48 | if (!id) | |
49 | id = projected_free.range_start(); | |
50 | projected_free.erase(id); | |
51 | ++projected_version; | |
52 | return id; | |
53 | } | |
54 | void InoTable::apply_alloc_id(inodeno_t id) | |
55 | { | |
56 | dout(10) << "apply_alloc_id " << id << " to " << projected_free << "/" << free << dendl; | |
57 | free.erase(id); | |
58 | ++version; | |
59 | } | |
60 | ||
61 | void InoTable::project_alloc_ids(interval_set<inodeno_t>& ids, int want) | |
62 | { | |
63 | assert(is_active()); | |
64 | while (want > 0) { | |
65 | inodeno_t start = projected_free.range_start(); | |
66 | inodeno_t end = projected_free.end_after(start); | |
67 | inodeno_t num = end - start; | |
68 | if (num > (inodeno_t)want) | |
69 | num = want; | |
70 | projected_free.erase(start, num); | |
71 | ids.insert(start, num); | |
72 | want -= num; | |
73 | } | |
74 | dout(10) << "project_alloc_ids " << ids << " to " << projected_free << "/" << free << dendl; | |
75 | ++projected_version; | |
76 | } | |
77 | void InoTable::apply_alloc_ids(interval_set<inodeno_t>& ids) | |
78 | { | |
79 | dout(10) << "apply_alloc_ids " << ids << " to " << projected_free << "/" << free << dendl; | |
80 | free.subtract(ids); | |
81 | ++version; | |
82 | } | |
83 | ||
84 | ||
85 | void InoTable::project_release_ids(interval_set<inodeno_t>& ids) | |
86 | { | |
87 | dout(10) << "project_release_ids " << ids << " to " << projected_free << "/" << free << dendl; | |
88 | projected_free.insert(ids); | |
89 | ++projected_version; | |
90 | } | |
91 | void InoTable::apply_release_ids(interval_set<inodeno_t>& ids) | |
92 | { | |
93 | dout(10) << "apply_release_ids " << ids << " to " << projected_free << "/" << free << dendl; | |
94 | free.insert(ids); | |
95 | ++version; | |
96 | } | |
97 | ||
98 | ||
99 | // | |
100 | ||
101 | void InoTable::replay_alloc_id(inodeno_t id) | |
102 | { | |
103 | assert(mds); // Only usable in online mode | |
104 | ||
105 | dout(10) << "replay_alloc_id " << id << dendl; | |
106 | if (free.contains(id)) { | |
107 | free.erase(id); | |
108 | projected_free.erase(id); | |
109 | } else { | |
110 | mds->clog->error() << "journal replay alloc " << id | |
111 | << " not in free " << free; | |
112 | } | |
113 | projected_version = ++version; | |
114 | } | |
115 | void InoTable::replay_alloc_ids(interval_set<inodeno_t>& ids) | |
116 | { | |
117 | assert(mds); // Only usable in online mode | |
118 | ||
119 | dout(10) << "replay_alloc_ids " << ids << dendl; | |
120 | interval_set<inodeno_t> is; | |
121 | is.intersection_of(free, ids); | |
122 | if (is == ids) { | |
123 | free.subtract(ids); | |
124 | projected_free.subtract(ids); | |
125 | } else { | |
126 | mds->clog->error() << "journal replay alloc " << ids << ", only " | |
127 | << is << " is in free " << free; | |
128 | free.subtract(is); | |
129 | projected_free.subtract(is); | |
130 | } | |
131 | projected_version = ++version; | |
132 | } | |
133 | void InoTable::replay_release_ids(interval_set<inodeno_t>& ids) | |
134 | { | |
135 | dout(10) << "replay_release_ids " << ids << dendl; | |
136 | free.insert(ids); | |
137 | projected_free.insert(ids); | |
138 | projected_version = ++version; | |
139 | } | |
140 | ||
141 | ||
142 | void InoTable::replay_reset() | |
143 | { | |
144 | dout(10) << "replay_reset " << free << dendl; | |
145 | skip_inos(inodeno_t(10000000)); // a lot! | |
146 | projected_free = free; | |
147 | projected_version = ++version; | |
148 | } | |
149 | ||
150 | ||
151 | void InoTable::skip_inos(inodeno_t i) | |
152 | { | |
153 | dout(10) << "skip_inos was " << free << dendl; | |
154 | inodeno_t first = free.range_start(); | |
155 | interval_set<inodeno_t> s; | |
156 | s.insert(first, i); | |
157 | s.intersection_of(free); | |
158 | free.subtract(s); | |
159 | projected_free = free; | |
160 | projected_version = ++version; | |
161 | dout(10) << "skip_inos now " << free << dendl; | |
162 | } | |
163 | ||
164 | void InoTable::dump(Formatter *f) const | |
165 | { | |
166 | f->open_object_section("inotable"); | |
167 | ||
168 | f->open_array_section("projected_free"); | |
169 | for (interval_set<inodeno_t>::const_iterator i = projected_free.begin(); i != projected_free.end(); ++i) { | |
170 | f->open_object_section("range"); | |
171 | f->dump_int("start", (*i).first); | |
172 | f->dump_int("len", (*i).second); | |
173 | f->close_section(); | |
174 | } | |
175 | f->close_section(); | |
176 | ||
177 | f->open_array_section("free"); | |
178 | for (interval_set<inodeno_t>::const_iterator i = free.begin(); i != free.end(); ++i) { | |
179 | f->open_object_section("range"); | |
180 | f->dump_int("start", (*i).first); | |
181 | f->dump_int("len", (*i).second); | |
182 | f->close_section(); | |
183 | } | |
184 | f->close_section(); | |
185 | ||
186 | f->close_section(); | |
187 | } | |
188 | ||
189 | ||
190 | void InoTable::generate_test_instances(list<InoTable*>& ls) | |
191 | { | |
192 | ls.push_back(new InoTable()); | |
193 | } | |
194 | ||
195 | ||
196 | bool InoTable::is_marked_free(inodeno_t id) const | |
197 | { | |
198 | return free.contains(id) || projected_free.contains(id); | |
199 | } | |
200 | ||
201 | bool InoTable::intersects_free( | |
202 | const interval_set<inodeno_t> &other, | |
203 | interval_set<inodeno_t> *intersection) | |
204 | { | |
205 | interval_set<inodeno_t> i; | |
206 | i.intersection_of(free, other); | |
207 | if (intersection != nullptr) { | |
208 | *intersection = i; | |
209 | } | |
210 | return !(i.empty()); | |
211 | } | |
212 | ||
213 | bool InoTable::repair(inodeno_t id) | |
214 | { | |
215 | if (projected_version != version) { | |
216 | // Can't do the repair while other things are in flight | |
217 | return false; | |
218 | } | |
219 | ||
220 | assert(is_marked_free(id)); | |
221 | dout(10) << "repair: before status. ino = 0x" << std::hex << id << " pver =" << projected_version << " ver= " << version << dendl; | |
222 | free.erase(id); | |
223 | projected_free.erase(id); | |
224 | projected_version = ++version; | |
225 | dout(10) << "repair: after status. ino = 0x" << std::hex <<id << " pver =" << projected_version << " ver= " << version << dendl; | |
226 | return true; | |
227 | } |