From fb65f530001699d7be799c0dfe4407059aadb1ef Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 1 Feb 2021 11:04:07 -0500 Subject: [PATCH] client: add ceph_ll_lookup_vino Add a new API function for looking up an inode via a vinodeno_t. This should give ganesha a way to reliably look up snapshot inodes. We do need to add some special handling for CEPH_SNAPDIRs. If we're looking for one, then find the non-snapped parent, and then call open_snapdir to get the snapdir inode. Also, have the function check the local cache before calling the MDS to look up an inode. Fixes: https://tracker.ceph.com/issues/48991 Signed-off-by: Jeff Layton (cherry picked from commit 70622079c2ec55222a139fa5042902e0b19bd839) Conflicts: src/client/Client.cc --- src/client/Client.cc | 49 +++++++++++++++++++++++++++++----- src/client/Client.h | 1 + src/include/cephfs/libcephfs.h | 4 +++ src/libcephfs.cc | 8 ++++++ 4 files changed, 55 insertions(+), 7 deletions(-) diff --git a/src/client/Client.cc b/src/client/Client.cc index 0b5d386e14ebe..85686e703a095 100755 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -10904,21 +10904,56 @@ int Client::ll_lookup(Inode *parent, const char *name, struct stat *attr, return r; } -int Client::ll_lookup_inode( - struct inodeno_t ino, +int Client::ll_lookup_vino( + vinodeno_t vino, const UserPerm& perms, Inode **inode) { ceph_assert(inode != NULL); - std::lock_guard lock(client_lock); - ldout(cct, 3) << "ll_lookup_inode " << ino << dendl; - + if (unmounting) return -ENOTCONN; - // Num1: get inode and *inode + std::lock_guard lock(client_lock); + ldout(cct, 3) << __func__ << vino << dendl; + + // Check the cache first + unordered_map::iterator p = inode_map.find(vino); + if (p != inode_map.end()) { + *inode = p->second; + _ll_get(*inode); + return 0; + } + + uint64_t snapid = vino.snapid; + + // for snapdir, find the non-snapped dir inode + if (snapid == CEPH_SNAPDIR) + vino.snapid = CEPH_NOSNAP; + + int r = _lookup_vino(vino, perms, inode); + if (r) + return r; + ceph_assert(*inode != NULL); + + if (snapid == CEPH_SNAPDIR) { + Inode *tmp = *inode; + + // open the snapdir and put the inode ref + *inode = open_snapdir(tmp); + _ll_forget(tmp, 1); + _ll_get(*inode); + } + return 0; +} + +int Client::ll_lookup_inode( + struct inodeno_t ino, + const UserPerm& perms, + Inode **inode) +{ vinodeno_t vino(ino, CEPH_NOSNAP); - return _lookup_vino(vino, perms, inode); + return ll_lookup_vino(vino, perms, inode); } int Client::ll_lookupx(Inode *parent, const char *name, Inode **out, diff --git a/src/client/Client.h b/src/client/Client.h index fdd250e197e18..13bbc29b235c2 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -480,6 +480,7 @@ public: int ll_lookup(Inode *parent, const char *name, struct stat *attr, Inode **out, const UserPerm& perms); int ll_lookup_inode(struct inodeno_t ino, const UserPerm& perms, Inode **inode); + int ll_lookup_vino(vinodeno_t vino, const UserPerm& perms, Inode **inode); int ll_lookupx(Inode *parent, const char *name, Inode **out, struct ceph_statx *stx, unsigned want, unsigned flags, const UserPerm& perms); diff --git a/src/include/cephfs/libcephfs.h b/src/include/cephfs/libcephfs.h index 94c80635030d1..f8eff8e88f762 100644 --- a/src/include/cephfs/libcephfs.h +++ b/src/include/cephfs/libcephfs.h @@ -1621,6 +1621,10 @@ int ceph_debug_get_file_caps(struct ceph_mount_info *cmount, const char *path); /* Low Level */ struct Inode *ceph_ll_get_inode(struct ceph_mount_info *cmount, vinodeno_t vino); + +int ceph_ll_lookup_vino(struct ceph_mount_info *cmount, vinodeno_t vino, + Inode **inode); + int ceph_ll_lookup_inode( struct ceph_mount_info *cmount, struct inodeno_t ino, diff --git a/src/libcephfs.cc b/src/libcephfs.cc index c18323be43f91..5ab93541d5e39 100644 --- a/src/libcephfs.cc +++ b/src/libcephfs.cc @@ -1587,6 +1587,14 @@ extern "C" struct Inode *ceph_ll_get_inode(class ceph_mount_info *cmount, } +extern "C" int ceph_ll_lookup_vino( + struct ceph_mount_info *cmount, + vinodeno_t vino, + Inode **inode) +{ + return (cmount->get_client())->ll_lookup_vino(vino, cmount->default_perms, inode); +} + /** * Populates the client cache with the requested inode, and its * parent dentry. -- 2.39.5