]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: add new getvxattr op
authorMilind Changire <mchangir@redhat.com>
Mon, 24 Jan 2022 08:14:17 +0000 (13:44 +0530)
committerMilind Changire <mchangir@redhat.com>
Thu, 17 Mar 2022 13:13:59 +0000 (18:43 +0530)
This new op fetches ceph namespace specific extended attributes
i.e. attributes  "ceph.dir.layout.json", "ceph.file.layout.json"
and "ceph.dir.pin*"

For layout attributes, value of the .json xattrs provide the
following features:
1. output in json format
2. resolves layout from the most closest ancestor inode, starting
   at self
3. adds an 'inheritance' field to show the layout inheritance
   where:
       @default - implies default system-wide layout
       @inherited - implies layout has been inherited from an ancestor
       @set - implies layout has been set for that specific inode
4. adds two fields: pool_name and pool_id to differentiate between
   the two values; especially for the situations where users have
   chosen to use purely digit sequences to name pools; since pool_id
   is system generated and its output is a decimal number as well,
   users cannot distinguish the value in the field named 'pool'

Fixes: https://tracker.ceph.com/issues/51062
Signed-off-by: Milind Changire <mchangir@redhat.com>
(cherry picked from commit b96c01da85315f52811d3ff81949dd7daefdefb5)

src/include/ceph_fs.h
src/mds/Server.cc
src/mds/Server.h

index eb73efa0366300507372d042311c35e7e51b07fc..aed669a7f4506bb51ebe22c541fac20efc22aa3e 100644 (file)
@@ -387,6 +387,7 @@ enum {
        CEPH_MDS_OP_LOOKUPPARENT = 0x00103,
        CEPH_MDS_OP_LOOKUPINO  = 0x00104,
        CEPH_MDS_OP_LOOKUPNAME = 0x00105,
+       CEPH_MDS_OP_GETVXATTR  = 0x00106,
 
        CEPH_MDS_OP_SETXATTR   = 0x01105,
        CEPH_MDS_OP_RMXATTR    = 0x01106,
index aa80a03b4af2d2b5099e76f6d08b17250c939adb..759d80c2459494d3569bcd0055e2dd5368bf514a 100644 (file)
@@ -198,6 +198,8 @@ void Server::create_logger()
                    "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",
@@ -2001,6 +2003,9 @@ void Server::perf_gather_op_latency(const cref_t<MClientRequest> &req, utime_t l
   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;
@@ -2573,6 +2578,9 @@ void Server::dispatch_client_request(MDRequestRef& mdr)
   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);
@@ -6275,6 +6283,159 @@ void Server::handle_client_removexattr(MDRequestRef& 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
index e378959c180e328b7953bbfbd3a457511f29e117..265bc9cf6da7adefb26755f54c7193a550bfad47 100644 (file)
@@ -80,6 +80,7 @@ enum {
   l_mdss_req_unlink_latency,
   l_mdss_cap_revoke_eviction,
   l_mdss_cap_acquisition_throttle,
+  l_mdss_req_getvxattr_latency,
   l_mdss_last,
 };
 
@@ -221,6 +222,7 @@ public:
                           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);
 
@@ -421,6 +423,33 @@ private:
            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) {