From 9f0c4227261e4fc76b6019f78d726fb179ba23d2 Mon Sep 17 00:00:00 2001 From: Patrick Donnelly Date: Mon, 26 Aug 2024 12:22:35 -0400 Subject: [PATCH] mds: wire up vxattr for changing charmap Signed-off-by: Patrick Donnelly Fixes: https://tracker.ceph.com/issues/66373 --- src/mds/CInode.cc | 13 ++++ src/mds/CInode.h | 2 + src/mds/Server.cc | 168 +++++++++++++++++++++++++++++++++++++++++++++- src/mds/Server.h | 17 +++-- 4 files changed, 194 insertions(+), 6 deletions(-) diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index 977f4b0876fe0..e83b562a1f96a 100644 --- a/src/mds/CInode.cc +++ b/src/mds/CInode.cc @@ -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 << " " << ∈ out << "]"; @@ -5549,6 +5552,16 @@ void CInode::set_export_pin(mds_rank_t rank) maybe_export_pin(true); } +charmap_md_t 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; diff --git a/src/mds/CInode.h b/src/mds/CInode.h index 8ae1d5f71687b..f70e01312cc3d 100644 --- a/src/mds/CInode.h +++ b/src/mds/CInode.h @@ -1013,6 +1013,8 @@ class CInode : public MDSCacheObject, public InodeStoreBase, public Counter 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); diff --git a/src/mds/Server.cc b/src/mds/Server.cc index 12ae35eb2606d..a410b999102c0 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -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(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; diff --git a/src/mds/Server.h b/src/mds/Server.h index d3ec363b092fc..351d6711b8a2b 100644 --- a/src/mds/Server.h +++ b/src/mds/Server.h @@ -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) { -- 2.39.5