From: Edwin Rodriguez Date: Mon, 18 Aug 2025 20:17:07 +0000 (-0400) Subject: mds: add ceph.dir.subvolume get vxattr X-Git-Tag: testing/wip-rishabh-testing-20250929.182116^2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=51fb4b6abe9daba651150055c7f768d8a6d61d48;p=ceph-ci.git mds: add ceph.dir.subvolume get vxattr This introduces handling for the "ceph.dir.subvolume" virtual xattr on directories. - Returns ASCII "1" when the directory is a subvolume root, "0" otherwise. QA: - Extend CephFS subvolume tests to validate vxattr retrieval and behavior around setting/removal. Fixes: https://tracker.ceph.com/issues/72556 Signed-off-by: Edwin Rodriguez --- diff --git a/qa/tasks/cephfs/test_subvolume.py b/qa/tasks/cephfs/test_subvolume.py index 9a1755b21f4..6d2f62d3d3f 100644 --- a/qa/tasks/cephfs/test_subvolume.py +++ b/qa/tasks/cephfs/test_subvolume.py @@ -213,6 +213,28 @@ class TestSubvolume(CephFSTestCase): # cleanup self.mount_a.run_shell(['rm', '-rf', 'group/subvol3']) + + def test_subvolume_vxattr_retrieval(self): + """ + To verify that the ceph.dir.subvolume vxattr can be acquired using getfattr + """ + # create subvolume dir + subvol_dir:str = 'group/subvol5' + self.mount_a.run_shell(['mkdir', subvol_dir]) + mkdir_fattr = self.mount_a.getfattr(subvol_dir, 'ceph.dir.subvolume') + self.assertEqual('0', mkdir_fattr) + + self.mount_a.setfattr(subvol_dir, 'ceph.dir.subvolume', '1') + new_fattr:str = self.mount_a.getfattr(subvol_dir, 'ceph.dir.subvolume') + self.assertEqual('1', new_fattr) + + # clear subvolume flag + self.mount_a.removexattr(subvol_dir, 'ceph.dir.subvolume') + + # cleanup + self.mount_a.run_shell(['rm', '-rf', subvol_dir]) + + class TestSubvolumeReplicated(CephFSTestCase): CLIENTS_REQUIRED = 1 MDSS_REQUIRED = 2 diff --git a/src/mds/Server.cc b/src/mds/Server.cc index fdfd5d3e08a..2c04de6aa6a 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -7284,6 +7284,9 @@ void Server::handle_client_getvxattr(const MDRequestRef& mdr) // since we only handle ceph vxattrs here r = -ENODATA; // no such attribute } + } 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 { // otherwise respond as invalid request // since we only handle ceph vxattrs here diff --git a/src/mds/Server.h b/src/mds/Server.h index 234afe0f533..9ee5a9b6879 100644 --- a/src/mds/Server.h +++ b/src/mds/Server.h @@ -505,21 +505,22 @@ private: static bool is_ceph_dir_vxattr(std::string_view xattr_name) { 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" || - xattr_name == "ceph.dir.layout.stripe_count" || - xattr_name == "ceph.dir.layout.pool" || - xattr_name == "ceph.dir.layout.pool_name" || - xattr_name == "ceph.dir.layout.pool_id" || - 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.charmap"sv || - xattr_name == "ceph.dir.normalization"sv || - xattr_name == "ceph.dir.encoding"sv || - xattr_name == "ceph.dir.casesensitive"sv; + xattr_name == "ceph.dir.layout.json" || + xattr_name == "ceph.dir.layout.object_size" || + xattr_name == "ceph.dir.layout.stripe_unit" || + xattr_name == "ceph.dir.layout.stripe_count" || + xattr_name == "ceph.dir.layout.pool" || + xattr_name == "ceph.dir.layout.pool_name" || + xattr_name == "ceph.dir.layout.pool_id" || + 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.charmap"sv || + xattr_name == "ceph.dir.normalization"sv || + xattr_name == "ceph.dir.encoding"sv || + xattr_name == "ceph.dir.casesensitive"sv || + xattr_name == "ceph.dir.subvolume"sv; } static bool is_ceph_file_vxattr(std::string_view xattr_name) {