]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
client: check client config and snaprealm flag before snapdir lookup
authorDhairya Parmar <dparmar@redhat.com>
Tue, 8 Jul 2025 21:25:36 +0000 (02:55 +0530)
committerDhairya Parmar <dparmar@redhat.com>
Thu, 25 Sep 2025 16:41:08 +0000 (22:11 +0530)
this commit adds a new client config client_respect_subvolume_snapshot_visibility
which acts as knob to have a per-client control over the snapshot visibility and
checks it along with the snaprealm flag while looking up a subvolume inode.

Fixes: https://tracker.ceph.com/issues/71740
Signed-off-by: Dhairya Parmar <dparmar@redhat.com>
src/client/Client.cc
src/client/Client.h
src/client/ClientSnapRealm.h
src/common/options/mds-client.yaml.in

index 4d802fa5d60290dc75382bac8abd411d87ffb2c9..e81ffbcadcdae6573b0055c1327509fffcaf5c1a 100644 (file)
@@ -431,6 +431,9 @@ Client::Client(Messenger *m, MonClient *mc, Objecter *objecter_)
   injected_write_delay_secs = std::chrono::duration<int>(
     cct->_conf.get_val<std::chrono::seconds>("client_inject_write_delay_secs")).count();
 
+  respect_subvolume_snapshot_visibility = cct->_conf.get_val<bool>(
+    "client_respect_subvolume_snapshot_visibility");
+
   if (cct->_conf->client_acl_type == "posix_acl")
     acl_type = POSIX_ACL;
 
