]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: wire up vxattr for changing charmap
authorPatrick Donnelly <pdonnell@redhat.com>
Mon, 26 Aug 2024 16:22:35 +0000 (12:22 -0400)
committerPatrick Donnelly <pdonnell@ibm.com>
Thu, 27 Feb 2025 18:41:55 +0000 (13:41 -0500)
Signed-off-by: Patrick Donnelly <pdonnell@redhat.com>
Fixes: https://tracker.ceph.com/issues/66373
src/mds/CInode.cc
src/mds/CInode.h
src/mds/Server.cc
src/mds/Server.h

index 977f4b0876fe0e2ff3c36379cb846a60967edd15..e83b562a1f96a84704f01f7e8617307d4ad685a9 100644 (file)
@@ -315,6 +315,9 @@ ostream& operator<<(ostream& out, const CInode& in)
   if (in.get_inode()->get_quiesce_block()) {
     out << " qblock";
   }
+  if (in.get_inode()->optmetadata.size() > 0) {
+    out << " " << in.get_inode()->optmetadata;
+  }
 
   out << " " << &in;
   out << "]";
@@ -5549,6 +5552,16 @@ void CInode::set_export_pin(mds_rank_t rank)
   maybe_export_pin(true);
 }
 
+charmap_md_t<mempool::mds_co::pool_allocator> const* CInode::get_charmap() const
+{
+  dout(25) << __func__ << ": " << *this << dendl;
+  auto const& pi = get_projected_inode();
+  if (pi->has_charmap()) {
+    return &pi->get_charmap();
+  }
+  return nullptr;
+}
+
 mds_rank_t CInode::get_export_pin(bool inherit) const
 {
   auto&& balancer = mdcache->mds->balancer;
index 8ae1d5f71687b007d2e7e7fe4c2ffa1452b3731b..f70e01312cc3db78a9451718eabb7ed53aae0767 100644 (file)
@@ -1013,6 +1013,8 @@ class CInode : public MDSCacheObject, public InodeStoreBase, public Counter<CIno
     return !projected_parent.empty();
   }
 
+  charmap_md_t<mempool::mds_co::pool_allocator> const* get_charmap() const;
+
   mds_rank_t get_export_pin(bool inherit=true) const;
   void check_pin_policy(mds_rank_t target);
   void set_export_pin(mds_rank_t rank);
index 12ae35eb2606db3e20e47a022d7ae0af0993cf9c..a410b999102c095ca5c33f981cfa610433563512 100644 (file)
@@ -5706,12 +5706,11 @@ void Server::handle_client_setlayout(const MDRequestRef& mdr)
   journal_and_reply(mdr, cur, 0, le, new C_MDS_inode_update_finish(this, mdr, cur));
 }
 
