<< " in dir " << dir->parent_inode->ino
<< dendl;
- if (dn) {
- if (dn->inode) {
- if (dn->inode->vino() == in->vino()) {
- touch_dn(dn);
- dout(12) << " had dentry " << dname
- << " with correct vino " << dn->inode->vino()
- << dendl;
- } else {
- dout(12) << " had dentry " << dname
- << " with WRONG vino " << dn->inode->vino()
- << dendl;
- unlink(dn, true);
- dn = NULL;
- }
+ if (dn && dn->inode) {
+ if (dn->inode->vino() == in->vino()) {
+ touch_dn(dn);
+ dout(12) << " had dentry " << dname
+ << " with correct vino " << dn->inode->vino()
+ << dendl;
} else {
- link(dir, dname, in, dn);
+ dout(12) << " had dentry " << dname
+ << " with WRONG vino " << dn->inode->vino()
+ << dendl;
+ unlink(dn, true);
+ dn = NULL;
}
}
- if (!dn) {
+ if (!dn || dn->inode == 0) {
// have inode linked elsewhere? -> unlink and relink!
if (in->dn) {
dout(12) << " had vino " << in->vino()
<< " not linked or linked at the right position, relinking"
<< dendl;
- dn = relink_inode(dir, dname, in);
+ dn = relink_inode(dir, dname, in, dn);
} else {
// link
dout(12) << " had vino " << in->vino()
<< " unlinked, linking" << dendl;
- dn = link(dir, dname, in);
+ dn = link(dir, dname, in, dn);
}
}
delete dn;
}
- Dentry *relink_inode(Dir *dir, const string& name, Inode *in) {
+ Dentry *relink_inode(Dir *dir, const string& name, Inode *in, Dentry *newdn=NULL) {
Dentry *olddn = in->dn;
Dir *olddir = olddn->dir; // note: might == dir!
+ bool made_new = false;
// newdn, attach to inode. don't touch inode ref.
- Dentry *newdn = new Dentry;
- newdn->dir = dir;
- newdn->name = name;
+ if (!newdn) {
+ made_new = true;
+ newdn = new Dentry;
+ newdn->dir = dir;
+ newdn->name = name;
+ } else {
+ assert(newdn->inode == NULL);
+ }
newdn->inode = in;
in->dn = newdn;
// link new dn to dir
dir->dentries[name] = newdn;
- lru.lru_insert_mid(newdn);
+ if (made_new)
+ lru.lru_insert_mid(newdn);
+ else
+ lru.lru_midtouch(newdn);
// olddir now empty? (remember, olddir might == dir)
if (olddir->is_empty())