]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mds: add ceph.dir.subvolume.snaps.visible vxattr
authorDhairya Parmar <dparmar@redhat.com>
Thu, 3 Jul 2025 11:52:38 +0000 (17:22 +0530)
committerDhairya Parmar <dparmar@redhat.com>
Mon, 6 Oct 2025 11:48:59 +0000 (17:18 +0530)
using SNAPDIR_VISIBILITY flag added in sr_t

Fixes: https://tracker.ceph.com/issues/71740
Signed-off-by: Dhairya Parmar <dparmar@redhat.com>
src/mds/Server.cc
src/mds/Server.h
src/mds/SnapRealm.cc
src/mds/snap.cc
src/mds/snap.h

index 2c04de6aa6ac4bd7b36ffa6f67cb5f1fe0314714..818b3718b48ec6ac1dab3ce4eade390b0202ad23 100644 (file)
@@ -6518,6 +6518,96 @@ void Server::handle_client_setvxattr(const MDRequestRef& mdr, CInode *cur)
     mdr->no_early_reply = true;
     pip = pi.inode.get();
     adjust_realm = true;
+  } else if (name == "ceph.dir.subvolume.snaps.visible"sv) {
+    if (!cur->is_dir()) {
+      respond_to_request(mdr, -EINVAL);
+      return;
+    }
+
+    bool val = true;
+    try {
+      std::string errstr;
+      val = strict_strtob(value, &errstr);
+      if (!errstr.empty()) {
+        dout(10) << "bad vxattr value, unable to parse bool for " << name
+                 << ": " << errstr << dendl;
+        respond_to_request(mdr, -EINVAL);
+        return;
+      }
+    } catch (boost::bad_lexical_cast const& e) {
+      dout(10) << "bad vxattr value, unable to parse bool for " << name
+               << ": " << e.what() << dendl;
+      respond_to_request(mdr, -EINVAL);
+      return;
+    }
+
+    // perform few checks with lightweight rdlock
+    if (!mdr->more()->rdonly_checks) {
+      lov.add_rdlock(&cur->snaplock);
+      if (!mds->locker->acquire_locks(mdr, lov)) {
+        dout(20) << "handle_client_getvxattr could not acquire rdlock on "
+                 << *cur << dendl;
+        return;
+      }
+
+      const auto srnode = cur->get_projected_srnode();
+      if (!srnode) {
+        dout(10) << "no-op since no snaprealm node found for "
+                 << req->get_filepath() << dendl;
+        respond_to_request(mdr, 0);
+        return; 
+      }
+      // check if visibility already matches the desired value
+      if (val == srnode->is_snapdir_visible()) {
+        dout(20) << "snapdir visibility for " << req->get_filepath()
+                 << " is already set to " << std::boolalpha << val << dendl;
+        respond_to_request(mdr, 0);
+        return;
+      }
+      
+      mdr->more()->rdonly_checks = true;
+      dout(20) << "dropping rdlock on " << *cur << dendl;
+      mds->locker->drop_locks(mdr.get());
+    }
+
+    if (!xlock_policylock(mdr, cur, false, true)) {
+      return;
+    }
+
+    /* Repeat rdlocks checks to see if anything changed b/w rdlock release and
+    *  xlock policylock acquisition
+    */ 
+    {
+      const auto srnode = cur->get_projected_srnode();
+      if (!srnode) {
+        dout(10) << "no-op since no snaprealm node found for "
+                 << req->get_filepath() << dendl;
+        respond_to_request(mdr, 0);
+        return; 
+      }
+
+      if (val == srnode->is_snapdir_visible()) {
+        dout(20) << "snapdir visibility for " << req->get_filepath()
+                 << " is already set to " << std::boolalpha << val << dendl;
+        respond_to_request(mdr, 0);
+        return;
+      }
+    }
+
+    adjust_realm = true;
+    auto pi = cur->project_inode(mdr, false, adjust_realm);
+    dout(20) << "setting snapdir visibility to " << std::boolalpha
+               << val << " for " << req->get_filepath() << dendl;
+    if (val) {
+      pi.snapnode->set_snapdir_visibility();
+    } else {
+      pi.snapnode->unset_snapdir_visibility();
+    }
+    pi.snapnode->last_modified = mdr->get_op_stamp();
+    pi.snapnode->change_attr++;
+
+    mdr->no_early_reply = true;
+    pip = pi.inode.get();
   } else if (name == "ceph.dir.pin"sv) {
     if (!cur->is_dir() || cur->is_root()) {
       respond_to_request(mdr, -EINVAL);
@@ -7287,6 +7377,19 @@ void Server::handle_client_getvxattr(const MDRequestRef& mdr)
   } else if (xattr_name == "ceph.dir.subvolume"sv) {
     const auto* srnode = cur->get_projected_srnode();
     *css << (srnode && srnode->is_subvolume() ? "1"sv : "0"sv);
+  } else if (xattr_name == "ceph.dir.subvolume.snaps.visible"sv) {
+    if (!cur->is_dir()) {
+      r = -ENOTDIR;
+    } else {
+      const auto srnode = cur->get_projected_srnode();
+      if (!srnode) {
+        dout(10) << "no-op since no snaprealm node found for "
+                 << mdr->client_request->get_filepath() << dendl;
+        r = 0;
+      } else {
+        *css << srnode->is_snapdir_visible();
+      }
+    }
   } else {
     // otherwise respond as invalid request
     // since we only handle ceph vxattrs here
index 9ee5a9b687956ffd2b1b840ec089f8a0c9c5ade6..445d9b38e912824e9f846d01933633f4e9534236 100644 (file)
@@ -500,7 +500,8 @@ private:
            xattr_name == "ceph.dir.charmap"sv ||
            xattr_name == "ceph.dir.normalization"sv ||
            xattr_name == "ceph.dir.encoding"sv ||
-           xattr_name == "ceph.dir.casesensitive"sv;
+           xattr_name == "ceph.dir.casesensitive"sv ||
+           xattr_name == "ceph.dir.subvolume.snaps.visible"sv;
   }
 
   static bool is_ceph_dir_vxattr(std::string_view xattr_name) {
@@ -520,7 +521,8 @@ private:
           xattr_name == "ceph.dir.normalization"sv ||
           xattr_name == "ceph.dir.encoding"sv ||
           xattr_name == "ceph.dir.casesensitive"sv ||
-          xattr_name == "ceph.dir.subvolume"sv;
+          xattr_name == "ceph.dir.subvolume"sv ||
+     xattr_name == "ceph.dir.subvolume.snaps.visible"sv;
   }
 
   static bool is_ceph_file_vxattr(std::string_view xattr_name) {
index c2fecac132bc06a2a2cc16087ce6766b8ac8ce42..03f30f45615120cb90ec3f3c90d1ca55b0064b19 100644 (file)
@@ -58,7 +58,8 @@ ostream& operator<<(ostream& out, const SnapRealm& realm)
   if (realm.srnode.is_parent_global())
     out << " global ";
   out << " last_modified " << realm.srnode.last_modified
-      << " change_attr " << realm.srnode.change_attr;
+      << " change_attr " << realm.srnode.change_attr
+      << " is_snapdir_visible " << realm.srnode.is_snapdir_visible();
   out << " " << &realm << ")";
   return out;
 }
index ca316d084a2d59723001d5a5dcdcfa81c9f91407..b3cd1fc3d0d68d21dbf36a66a7386e1c7a7a0adb 100644 (file)
@@ -194,6 +194,7 @@ void sr_t::dump(Formatter *f) const
   f->dump_unsigned("last_destroyed", last_destroyed);
   f->dump_stream("last_modified") << last_modified;
   f->dump_unsigned("change_attr", change_attr);
+  f->dump_unsigned("is_snapdir_visible", is_snapdir_visible());
   f->dump_unsigned("current_parent_since", current_parent_since);
 
   f->open_array_section("snaps");
@@ -247,3 +248,11 @@ std::list<sr_t> sr_t::generate_test_instances()
   return ls;
 }
 
