]> git.proxmox.com Git - ceph.git/blame - ceph/src/mds/Mutation.cc
import quincy beta 17.1.0
[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
271void MutationImpl::_dump_op_descriptor_unlocked(ostream& stream) const
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
AA
448{
449 msg_lock.lock();
9f95a23c 450 cref_t<MClientRequest> req;
11fdf7f2 451 req.swap(client_request);
f91f0fd5 452 client_request = req;
91327a77
AA
453 msg_lock.unlock();
454 return req;
455}
456
f67539c2 457void MDRequestImpl::reset_peer_request(const cref_t<MMDSPeerRequest>& req)
91327a77
AA
458{
459 msg_lock.lock();
f67539c2
TL
460 cref_t<MMDSPeerRequest> old;
461 old.swap(peer_request);
462 peer_request = req;
91327a77 463 msg_lock.unlock();
11fdf7f2 464 old.reset();
91327a77
AA
465}
466
7c673cae
FG
467void MDRequestImpl::print(ostream &out) const
468{
9f95a23c 469 out << "request(" << reqid << " nref=" << nref;
7c673cae 470 //if (request) out << " " << *request;
f67539c2 471 if (is_peer()) out << " peer_to mds." << peer_to_mds;
7c673cae 472 if (client_request) out << " cr=" << client_request;
f67539c2 473 if (peer_request) out << " sr=" << peer_request;
7c673cae
FG
474 out << ")";
475}
476
477void MDRequestImpl::dump(Formatter *f) const
478{
479 _dump(f);
480}
481
482void MDRequestImpl::_dump(Formatter *f) const
483{
484 f->dump_string("flag_point", state_string());
485 f->dump_stream("reqid") << reqid;
486 {
91327a77 487 msg_lock.lock();
11fdf7f2 488 auto _client_request = client_request;
f67539c2 489 auto _peer_request =peer_request;
91327a77
AA
490 msg_lock.unlock();
491
492 if (_client_request) {
7c673cae
FG
493 f->dump_string("op_type", "client_request");
494 f->open_object_section("client_info");
91327a77
AA
495 f->dump_stream("client") << _client_request->get_orig_source();
496 f->dump_int("tid", _client_request->get_tid());
7c673cae 497 f->close_section(); // client_info
f67539c2
TL
498 } else if (is_peer()) { // replies go to an existing mdr
499 f->dump_string("op_type", "peer_request");
500 f->open_object_section("leader_info");
501 f->dump_stream("leader") << peer_to_mds;
502 f->close_section(); // leader_info
503
504 if (_peer_request) {
505 f->open_object_section("request_info");
506 f->dump_int("attempt", _peer_request->get_attempt());
507 f->dump_string("op_type",
508 MMDSPeerRequest::get_opname(_peer_request->get_op()));
509 f->dump_int("lock_type", _peer_request->get_lock_type());
510 f->dump_stream("object_info") << _peer_request->get_object_info();
511 f->dump_stream("srcdnpath") << _peer_request->srcdnpath;
512 f->dump_stream("destdnpath") << _peer_request->destdnpath;
513 f->dump_stream("witnesses") << _peer_request->witnesses;
514 f->dump_bool("has_inode_export",
515 _peer_request->inode_export_v != 0);
516 f->dump_int("inode_export_v", _peer_request->inode_export_v);
517 f->dump_stream("op_stamp") << _peer_request->op_stamp;
518 f->close_section(); // request_info
519 }
7c673cae
FG
520 }
521 else if (internal_op != -1) { // internal request
522 f->dump_string("op_type", "internal_op");
523 f->dump_int("internal_op", internal_op);
524 f->dump_string("op_name", ceph_mds_op_name(internal_op));
525 }
526 else {
527 f->dump_string("op_type", "no_available_op_found");
528 }
529 }
530 {
531 f->open_array_section("events");
11fdf7f2 532 std::lock_guard l(lock);
7c673cae
FG
533 for (auto& i : events) {
534 f->dump_object("event", i);
535 }
536 f->close_section(); // events
537 }
538}
539
540void MDRequestImpl::_dump_op_descriptor_unlocked(ostream& stream) const
541{
91327a77 542 msg_lock.lock();
11fdf7f2 543 auto _client_request = client_request;
f67539c2 544 auto _peer_request = peer_request;
91327a77
AA
545 msg_lock.unlock();
546
547 if (_client_request) {
548 _client_request->print(stream);
f67539c2
TL
549 } else if (_peer_request) {
550 _peer_request->print(stream);
551 } else if (is_peer()) {
552 stream << "peer_request:" << reqid;
7c673cae
FG
553 } else if (internal_op >= 0) {
554 stream << "internal op " << ceph_mds_op_name(internal_op) << ":" << reqid;
555 } else {
f67539c2 556 // drat, it's triggered by a peer request, but we don't have a message
7c673cae
FG
557 // FIXME
558 stream << "rejoin:" << reqid;
559 }
560}
9f95a23c
TL
561
562void MDLockCache::attach_locks()
563{
564 ceph_assert(!items_lock);
565 items_lock.reset(new LockItem[locks.size()]);
566 int i = 0;
567 for (auto& p : locks) {
568 items_lock[i].parent = this;
569 p.lock->add_cache(items_lock[i]);
570 ++i;
571 }
572}
573
574void MDLockCache::attach_dirfrags(std::vector<CDir*>&& dfv)
575{
576 std::sort(dfv.begin(), dfv.end());
577 auto last = std::unique(dfv.begin(), dfv.end());
578 dfv.erase(last, dfv.end());
579 auth_pinned_dirfrags = std::move(dfv);
580
581 ceph_assert(!items_dir);
582 items_dir.reset(new DirItem[auth_pinned_dirfrags.size()]);
583 int i = 0;
584 for (auto dir : auth_pinned_dirfrags) {
585 items_dir[i].parent = this;
586 dir->lock_caches_with_auth_pins.push_back(&items_dir[i].item_dir);
587 ++i;
588 }
589}
590
1911f103 591void MDLockCache::detach_locks()
9f95a23c
TL
592{
593 ceph_assert(items_lock);
594 int i = 0;
595 for (auto& p : locks) {
596 auto& item = items_lock[i];
597 p.lock->remove_cache(item);
598 ++i;
599 }
600 items_lock.reset();
1911f103 601}
9f95a23c 602
1911f103
TL
603void MDLockCache::detach_dirfrags()
604{
9f95a23c 605 ceph_assert(items_dir);
1911f103 606 int i = 0;
9f95a23c
TL
607 for (auto dir : auth_pinned_dirfrags) {
608 (void)dir;
609 items_dir[i].item_dir.remove_myself();
610 ++i;
611 }
612 items_dir.reset();
613}