From: Patrick Donnelly Date: Tue, 11 Mar 2025 14:28:01 +0000 (-0400) Subject: client: avoid multiple calls to path_walk X-Git-Tag: v20.3.0~374^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=af8d267e5f8123eaf3cb311b7d608025468429f9;p=ceph.git client: avoid multiple calls to path_walk When we wrap a dname after a path walk, we cannot do another path walk. Originally this method was setup to permit that but with (upcoming) encryption it cannot work. The dname from the path_walk is in the encrypted namespace so we cannot do another lookup in a second path_walk. Signed-off-by: Patrick Donnelly --- diff --git a/src/client/Client.cc b/src/client/Client.cc index 5090e718268..f4f8b08befa 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -7892,7 +7892,13 @@ int Client::do_mkdirat(int dirfd, const char *relpath, mode_t mode, const UserPe if (r < 0) { return r; } - return _mkdir(dirinode.get(), relpath, mode, perm, 0, {}, std::move(alternate_name)); + + walk_dentry_result wdr; + if (int rc = path_walk(dirinode, filepath(relpath), &wdr, perm, {.require_target = false}); rc < 0) { + return rc; + } + + return _mkdir(wdr, mode, perm, 0, {}, std::move(alternate_name)); } int Client::mkdirs(const char *relpath, mode_t mode, const UserPerm& perms) @@ -7914,7 +7920,7 @@ int Client::mkdirs(const char *relpath, mode_t mode, const UserPerm& perms) if (int rc = path_walk(cwd, path, &wdr, perms, {.followsym = false}); rc < 0) { if (rc == -ENOENT) { InodeRef in; - rc = _mkdir(wdr.diri.get(), wdr.dname.c_str(), mode, perms, &in); + rc = _mkdir(wdr, mode, perms, &in); switch (rc) { case 0: case EEXIST: @@ -13055,12 +13061,15 @@ int Client::mksnap(const char *relpath, const char *name, const UserPerm& perm, return -ENOTCONN; std::scoped_lock l(client_lock); - InodeRef in; - if (int rc = path_walk(cwd, filepath(relpath), &in, perm, {}); rc < 0) { + walk_dentry_result wdr; + if (int rc = path_walk(cwd, filepath(relpath), &wdr, perm, {}); rc < 0) { return rc; } - auto snapdir = open_snapdir(in.get()); - return _mkdir(snapdir.get(), name, mode, perm, nullptr, metadata); + auto snapdir = open_snapdir(wdr.target); + if (int rc = path_walk(std::move(snapdir), filepath(name), &wdr, perm, {.require_target = false}); rc < 0) { + return rc; + } + return _mkdir(wdr, mode, perm, nullptr, metadata); } int Client::rmsnap(const char *relpath, const char *name, const UserPerm& perms, bool check_perms) @@ -14873,18 +14882,15 @@ int Client::_create(const walk_dentry_result& wdr, int flags, mode_t mode, return res; } -int Client::_mkdir(Inode *dir, const char *name, mode_t mode, const UserPerm& perm, +int Client::_mkdir(const walk_dentry_result& wdr, mode_t mode, const UserPerm& perm, InodeRef *inp, const std::map &metadata, std::string alternate_name) { - ldout(cct, 8) << "_mkdir(" << dir->ino << " " << name << ", 0" << oct - << mode << dec << ", uid " << perm.uid() + ldout(cct, 8) << "_mkdir(" << wdr << ", 0o" << std::oct << mode << std::dec + << ", uid " << perm.uid() << ", gid " << perm.gid() << ")" << dendl; - walk_dentry_result wdr; - if (int rc = path_walk(dir, filepath(name), &wdr, perm, {.require_target = false}); rc < 0) { - return rc; - } else if (rc == 0 && wdr.target) { + if (wdr.target) { return -EEXIST; } @@ -14963,8 +14969,13 @@ int Client::ll_mkdir(Inode *parent, const char *name, mode_t mode, std::scoped_lock lock(client_lock); + walk_dentry_result wdr; + if (int rc = path_walk(parent, filepath(name), &wdr, perm, {.require_target = false}); rc < 0) { + return rc; + } + InodeRef in; - int r = _mkdir(parent, name, mode, perm, &in); + int r = _mkdir(wdr, mode, perm, &in); if (r == 0) { fill_stat(in, attr); _ll_get(in.get()); @@ -14994,8 +15005,13 @@ int Client::ll_mkdirx(Inode *parent, const char *name, mode_t mode, Inode **out, std::scoped_lock lock(client_lock); + walk_dentry_result wdr; + if (int rc = path_walk(parent, filepath(name), &wdr, perms, {.require_target = false}); rc < 0) { + return rc; + } + InodeRef in; - int r = _mkdir(parent, name, mode, perms, &in); + int r = _mkdir(wdr, mode, perms, &in); if (r == 0) { fill_statx(in, statx_to_mask(flags, want), stx); _ll_get(in.get()); diff --git a/src/client/Client.h b/src/client/Client.h index 23376052f9e..d023172c5c0 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -1701,7 +1701,7 @@ private: int _link(Inode *diri_from, const char* path_from, Inode* diri_to, const char* path_to, const UserPerm& perm, std::string alternate_name); int _unlink(Inode *dir, const char *name, const UserPerm& perm); int _rename(Inode *olddir, const char *oname, Inode *ndir, const char *nname, const UserPerm& perm, std::string alternate_name); - int _mkdir(Inode *dir, const char *name, mode_t mode, const UserPerm& perm, + int _mkdir(const walk_dentry_result& wdr, mode_t mode, const UserPerm& perm, InodeRef *inp = 0, const std::map &metadata={}, std::string alternate_name=""); int _rmdir(Inode *dir, const char *name, const UserPerm& perms, bool check_perms=true);