dirty_rstat_inodes(member_offset(CInode, dirty_rstat_item)),
dirty_dentries(member_offset(CDentry, item_dir_dirty)),
item_dirty(this), item_new(this),
+ lock_caches_with_auth_pins(member_offset(MDLockCache::DirItem, item_dir)),
dir_rep(REP_NONE),
pop_me(mdcache->decayrate),
pop_nested(mdcache->decayrate),
// gets decreased. Subtree become 'frozen' when the counter reaches zero.
freeze_tree_state = std::make_shared<freeze_tree_state_t>(this);
freeze_tree_state->auth_pins += get_auth_pins() + get_dir_auth_pins();
+ if (!lock_caches_with_auth_pins.empty())
+ cache->mds->locker->invalidate_lock_caches(this);
_walk_tree([this](CDir *dir) {
if (dir->freeze_tree_state)
return false;
dir->freeze_tree_state = freeze_tree_state;
freeze_tree_state->auth_pins += dir->get_auth_pins() + dir->get_dir_auth_pins();
+ if (!dir->lock_caches_with_auth_pins.empty())
+ cache->mds->locker->invalidate_lock_caches(dir);
return true;
- }
+ }
);
if (is_freezeable(true)) {
return true;
} else {
state_set(STATE_FREEZINGDIR);
+ if (!lock_caches_with_auth_pins.empty())
+ cache->mds->locker->invalidate_lock_caches(this);
dout(10) << "freeze_dir + wait " << *this << dendl;
return false;
}
elist<CDentry*> dirty_dentries;
elist<CDir*>::item item_dirty, item_new;
+ // lock caches that auth-pin me
+ elist<MDLockCache::DirItem*> lock_caches_with_auth_pins;
+
// all dirfrags within freezing/frozen tree reference the 'state'
std::shared_ptr<freeze_tree_state_t> freeze_tree_state;
parent = projected_parent.front();
projected_parent.pop_front();
}
+ bool is_parent_projected() const {
+ return !projected_parent.empty();
+ }
void maybe_export_pin(bool update=false);
void set_export_pin(mds_rank_t rank);
put_lock_cache(lock_cache);
}
+// ask lock caches to release auth pins
+void Locker::invalidate_lock_caches(CDir *dir)
+{
+ dout(10) << "invalidate_lock_caches on " << *dir << dendl;
+ auto &lock_caches = dir->lock_caches_with_auth_pins;
+ while (!lock_caches.empty()) {
+ invalidate_lock_cache(lock_caches.front()->parent);
+ }
+}
+
// ask lock caches to release locks
void Locker::invalidate_lock_caches(SimpleLock *lock)
{
if (p.first != diri && !ancestors.count(p.first))
continue;
auto& stat = p.second;
- if (stat.auth_pinned && !p.first->can_auth_pin()) {
- dout(10) << " can't auth_pin(freezing?) lock parent " << *p.first << ", noop" << dendl;
- return;
+ if (stat.auth_pinned) {
+ if (!p.first->can_auth_pin()) {
+ dout(10) << " can't auth_pin(freezing?) lock parent " << *p.first << ", noop" << dendl;
+ return;
+ }
+ if (CInode *in = dynamic_cast<CInode*>(p.first); in->is_parent_projected()) {
+ CDir *dir = in->get_projected_parent_dir();
+ if (!dir->can_auth_pin()) {
+ dout(10) << " can't auth_pin(!auth|freezing?) dirfrag " << *dir << ", noop" << dendl;
+ return;
+ }
+ }
}
}
lock_cache->auth_pin(p.first);
else
lock_cache->pin(p.first);
+
+ if (CInode *in = dynamic_cast<CInode*>(p.first)) {
+ CDentry *pdn = in->get_projected_parent_dn();
+ if (pdn)
+ dfv.push_back(pdn->get_dir());
+ } else if (CDentry *dn = dynamic_cast<CDentry*>(p.first)) {
+ dfv.push_back(dn->get_dir());
+ } else {
+ ceph_assert(0 == "unknown type of lock parent");
+ }
}
+ lock_cache->attach_dirfrags(std::move(dfv));
for (auto it = mdr->locks.begin(); it != mdr->locks.end(); ) {
MDSCacheObject *obj = it->lock->get_parent();
void create_lock_cache(MDRequestRef& mdr, CInode *diri);
bool find_and_attach_lock_cache(MDRequestRef& mdr, CInode *diri);
+ void invalidate_lock_caches(CDir *dir);
void invalidate_lock_caches(SimpleLock *lock);
void invalidate_lock_cache(MDLockCache *lock_cache);
void put_lock_cache(MDLockCache* lock_cache);
}
}
+void MDLockCache::attach_dirfrags(std::vector<CDir*>&& dfv)
+{
+ std::sort(dfv.begin(), dfv.end());
+ auto last = std::unique(dfv.begin(), dfv.end());
+ dfv.erase(last, dfv.end());
+ auth_pinned_dirfrags = std::move(dfv);
+
+ ceph_assert(!items_dir);
+ items_dir.reset(new DirItem[auth_pinned_dirfrags.size()]);
+ int i = 0;
+ for (auto dir : auth_pinned_dirfrags) {
+ items_dir[i].parent = this;
+ dir->lock_caches_with_auth_pins.push_back(&items_dir[i].item_dir);
+ ++i;
+ }
+}
+
void MDLockCache::detach_all()
{
ceph_assert(items_lock);
++i;
}
items_lock.reset();
+
+ ceph_assert(items_dir);
+ i = 0;
+ for (auto dir : auth_pinned_dirfrags) {
+ (void)dir;
+ items_dir[i].item_dir.remove_myself();
+ ++i;
+ }
+ items_dir.reset();
}
// link myself to locked locks
std::unique_ptr<LockItem[]> items_lock;
+ struct DirItem {
+ MDLockCache *parent = nullptr;
+ elist<DirItem*>::item item_dir;
+ };
+ // link myself to auth-pinned dirfrags
+ std::unique_ptr<DirItem[]> items_dir;
+ std::vector<CDir*> auth_pinned_dirfrags;
+
int ref = 1;
bool invalidating = false;