]>
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 "Mutation.h" | |
16 | #include "ScatterLock.h" | |
17 | #include "CDir.h" | |
18 | ||
7c673cae FG |
19 | // MutationImpl |
20 | ||
21 | void MutationImpl::pin(MDSCacheObject *o) | |
22 | { | |
23 | if (pins.count(o) == 0) { | |
24 | o->get(MDSCacheObject::PIN_REQUEST); | |
25 | pins.insert(o); | |
26 | } | |
27 | } | |
28 | ||
29 | void MutationImpl::unpin(MDSCacheObject *o) | |
30 | { | |
11fdf7f2 | 31 | ceph_assert(pins.count(o)); |
7c673cae FG |
32 | o->put(MDSCacheObject::PIN_REQUEST); |
33 | pins.erase(o); | |
34 | } | |
35 | ||
36 | void MutationImpl::set_stickydirs(CInode *in) | |
37 | { | |
11fdf7f2 | 38 | if (!stickydiri || stickydiri != in) { |
7c673cae | 39 | in->get_stickydirs(); |
11fdf7f2 TL |
40 | if (stickydiri) |
41 | stickydiri->put_stickydirs(); | |
42 | stickydiri = in; | |
43 | } | |
44 | } | |
45 | ||
46 | void MutationImpl::put_stickydirs() | |
47 | { | |
48 | if (stickydiri) { | |
49 | stickydiri->put_stickydirs(); | |
50 | stickydiri = nullptr; | |
51 | ||
7c673cae FG |
52 | } |
53 | } | |
54 | ||
55 | void MutationImpl::drop_pins() | |
56 | { | |
11fdf7f2 TL |
57 | for (auto& o : pins) |
58 | o->put(MDSCacheObject::PIN_REQUEST); | |
7c673cae FG |
59 | pins.clear(); |
60 | } | |
61 | ||
62 | void MutationImpl::start_locking(SimpleLock *lock, int target) | |
63 | { | |
11fdf7f2 | 64 | ceph_assert(locking == NULL); |
7c673cae FG |
65 | pin(lock->get_parent()); |
66 | locking = lock; | |
67 | locking_target_mds = target; | |
68 | } | |
69 | ||
70 | void MutationImpl::finish_locking(SimpleLock *lock) | |
71 | { | |
11fdf7f2 | 72 | ceph_assert(locking == lock); |
7c673cae FG |
73 | locking = NULL; |
74 | locking_target_mds = -1; | |
75 | } | |
76 | ||
11fdf7f2 TL |
77 | void MutationImpl::LockOpVec::erase_rdlock(SimpleLock* lock) |
78 | { | |
79 | for (int i = size() - 1; i >= 0; --i) { | |
80 | auto& op = (*this)[i]; | |
81 | if (op.lock == lock && op.is_rdlock()) { | |
82 | erase(begin() + i); | |
83 | return; | |
84 | } | |
85 | } | |
86 | } | |
87 | ||
88 | void MutationImpl::LockOpVec::sort_and_merge() | |
89 | { | |
90 | std::sort(begin(), end(), SimpleLock::ptr_lt()); | |
91 | // merge ops on the same lock | |
92 | for (auto i = end() - 1; i > begin(); ) { | |
93 | auto j = i; | |
94 | while (--j >= begin()) { | |
95 | if (i->lock != j->lock) | |
96 | break; | |
97 | } | |
98 | if (i - j == 1) { | |
99 | i = j; | |
100 | continue; | |
101 | } | |
102 | ||
103 | // merge | |
104 | ++j; | |
105 | for (auto k = i; k > j; --k) { | |
106 | if (k->is_remote_wrlock()) { | |
107 | ceph_assert(!j->is_remote_wrlock()); | |
108 | j->wrlock_target = k->wrlock_target; | |
109 | } | |
110 | j->flags |= k->flags; | |
111 | } | |
112 | if (j->is_xlock()) { | |
113 | // xlock overwrites other types | |
114 | ceph_assert(!j->is_remote_wrlock()); | |
115 | j->flags = MutationImpl::LockOp::XLOCK; | |
116 | } | |
117 | erase(j + 1, i + 1); | |
118 | i = j - 1; | |
119 | } | |
120 | } | |
7c673cae FG |
121 | |
122 | // auth pins | |
123 | bool MutationImpl::is_auth_pinned(MDSCacheObject *object) const | |
124 | { | |
125 | return auth_pins.count(object) || remote_auth_pins.count(object); | |
126 | } | |
127 | ||
128 | void MutationImpl::auth_pin(MDSCacheObject *object) | |
129 | { | |
130 | if (!is_auth_pinned(object)) { | |
131 | object->auth_pin(this); | |
132 | auth_pins.insert(object); | |
133 | } | |
134 | } | |
135 | ||
136 | void MutationImpl::auth_unpin(MDSCacheObject *object) | |
137 | { | |
11fdf7f2 | 138 | ceph_assert(auth_pins.count(object)); |
7c673cae FG |
139 | object->auth_unpin(this); |
140 | auth_pins.erase(object); | |
141 | } | |
142 | ||
143 | void MutationImpl::drop_local_auth_pins() | |
144 | { | |
11fdf7f2 TL |
145 | for (const auto& p : auth_pins) { |
146 | ceph_assert(p->is_auth()); | |
147 | p->auth_unpin(this); | |
7c673cae FG |
148 | } |
149 | auth_pins.clear(); | |
150 | } | |
151 | ||
152 | void MutationImpl::add_projected_inode(CInode *in) | |
153 | { | |
154 | projected_inodes.push_back(in); | |
155 | } | |
156 | ||
157 | void MutationImpl::pop_and_dirty_projected_inodes() | |
158 | { | |
159 | while (!projected_inodes.empty()) { | |
160 | CInode *in = projected_inodes.front(); | |
161 | projected_inodes.pop_front(); | |
162 | in->pop_and_dirty_projected_inode(ls); | |
163 | } | |
164 | } | |
165 | ||
166 | void MutationImpl::add_projected_fnode(CDir *dir) | |
167 | { | |
168 | projected_fnodes.push_back(dir); | |
169 | } | |
170 | ||
171 | void MutationImpl::pop_and_dirty_projected_fnodes() | |
172 | { | |
173 | while (!projected_fnodes.empty()) { | |
174 | CDir *dir = projected_fnodes.front(); | |
175 | projected_fnodes.pop_front(); | |
176 | dir->pop_and_dirty_projected_fnode(ls); | |
177 | } | |
178 | } | |
179 | ||
180 | void MutationImpl::add_updated_lock(ScatterLock *lock) | |
181 | { | |
182 | updated_locks.push_back(lock); | |
183 | } | |
184 | ||
185 | void MutationImpl::add_cow_inode(CInode *in) | |
186 | { | |
187 | pin(in); | |
188 | dirty_cow_inodes.push_back(in); | |
189 | } | |
190 | ||
191 | void MutationImpl::add_cow_dentry(CDentry *dn) | |
192 | { | |
193 | pin(dn); | |
194 | dirty_cow_dentries.push_back(pair<CDentry*,version_t>(dn, dn->get_projected_version())); | |
195 | } | |
196 | ||
197 | void MutationImpl::apply() | |
198 | { | |
199 | pop_and_dirty_projected_inodes(); | |
200 | pop_and_dirty_projected_fnodes(); | |
201 | ||
202 | for (list<CInode*>::iterator p = dirty_cow_inodes.begin(); | |
203 | p != dirty_cow_inodes.end(); | |
204 | ++p) | |
205 | (*p)->_mark_dirty(ls); | |
206 | for (list<pair<CDentry*,version_t> >::iterator p = dirty_cow_dentries.begin(); | |
207 | p != dirty_cow_dentries.end(); | |
208 | ++p) | |
209 | p->first->mark_dirty(p->second, ls); | |
210 | ||
211 | for (list<ScatterLock*>::iterator p = updated_locks.begin(); | |
212 | p != updated_locks.end(); | |
213 | ++p) | |
214 | (*p)->mark_dirty(); | |
215 | } | |
216 | ||
217 | void MutationImpl::cleanup() | |
218 | { | |
219 | drop_local_auth_pins(); | |
220 | drop_pins(); | |
221 | } | |
222 | ||
223 | void MutationImpl::_dump_op_descriptor_unlocked(ostream& stream) const | |
224 | { | |
225 | stream << "Mutation"; | |
226 | } | |
227 | ||
228 | // MDRequestImpl | |
229 | ||
230 | MDRequestImpl::~MDRequestImpl() | |
231 | { | |
7c673cae FG |
232 | delete _more; |
233 | } | |
234 | ||
235 | MDRequestImpl::More* MDRequestImpl::more() | |
236 | { | |
237 | if (!_more) | |
238 | _more = new More(); | |
239 | return _more; | |
240 | } | |
241 | ||
242 | bool MDRequestImpl::has_more() const | |
243 | { | |
244 | return _more != nullptr; | |
245 | } | |
246 | ||
247 | bool MDRequestImpl::has_witnesses() | |
248 | { | |
249 | return (_more != nullptr) && (!_more->witnessed.empty()); | |
250 | } | |
251 | ||
252 | bool MDRequestImpl::slave_did_prepare() | |
253 | { | |
254 | return has_more() && more()->slave_commit; | |
255 | } | |
256 | ||
257 | bool MDRequestImpl::slave_rolling_back() | |
258 | { | |
259 | return has_more() && more()->slave_rolling_back; | |
260 | } | |
261 | ||
262 | bool MDRequestImpl::did_ino_allocation() const | |
263 | { | |
264 | return alloc_ino || used_prealloc_ino || prealloc_inos.size(); | |
265 | } | |
266 | ||
267 | bool MDRequestImpl::freeze_auth_pin(CInode *inode) | |
268 | { | |
11fdf7f2 | 269 | ceph_assert(!more()->rename_inode || more()->rename_inode == inode); |
7c673cae FG |
270 | more()->rename_inode = inode; |
271 | more()->is_freeze_authpin = true; | |
272 | auth_pin(inode); | |
273 | if (!inode->freeze_inode(1)) { | |
274 | return false; | |
275 | } | |
276 | inode->freeze_auth_pin(); | |
277 | inode->unfreeze_inode(); | |
278 | return true; | |
279 | } | |
280 | ||
281 | void MDRequestImpl::unfreeze_auth_pin(bool clear_inode) | |
282 | { | |
11fdf7f2 | 283 | ceph_assert(more()->is_freeze_authpin); |
7c673cae FG |
284 | CInode *inode = more()->rename_inode; |
285 | if (inode->is_frozen_auth_pin()) | |
286 | inode->unfreeze_auth_pin(); | |
287 | else | |
288 | inode->unfreeze_inode(); | |
289 | more()->is_freeze_authpin = false; | |
290 | if (clear_inode) | |
291 | more()->rename_inode = NULL; | |
292 | } | |
293 | ||
294 | void MDRequestImpl::set_remote_frozen_auth_pin(CInode *inode) | |
295 | { | |
296 | more()->rename_inode = inode; | |
297 | more()->is_remote_frozen_authpin = true; | |
298 | } | |
299 | ||
300 | void MDRequestImpl::set_ambiguous_auth(CInode *inode) | |
301 | { | |
11fdf7f2 TL |
302 | ceph_assert(!more()->rename_inode || more()->rename_inode == inode); |
303 | ceph_assert(!more()->is_ambiguous_auth); | |
7c673cae FG |
304 | |
305 | inode->set_ambiguous_auth(); | |
306 | more()->rename_inode = inode; | |
307 | more()->is_ambiguous_auth = true; | |
308 | } | |
309 | ||
310 | void MDRequestImpl::clear_ambiguous_auth() | |
311 | { | |
312 | CInode *inode = more()->rename_inode; | |
11fdf7f2 | 313 | ceph_assert(inode && more()->is_ambiguous_auth); |
7c673cae FG |
314 | inode->clear_ambiguous_auth(); |
315 | more()->is_ambiguous_auth = false; | |
316 | } | |
317 | ||
318 | bool MDRequestImpl::can_auth_pin(MDSCacheObject *object) | |
319 | { | |
320 | return object->can_auth_pin() || | |
321 | (is_auth_pinned(object) && has_more() && | |
322 | more()->is_freeze_authpin && | |
323 | more()->rename_inode == object); | |
324 | } | |
325 | ||
326 | void MDRequestImpl::drop_local_auth_pins() | |
327 | { | |
328 | if (has_more() && more()->is_freeze_authpin) | |
329 | unfreeze_auth_pin(true); | |
330 | MutationImpl::drop_local_auth_pins(); | |
331 | } | |
332 | ||
333 | const filepath& MDRequestImpl::get_filepath() | |
334 | { | |
335 | if (client_request) | |
336 | return client_request->get_filepath(); | |
337 | return more()->filepath1; | |
338 | } | |
339 | ||
340 | const filepath& MDRequestImpl::get_filepath2() | |
341 | { | |
342 | if (client_request) | |
343 | return client_request->get_filepath2(); | |
344 | return more()->filepath2; | |
345 | } | |
346 | ||
347 | void MDRequestImpl::set_filepath(const filepath& fp) | |
348 | { | |
11fdf7f2 | 349 | ceph_assert(!client_request); |
7c673cae FG |
350 | more()->filepath1 = fp; |
351 | } | |
352 | ||
353 | void MDRequestImpl::set_filepath2(const filepath& fp) | |
354 | { | |
11fdf7f2 | 355 | ceph_assert(!client_request); |
7c673cae FG |
356 | more()->filepath2 = fp; |
357 | } | |
358 | ||
b32b8144 | 359 | bool MDRequestImpl::is_queued_for_replay() const |
7c673cae | 360 | { |
b32b8144 | 361 | return client_request ? client_request->is_queued_for_replay() : false; |
7c673cae FG |
362 | } |
363 | ||
11fdf7f2 | 364 | MClientRequest::const_ref MDRequestImpl::release_client_request() |
91327a77 AA |
365 | { |
366 | msg_lock.lock(); | |
11fdf7f2 TL |
367 | MClientRequest::const_ref req; |
368 | req.swap(client_request); | |
91327a77 AA |
369 | msg_lock.unlock(); |
370 | return req; | |
371 | } | |
372 | ||
11fdf7f2 | 373 | void MDRequestImpl::reset_slave_request(const MMDSSlaveRequest::const_ref& req) |
91327a77 AA |
374 | { |
375 | msg_lock.lock(); | |
11fdf7f2 TL |
376 | MMDSSlaveRequest::const_ref old; |
377 | old.swap(slave_request); | |
91327a77 AA |
378 | slave_request = req; |
379 | msg_lock.unlock(); | |
11fdf7f2 | 380 | old.reset(); |
91327a77 AA |
381 | } |
382 | ||
7c673cae FG |
383 | void MDRequestImpl::print(ostream &out) const |
384 | { | |
385 | out << "request(" << reqid; | |
386 | //if (request) out << " " << *request; | |
387 | if (is_slave()) out << " slave_to mds." << slave_to_mds; | |
388 | if (client_request) out << " cr=" << client_request; | |
389 | if (slave_request) out << " sr=" << slave_request; | |
390 | out << ")"; | |
391 | } | |
392 | ||
393 | void MDRequestImpl::dump(Formatter *f) const | |
394 | { | |
395 | _dump(f); | |
396 | } | |
397 | ||
398 | void MDRequestImpl::_dump(Formatter *f) const | |
399 | { | |
400 | f->dump_string("flag_point", state_string()); | |
401 | f->dump_stream("reqid") << reqid; | |
402 | { | |
91327a77 | 403 | msg_lock.lock(); |
11fdf7f2 TL |
404 | auto _client_request = client_request; |
405 | auto _slave_request =slave_request; | |
91327a77 AA |
406 | msg_lock.unlock(); |
407 | ||
408 | if (_client_request) { | |
7c673cae FG |
409 | f->dump_string("op_type", "client_request"); |
410 | f->open_object_section("client_info"); | |
91327a77 AA |
411 | f->dump_stream("client") << _client_request->get_orig_source(); |
412 | f->dump_int("tid", _client_request->get_tid()); | |
7c673cae | 413 | f->close_section(); // client_info |
91327a77 | 414 | } else if (is_slave() && _slave_request) { // replies go to an existing mdr |
7c673cae FG |
415 | f->dump_string("op_type", "slave_request"); |
416 | f->open_object_section("master_info"); | |
91327a77 | 417 | f->dump_stream("master") << _slave_request->get_orig_source(); |
7c673cae FG |
418 | f->close_section(); // master_info |
419 | ||
420 | f->open_object_section("request_info"); | |
91327a77 | 421 | f->dump_int("attempt", _slave_request->get_attempt()); |
7c673cae | 422 | f->dump_string("op_type", |
91327a77 AA |
423 | MMDSSlaveRequest::get_opname(_slave_request->get_op())); |
424 | f->dump_int("lock_type", _slave_request->get_lock_type()); | |
425 | f->dump_stream("object_info") << _slave_request->get_object_info(); | |
426 | f->dump_stream("srcdnpath") << _slave_request->srcdnpath; | |
427 | f->dump_stream("destdnpath") << _slave_request->destdnpath; | |
428 | f->dump_stream("witnesses") << _slave_request->witnesses; | |
7c673cae | 429 | f->dump_bool("has_inode_export", |
91327a77 AA |
430 | _slave_request->inode_export_v != 0); |
431 | f->dump_int("inode_export_v", _slave_request->inode_export_v); | |
432 | f->dump_stream("op_stamp") << _slave_request->op_stamp; | |
7c673cae FG |
433 | f->close_section(); // request_info |
434 | } | |
435 | else if (internal_op != -1) { // internal request | |
436 | f->dump_string("op_type", "internal_op"); | |
437 | f->dump_int("internal_op", internal_op); | |
438 | f->dump_string("op_name", ceph_mds_op_name(internal_op)); | |
439 | } | |
440 | else { | |
441 | f->dump_string("op_type", "no_available_op_found"); | |
442 | } | |
443 | } | |
444 | { | |
445 | f->open_array_section("events"); | |
11fdf7f2 | 446 | std::lock_guard l(lock); |
7c673cae FG |
447 | for (auto& i : events) { |
448 | f->dump_object("event", i); | |
449 | } | |
450 | f->close_section(); // events | |
451 | } | |
452 | } | |
453 | ||
454 | void MDRequestImpl::_dump_op_descriptor_unlocked(ostream& stream) const | |
455 | { | |
91327a77 | 456 | msg_lock.lock(); |
11fdf7f2 TL |
457 | auto _client_request = client_request; |
458 | auto _slave_request = slave_request; | |
91327a77 AA |
459 | msg_lock.unlock(); |
460 | ||
461 | if (_client_request) { | |
462 | _client_request->print(stream); | |
463 | } else if (_slave_request) { | |
464 | _slave_request->print(stream); | |
7c673cae FG |
465 | } else if (internal_op >= 0) { |
466 | stream << "internal op " << ceph_mds_op_name(internal_op) << ":" << reqid; | |
467 | } else { | |
468 | // drat, it's triggered by a slave request, but we don't have a message | |
469 | // FIXME | |
470 | stream << "rejoin:" << reqid; | |
471 | } | |
472 | } |