summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSage Weil <sage@inktank.com>2013-05-15 11:03:41 -0700
committerSage Weil <sage@inktank.com>2013-06-24 21:21:47 -0700
commit14af8c44582f2cefb179a9854053c17aac3ece92 (patch)
tree2bd1dc632d307dad06549cf34092531f9f316c2a
parent5dfe5e502be1156788878714e7e53d31488d26f0 (diff)
downloadceph-14af8c44582f2cefb179a9854053c17aac3ece92.tar.gz
client: leave NULL dentry in place on ENOENT during lookup
If we get a NULL lookup result, unlink the inode but leave the dentry in place. Signed-off-by: Sage Weil <sage@inktank.com>
-rw-r--r--src/client/Client.cc52
-rw-r--r--src/client/Client.h2
2 files changed, 29 insertions, 25 deletions
diff --git a/src/client/Client.cc b/src/client/Client.cc
index 34e5d8d1ed7..59cf62c9f5c 100644
--- a/src/client/Client.cc
+++ b/src/client/Client.cc
@@ -468,7 +468,7 @@ void Client::trim_dentry(Dentry *dn)
dn->dir->parent_inode->flags &= ~I_COMPLETE;
dn->dir->release_count++;
}
- unlink(dn, false);
+ unlink(dn, false, false);
}
@@ -662,7 +662,7 @@ Inode * Client::add_update_inode(InodeStat *st, utime_t from, MetaSession *sessi
ldout(cct, 10) << " dir is open on empty dir " << in->ino << " with "
<< in->dir->dentry_map.size() << " entries, tearing down" << dendl;
while (!in->dir->dentry_map.empty())
- unlink(in->dir->dentry_map.begin()->second, true);
+ unlink(in->dir->dentry_map.begin()->second, true, true);
close_dir(in->dir);
}
}
@@ -696,7 +696,7 @@ Dentry *Client::insert_dentry_inode(Dir *dir, const string& dname, LeaseStat *dl
ldout(cct, 12) << " had dentry " << dname
<< " with WRONG vino " << dn->inode->vino()
<< dendl;
- unlink(dn, true);
+ unlink(dn, true, false);
dn = NULL;
}
}
@@ -704,7 +704,7 @@ Dentry *Client::insert_dentry_inode(Dir *dir, const string& dname, LeaseStat *dl
if (!dn || dn->inode == 0) {
in->get();
if (old_dentry)
- unlink(old_dentry, dir == old_dentry->dir); // keep dir open if its the same dir
+ unlink(old_dentry, dir == old_dentry->dir, false); // keep dir open if its the same dir
dn = link(dir, dname, in, dn);
in->put();
if (set_offset) {
@@ -830,7 +830,7 @@ void Client::insert_readdir_results(MetaRequest *request, MetaSession *session,
ldout(cct, 15) << "insert_trace unlink '" << pd->first << "'" << dendl;
Dentry *dn = pd->second;
++pd;
- unlink(dn, true);
+ unlink(dn, true, false);
} else {
++pd;
}
@@ -849,7 +849,7 @@ void Client::insert_readdir_results(MetaRequest *request, MetaSession *session,
if (pd->second->inode != in) {
// replace incorrect dentry
++pd; // we are about to unlink this guy, move past it.
- unlink(olddn, true);
+ unlink(olddn, true, false);
dn = link(dir, dname, in, NULL);
} else {
// keep existing dn
@@ -880,7 +880,7 @@ void Client::insert_readdir_results(MetaRequest *request, MetaSession *session,
ldout(cct, 15) << "insert_trace unlink '" << pd->first << "'" << dendl;
Dentry *dn = pd->second;
++pd;
- unlink(dn, true);
+ unlink(dn, true, false);
} else
++pd;
}
@@ -964,7 +964,7 @@ Inode* Client::insert_trace(MetaRequest *request, MetaSession *session)
if (diri->dir && diri->dir->dentries.count(dname)) {
Dentry *dn = diri->dir->dentries[dname];
if (dn->inode)
- unlink(dn, false);
+ unlink(dn, true, true);
}
}
} else if (reply->head.op == CEPH_MDS_OP_LOOKUPSNAP ||
@@ -988,7 +988,7 @@ Inode* Client::insert_trace(MetaRequest *request, MetaSession *session)
if (diri->dir && diri->dir->dentries.count(dname)) {
Dentry *dn = diri->dir->dentries[dname];
if (dn->inode)
- unlink(dn, false);
+ unlink(dn, true, true);
}
}
}
@@ -1190,7 +1190,7 @@ int Client::verify_reply_trace(int r,
// the same here.
Dentry *od = request->old_dentry();
if (od) {
- unlink(od, false);
+ unlink(od, false, false);
}
if (d->dir) {
@@ -2139,7 +2139,7 @@ Dentry* Client::link(Dir *dir, const string& name, Inode *in, Dentry *dn)
if (in->is_dir() && !in->dn_set.empty()) {
Dentry *olddn = in->get_first_parent();
assert(olddn->dir != dir || olddn->name != name);
- unlink(olddn, false);
+ unlink(olddn, false, false);
}
in->dn_set.insert(dn);
@@ -2150,7 +2150,7 @@ Dentry* Client::link(Dir *dir, const string& name, Inode *in, Dentry *dn)
return dn;
}
-void Client::unlink(Dentry *dn, bool keepdir)
+void Client::unlink(Dentry *dn, bool keepdir, bool keepdentry)
{
Inode *in = dn->inode;
ldout(cct, 15) << "unlink dir " << dn->dir->parent_inode << " '" << dn->name << "' dn " << dn
@@ -2166,17 +2166,21 @@ void Client::unlink(Dentry *dn, bool keepdir)
ldout(cct, 20) << "unlink inode " << in << " parents now " << in->dn_set << dendl;
put_inode(in);
}
-
- // unlink from dir
- dn->dir->dentries.erase(dn->name);
- dn->dir->dentry_map.erase(dn->name);
- if (dn->dir->is_empty() && !keepdir)
- close_dir(dn->dir);
- dn->dir = 0;
- // delete den
- lru.lru_remove(dn);
- dn->put();
+ if (!keepdentry) {
+ ldout(cct, 15) << "unlink removing '" << dn->name << "' dn " << dn << dendl;
+
+ // unlink from dir
+ dn->dir->dentries.erase(dn->name);
+ dn->dir->dentry_map.erase(dn->name);
+ if (dn->dir->is_empty() && !keepdir)
+ close_dir(dn->dir);
+ dn->dir = 0;
+
+ // delete den
+ lru.lru_remove(dn);
+ dn->put();
+ }
}
@@ -7241,7 +7245,7 @@ int Client::_unlink(Inode *dir, const char *name, int uid, int gid)
if (res == 0) {
if (dir->dir && dir->dir->dentries.count(name)) {
Dentry *dn = dir->dir->dentries[name];
- unlink(dn, false);
+ unlink(dn, false, false);
}
}
ldout(cct, 10) << "unlink result is " << res << dendl;
@@ -7303,7 +7307,7 @@ int Client::_rmdir(Inode *dir, const char *name, int uid, int gid)
if (dn->inode->dir && dn->inode->dir->is_empty() &&
(dn->inode->dn_set.size() == 1))
close_dir(dn->inode->dir); // FIXME: maybe i shoudl proactively hose the whole subtree from cache?
- unlink(dn, false);
+ unlink(dn, false, false);
}
}
diff --git a/src/client/Client.h b/src/client/Client.h
index 22c6852baa6..42c81296a00 100644
--- a/src/client/Client.h
+++ b/src/client/Client.h
@@ -360,7 +360,7 @@ protected:
* a new inode to a pre-created Dentry
*/
Dentry* link(Dir *dir, const string& name, Inode *in, Dentry *dn);
- void unlink(Dentry *dn, bool keepdir);
+ void unlink(Dentry *dn, bool keepdir, bool keepdentry);
// path traversal for high-level interface
Inode *cwd;