]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
cephfs: add ceph_may_delete function
authorLucian Petrut <lpetrut@cloudbasesolutions.com>
Fri, 26 Feb 2021 08:32:38 +0000 (08:32 +0000)
committerLucian Petrut <lpetrut@cloudbasesolutions.com>
Fri, 5 Mar 2021 07:59:49 +0000 (07:59 +0000)
We're adding a new libcephfs function: ceph_may_delete. It checks
if the mount permissions allow deleting a file or directory, without
actually deleting it.

This will allow us to drop the redundant permission checks at
ceph-dokan level, saving about 1500 LOC.

Note that the "DeleteFile" Dokan callback expects us to say if a
delete operation is allowed. The "Cleanup" callback is supposed
to perform the actual file or directory deletion.

Signed-off-by: Lucian Petrut <lpetrut@cloudbasesolutions.com>
src/client/Client.cc
src/client/Client.h
src/include/cephfs/libcephfs.h
src/libcephfs.cc

index 4b5aec4b3efb7545c8789155a0eca2013af422b2..b7e5fca981c9f77b5c15033cec46b1958b3a96cd 100644 (file)
@@ -5771,6 +5771,31 @@ out:
   return r;
 }
 
+int Client::may_delete(const char *relpath, const UserPerm& perms) {
+  ldout(cct, 20) << __func__ << " " << relpath << "; " << perms << dendl;
+
+  RWRef_t mref_reader(mount_state, CLIENT_MOUNTING);
+  if (!mref_reader.is_state_satisfied())
+    return -ENOTCONN;
+
+  filepath path(relpath);
+  string name = path.last_dentry();
+  path.pop_dentry();
+  InodeRef dir;
+
+  std::scoped_lock lock(client_lock);
+  int r = path_walk(path, &dir, perms);
+  if (r < 0)
+    return r;
+  if (cct->_conf->client_permissions) {
+    int r = may_delete(dir.get(), name.c_str(), perms);
+    if (r < 0)
+      return r;
+  }
+
+  return 0;
+}
+
 int Client::may_hardlink(Inode *in, const UserPerm& perms)
 {
   ldout(cct, 20) << __func__ << " " << *in << "; " << perms << dendl;
index 401d2fefaadd77973f8fdec22b321a63238008a5..40ab802899beafa5c5b58868661bad1fe2f3bb5b 100644 (file)
@@ -369,6 +369,7 @@ public:
   loff_t telldir(dir_result_t *dirp);
   void seekdir(dir_result_t *dirp, loff_t offset);
 
+  int may_delete(const char *relpath, const UserPerm& perms);
   int link(const char *existing, const char *newname, const UserPerm& perm, std::string alternate_name="");
   int unlink(const char *path, const UserPerm& perm);
   int rename(const char *from, const char *to, const UserPerm& perm, std::string alternate_name="");
index d3dbb2f84297dc4b053133fbb853149d514169c2..6466da6177f920a6d2b84ba07987e8a96ff218ba 100644 (file)
@@ -746,6 +746,16 @@ int ceph_symlink(struct ceph_mount_info *cmount, const char *existing, const cha
  * @{
  */
 
+
+/**
+ * Checks if deleting a file, link or directory is allowed.
+ *
+ * @param cmount the ceph mount handle to use.
+ * @param path the path of the file, link or directory.
+ * @returns 0 on success or negative error code on failure.
+ */
+int ceph_may_delete(struct ceph_mount_info *cmount, const char *path);
+
 /**
  * Removes a file, link, or symbolic link.  If the file/link has multiple links to it, the
  * file will not disappear from the namespace until all references to it are removed.
index 806ad7a0a994e481c532db05e3f23d9b632ff832..948d80442f8f50caabe747b3fe6175f76abddabd 100644 (file)
@@ -706,6 +706,13 @@ extern "C" void ceph_seekdir(struct ceph_mount_info *cmount, struct ceph_dir_res
   cmount->get_client()->seekdir(reinterpret_cast<dir_result_t*>(dirp), offset);
 }
 
+extern "C" int ceph_may_delete(struct ceph_mount_info *cmount, const char *path)
+{
+  if (!cmount->is_mounted())
+    return -ENOTCONN;
+  return cmount->get_client()->may_delete(path, cmount->default_perms);
+}
+
 extern "C" int ceph_link (struct ceph_mount_info *cmount, const char *existing,
                          const char *newname)
 {