@@ -5314,13 +5317,16 @@ static bool has_new_snaps(const SnapContext& old_snapc,
 }
 
 struct SnapRealmInfoMeta {
-  SnapRealmInfoMeta(utime_t last_modified, uint64_t change_attr)
+  SnapRealmInfoMeta(utime_t last_modified,
+                    uint64_t change_attr,
+                    bool is_snapdir_visible)
     : last_modified(last_modified),
-      change_attr(change_attr) {
-  }
+      change_attr(change_attr),
+      is_snapdir_visible(is_snapdir_visible) {}
 
   utime_t last_modified;
   uint64_t change_attr;
+  bool is_snapdir_visible;
 };
 
 static std::pair<SnapRealmInfo, std::optional<SnapRealmInfoMeta>> get_snap_realm_info(
@@ -5328,7 +5334,8 @@ static std::pair<SnapRealmInfo, std::optional<SnapRealmInfoMeta>> get_snap_realm
   if (session->mds_features.test(CEPHFS_FEATURE_NEW_SNAPREALM_INFO)) {
     SnapRealmInfoNew ninfo;
     decode(ninfo, p);
-    return std::make_pair(ninfo.info, SnapRealmInfoMeta(ninfo.last_modified, ninfo.change_attr));
+    return std::make_pair(ninfo.info, SnapRealmInfoMeta(ninfo.last_modified,
+                          ninfo.change_attr, ninfo.flags & SnapRealmInfoNew::SNAPDIR_VISIBILITY));
   } else {
     SnapRealmInfo info;
     decode(info, p);
@@ -5386,6 +5393,7 @@ void Client::update_snap_trace(MetaSession *session, const bufferlist& bl, SnapR
       if (realm_info_meta) {
         realm->last_modified = (*realm_info_meta).last_modified;
         realm->change_attr = (*realm_info_meta).change_attr;
+        realm->is_snapdir_visible = (*realm_info_meta).is_snapdir_visible;
       }
       realm->my_snaps = info.my_snaps;
       invalidate = true;
@@ -7602,6 +7610,11 @@ int Client::_lookup(const InodeRef& dir, const std::string& name, std::string& a
 
   if (dname == cct->_conf->client_snapdir &&
       dir->snapid == CEPH_NOSNAP) {
+    if (respect_subvolume_snapshot_visibility &&
+        !dir->snaprealm->is_snapdir_visible) {
+      r = -EPERM;
+      goto done;
+    }
     *target = open_snapdir(dir);
     goto done;
   }
@@ -13336,6 +13349,10 @@ int Client::mksnap(const char *relpath, const char *name, const UserPerm& perm,
   if (int rc = path_walk(cwd, filepath(relpath), &wdr, perm, {}); rc < 0) {
     return rc;
   }
+  if (respect_subvolume_snapshot_visibility &&
+      !wdr.target->snaprealm->is_snapdir_visible) {
+      return -EPERM;
+  }
   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;
@@ -13354,6 +13371,10 @@ int Client::rmsnap(const char *relpath, const char *name, const UserPerm& perms,
   if (int rc = path_walk(cwd, filepath(relpath), &in, perms, {}); rc < 0) {
     return rc;
   }
+  if (respect_subvolume_snapshot_visibility &&
+      !in->snaprealm->is_snapdir_visible) {
+      return -EPERM;
+  }
   auto snapdir = open_snapdir(in.get());
   return _rmdir(snapdir.get(), name, perms, check_perms);
 }
@@ -17659,6 +17680,7 @@ std::vector<std::string> Client::get_tracked_keys() const noexcept
     "client_oc_size",
     "client_oc_target_dirty",
     "client_permissions",
+    "client_respect_subvolume_snapshot_visibility",
     "fuse_default_permissions"
   });
   static_assert(std::is_sorted(begin(as_sv), end(as_sv)));
@@ -17717,6 +17739,10 @@ void Client::handle_conf_change(const ConfigProxy& conf,
     injected_write_delay_secs = std::chrono::duration<int>(
       cct->_conf.get_val<std::chrono::seconds>("client_inject_write_delay_secs")).count();
   }
+  if (changed.count("client_respect_subvolume_snapshot_visibility")) {
+    respect_subvolume_snapshot_visibility = cct->_conf.get_val<bool>(
+      "client_respect_subvolume_snapshot_visibility");
+  }
 }
 
 void intrusive_ptr_add_ref(Inode *in)
index 0847ea5c69e95ee6c966f0a37af8bcc686361326..bc7386a5ed9246442541da583de46bcb2ef2f7ff 100644 (file)
@@ -2058,6 +2058,7 @@ private:
   bool is_fuse = false;
   bool client_permissions;
   bool fuse_default_permissions;
+  bool respect_subvolume_snapshot_visibility;
 
   std::locale m_locale;
 };
index 4b7eabff572f9ff627a0fa7fc2fbe8097ac6fac8..3f5da9a8ed541fad7fdee1fe47ac98aac39da268 100644 (file)
@@ -29,6 +29,7 @@ struct SnapRealm {
   std::set<SnapRealm*> pchildren;
   utime_t last_modified;
   uint64_t change_attr;
+  bool is_snapdir_visible = true;
 
 private:
   SnapContext cached_snap_context;  // my_snaps + parent snaps + past_parent_snaps
@@ -62,6 +63,7 @@ inline std::ostream& operator<<(std::ostream& out, const SnapRealm& r) {
             << " cached_snapc=" << r.cached_snap_context
             << " last_modified=" << r.last_modified
             << " change_attr=" << r.change_attr
+             << " is_snapdir_visible=" << r.is_snapdir_visible
             << ")";
 }
 
index f80562d08c028779a58a568314fd6ffb71c71d6d..cb77a0c91ff2768ba888c050c50a1b19a2d3abeb 100644 (file)
@@ -589,6 +589,17 @@ options:
   - mds_client
   flags:
   - runtime
+- name: client_respect_subvolume_snapshot_visibility
+  type: bool
+  level: advanced
+  desc: Respect subvolume snapshot visibility
+  long_desc: Option to decide whether to respect the is_snapdir_visible flag
+    set in each subvolume's snaprealm
+  default: false
+  services:
+  - mds_client
+  flags:
+  - runtime
 - name: client_file_blockdiff_max_concurrent_object_scans
   type: uint
   level: advanced