1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
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.
16 #include "ScatterLock.h"
21 void MutationImpl::pin(MDSCacheObject
*o
)
23 auto& stat
= object_states
[o
];
25 o
->get(MDSCacheObject::PIN_REQUEST
);
31 void MutationImpl::unpin(MDSCacheObject
*o
)
33 auto& stat
= object_states
[o
];
34 ceph_assert(stat
.pinned
);
35 o
->put(MDSCacheObject::PIN_REQUEST
);
40 void MutationImpl::set_stickydirs(CInode
*in
)
42 if (!stickydiri
|| stickydiri
!= in
) {
45 stickydiri
->put_stickydirs();
50 void MutationImpl::put_stickydirs()
53 stickydiri
->put_stickydirs();
59 void MutationImpl::drop_pins()
61 for (auto& p
: object_states
) {
62 if (p
.second
.pinned
) {
63 p
.first
->put(MDSCacheObject::PIN_REQUEST
);
64 p
.second
.pinned
= false;
70 void MutationImpl::start_locking(SimpleLock
*lock
, int target
)
72 ceph_assert(locking
== NULL
);
73 pin(lock
->get_parent());
75 locking_target_mds
= target
;
78 void MutationImpl::finish_locking(SimpleLock
*lock
)
80 ceph_assert(locking
== lock
);
82 locking_target_mds
= -1;
85 bool MutationImpl::is_rdlocked(SimpleLock
*lock
) const {
86 auto it
= locks
.find(lock
);
87 if (it
!= locks
.end() && it
->is_rdlock())
90 return static_cast<const MutationImpl
*>(lock_cache
)->is_rdlocked(lock
);
94 bool MutationImpl::is_wrlocked(SimpleLock
*lock
) const {
95 auto it
= locks
.find(lock
);
96 if (it
!= locks
.end() && it
->is_wrlock())
99 return static_cast<const MutationImpl
*>(lock_cache
)->is_wrlocked(lock
);
103 void MutationImpl::LockOpVec::erase_rdlock(SimpleLock
* lock
)
105 for (int i
= size() - 1; i
>= 0; --i
) {
106 auto& op
= (*this)[i
];
107 if (op
.lock
== lock
&& op
.is_rdlock()) {
113 void MutationImpl::LockOpVec::sort_and_merge()
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
;
120 for (auto i
= begin(), j
= i
; ; ++i
) {
122 std::sort(j
, i
, cmp
);
125 if (j
->lock
->get_parent() != i
->lock
->get_parent()) {
126 std::sort(j
, i
, cmp
);
130 // merge ops on the same lock
131 for (auto i
= end() - 1; i
> begin(); ) {
133 while (--j
>= begin()) {
134 if (i
->lock
!= j
->lock
)
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
;
148 j
->flags
|= k
->flags
;
151 // xlock overwrites other types
152 ceph_assert(!j
->is_remote_wrlock());
153 j
->flags
= LockOp::XLOCK
;
161 bool MutationImpl::is_auth_pinned(MDSCacheObject
*object
) const
163 auto stat_p
= find_object_state(object
);
166 return stat_p
->auth_pinned
|| stat_p
->remote_auth_pinned
!= MDS_RANK_NONE
;
169 void MutationImpl::auth_pin(MDSCacheObject
*object
)
171 auto &stat
= object_states
[object
];
172 if (!stat
.auth_pinned
) {
173 object
->auth_pin(this);
174 stat
.auth_pinned
= true;
179 void MutationImpl::auth_unpin(MDSCacheObject
*object
)
181 auto &stat
= object_states
[object
];
182 ceph_assert(stat
.auth_pinned
);
183 object
->auth_unpin(this);
184 stat
.auth_pinned
= false;
188 void MutationImpl::drop_local_auth_pins()
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;
200 void MutationImpl::set_remote_auth_pinned(MDSCacheObject
*object
, mds_rank_t from
)
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
;
207 ceph_assert(stat
.remote_auth_pinned
== from
);
211 void MutationImpl::_clear_remote_auth_pinned(ObjectState
&stat
)
213 ceph_assert(stat
.remote_auth_pinned
!= MDS_RANK_NONE
);
214 stat
.remote_auth_pinned
= MDS_RANK_NONE
;
215 --num_remote_auth_pins
;
218 void MutationImpl::add_projected_inode(CInode
*in
)
220 projected_inodes
.push_back(in
);
223 void MutationImpl::pop_and_dirty_projected_inodes()
225 while (!projected_inodes
.empty()) {
226 CInode
*in
= projected_inodes
.front();
227 projected_inodes
.pop_front();
228 in
->pop_and_dirty_projected_inode(ls
);
232 void MutationImpl::add_projected_fnode(CDir
*dir
)
234 projected_fnodes
.push_back(dir
);
237 void MutationImpl::pop_and_dirty_projected_fnodes()
239 for (const auto& dir
: projected_fnodes
) {
240 dir
->pop_and_dirty_projected_fnode(ls
);
242 projected_fnodes
.clear();
245 void MutationImpl::add_updated_lock(ScatterLock
*lock
)
247 updated_locks
.push_back(lock
);
250 void MutationImpl::add_cow_inode(CInode
*in
)
253 dirty_cow_inodes
.push_back(in
);
256 void MutationImpl::add_cow_dentry(CDentry
*dn
)
259 dirty_cow_dentries
.push_back(pair
<CDentry
*,version_t
>(dn
, dn
->get_projected_version()));
262 void MutationImpl::apply()
264 pop_and_dirty_projected_inodes();
265 pop_and_dirty_projected_fnodes();
267 for (const auto& in
: dirty_cow_inodes
) {
270 for (const auto& [dentry
, v
] : dirty_cow_dentries
) {
271 dentry
->mark_dirty(v
, ls
);
274 for (const auto& lock
: updated_locks
) {
279 void MutationImpl::cleanup()
281 drop_local_auth_pins();
285 void MutationImpl::_dump_op_descriptor_unlocked(ostream
& stream
) const
287 stream
<< "Mutation";
292 MDRequestImpl::~MDRequestImpl()
297 MDRequestImpl::More
* MDRequestImpl::more()
304 bool MDRequestImpl::has_more() const
306 return _more
!= nullptr;
309 bool MDRequestImpl::has_witnesses()
311 return (_more
!= nullptr) && (!_more
->witnessed
.empty());
314 bool MDRequestImpl::slave_did_prepare()
316 return has_more() && more()->slave_commit
;
319 bool MDRequestImpl::slave_rolling_back()
321 return has_more() && more()->slave_rolling_back
;
324 bool MDRequestImpl::freeze_auth_pin(CInode
*inode
)
326 ceph_assert(!more()->rename_inode
|| more()->rename_inode
== inode
);
327 more()->rename_inode
= inode
;
328 more()->is_freeze_authpin
= true;
330 if (!inode
->freeze_inode(1)) {
333 inode
->freeze_auth_pin();
334 inode
->unfreeze_inode();
338 void MDRequestImpl::unfreeze_auth_pin(bool clear_inode
)
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();
345 inode
->unfreeze_inode();
346 more()->is_freeze_authpin
= false;
348 more()->rename_inode
= NULL
;
351 void MDRequestImpl::set_remote_frozen_auth_pin(CInode
*inode
)
353 more()->rename_inode
= inode
;
354 more()->is_remote_frozen_authpin
= true;
357 void MDRequestImpl::set_ambiguous_auth(CInode
*inode
)
359 ceph_assert(!more()->rename_inode
|| more()->rename_inode
== inode
);
360 ceph_assert(!more()->is_ambiguous_auth
);
362 inode
->set_ambiguous_auth();
363 more()->rename_inode
= inode
;
364 more()->is_ambiguous_auth
= true;
367 void MDRequestImpl::clear_ambiguous_auth()
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;
375 bool MDRequestImpl::can_auth_pin(MDSCacheObject
*object
)
377 return object
->can_auth_pin() ||
378 (is_auth_pinned(object
) && has_more() &&
379 more()->is_freeze_authpin
&&
380 more()->rename_inode
== object
);
383 void MDRequestImpl::drop_local_auth_pins()
385 if (has_more() && more()->is_freeze_authpin
)
386 unfreeze_auth_pin(true);
387 MutationImpl::drop_local_auth_pins();
390 const filepath
& MDRequestImpl::get_filepath()
393 return client_request
->get_filepath();
394 return more()->filepath1
;
397 const filepath
& MDRequestImpl::get_filepath2()
400 return client_request
->get_filepath2();
401 return more()->filepath2
;
404 void MDRequestImpl::set_filepath(const filepath
& fp
)
406 ceph_assert(!client_request
);
407 more()->filepath1
= fp
;
410 void MDRequestImpl::set_filepath2(const filepath
& fp
)
412 ceph_assert(!client_request
);
413 more()->filepath2
= fp
;
416 bool MDRequestImpl::is_queued_for_replay() const
418 return client_request
? client_request
->is_queued_for_replay() : false;
421 bool MDRequestImpl::is_batch_op()
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);
429 int MDRequestImpl::compare_paths()
431 if (dir_root
[0] < dir_root
[1])
433 if (dir_root
[0] > dir_root
[1])
435 if (dir_depth
[0] < dir_depth
[1])
437 if (dir_depth
[0] > dir_depth
[1])
442 cref_t
<MClientRequest
> MDRequestImpl::release_client_request()
445 cref_t
<MClientRequest
> req
;
446 req
.swap(client_request
);
451 void MDRequestImpl::reset_slave_request(const cref_t
<MMDSSlaveRequest
>& req
)
454 cref_t
<MMDSSlaveRequest
> old
;
455 old
.swap(slave_request
);
461 void MDRequestImpl::print(ostream
&out
) const
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
;
471 void MDRequestImpl::dump(Formatter
*f
) const
476 void MDRequestImpl::_dump(Formatter
*f
) const
478 f
->dump_string("flag_point", state_string());
479 f
->dump_stream("reqid") << reqid
;
482 auto _client_request
= client_request
;
483 auto _slave_request
=slave_request
;
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
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
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
));
519 f
->dump_string("op_type", "no_available_op_found");
523 f
->open_array_section("events");
524 std::lock_guard
l(lock
);
525 for (auto& i
: events
) {
526 f
->dump_object("event", i
);
528 f
->close_section(); // events
532 void MDRequestImpl::_dump_op_descriptor_unlocked(ostream
& stream
) const
535 auto _client_request
= client_request
;
536 auto _slave_request
= slave_request
;
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
;
546 // drat, it's triggered by a slave request, but we don't have a message
548 stream
<< "rejoin:" << reqid
;
552 void MDLockCache::attach_locks()
554 ceph_assert(!items_lock
);
555 items_lock
.reset(new LockItem
[locks
.size()]);
557 for (auto& p
: locks
) {
558 items_lock
[i
].parent
= this;
559 p
.lock
->add_cache(items_lock
[i
]);
564 void MDLockCache::attach_dirfrags(std::vector
<CDir
*>&& dfv
)
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
);
571 ceph_assert(!items_dir
);
572 items_dir
.reset(new DirItem
[auth_pinned_dirfrags
.size()]);
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
);
581 void MDLockCache::detach_locks()
583 ceph_assert(items_lock
);
585 for (auto& p
: locks
) {
586 auto& item
= items_lock
[i
];
587 p
.lock
->remove_cache(item
);
593 void MDLockCache::detach_dirfrags()
595 ceph_assert(items_dir
);
597 for (auto dir
: auth_pinned_dirfrags
) {
599 items_dir
[i
].item_dir
.remove_myself();