assert(is_dir());
assert(is_projected());
get_projected_inode()->export_pin = rank;
- if (rank == mdcache->mds->get_nodeid()) {
- link_export_pin();
- } else {
- unlink_export_pin();
- }
maybe_export_pin();
}
-mds_rank_t CInode::get_export_pin(bool inherit) const
+mds_rank_t CInode::get_export_pin(void) const
{
/* An inode that is export pinned may not necessarily be a subtree root, we
* need to traverse the parents. A base or system inode cannot be pinned.
if (pin >= 0) {
return pin;
}
- if (!inherit)
- break;
}
return MDS_RANK_NONE;
}
return true;
}
}
-
-void CInode::unlink_export_pin(void)
-{
- if (is_dir()) {
- auto list = export_pin_parent_link.get_list();
- if (list) {
- CDentry *entry = get_projected_parent_dn();
- assert(entry);
- CInode *parent = entry->dir->inode;
- assert(parent && list == &parent->export_pin_list);
- export_pin_parent_link.remove_myself();
- if (list->empty()) {
- parent->unlink_export_pin();
- }
- }
- }
-}
-
-/* Because an inode may be pinned to us **but not a subtree**, it is necessary
- * to be able to convert this inode (actually, its fragments) to subtrees if
- * this inode's parent is exported. This chain of linked lists keeps track of
- * pinned children.
- */
-void CInode::link_export_pin(void)
-{
- if (is_dir()) {
- mds_rank_t pin = get_projected_inode()->export_pin;
- if (pin >= 0 && pin == mdcache->mds->get_nodeid()) {
- unlink_export_pin();
- CDentry *cde = get_projected_parent_dn();
- while (cde) {
- cde->dir->inode->export_pin_list.push_front(&cde->get_projected_linkage()->inode->export_pin_parent_link);
- cde = cde->dir->inode->get_projected_parent_dn();
- }
- }
- }
-}
nestlock(this, &nestlock_type),
flocklock(this, &flocklock_type),
policylock(this, &policylock_type),
- loner_cap(-1), want_loner_cap(-1),
- export_pin_parent_link(this)
+ loner_cap(-1), want_loner_cap(-1)
{
state = 0;
if (auth) state_set(STATE_AUTH);
clear_file_locks();
assert(num_projected_xattrs == 0);
assert(num_projected_srnodes == 0);
- assert(export_pin_list.empty());
- unlink_export_pin();
}
void set_primary_parent(CDentry *p) {
assert(parent == 0);
parent = p;
- link_export_pin();
}
void remove_primary_parent(CDentry *dn) {
assert(dn == parent);
- if (projected_parent.empty())
- unlink_export_pin();
parent = 0;
}
void add_remote_parent(CDentry *p);
void push_projected_parent(CDentry *dn) {
projected_parent.push_back(dn);
- link_export_pin(); /* fix export pin links */
}
void pop_projected_parent() {
assert(projected_parent.size());
void maybe_export_pin();
public:
void set_export_pin(mds_rank_t rank);
- mds_rank_t get_export_pin(bool inherit=true) const;
+ mds_rank_t get_export_pin(void) const;
bool is_exportable(mds_rank_t dest) const;
-private:
- xlist<CInode *> export_pin_list;
- xlist<CInode *>::item export_pin_parent_link;
-public:
- void link_export_pin(void);
- void unlink_export_pin(void);
-
void print(ostream& out) override;
void dump(Formatter *f) const;
show_subtrees();
}
-void MDCache::split_export_pins(CInode *dir)
-{
- assert(dir->is_dir());
- for (CInode *in : dir->export_pin_list) {
- mds_rank_t export_pin = in->get_export_pin(false);
- if (export_pin >= 0 && export_pin == mds->get_nodeid()) {
- dout(7) << "splitting fragments of " << *in << dendl;
- std::list<CDir *> ls;
- in->get_dirfrags(ls);
- for (auto &cd : ls) {
- if (cd->is_full_dir_auth()) {
- adjust_subtree_auth(cd, mds_authority_t(mds->get_nodeid(), CDIR_AUTH_UNKNOWN));
- }
- }
- } else {
- split_export_pins(in);
- }
- }
-}
void MDCache::try_subtree_merge(CDir *dir)
{
void repair_dirfrag_stats(CDir *dir);
public:
- void split_export_pins(CDir *dir) {
- return split_export_pins(dir->inode);
- }
- void split_export_pins(CInode *dir);
-
/* Because exports may fail, this set lets us keep track of inodes that need exporting. */
std::set<CInode *> export_pin_queue;
};
// note the bounds.
// force it into a subtree by listing auth as <me,me>.
cache->adjust_subtree_auth(dir, mds->get_nodeid(), mds->get_nodeid());
-
- /* force export pinned children into separate subtrees */
- cache->split_export_pins(dir);
-
set<CDir*> bounds;
cache->get_subtree_bounds(dir, bounds);
continue;
}
+ /* XXX The inode may be pinned to me (in->get_inode().export_pin) but it is
+ * not a subtree by the time I've found it here. So, keeping it is
+ * difficult as we've already notified the importer of the subtree bounds
+ * (MExportDirPrep). Creating a new subtree for this pinned inode would
+ * probably require widespread changes and is not worth the effort since
+ * the importer will simply export this inode and its subtrees back to us
+ * (Migrator::decode_import_inode). This should be rare enough to not
+ * justify mucking with things here.
+ */
+
// primary link
// -- inode
exportbl.append("I", 1); // inode dentry