+void sr_t::print(std::ostream& out) const {
+  out << "sr_t(seq=" << seq
+      << " created=" << created
+      << " last_created=" << last_created
+      << " last_destroyed=" << last_destroyed
+      << " flags=" << flags << ")";
+}
+
index de529ac4c2d1aa351bcd5e3aeba5c5ba5b75fdee..8bd53cefb4740eef0d348dd4b3cbaf9f1b00239c 100644 (file)
@@ -87,10 +87,15 @@ struct sr_t {
   void clear_subvolume() { flags &= ~SUBVOLUME; }
   bool is_subvolume() const { return flags & SUBVOLUME; }
 
+  void set_snapdir_visibility() { flags |= SNAPDIR_VISIBILITY; }
+  void unset_snapdir_visibility() { flags &= ~SNAPDIR_VISIBILITY; }
+  bool is_snapdir_visible() const { return flags & SNAPDIR_VISIBILITY; }
+
   void encode(ceph::buffer::list &bl) const;
   void decode(ceph::buffer::list::const_iterator &bl);
   void dump(ceph::Formatter *f) const;
   static std::list<sr_t> generate_test_instances();
+  void print(std::ostream&) const;
 
   snapid_t seq = 0;                     // basically, a version/seq # for changes to _this_ realm.
   snapid_t created = 0;                 // when this realm was created.
@@ -105,11 +110,13 @@ struct sr_t {
   uint64_t change_attr = 0;             // tracks changes to snap
                                         // realm attrs.
 
-  __u32 flags = 0;
   enum {
     PARENT_GLOBAL      = 1 << 0,
     SUBVOLUME          = 1 << 1,
+    SNAPDIR_VISIBILITY = 1 << 2,
   };
+
+  __u32 flags = SNAPDIR_VISIBILITY; // snapdir visibility is always on by default
 };
 WRITE_CLASS_ENCODER(sr_t)