diff options
author | Sage Weil <sage@inktank.com> | 2013-05-15 11:03:41 -0700 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2013-06-24 21:21:47 -0700 |
commit | 14af8c44582f2cefb179a9854053c17aac3ece92 (patch) | |
tree | 2bd1dc632d307dad06549cf34092531f9f316c2a | |
parent | 5dfe5e502be1156788878714e7e53d31488d26f0 (diff) | |
download | ceph-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.cc | 52 | ||||
-rw-r--r-- | src/client/Client.h | 2 |
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; |