From: John Spray Date: Wed, 3 Sep 2014 01:00:33 +0000 (+0100) Subject: client: fix crash in trim_caps X-Git-Tag: v0.86~68^2~12 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=c328486f246f100ac4fc23c9337f2cbb92d28105;p=ceph.git client: fix crash in trim_caps In a75af4c2, procedure was added to invalidate root's dentries if the trimming failed to free enough caps. This would sometimes crash because root->dir wasn't necessarily open. Fix by only doing it if root dir is open, though I suspect this may not be the end of it... Signed-off-by: John Spray --- diff --git a/src/client/Client.cc b/src/client/Client.cc index 667b700b004e..d749dd05a383 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -3171,10 +3171,12 @@ void Client::trim_caps(MetaSession *s, int max) set::iterator q = in->dn_set.begin(); while (q != in->dn_set.end()) { Dentry *dn = *q++; - if (dn->lru_is_expireable()) + if (dn->lru_is_expireable()) { trim_dentry(dn); - else + } else { + ldout(cct, 20) << " not expirable: " << dn->name << dendl; all = false; + } } if (all) trimmed++; @@ -3191,11 +3193,17 @@ void Client::trim_caps(MetaSession *s, int max) // notify kernel to invalidate top level directory entries. As a side effect, // unused inodes underneath these entries get pruned. if (dentry_invalidate_cb && s->caps.size() > max) { - for (ceph::unordered_map::iterator p = root->dir->dentries.begin(); - p != root->dir->dentries.end(); - ++p) { - if (p->second->inode) - _schedule_invalidate_dentry_callback(p->second, false); + assert(root); + if (root->dir) { + for (ceph::unordered_map::iterator p = root->dir->dentries.begin(); + p != root->dir->dentries.end(); + ++p) { + if (p->second->inode) + _schedule_invalidate_dentry_callback(p->second, false); + } + } else { + // This seems unnatural, as long as we are holding caps they must be on + // some descendent of the root, so why don't we have the root open? } } }