diff --git a/src/client/Client.cc b/src/client/Client.cc index 6b34e4a..b303e80 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -6077,15 +6081,13 @@ int Client::_do_lookup(Inode *dir, const string& name, int mask, return r; } -int Client::_lookup(Inode *dir, const string& dname, int mask, InodeRef *target, - const UserPerm& perms) +int Client::_lookup_dcache(Inode *dir, const string& dname, int mask, InodeRef *target, + const UserPerm& perms) { - int r = 0; Dentry *dn = NULL; if (!dir->is_dir()) { - r = -ENOTDIR; - goto done; + return -ENOTDIR; } if (dname == "..") { @@ -6093,23 +6095,22 @@ int Client::_lookup(Inode *dir, const string& dname, int mask, InodeRef *target, *target = dir; else *target = dir->get_first_parent()->dir->parent_inode; //dirs can't be hard-linked - goto done; + return 0; } if (dname == ".") { *target = dir; - goto done; + return 0; } if (dname.length() > NAME_MAX) { - r = -ENAMETOOLONG; - goto done; + return -ENAMETOOLONG; } if (dname == cct->_conf->client_snapdir && dir->snapid == CEPH_NOSNAP) { *target = open_snapdir(dir); - goto done; + return 0; } if (dir->dir && @@ -6159,19 +6160,23 @@ int Client::_lookup(Inode *dir, const string& dname, int mask, InodeRef *target, return -ENOENT; } } + return -EAGAIN; - r = _do_lookup(dir, dname, mask, target, perms); - goto done; - - hit_dn: +hit_dn: if (dn->inode) { *target = dn->inode; - } else { - r = -ENOENT; } touch_dn(dn); + return dn->inode ? 0 : -ENOENT; +} + +int Client::_lookup(Inode *dir, const string& dname, int mask, InodeRef *target, + const UserPerm& perms) +{ + int r = _lookup_dcache(dir, dname, mask, target, perms); + if (r == -EAGAIN) + r = _do_lookup(dir, dname, mask, target, perms); - done: if (r < 0) ldout(cct, 10) << "_lookup " << *dir << " " << dname << " = " << r << dendl; else @@ -10076,12 +10081,22 @@ int Client::ll_lookup(Inode *parent, const char *name, struct stat *attr, string dname(name); InodeRef in; - r = _lookup(parent, dname, CEPH_STAT_CAP_INODE_ALL, &in, perms); - if (r < 0) { + r = _lookup_dcache(parent, dname, 0, &in, perms); + if (r < 0 && r != -EAGAIN) { attr->st_ino = 0; goto out; } + // Avoid lookup CEPH_STAT_CAP_INODE_ALL when user of libcephfs + // has already cached the inode. + if (r == -EAGAIN || in->ll_ref == 0) { + r = _lookup(parent, dname, CEPH_STAT_CAP_INODE_ALL, &in, perms); + if (r < 0) { + attr->st_ino = 0; + goto out; + } + } + assert(in); fill_stat(in, attr); _ll_get(in.get()); diff --git a/src/client/Client.h b/src/client/Client.h index b6369a2..23c752b 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -776,6 +776,8 @@ private: int _do_lookup(Inode *dir, const string& name, int mask, InodeRef *target, const UserPerm& perms); + int _lookup_dcache(Inode *dir, const string& dname, int mask, InodeRef *target, + const UserPerm& perm); int _lookup(Inode *dir, const string& dname, int mask, InodeRef *target, const UserPerm& perm);