From: Yan, Zheng Date: Fri, 21 Feb 2014 06:37:51 +0000 (+0800) Subject: client: check inode's cap when looking up dentry X-Git-Tag: v0.79~179^2~3 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=23de48b258f5c4147496051dfd689e0392af2d2e;p=ceph.git client: check inode's cap when looking up dentry Some inodes in readdir reply may have no caps. Getattr mds request for these inodes can return -ESTALE. The fix is consider dentry that links to inode with no caps as invalid. Invalid dentry causes a lookup request to send to the mds, the MDS will send caps back. Signed-off-by: Yan, Zheng --- diff --git a/src/client/Client.cc b/src/client/Client.cc index 5d2bd56ce216..e75262ced1aa 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -4154,30 +4154,34 @@ int Client::_lookup(Inode *dir, const string& dname, Inode **target) << " seq " << dn->lease_seq << dendl; - // is dn lease valid? - utime_t now = ceph_clock_now(cct); - if (dn->lease_mds >= 0 && - dn->lease_ttl > now && - mds_sessions.count(dn->lease_mds)) { - MetaSession *s = mds_sessions[dn->lease_mds]; - if (s->cap_ttl > now && - s->cap_gen == dn->lease_gen) { + if (!dn->inode || dn->inode->is_any_caps()) { + // is dn lease valid? + utime_t now = ceph_clock_now(cct); + if (dn->lease_mds >= 0 && + dn->lease_ttl > now && + mds_sessions.count(dn->lease_mds)) { + MetaSession *s = mds_sessions[dn->lease_mds]; + if (s->cap_ttl > now && + s->cap_gen == dn->lease_gen) { + *target = dn->inode; + // touch this mds's dir cap too, even though we don't _explicitly_ use it here, to + // make trim_caps() behave. + dir->try_touch_cap(dn->lease_mds); + touch_dn(dn); + goto done; + } + ldout(cct, 20) << " bad lease, cap_ttl " << s->cap_ttl << ", cap_gen " << s->cap_gen + << " vs lease_gen " << dn->lease_gen << dendl; + } + // dir lease? + if (dir->caps_issued_mask(CEPH_CAP_FILE_SHARED) && + dn->cap_shared_gen == dir->shared_gen) { *target = dn->inode; - // touch this mds's dir cap too, even though we don't _explicitly_ use it here, to - // make trim_caps() behave. - dir->try_touch_cap(dn->lease_mds); touch_dn(dn); goto done; } - ldout(cct, 20) << " bad lease, cap_ttl " << s->cap_ttl << ", cap_gen " << s->cap_gen - << " vs lease_gen " << dn->lease_gen << dendl; - } - // dir lease? - if (dir->caps_issued_mask(CEPH_CAP_FILE_SHARED) && - dn->cap_shared_gen == dir->shared_gen) { - *target = dn->inode; - touch_dn(dn); - goto done; + } else { + ldout(cct, 20) << " no cap on " << dn->inode->vino() << dendl; } } else { // can we conclude ENOENT locally?