-bool Server::xlock_policylock(const MDRequestRef& mdr, CInode *in, bool want_layout, bool xlock_snaplock)
+bool Server::xlock_policylock(const MDRequestRef& mdr, CInode *in, bool want_layout, bool xlock_snaplock, MutationImpl::LockOpVec lov)
 {
   if (mdr->locking_state & MutationImpl::ALL_LOCKED)
     return true;
 
-  MutationImpl::LockOpVec lov;
   lov.add_xlock(&in->policylock);
   if (xlock_snaplock)
     lov.add_xlock(&in->snaplock);
@@ -6501,6 +6500,136 @@ void Server::handle_client_setvxattr(const MDRequestRef& mdr, CInode *cur)
     auto pi = cur->project_inode(mdr);
     cur->setxattr_ephemeral_dist(val);
     pip = pi.inode.get();
+  } else if (name == "ceph.dir.charmap"sv) {
+    // inheritance / InodeStat
+    if (!cur->is_dir() || cur->is_root()) {
+      respond_to_request(mdr, -EINVAL);
+      return;
+    }
+
+    dout(25) << "not root, is dir" << dendl;
+
+    MutationImpl::LockOpVec lov;
+    lov.add_rdlock(&cur->filelock);   // to verify it's empty
+    if (!xlock_policylock(mdr, cur, false, false, std::move(lov)))
+      return;
+
+    if (_dir_is_nonempty(mdr, cur)) {
+      respond_to_request(mdr, -ENOTEMPTY);
+      return;
+    }
+    if (cur->snaprealm && cur->snaprealm->srnode.snaps.size()) {
+      respond_to_request(mdr, -ENOTEMPTY);
+      return;
+    }
+
+    if (is_rmxattr) {
+      if (!cur->get_projected_inode()->has_charmap()) {
+        respond_to_request(mdr, 0);
+        return;
+      }
+      auto pi = cur->project_inode(mdr);
+      pip = pi.inode.get();
+      dout(20) << "deleting charmap metadata" << dendl;
+      pip->del_charmap();
+    } else {
+      respond_to_request(mdr, -EINVAL);
+      return;
+    }
+  } else if (name == "ceph.dir.casesensitive"sv) {
+    if (is_rmxattr) {
+      value = "1";
+    }
+
+    MutationImpl::LockOpVec lov;
+    lov.add_rdlock(&cur->filelock);   // to verify it's empty
+    if (!xlock_policylock(mdr, cur, false, false, std::move(lov)))
+      return;
+
+    if (_dir_is_nonempty(mdr, cur)) {
+      respond_to_request(mdr, -ENOTEMPTY);
+      return;
+    }
+    if (cur->snaprealm && cur->snaprealm->srnode.snaps.size()) {
+      respond_to_request(mdr, -ENOTEMPTY);
+      return;
+    }
+
+    bool val;
+    try {
+      val = boost::lexical_cast<bool>(value);
+    } catch (boost::bad_lexical_cast const&) {
+      dout(10) << "bad vxattr value, unable to parse bool for " << name << dendl;
+      respond_to_request(mdr, -EINVAL);
+      return;
+    }
+
+    auto pi = cur->project_inode(mdr);
+    pip = pi.inode.get();
+    auto& c = pip->set_charmap();
+    if (val) {
+      c.mark_casesensitive();
+      dout(20) << "marking case sensitive: " << c << dendl;
+    } else  {
+      c.mark_caseinsensitive();
+      dout(20) << "marking case insensitive: " << c << dendl;
+    }
+  } else if (name == "ceph.dir.normalization"sv) {
+    if (is_rmxattr) {
+      value = "";
+    }
+
+    MutationImpl::LockOpVec lov;
+    lov.add_rdlock(&cur->filelock);   // to verify it's empty
+    if (!xlock_policylock(mdr, cur, false, false, std::move(lov)))
+      return;
+
+    if (_dir_is_nonempty(mdr, cur)) {
+      respond_to_request(mdr, -ENOTEMPTY);
+      return;
+    }
+    if (cur->snaprealm && cur->snaprealm->srnode.snaps.size()) {
+      respond_to_request(mdr, -ENOTEMPTY);
+      return;
+    }
+
+    auto pi = cur->project_inode(mdr);
+    pip = pi.inode.get();
+    auto& c = pip->set_charmap();
+    if (value.size() > 0) {
+      c.set_normalization(value);
+    } else {
+      c.set_normalization(c.get_default_normalization());
+    }
+    dout(20) << "set normalization: " << c << dendl;
+  } else if (name == "ceph.dir.encoding"sv) {
+    if (is_rmxattr) {
+      value = "";
+    }
+
+    MutationImpl::LockOpVec lov;
+    lov.add_rdlock(&cur->filelock);   // to verify it's empty
+    if (!xlock_policylock(mdr, cur, false, false, std::move(lov)))
+      return;
+
+    if (_dir_is_nonempty(mdr, cur)) {
+      respond_to_request(mdr, -ENOTEMPTY);
+      return;
+    }
+    if (cur->snaprealm && cur->snaprealm->srnode.snaps.size()) {
+      respond_to_request(mdr, -ENOTEMPTY);
+      return;
+    }
+
+    auto pi = cur->project_inode(mdr);
+    pip = pi.inode.get();
+    auto& c = pip->set_charmap();
+    if (value.size() > 0) {
+      c.set_encoding(value);
+    } else {
+      c.set_encoding(c.get_default_encoding());
+    }
+    dout(20) << "set encoding: " << c << dendl;
   } else {
     dout(10) << " unknown vxattr " << name << dendl;
     respond_to_request(mdr, -EINVAL);
@@ -7004,6 +7133,41 @@ void Server::handle_client_getvxattr(const MDRequestRef& mdr)
     }
   } else if (xattr_name == "ceph.quiesce.block"sv) {
     *css << cur->get_projected_inode()->get_quiesce_block();
+  } else if (xattr_name == "ceph.dir.charmap"sv) {
+    auto&& pip = cur->get_projected_inode();
+    if (!pip->has_charmap()) {
+      r = -ENODATA;
+    } else {
+      auto& c = pip->get_charmap();
+      Formatter* f = new JSONFormatter;
+      f->dump_object("charmap", c);
+      f->flush(*css);
+      delete f;
+    }
+  } else if (xattr_name == "ceph.dir.casesensitive"sv) {
+    auto&& pip = cur->get_projected_inode();
+    if (!pip->has_charmap()) {
+      r = -ENODATA;
+    } else {
+      auto& c = pip->get_charmap();
+      *css << c.is_casesensitive();
+    }
+  } else if (xattr_name == "ceph.dir.encoding"sv) {
+    auto&& pip = cur->get_projected_inode();
+    if (!pip->has_charmap()) {
+      r = -ENODATA;
+    } else {
+      auto& c = pip->get_charmap();
+      *css << c.get_encoding();
+    }
+  } else if (xattr_name == "ceph.dir.normalization"sv) {
+    auto&& pip = cur->get_projected_inode();
+    if (!pip->has_charmap()) {
+      r = -ENODATA;
+    } else {
+      auto& c = pip->get_charmap();
+      *css << c.get_normalization();
+    }
   } else if (xattr_name.substr(0, 12) == "ceph.dir.pin"sv) {
     if (xattr_name == "ceph.dir.pin"sv) {
       *css << cur->get_projected_inode()->export_pin;
index d3ec363b092fc79c401191f4aa6510fb39e86a29..351d6711b8a2b9b9611910a567fc5017a51c0589 100644 (file)
@@ -216,7 +216,8 @@ public:
   void handle_client_file_readlock(const MDRequestRef& mdr);
 
   bool xlock_policylock(const MDRequestRef& mdr, CInode *in,
-                       bool want_layout=false, bool xlock_snaplock=false);
+                       bool want_layout=false, bool xlock_snaplock=false,
+                        MutationImpl::LockOpVec lov={});
   CInode* try_get_auth_inode(const MDRequestRef& mdr, inodeno_t ino);
   void handle_client_setattr(const MDRequestRef& mdr);
   void handle_client_setlayout(const MDRequestRef& mdr);
@@ -448,11 +449,15 @@ private:
            xattr_name == "ceph.dir.subvolume" ||
            xattr_name == "ceph.dir.pin" ||
            xattr_name == "ceph.dir.pin.random" ||
-           xattr_name == "ceph.dir.pin.distributed";
+           xattr_name == "ceph.dir.pin.distributed" ||
+           xattr_name == "ceph.dir.charmap"sv ||
+           xattr_name == "ceph.dir.normalization"sv ||
+           xattr_name == "ceph.dir.encoding"sv ||
+           xattr_name == "ceph.dir.casesensitive"sv;
   }
 
   static bool is_ceph_dir_vxattr(std::string_view xattr_name) {
-    return (xattr_name == "ceph.dir.layout" ||
+    return xattr_name == "ceph.dir.layout" ||
            xattr_name == "ceph.dir.layout.json" ||
            xattr_name == "ceph.dir.layout.object_size" ||
            xattr_name == "ceph.dir.layout.stripe_unit" ||
@@ -463,7 +468,11 @@ private:
            xattr_name == "ceph.dir.layout.pool_namespace" ||
            xattr_name == "ceph.dir.pin" ||
            xattr_name == "ceph.dir.pin.random" ||
-           xattr_name == "ceph.dir.pin.distributed");
+           xattr_name == "ceph.dir.pin.distributed" ||
+            xattr_name == "ceph.dir.charmap"sv ||
+            xattr_name == "ceph.dir.normalization"sv ||
+            xattr_name == "ceph.dir.encoding"sv ||
+            xattr_name == "ceph.dir.casesensitive"sv;
   }
 
   static bool is_ceph_file_vxattr(std::string_view xattr_name) {