]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
client: avoid multiple calls to path_walk 62230/head
authorPatrick Donnelly <pdonnell@ibm.com>
Tue, 11 Mar 2025 14:28:01 +0000 (10:28 -0400)
committerPatrick Donnelly <pdonnell@ibm.com>
Tue, 11 Mar 2025 19:05:07 +0000 (15:05 -0400)
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 <pdonnell@ibm.com>
src/client/Client.cc
src/client/Client.h

index 5090e7182687ed918c7bc3c869da91cde8d8ade2..f4f8b08befa78e2601f34d998f3f5c41985853e4 100644 (file)
@@ -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<std::string, std::string> &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());
index 23376052f9efc9020f2778603005ca95f828452d..d023172c5c0d9fd248b4d3062ce7eea2aefbee72 100644 (file)
@@ -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<std::string, std::string> &metadata={},
              std::string alternate_name="");
   int _rmdir(Inode *dir, const char *name, const UserPerm& perms, bool check_perms=true);