]> git.proxmox.com Git - ceph.git/blame - ceph/src/mds/Mutation.cc
Import ceph 15.2.8
[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"
17#include "CDir.h"
18
7c673cae
FG
19// MutationImpl
20
21void MutationImpl::pin(MDSCacheObject *o)
22{
9f95a23c
TL
23 auto& stat = object_states[o];
24 if (!stat.pinned) {
7c673cae 25 o->get(MDSCacheObject::PIN_REQUEST);
9f95a23c
TL
26 stat.pinned = true;
27 ++num_pins;
7c673cae
FG
28 }
29}
30
31void MutationImpl::unpin(MDSCacheObject *o)
32{
9f95a23c
TL
33 auto& stat = object_states[o];
34 ceph_assert(stat.pinned);
7c673cae 35 o->put(MDSCacheObject::PIN_REQUEST);
9f95a23c
TL
36 stat.pinned = false;
37 --num_pins;
7c673cae
FG
38}
39
40void MutationImpl::set_stickydirs(CInode *in)
41{
11fdf7f2 42 if (!stickydiri || stickydiri != in) {
7c673cae 43 in->get_stickydirs();
11fdf7f2
TL
44 if (stickydiri)
45 stickydiri->put_stickydirs();
46 stickydiri = in;
47 }
48}
49
50void MutationImpl::put_stickydirs()
51{
52 if (stickydiri) {
53 stickydiri->put_stickydirs();
54 stickydiri = nullptr;
55
7c673cae
FG
56 }
57}
58
59void MutationImpl::drop_pins()
60{
9f95a23c
TL
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 }
7c673cae
FG
68}
69
70void MutationImpl::start_locking(SimpleLock *lock, int target)
71{
11fdf7f2 72 ceph_assert(locking == NULL);
7c673cae
FG
73 pin(lock->get_parent());
74 locking = lock;
75 locking_target_mds = target;
76}
77
78void MutationImpl::finish_locking(SimpleLock *lock)
79{
11fdf7f2 80 ceph_assert(locking == lock);
7c673cae
FG
81 locking = NULL;
82 locking_target_mds = -1;
83}
84
9f95a23c
TL
85bool 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
94bool 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
11fdf7f2
TL
103void 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}
11fdf7f2
TL
113void MutationImpl::LockOpVec::sort_and_merge()
114{
9f95a23c
TL
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 }
11fdf7f2
TL
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 }
11fdf7f2
TL
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());
9f95a23c 153 j->flags = LockOp::XLOCK;
11fdf7f2
TL
154 }
155 erase(j + 1, i + 1);
156 i = j - 1;
157 }
158}
7c673cae
FG
159
160// auth pins
161bool MutationImpl::is_auth_pinned(MDSCacheObject *object) const
162{
9f95a23c
TL
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;
7c673cae
FG
167}
168
169void MutationImpl::auth_pin(MDSCacheObject *object)
170{
9f95a23c
TL
171 auto &stat = object_states[object];
172 if (!stat.auth_pinned) {
7c673cae 173 object->auth_pin(this);
9f95a23c
TL
174 stat.auth_pinned = true;
175 ++num_auth_pins;
7c673cae
FG
176 }
177}
178
179void MutationImpl::auth_unpin(MDSCacheObject *object)
180{
9f95a23c
TL
181 auto &stat = object_states[object];
182 ceph_assert(stat.auth_pinned);
7c673cae 183 object->auth_unpin(this);
9f95a23c
TL
184 stat.auth_pinned = false;
185 --num_auth_pins;
7c673cae
FG
186}
187
188void MutationImpl::drop_local_auth_pins()
189{
9f95a23c
TL
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
200void 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);
7c673cae 208 }
9f95a23c
TL
209}
210
211void 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;
7c673cae
FG
216}
217
218void MutationImpl::add_projected_inode(CInode *in)
219{
220 projected_inodes.push_back(in);
221}
222
223void 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
232void MutationImpl::add_projected_fnode(CDir *dir)
233{
234 projected_fnodes.push_back(dir);
235}
236
237void MutationImpl::pop_and_dirty_projected_fnodes()
238{
9f95a23c 239 for (const auto& dir : projected_fnodes) {
7c673cae
FG
240 dir->pop_and_dirty_projected_fnode(ls);
241 }
9f95a23c 242 projected_fnodes.clear();
7c673cae
FG
243}
244
245void MutationImpl::add_updated_lock(ScatterLock *lock)
246{
247 updated_locks.push_back(lock);
248}
249
250void MutationImpl::add_cow_inode(CInode *in)
251{
252 pin(in);
253 dirty_cow_inodes.push_back(in);
254}
255
256void 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
262void MutationImpl::apply()
263{
264 pop_and_dirty_projected_inodes();
265 pop_and_dirty_projected_fnodes();
266
9f95a23c
TL
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 }
7c673cae 273
9f95a23c
TL
274 for (const auto& lock : updated_locks) {
275 lock->mark_dirty();
276 }
7c673cae
FG
277}
278
279void MutationImpl::cleanup()
280{
281 drop_local_auth_pins();
282 drop_pins();
283}
284
285void MutationImpl::_dump_op_descriptor_unlocked(ostream& stream) const
286{
287 stream << "Mutation";
288}
289
290// MDRequestImpl
291
292MDRequestImpl::~MDRequestImpl()
293{
7c673cae
FG
294 delete _more;
295}
296
297MDRequestImpl::More* MDRequestImpl::more()
298{
299 if (!_more)
300 _more = new More();
301 return _more;
302}
303
304bool MDRequestImpl::has_more() const
305{
306 return _more != nullptr;
307}
308
309bool MDRequestImpl::has_witnesses()
310{
311 return (_more != nullptr) && (!_more->witnessed.empty());
312}
313
314bool MDRequestImpl::slave_did_prepare()
315{
316 return has_more() && more()->slave_commit;
317}
318
319bool MDRequestImpl::slave_rolling_back()
320{
321 return has_more() && more()->slave_rolling_back;
322}
323
7c673cae
FG
324bool MDRequestImpl::freeze_auth_pin(CInode *inode)
325{
11fdf7f2 326 ceph_assert(!more()->rename_inode || more()->rename_inode == inode);
7c673cae
FG
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
338void MDRequestImpl::unfreeze_auth_pin(bool clear_inode)
339{
11fdf7f2 340 ceph_assert(more()->is_freeze_authpin);
7c673cae
FG
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
351void MDRequestImpl::set_remote_frozen_auth_pin(CInode *inode)
352{
353 more()->rename_inode = inode;
354 more()->is_remote_frozen_authpin = true;
355}
356
357void MDRequestImpl::set_ambiguous_auth(CInode *inode)
358{
11fdf7f2
TL
359 ceph_assert(!more()->rename_inode || more()->rename_inode == inode);
360 ceph_assert(!more()->is_ambiguous_auth);
7c673cae
FG
361
362 inode->set_ambiguous_auth();
363 more()->rename_inode = inode;
364 more()->is_ambiguous_auth = true;
365}
366
367void MDRequestImpl::clear_ambiguous_auth()
368{
369 CInode *inode = more()->rename_inode;
11fdf7f2 370 ceph_assert(inode && more()->is_ambiguous_auth);
7c673cae
FG
371 inode->clear_ambiguous_auth();
372 more()->is_ambiguous_auth = false;
373}
374
375bool 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
383void 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
390const filepath& MDRequestImpl::get_filepath()
391{
392 if (client_request)
393 return client_request->get_filepath();
394 return more()->filepath1;
395}
396
397const filepath& MDRequestImpl::get_filepath2()
398{
399 if (client_request)
400 return client_request->get_filepath2();
401 return more()->filepath2;
402}
403
404void MDRequestImpl::set_filepath(const filepath& fp)
405{
11fdf7f2 406 ceph_assert(!client_request);
7c673cae
FG
407 more()->filepath1 = fp;
408}
409
410void MDRequestImpl::set_filepath2(const filepath& fp)
411{
11fdf7f2 412 ceph_assert(!client_request);
7c673cae
FG
413 more()->filepath2 = fp;
414}
415
b32b8144 416bool MDRequestImpl::is_queued_for_replay() const
7c673cae 417{
b32b8144 418 return client_request ? client_request->is_queued_for_replay() : false;
7c673cae
FG
419}
420
f91f0fd5 421bool MDRequestImpl::can_batch()
9f95a23c 422{
f91f0fd5
TL
423 if (num_auth_pins || num_remote_auth_pins || lock_cache || !locks.empty())
424 return false;
425
426 auto op = client_request->get_op();
427 auto& path = client_request->get_filepath();
428 if (op == CEPH_MDS_OP_GETATTR) {
429 if (path.depth() == 0)
430 return true;
431 } else if (op == CEPH_MDS_OP_LOOKUP) {
432 if (path.depth() == 1 && !path.is_last_snap())
433 return true;
434 }
435
436 return false;
437}
438
439std::unique_ptr<BatchOp> MDRequestImpl::release_batch_op()
440{
441 int mask = client_request->head.args.getattr.mask;
442 auto it = batch_op_map->find(mask);
443 std::unique_ptr<BatchOp> bop = std::move(it->second);
444 batch_op_map->erase(it);
445 return bop;
9f95a23c
TL
446}
447
448int MDRequestImpl::compare_paths()
449{
450 if (dir_root[0] < dir_root[1])
451 return -1;
452 if (dir_root[0] > dir_root[1])
453 return 1;
454 if (dir_depth[0] < dir_depth[1])
455 return -1;
456 if (dir_depth[0] > dir_depth[1])
457 return 1;
458 return 0;
459}
460
461cref_t<MClientRequest> MDRequestImpl::release_client_request()
91327a77
AA
462{
463 msg_lock.lock();
9f95a23c 464 cref_t<MClientRequest> req;
11fdf7f2 465 req.swap(client_request);
f91f0fd5 466 client_request = req;
91327a77
AA
467 msg_lock.unlock();
468 return req;
469}
470
9f95a23c 471void MDRequestImpl::reset_slave_request(const cref_t<MMDSSlaveRequest>& req)
91327a77
AA
472{
473 msg_lock.lock();
9f95a23c 474 cref_t<MMDSSlaveRequest> old;
11fdf7f2 475 old.swap(slave_request);
91327a77
AA
476 slave_request = req;
477 msg_lock.unlock();
11fdf7f2 478 old.reset();
91327a77
AA
479}
480
7c673cae
FG
481void MDRequestImpl::print(ostream &out) const
482{
9f95a23c 483 out << "request(" << reqid << " nref=" << nref;
7c673cae
FG
484 //if (request) out << " " << *request;
485 if (is_slave()) out << " slave_to mds." << slave_to_mds;
486 if (client_request) out << " cr=" << client_request;
487 if (slave_request) out << " sr=" << slave_request;
488 out << ")";
489}
490
491void MDRequestImpl::dump(Formatter *f) const
492{
493 _dump(f);
494}
495
496void MDRequestImpl::_dump(Formatter *f) const
497{
498 f->dump_string("flag_point", state_string());
499 f->dump_stream("reqid") << reqid;
500 {
91327a77 501 msg_lock.lock();
11fdf7f2
TL
502 auto _client_request = client_request;
503 auto _slave_request =slave_request;
91327a77
AA
504 msg_lock.unlock();
505
506 if (_client_request) {
7c673cae
FG
507 f->dump_string("op_type", "client_request");
508 f->open_object_section("client_info");
91327a77
AA
509 f->dump_stream("client") << _client_request->get_orig_source();
510 f->dump_int("tid", _client_request->get_tid());
7c673cae 511 f->close_section(); // client_info
91327a77 512 } else if (is_slave() && _slave_request) { // replies go to an existing mdr
7c673cae
FG
513 f->dump_string("op_type", "slave_request");
514 f->open_object_section("master_info");
91327a77 515 f->dump_stream("master") << _slave_request->get_orig_source();
7c673cae
FG
516 f->close_section(); // master_info
517
518 f->open_object_section("request_info");
91327a77 519 f->dump_int("attempt", _slave_request->get_attempt());
7c673cae 520 f->dump_string("op_type",
91327a77
AA
521 MMDSSlaveRequest::get_opname(_slave_request->get_op()));
522 f->dump_int("lock_type", _slave_request->get_lock_type());
523 f->dump_stream("object_info") << _slave_request->get_object_info();
524 f->dump_stream("srcdnpath") << _slave_request->srcdnpath;
525 f->dump_stream("destdnpath") << _slave_request->destdnpath;
526 f->dump_stream("witnesses") << _slave_request->witnesses;
7c673cae 527 f->dump_bool("has_inode_export",
91327a77
AA
528 _slave_request->inode_export_v != 0);
529 f->dump_int("inode_export_v", _slave_request->inode_export_v);
530 f->dump_stream("op_stamp") << _slave_request->op_stamp;
7c673cae
FG
531 f->close_section(); // request_info
532 }
533 else if (internal_op != -1) { // internal request
534 f->dump_string("op_type", "internal_op");
535 f->dump_int("internal_op", internal_op);
536 f->dump_string("op_name", ceph_mds_op_name(internal_op));
537 }
538 else {
539 f->dump_string("op_type", "no_available_op_found");
540 }
541 }
542 {
543 f->open_array_section("events");
11fdf7f2 544 std::lock_guard l(lock);
7c673cae
FG
545 for (auto& i : events) {
546 f->dump_object("event", i);
547 }
548 f->close_section(); // events
549 }
550}
551
552void MDRequestImpl::_dump_op_descriptor_unlocked(ostream& stream) const
553{
91327a77 554 msg_lock.lock();
11fdf7f2
TL
555 auto _client_request = client_request;
556 auto _slave_request = slave_request;
91327a77
AA
557 msg_lock.unlock();
558
559 if (_client_request) {
560 _client_request->print(stream);
561 } else if (_slave_request) {
562 _slave_request->print(stream);
7c673cae
FG
563 } else if (internal_op >= 0) {
564 stream << "internal op " << ceph_mds_op_name(internal_op) << ":" << reqid;
565 } else {
566 // drat, it's triggered by a slave request, but we don't have a message
567 // FIXME
568 stream << "rejoin:" << reqid;
569 }
570}
9f95a23c
TL
571
572void MDLockCache::attach_locks()
573{
574 ceph_assert(!items_lock);
575 items_lock.reset(new LockItem[locks.size()]);
576 int i = 0;
577 for (auto& p : locks) {
578 items_lock[i].parent = this;
579 p.lock->add_cache(items_lock[i]);
580 ++i;
581 }
582}
583
584void MDLockCache::attach_dirfrags(std::vector<CDir*>&& dfv)
585{
586 std::sort(dfv.begin(), dfv.end());
587 auto last = std::unique(dfv.begin(), dfv.end());
588 dfv.erase(last, dfv.end());
589 auth_pinned_dirfrags = std::move(dfv);
590
591 ceph_assert(!items_dir);
592 items_dir.reset(new DirItem[auth_pinned_dirfrags.size()]);
593 int i = 0;
594 for (auto dir : auth_pinned_dirfrags) {
595 items_dir[i].parent = this;
596 dir->lock_caches_with_auth_pins.push_back(&items_dir[i].item_dir);
597 ++i;
598 }
599}
600
1911f103 601void MDLockCache::detach_locks()
9f95a23c
TL
602{
603 ceph_assert(items_lock);
604 int i = 0;
605 for (auto& p : locks) {
606 auto& item = items_lock[i];
607 p.lock->remove_cache(item);
608 ++i;
609 }
610 items_lock.reset();
1911f103 611}
9f95a23c 612
1911f103
TL
613void MDLockCache::detach_dirfrags()
614{
9f95a23c 615 ceph_assert(items_dir);
1911f103 616 int i = 0;
9f95a23c
TL
617 for (auto dir : auth_pinned_dirfrags) {
618 (void)dir;
619 items_dir[i].item_dir.remove_myself();
620 ++i;
621 }
622 items_dir.reset();
623}