From 95edad2d058575231bb9b5468559f7b42667f40e Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 3 Jan 2017 12:56:51 -0500 Subject: [PATCH] client: don't use special faked-up inode for /.. The CEPH_INO_DOTDOT thing is quite strange. Under most OS (Linux included), the parent of the root is itself. IOW, at the root, '.' and '..' refer to the same inode. Change the ceph client to do the same, as this allows users to get valid stat info for '..', as well as elimnating some special-casing. Also in several places, we're checking dn_set.empty as an indicator of being the root. While that is true for the root, it's also true for unlinked directories. This patch has treats them the same. An unlinked directory will be reparented to itself, effectively acting as a root of its own. Fixes: http://tracker.ceph.com/issues/18408 Signed-off-by: Jeff Layton (cherry picked from commit 30d4ca01db0de9a1e12658793ba9bf9faf0331dd) --- src/client/Client.cc | 25 ++++++++----------------- src/include/ceph_fs.h | 1 - 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/src/client/Client.cc b/src/client/Client.cc index 282c57bb18165..c09af04b0c3a2 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -5876,7 +5876,7 @@ int Client::_lookup(Inode *dir, const string& dname, int mask, if (dname == "..") { if (dir->dn_set.empty()) - r = -ENOENT; + *target = dir; else *target = dir->get_first_parent()->dir->parent_inode; //dirs can't be hard-linked goto done; @@ -7216,16 +7216,14 @@ int Client::readdir_r_cb(dir_result_t *d, add_dirent_cb_t cb, void *p) if (dirp->offset == 1) { ldout(cct, 15) << " including .." << dendl; uint64_t next_off = 2; - if (!diri->dn_set.empty()) { - InodeRef& in = diri->get_first_parent()->inode; - fill_stat(in, &st); - fill_dirent(&de, "..", S_IFDIR, st.st_ino, next_off); - } else { - /* must be at the root (no parent), - * so we add the dotdot with a special inode (3) */ - fill_dirent(&de, "..", S_IFDIR, CEPH_INO_DOTDOT, next_off); - } + InodeRef in; + if (diri->dn_set.empty()) + in = diri; + else + in = diri->get_first_parent()->inode; + fill_stat(in, &st); + fill_dirent(&de, "..", S_IFDIR, st.st_ino, next_off); client_lock.Unlock(); int r = cb(p, &de, &st, -1, next_off); @@ -9614,13 +9612,6 @@ int Client::ll_getattr(Inode *in, struct stat *attr, int uid, int gid) tout(cct) << "ll_getattr" << std::endl; tout(cct) << vino.ino.val << std::endl; - /* special case for dotdot (..) */ - if (vino.ino.val == CEPH_INO_DOTDOT) { - attr->st_mode = S_IFDIR | 0755; - attr->st_nlink = 2; - return 0; - } - int res; if (vino.snapid < CEPH_NOSNAP) res = 0; diff --git a/src/include/ceph_fs.h b/src/include/ceph_fs.h index e8f5f2f5d576d..3f1128677f139 100644 --- a/src/include/ceph_fs.h +++ b/src/include/ceph_fs.h @@ -28,7 +28,6 @@ #define CEPH_INO_ROOT 1 #define CEPH_INO_CEPH 2 /* hidden .ceph dir */ -#define CEPH_INO_DOTDOT 3 /* used by ceph fuse for parent (..) */ #define CEPH_INO_LOST_AND_FOUND 4 /* reserved ino for use in recovery */ /* arbitrary limit on max # of monitors (cluster of 3 is typical) */ -- 2.39.5