"Request type set file layout latency");
plb.add_time_avg(l_mdss_req_setdirlayout_latency, "req_setdirlayout_latency",
"Request type set directory layout latency");
+ plb.add_time_avg(l_mdss_req_getvxattr_latency, "req_getvxattr_latency",
+ "Request type get virtual extended attribute latency");
plb.add_time_avg(l_mdss_req_setxattr_latency, "req_setxattr_latency",
"Request type set extended attribute latency");
plb.add_time_avg(l_mdss_req_rmxattr_latency, "req_rmxattr_latency",
case CEPH_MDS_OP_SETDIRLAYOUT:
code = l_mdss_req_setdirlayout_latency;
break;
+ case CEPH_MDS_OP_GETVXATTR:
+ code = l_mdss_req_getvxattr_latency;
+ break;
case CEPH_MDS_OP_SETXATTR:
code = l_mdss_req_setxattr_latency;
break;
case CEPH_MDS_OP_GETATTR:
handle_client_getattr(mdr, false);
break;
+ case CEPH_MDS_OP_GETVXATTR:
+ handle_client_getvxattr(mdr);
+ break;
case CEPH_MDS_OP_SETATTR:
handle_client_setattr(mdr);
journal_and_reply(mdr, cur, 0, le, new C_MDS_inode_update_finish(this, mdr, cur));
}
+void Server::handle_client_getvxattr(MDRequestRef& mdr)
+{
+ const auto& req = mdr->client_request;
+ string xattr_name{req->get_path2()};
+
+ // is a ceph virtual xattr?
+ if (!is_ceph_vxattr(xattr_name)) {
+ respond_to_request(mdr, -CEPHFS_ENODATA);
+ return;
+ }
+
+ CInode *cur = rdlock_path_pin_ref(mdr, true, false);
+ if (!cur) {
+ return;
+ }
+
+ if (is_ceph_dir_vxattr(xattr_name)) {
+ if (!cur->is_dir()) {
+ respond_to_request(mdr, -CEPHFS_ENODATA);
+ return;
+ }
+ } else if (is_ceph_file_vxattr(xattr_name)) {
+ if (cur->is_dir()) {
+ respond_to_request(mdr, -CEPHFS_ENODATA);
+ return;
+ }
+ }
+
+ CachedStackStringStream css;
+ int r = 0;
+ ceph::bufferlist bl;
+ // handle these vxattrs
+ if ((xattr_name.substr(0, 15) == "ceph.dir.layout"sv) ||
+ (xattr_name.substr(0, 16) == "ceph.file.layout"sv)) {
+ std::string layout_field;
+
+ struct layout_xattr_info_t {
+ enum class InheritanceStatus : uint32_t {
+ DEFAULT = 0,
+ SET = 1,
+ INHERITED = 2
+ };
+
+ const file_layout_t layout;
+ const InheritanceStatus status;
+
+ layout_xattr_info_t(const file_layout_t& l, InheritanceStatus inh)
+ : layout(l), status(inh) { }
+
+ static std::string status_to_string(InheritanceStatus status) {
+ switch (status) {
+ case InheritanceStatus::DEFAULT: return "default"s;
+ case InheritanceStatus::SET: return "set"s;
+ case InheritanceStatus::INHERITED: return "inherited"s;
+ default: return "unknown"s;
+ }
+ }
+ };
+
+ auto is_default_layout = [&](const file_layout_t& layout) -> bool {
+ return (layout == mdcache->default_file_layout);
+ };
+ auto get_inherited_layout = [&](CInode *cur) -> layout_xattr_info_t {
+ auto orig_in = cur;
+
+ while (cur) {
+ if (cur->get_projected_inode()->has_layout()) {
+ auto& curr_layout = cur->get_projected_inode()->layout;
+ if (is_default_layout(curr_layout)) {
+ return {curr_layout, layout_xattr_info_t::InheritanceStatus::DEFAULT};
+ }
+ if (cur == orig_in) {
+ // we've found a new layout at this inode
+ return {curr_layout, layout_xattr_info_t::InheritanceStatus::SET};
+ } else {
+ return {curr_layout, layout_xattr_info_t::InheritanceStatus::INHERITED};
+ }
+ }
+
+ if (cur->is_root()) {
+ break;
+ }
+
+ cur = cur->get_projected_parent_dir()->get_inode();
+ }
+ mds->clog->error() << "no layout found at root dir!";
+ ceph_abort("no layout found at root dir! something is really messed up with layouts!");
+ };
+
+ if (xattr_name == "ceph.dir.layout.json"sv ||
+ xattr_name == "ceph.file.layout.json"sv) {
+ // fetch layout only for valid xattr_name
+ const auto lxi = get_inherited_layout(cur);
+
+ *css << "{\"stripe_unit\": " << lxi.layout.stripe_unit
+ << ", \"stripe_count\": " << lxi.layout.stripe_count
+ << ", \"object_size\": " << lxi.layout.object_size
+ << ", \"pool_name\": ";
+ mds->objecter->with_osdmap([lxi, &css](const OSDMap& o) {
+ *css << "\"";
+ if (o.have_pg_pool(lxi.layout.pool_id)) {
+ *css << o.get_pool_name(lxi.layout.pool_id);
+ }
+ *css << "\"";
+ });
+ *css << ", \"pool_id\": " << (uint64_t)lxi.layout.pool_id;
+ *css << ", \"pool_namespace\": \"" << lxi.layout.pool_ns << "\"";
+ *css << ", \"inheritance\": \"@"
+ << layout_xattr_info_t::status_to_string(lxi.status) << "\"}";
+ } else if ((xattr_name == "ceph.dir.layout.pool_name"sv) ||
+ (xattr_name == "ceph.file.layout.pool_name"sv)) {
+ // fetch layout only for valid xattr_name
+ const auto lxi = get_inherited_layout(cur);
+ mds->objecter->with_osdmap([lxi, &css](const OSDMap& o) {
+ if (o.have_pg_pool(lxi.layout.pool_id)) {
+ *css << o.get_pool_name(lxi.layout.pool_id);
+ }
+ });
+ } else if ((xattr_name == "ceph.dir.layout.pool_id"sv) ||
+ (xattr_name == "ceph.file.layout.pool_id"sv)) {
+ // fetch layout only for valid xattr_name
+ const auto lxi = get_inherited_layout(cur);
+ *css << (uint64_t)lxi.layout.pool_id;
+ } else {
+ r = -CEPHFS_ENODATA; // no such attribute
+ }
+ } 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;
+ } else if (xattr_name == "ceph.dir.pin.random"sv) {
+ *css << cur->get_projected_inode()->export_ephemeral_random_pin;
+ } else if (xattr_name == "ceph.dir.pin.distributed"sv) {
+ *css << cur->get_projected_inode()->export_ephemeral_distributed_pin;
+ } else {
+ // otherwise respond as invalid request
+ // since we only handle ceph vxattrs here
+ r = -CEPHFS_ENODATA; // no such attribute
+ }
+ } else {
+ // otherwise respond as invalid request
+ // since we only handle ceph vxattrs here
+ r = -CEPHFS_ENODATA; // no such attribute
+ }
+
+ if (r == 0) {
+ ENCODE_START(1, 1, bl);
+ encode(css->strv(), bl);
+ ENCODE_FINISH(bl);
+ mdr->reply_extra_bl = bl;
+ }
+
+ respond_to_request(mdr, r);
+}
// =================================================================
// DIRECTORY and NAMESPACE OPS
l_mdss_req_unlink_latency,
l_mdss_cap_revoke_eviction,
l_mdss_cap_acquisition_throttle,
+ l_mdss_req_getvxattr_latency,
l_mdss_last,
};
file_layout_t *layout);
void handle_set_vxattr(MDRequestRef& mdr, CInode *cur);
void handle_remove_vxattr(MDRequestRef& mdr, CInode *cur);
+ void handle_client_getvxattr(MDRequestRef& mdr);
void handle_client_setxattr(MDRequestRef& mdr);
void handle_client_removexattr(MDRequestRef& mdr);
xattr_name == "ceph.dir.pin.distributed"sv;
}
+ 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");
+ }
+
+ static bool is_ceph_file_vxattr(std::string_view xattr_name) {
+ return (xattr_name == "ceph.file.layout" ||
+ xattr_name == "ceph.file.layout.json" ||
+ xattr_name == "ceph.file.layout.object_size" ||
+ xattr_name == "ceph.file.layout.stripe_unit" ||
+ xattr_name == "ceph.file.layout.stripe_count" ||
+ xattr_name == "ceph.file.layout.pool" ||
+ xattr_name == "ceph.file.layout.pool_name" ||
+ xattr_name == "ceph.file.layout.pool_id" ||
+ xattr_name == "ceph.file.layout.pool_namespace");
+ }
+
static bool is_allowed_ceph_xattr(std::string_view xattr_name) {
// not a ceph xattr -- allow!
if (xattr_name.rfind("ceph.", 0) != 0) {