@@ -431,6 +431,9 @@ Client::Client(Messenger *m, MonClient *mc, Objecter *objecter_)
431431 injected_write_delay_secs = std::chrono::duration<int>(
432432 cct->_conf.get_val<std::chrono::seconds>("client_inject_write_delay_secs")).count();
433433
434+ respect_subvolume_snapshot_visibility = cct->_conf.get_val<bool>(
435+ "client_respect_subvolume_snapshot_visibility");
436+
434437 if (cct->_conf->client_acl_type == "posix_acl")
435438 acl_type = POSIX_ACL;
436439
@@ -5314,21 +5317,25 @@ static bool has_new_snaps(const SnapContext& old_snapc,
53145317}
53155318
53165319struct SnapRealmInfoMeta {
5317- SnapRealmInfoMeta(utime_t last_modified, uint64_t change_attr)
5320+ SnapRealmInfoMeta(utime_t last_modified,
5321+ uint64_t change_attr,
5322+ bool is_snapdir_visible)
53185323 : last_modified(last_modified),
5319- change_attr(change_attr) {
5320- }
5324+ change_attr(change_attr),
5325+ is_snapdir_visible(is_snapdir_visible) { }
53215326
53225327 utime_t last_modified;
53235328 uint64_t change_attr;
5329+ bool is_snapdir_visible;
53245330};
53255331
53265332static std::pair<SnapRealmInfo, std::optional<SnapRealmInfoMeta>> get_snap_realm_info(
53275333 MetaSession *session, bufferlist::const_iterator &p) {
53285334 if (session->mds_features.test(CEPHFS_FEATURE_NEW_SNAPREALM_INFO)) {
53295335 SnapRealmInfoNew ninfo;
53305336 decode(ninfo, p);
5331- return std::make_pair(ninfo.info, SnapRealmInfoMeta(ninfo.last_modified, ninfo.change_attr));
5337+ return std::make_pair(ninfo.info, SnapRealmInfoMeta(ninfo.last_modified,
5338+ ninfo.change_attr, ninfo.flags & SnapRealmInfoNew::SNAPDIR_VISIBILITY));
53325339 } else {
53335340 SnapRealmInfo info;
53345341 decode(info, p);
@@ -5386,6 +5393,7 @@ void Client::update_snap_trace(MetaSession *session, const bufferlist& bl, SnapR
53865393 if (realm_info_meta) {
53875394 realm->last_modified = (*realm_info_meta).last_modified;
53885395 realm->change_attr = (*realm_info_meta).change_attr;
5396+ realm->is_snapdir_visible = (*realm_info_meta).is_snapdir_visible;
53895397 }
53905398 realm->my_snaps = info.my_snaps;
53915399 invalidate = true;
@@ -7602,6 +7610,11 @@ int Client::_lookup(const InodeRef& dir, const std::string& name, std::string& a
76027610
76037611 if (dname == cct->_conf->client_snapdir &&
76047612 dir->snapid == CEPH_NOSNAP) {
7613+ if (respect_subvolume_snapshot_visibility &&
7614+ !dir->snaprealm->is_snapdir_visible) {
7615+ r = -EPERM;
7616+ goto done;
7617+ }
76057618 *target = open_snapdir(dir);
76067619 goto done;
76077620 }
@@ -13336,6 +13349,10 @@ int Client::mksnap(const char *relpath, const char *name, const UserPerm& perm,
1333613349 if (int rc = path_walk(cwd, filepath(relpath), &wdr, perm, {}); rc < 0) {
1333713350 return rc;
1333813351 }
13352+ if (respect_subvolume_snapshot_visibility &&
13353+ !wdr.target->snaprealm->is_snapdir_visible) {
13354+ return -EPERM;
13355+ }
1333913356 auto snapdir = open_snapdir(wdr.target);
1334013357 if (int rc = path_walk(std::move(snapdir), filepath(name), &wdr, perm, {.require_target = false}); rc < 0) {
1334113358 return rc;
@@ -13354,6 +13371,10 @@ int Client::rmsnap(const char *relpath, const char *name, const UserPerm& perms,
1335413371 if (int rc = path_walk(cwd, filepath(relpath), &in, perms, {}); rc < 0) {
1335513372 return rc;
1335613373 }
13374+ if (respect_subvolume_snapshot_visibility &&
13375+ !in->snaprealm->is_snapdir_visible) {
13376+ return -EPERM;
13377+ }
1335713378 auto snapdir = open_snapdir(in.get());
1335813379 return _rmdir(snapdir.get(), name, perms, check_perms);
1335913380}
@@ -17659,6 +17680,7 @@ std::vector<std::string> Client::get_tracked_keys() const noexcept
1765917680 "client_oc_size",
1766017681 "client_oc_target_dirty",
1766117682 "client_permissions",
17683+ "client_respect_subvolume_snapshot_visibility",
1766217684 "fuse_default_permissions"
1766317685 });
1766417686 static_assert(std::is_sorted(begin(as_sv), end(as_sv)));
@@ -17717,6 +17739,10 @@ void Client::handle_conf_change(const ConfigProxy& conf,
1771717739 injected_write_delay_secs = std::chrono::duration<int>(
1771817740 cct->_conf.get_val<std::chrono::seconds>("client_inject_write_delay_secs")).count();
1771917741 }
17742+ if (changed.count("client_respect_subvolume_snapshot_visibility")) {
17743+ respect_subvolume_snapshot_visibility = cct->_conf.get_val<bool>(
17744+ "client_respect_subvolume_snapshot_visibility");
17745+ }
1772017746}
1772117747
1772217748void intrusive_ptr_add_ref(Inode *in)
0 commit comments