]> git.proxmox.com Git - ceph.git/blob - ceph/src/mds/Mutation.cc
import 15.2.2 octopus source
[ceph.git] / ceph / src / mds / Mutation.cc
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
19 // MutationImpl
20
21 void MutationImpl::pin(MDSCacheObject *o)
22 {
23 auto& stat = object_states[o];
24 if (!stat.pinned) {
25 o->get(MDSCacheObject::PIN_REQUEST);
26 stat.pinned = true;
27 ++num_pins;
28 }
29 }
30
31 void MutationImpl::unpin(MDSCacheObject *o)
32 {
33 auto& stat = object_states[o];
34 ceph_assert(stat.pinned);
35 o->put(MDSCacheObject::PIN_REQUEST);
36 stat.pinned = false;
37 --num_pins;
38 }
39
40 void MutationImpl::set_stickydirs(CInode *in)
41 {
42 if (!stickydiri || stickydiri != in) {
43 in->get_stickydirs();
44 if (stickydiri)
45 stickydiri->put_stickydirs();
46 stickydiri = in;
47 }
48 }
49
50 void MutationImpl::put_stickydirs()
51 {
52 if (stickydiri) {
53 stickydiri->put_stickydirs();
54 stickydiri = nullptr;
55
56 }
57 }
58
59 void MutationImpl::drop_pins()
60 {
61 for (auto& p : object_states) {
62 if (p.second.pinned) {
63 p.first->put(MDSCacheObject::PIN_REQUEST);
64 p.second.pinned = false;
65 --num_pins;
66 }
67 }
68 }
69
70 void MutationImpl::start_locking(SimpleLock *lock, int target)
71 {
72 ceph_assert(locking == NULL);
73 pin(lock->get_parent());
74 locking = lock;
75 locking_target_mds = target;
76 }
77
78 void MutationImpl::finish_locking(SimpleLock *lock)
79 {
80 ceph_assert(locking == lock);
81 locking = NULL;
82 locking_target_mds = -1;
83 }
84
85 bool MutationImpl::is_rdlocked(SimpleLock *lock) const {
86 auto it = locks.find(lock);
87 if (it != locks.end() && it->is_rdlock())
88 return true;
89 if (lock_cache)
90 return static_cast<const MutationImpl*>(lock_cache)->is_rdlocked(lock);
91 return false;
92 }
93
94 bool MutationImpl::is_wrlocked(SimpleLock *lock) const {
95 auto it = locks.find(lock);
96 if (it != locks.end() && it->is_wrlock())
97 return true;
98 if (lock_cache)
99 return static_cast<const MutationImpl*>(lock_cache)->is_wrlocked(lock);
100 return false;
101 }
102
103 void MutationImpl::LockOpVec::erase_rdlock(SimpleLock* lock)
104 {
105 for (int i = size() - 1; i >= 0; --i) {
106 auto& op = (*this)[i];
107 if (op.lock == lock && op.is_rdlock()) {
108 erase(begin() + i);
109 return;
110 }
111 }
112 }
113 void MutationImpl::LockOpVec::sort_and_merge()
114 {
115 // sort locks on the same object
116 auto cmp = [](const LockOp &l, const LockOp &r) {
117 ceph_assert(l.lock->get_parent() == r.lock->get_parent());
118 return l.lock->type->type < r.lock->type->type;
119 };
120 for (auto i = begin(), j = i; ; ++i) {
121 if (i == end()) {
122 std::sort(j, i, cmp);
123 break;
124 }
125 if (j->lock->get_parent() != i->lock->get_parent()) {
126 std::sort(j, i, cmp);
127 j = i;
128 }
129 }
130 // merge ops on the same lock
131 for (auto i = end() - 1; i > begin(); ) {
132 auto j = i;
133 while (--j >= begin()) {
134 if (i->lock != j->lock)
135 break;
136 }
137 if (i - j == 1) {
138 i = j;
139 continue;
140 }
141 // merge
142 ++j;
143 for (auto k = i; k > j; --k) {
144 if (k->is_remote_wrlock()) {
145 ceph_assert(!j->is_remote_wrlock());
146 j->wrlock_target = k->wrlock_target;
147 }
148 j->flags |= k->flags;
149 }
150 if (j->is_xlock()) {
151 // xlock overwrites other types
152 ceph_assert(!j->is_remote_wrlock());
153 j->flags = LockOp::XLOCK;
154 }
155 erase(j + 1, i + 1);
156 i = j - 1;
157 }
158 }
159
160 // auth pins
161 bool MutationImpl::is_auth_pinned(MDSCacheObject *object) const
162 {
163 auto stat_p = find_object_state(object);
164 if (!stat_p)
165 return false;
166 return stat_p->auth_pinned || stat_p->remote_auth_pinned != MDS_RANK_NONE;
167 }
168
169 void MutationImpl::auth_pin(MDSCacheObject *object)
170 {
171 auto &stat = object_states[object];
172 if (!stat.auth_pinned) {
173 object->auth_pin(this);
174 stat.auth_pinned = true;
175 ++num_auth_pins;
176 }
177 }
178
179 void MutationImpl::auth_unpin(MDSCacheObject *object)
180 {
181 auto &stat = object_states[object];
182 ceph_assert(stat.auth_pinned);
183 object->auth_unpin(this);
184 stat.auth_pinned = false;
185 --num_auth_pins;
186 }
187
188 void MutationImpl::drop_local_auth_pins()
189 {
190 for (auto& p : object_states) {
191 if (p.second.auth_pinned) {
192 ceph_assert(p.first->is_auth());
193 p.first->auth_unpin(this);
194 p.second.auth_pinned = false;
195 --num_auth_pins;
196 }
197 }
198 }
199
200 void MutationImpl::set_remote_auth_pinned(MDSCacheObject *object, mds_rank_t from)
201 {
202 auto &stat = object_states[object];
203 if (stat.remote_auth_pinned == MDS_RANK_NONE) {
204 stat.remote_auth_pinned = from;
205 ++num_remote_auth_pins;
206 } else {
207 ceph_assert(stat.remote_auth_pinned == from);
208 }
209 }
210
211 void MutationImpl::_clear_remote_auth_pinned(ObjectState &stat)
212 {
213 ceph_assert(stat.remote_auth_pinned != MDS_RANK_NONE);
214 stat.remote_auth_pinned = MDS_RANK_NONE;
215 --num_remote_auth_pins;
216 }
217
218 void MutationImpl::add_projected_inode(CInode *in)
219 {
220 projected_inodes.push_back(in);
221 }
222
223 void MutationImpl::pop_and_dirty_projected_inodes()
224 {
225 while (!projected_inodes.empty()) {
226 CInode *in = projected_inodes.front();
227 projected_inodes.pop_front();
228 in->pop_and_dirty_projected_inode(ls);
229 }
230 }
231
232 void MutationImpl::add_projected_fnode(CDir *dir)
233 {
234 projected_fnodes.push_back(dir);
235 }
236
237 void MutationImpl::pop_and_dirty_projected_fnodes()
238 {
239 for (const auto& dir : projected_fnodes) {
240 dir->pop_and_dirty_projected_fnode(ls);
241 }
242 projected_fnodes.clear();
243 }
244
245 void MutationImpl::add_updated_lock(ScatterLock *lock)
246 {
247 updated_locks.push_back(lock);
248 }
249
250 void MutationImpl::add_cow_inode(CInode *in)
251 {
252 pin(in);
253 dirty_cow_inodes.push_back(in);
254 }
255
256 void MutationImpl::add_cow_dentry(CDentry *dn)
257 {
258 pin(dn);
259 dirty_cow_dentries.push_back(pair<CDentry*,version_t>(dn, dn->get_projected_version()));
260 }
261
262 void MutationImpl::apply()
263 {
264 pop_and_dirty_projected_inodes();
265 pop_and_dirty_projected_fnodes();
266
267 for (const auto& in : dirty_cow_inodes) {
268 in->_mark_dirty(ls);
269 }
270 for (const auto& [dentry, v] : dirty_cow_dentries) {
271 dentry->mark_dirty(v, ls);
272 }
273
274 for (const auto& lock : updated_locks) {
275 lock->mark_dirty();
276 }
277 }
278
279 void MutationImpl::cleanup()
280 {
281 drop_local_auth_pins();
282 drop_pins();
283 }
284
285 void MutationImpl::_dump_op_descriptor_unlocked(ostream& stream) const
286 {
287 stream << "Mutation";
288 }
289
290 // MDRequestImpl
291
292 MDRequestImpl::~MDRequestImpl()
293 {
294 delete _more;
295 }
296
297 MDRequestImpl::More* MDRequestImpl::more()
298 {
299 if (!_more)
300 _more = new More();
301 return _more;
302 }
303
304 bool MDRequestImpl::has_more() const
305 {
306 return _more != nullptr;
307 }
308
309 bool MDRequestImpl::has_witnesses()
310 {
311 return (_more != nullptr) && (!_more->witnessed.empty());
312 }
313
314 bool MDRequestImpl::slave_did_prepare()
315 {
316 return has_more() && more()->slave_commit;
317 }
318
319 bool MDRequestImpl::slave_rolling_back()
320 {
321 return has_more() && more()->slave_rolling_back;
322 }
323
324 bool MDRequestImpl::freeze_auth_pin(CInode *inode)
325 {
326 ceph_assert(!more()->rename_inode || more()->rename_inode == inode);
327 more()->rename_inode = inode;
328 more()->is_freeze_authpin = true;
329 auth_pin(inode);
330 if (!inode->freeze_inode(1)) {
331 return false;
332 }
333 inode->freeze_auth_pin();
334 inode->unfreeze_inode();
335 return true;
336 }
337
338 void MDRequestImpl::unfreeze_auth_pin(bool clear_inode)
339 {
340 ceph_assert(more()->is_freeze_authpin);
341 CInode *inode = more()->rename_inode;
342 if (inode->is_frozen_auth_pin())
343 inode->unfreeze_auth_pin();
344 else
345 inode->unfreeze_inode();
346 more()->is_freeze_authpin = false;
347 if (clear_inode)
348 more()->rename_inode = NULL;
349 }
350
351 void MDRequestImpl::set_remote_frozen_auth_pin(CInode *inode)
352 {
353 more()->rename_inode = inode;
354 more()->is_remote_frozen_authpin = true;
355 }
356
357 void MDRequestImpl::set_ambiguous_auth(CInode *inode)
358 {
359 ceph_assert(!more()->rename_inode || more()->rename_inode == inode);
360 ceph_assert(!more()->is_ambiguous_auth);
361
362 inode->set_ambiguous_auth();
363 more()->rename_inode = inode;
364 more()->is_ambiguous_auth = true;
365 }
366
367 void MDRequestImpl::clear_ambiguous_auth()
368 {
369 CInode *inode = more()->rename_inode;
370 ceph_assert(inode && more()->is_ambiguous_auth);
371 inode->clear_ambiguous_auth();
372 more()->is_ambiguous_auth = false;
373 }
374
375 bool MDRequestImpl::can_auth_pin(MDSCacheObject *object)
376 {
377 return object->can_auth_pin() ||
378 (is_auth_pinned(object) && has_more() &&
379 more()->is_freeze_authpin &&
380 more()->rename_inode == object);
381 }
382
383 void MDRequestImpl::drop_local_auth_pins()
384 {
385 if (has_more() && more()->is_freeze_authpin)
386 unfreeze_auth_pin(true);
387 MutationImpl::drop_local_auth_pins();
388 }
389
390 const filepath& MDRequestImpl::get_filepath()
391 {
392 if (client_request)
393 return client_request->get_filepath();
394 return more()->filepath1;
395 }
396
397 const filepath& MDRequestImpl::get_filepath2()
398 {
399 if (client_request)
400 return client_request->get_filepath2();
401 return more()->filepath2;
402 }
403
404 void MDRequestImpl::set_filepath(const filepath& fp)
405 {
406 ceph_assert(!client_request);
407 more()->filepath1 = fp;
408 }
409
410 void MDRequestImpl::set_filepath2(const filepath& fp)
411 {
412 ceph_assert(!client_request);
413 more()->filepath2 = fp;
414 }
415
416 bool MDRequestImpl::is_queued_for_replay() const
417 {
418 return client_request ? client_request->is_queued_for_replay() : false;
419 }
420
421 bool MDRequestImpl::is_batch_op()
422 {
423 return (client_request->get_op() == CEPH_MDS_OP_LOOKUP &&
424 client_request->get_filepath().depth() == 1) ||
425 (client_request->get_op() == CEPH_MDS_OP_GETATTR &&
426 client_request->get_filepath().depth() == 0);
427 }
428
429 int MDRequestImpl::compare_paths()
430 {
431 if (dir_root[0] < dir_root[1])
432 return -1;
433 if (dir_root[0] > dir_root[1])
434 return 1;
435 if (dir_depth[0] < dir_depth[1])
436 return -1;
437 if (dir_depth[0] > dir_depth[1])
438 return 1;
439 return 0;
440 }
441
442 cref_t<MClientRequest> MDRequestImpl::release_client_request()
443 {
444 msg_lock.lock();
445 cref_t<MClientRequest> req;
446 req.swap(client_request);
447 msg_lock.unlock();
448 return req;
449 }
450
451 void MDRequestImpl::reset_slave_request(const cref_t<MMDSSlaveRequest>& req)
452 {
453 msg_lock.lock();
454 cref_t<MMDSSlaveRequest> old;
455 old.swap(slave_request);
456 slave_request = req;
457 msg_lock.unlock();
458 old.reset();
459 }
460
461 void MDRequestImpl::print(ostream &out) const
462 {
463 out << "request(" << reqid << " nref=" << nref;
464 //if (request) out << " " << *request;
465 if (is_slave()) out << " slave_to mds." << slave_to_mds;
466 if (client_request) out << " cr=" << client_request;
467 if (slave_request) out << " sr=" << slave_request;
468 out << ")";
469 }
470
471 void MDRequestImpl::dump(Formatter *f) const
472 {
473 _dump(f);
474 }
475
476 void MDRequestImpl::_dump(Formatter *f) const
477 {
478 f->dump_string("flag_point", state_string());
479 f->dump_stream("reqid") << reqid;
480 {
481 msg_lock.lock();
482 auto _client_request = client_request;
483 auto _slave_request =slave_request;
484 msg_lock.unlock();
485
486 if (_client_request) {
487 f->dump_string("op_type", "client_request");
488 f->open_object_section("client_info");
489 f->dump_stream("client") << _client_request->get_orig_source();
490 f->dump_int("tid", _client_request->get_tid());
491 f->close_section(); // client_info
492 } else if (is_slave() && _slave_request) { // replies go to an existing mdr
493 f->dump_string("op_type", "slave_request");
494 f->open_object_section("master_info");
495 f->dump_stream("master") << _slave_request->get_orig_source();
496 f->close_section(); // master_info
497
498 f->open_object_section("request_info");
499 f->dump_int("attempt", _slave_request->get_attempt());
500 f->dump_string("op_type",
501 MMDSSlaveRequest::get_opname(_slave_request->get_op()));
502 f->dump_int("lock_type", _slave_request->get_lock_type());
503 f->dump_stream("object_info") << _slave_request->get_object_info();
504 f->dump_stream("srcdnpath") << _slave_request->srcdnpath;
505 f->dump_stream("destdnpath") << _slave_request->destdnpath;
506 f->dump_stream("witnesses") << _slave_request->witnesses;
507 f->dump_bool("has_inode_export",
508 _slave_request->inode_export_v != 0);
509 f->dump_int("inode_export_v", _slave_request->inode_export_v);
510 f->dump_stream("op_stamp") << _slave_request->op_stamp;
511 f->close_section(); // request_info
512 }
513 else if (internal_op != -1) { // internal request
514 f->dump_string("op_type", "internal_op");
515 f->dump_int("internal_op", internal_op);
516 f->dump_string("op_name", ceph_mds_op_name(internal_op));
517 }
518 else {
519 f->dump_string("op_type", "no_available_op_found");
520 }
521 }
522 {
523 f->open_array_section("events");
524 std::lock_guard l(lock);
525 for (auto& i : events) {
526 f->dump_object("event", i);
527 }
528 f->close_section(); // events
529 }
530 }
531
532 void MDRequestImpl::_dump_op_descriptor_unlocked(ostream& stream) const
533 {
534 msg_lock.lock();
535 auto _client_request = client_request;
536 auto _slave_request = slave_request;
537 msg_lock.unlock();
538
539 if (_client_request) {
540 _client_request->print(stream);
541 } else if (_slave_request) {
542 _slave_request->print(stream);
543 } else if (internal_op >= 0) {
544 stream << "internal op " << ceph_mds_op_name(internal_op) << ":" << reqid;
545 } else {
546 // drat, it's triggered by a slave request, but we don't have a message
547 // FIXME
548 stream << "rejoin:" << reqid;
549 }
550 }
551
552 void MDLockCache::attach_locks()
553 {
554 ceph_assert(!items_lock);
555 items_lock.reset(new LockItem[locks.size()]);
556 int i = 0;
557 for (auto& p : locks) {
558 items_lock[i].parent = this;
559 p.lock->add_cache(items_lock[i]);
560 ++i;
561 }
562 }
563
564 void MDLockCache::attach_dirfrags(std::vector<CDir*>&& dfv)
565 {
566 std::sort(dfv.begin(), dfv.end());
567 auto last = std::unique(dfv.begin(), dfv.end());
568 dfv.erase(last, dfv.end());
569 auth_pinned_dirfrags = std::move(dfv);
570
571 ceph_assert(!items_dir);
572 items_dir.reset(new DirItem[auth_pinned_dirfrags.size()]);
573 int i = 0;
574 for (auto dir : auth_pinned_dirfrags) {
575 items_dir[i].parent = this;
576 dir->lock_caches_with_auth_pins.push_back(&items_dir[i].item_dir);
577 ++i;
578 }
579 }
580
581 void MDLockCache::detach_locks()
582 {
583 ceph_assert(items_lock);
584 int i = 0;
585 for (auto& p : locks) {
586 auto& item = items_lock[i];
587 p.lock->remove_cache(item);
588 ++i;
589 }
590 items_lock.reset();
591 }
592
593 void MDLockCache::detach_dirfrags()
594 {
595 ceph_assert(items_dir);
596 int i = 0;
597 for (auto dir : auth_pinned_dirfrags) {
598 (void)dir;
599 items_dir[i].item_dir.remove_myself();
600 ++i;
601 }
602 items_dir.reset();
603 }