From e635fb0cc532d687af742aedb2f2d505264f46d9 Mon Sep 17 00:00:00 2001 From: Patrick Donnelly Date: Tue, 11 Mar 2025 10:28:01 -0400 Subject: [PATCH] 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 (cherry picked from commit af8d267e5f8123eaf3cb311b7d608025468429f9) --- src/client/Client.cc | 46 +++++++++++++++++++++++++++++--------------- src/client/Client.h | 2 +- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/client/Client.cc b/src/client/Client.cc index 63fc0dec003..674a2a60636 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -7873,7 +7873,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) @@ -7895,7 +7901,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: @@ -12988,12 +12994,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) @@ -14806,18 +14815,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; } @@ -14896,8 +14902,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()); @@ -14927,8 +14938,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 0f2cbb172c6..2337d9a027e 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -1683,7 +1683,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); -- 2.39.5