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