* Don't call this with in==NULL, use get_or_create for that * leave dn set to default NULL unless you're trying to add * a new inode to a pre-created Dentry */
| 3748 | * a new inode to a pre-created Dentry |
| 3749 | */ |
| 3750 | Dentry* Client::link(Dir *dir, const string& name, Inode *in, Dentry *dn) |
| 3751 | { |
| 3752 | if (!dn) { |
| 3753 | // create a new Dentry |
| 3754 | dn = new Dentry(dir, name); |
| 3755 | |
| 3756 | lru.lru_insert_mid(dn); // mid or top? |
| 3757 | |
| 3758 | if(in) { |
| 3759 | ldout(cct, 15) << "link dir " << *dir->parent_inode << " '" << name << "' to inode " << *in |
| 3760 | << " dn " << *dn << " (new dn)" << dendl; |
| 3761 | } else { |
| 3762 | ldout(cct, 15) << "link dir " << *dir->parent_inode << " '" << name << "' " |
| 3763 | << " dn " << *dn << " (new dn)" << dendl; |
| 3764 | } |
| 3765 | } else { |
| 3766 | ceph_assert(!dn->inode); |
| 3767 | ldout(cct, 15) << "link dir " << *dir->parent_inode << " '" << name << "' to inode " << in |
| 3768 | << " dn " << *dn << " (old dn)" << dendl; |
| 3769 | } |
| 3770 | |
| 3771 | if (in) { // link to inode |
| 3772 | InodeRef tmp_ref; |
| 3773 | // only one parent for directories! |
| 3774 | if (in->is_dir() && !in->dentries.empty()) { |
| 3775 | tmp_ref = in; // prevent unlink below from freeing the inode. |
| 3776 | Dentry *olddn = in->get_first_parent(); |
| 3777 | ceph_assert(olddn->dir != dir || olddn->name != name); |
| 3778 | Inode *old_diri = olddn->dir->parent_inode; |
| 3779 | clear_dir_complete_and_ordered(old_diri, true); |
| 3780 | unlink(olddn, true, true); // keep dir, dentry |
| 3781 | } |
| 3782 | |
| 3783 | dn->link(in); |
| 3784 | inc_dentry_nr(); |
| 3785 | ldout(cct, 20) << "link inode " << in << " parents now " << in->dentries << dendl; |
| 3786 | } |
| 3787 | |
| 3788 | return dn; |
| 3789 | } |
| 3790 | |
| 3791 | void Client::unlink(Dentry *dn, bool keepdir, bool keepdentry) |
| 3792 | { |
no test coverage detected