]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/rgw/rgw_common.h
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rgw / rgw_common.h
index 25e5b24ad8170dde5731188b187993f92a26c72b..d0bd47253a847480cbb642169e95ca8d26d3d920 100644 (file)
@@ -1,4 +1,4 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
 // vim: ts=8 sw=2 smarttab ft=cpp
 
 /*
@@ -9,9 +9,9 @@
  *
  * This is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software 
+ * License version 2.1, as published by the Free Software
  * Foundation.  See file COPYING.
- * 
+ *
  */
 
 #pragma once
 #include <atomic>
 #include <unordered_map>
 
+#include <fmt/format.h>
+
 #include "common/ceph_crypto.h"
 #include "common/random_string.h"
 #include "rgw_acl.h"
 #include "rgw_bucket_layout.h"
 #include "rgw_cors.h"
+#include "rgw_basic_types.h"
 #include "rgw_iam_policy.h"
-#include "rgw_quota.h"
+#include "rgw_quota_types.h"
 #include "rgw_string.h"
 #include "common/async/yield_context.h"
 #include "rgw_website.h"
 #include "include/rados/librados.hpp"
 #include "rgw_public_access.h"
 #include "common/tracer.h"
+#include "rgw_sal_fwd.h"
 
 namespace ceph {
   class Formatter;
 }
 
 namespace rgw::sal {
-  class User;
-  class Bucket;
-  class Object;
   using Attrs = std::map<std::string, ceph::buffer::list>;
 }
 
+namespace rgw::lua {
+  class Background;
+}
+
+struct RGWProcessEnv;
+
 using ceph::crypto::MD5;
 
 #define RGW_ATTR_PREFIX  "user.rgw."
@@ -129,6 +136,15 @@ using ceph::crypto::MD5;
 
 #define RGW_ATTR_APPEND_PART_NUM    RGW_ATTR_PREFIX "append_part_num"
 
+/* Attrs to store cloudtier config information. These are used internally
+ * for the replication of cloudtiered objects but not stored as xattrs in
+ * the head object. */
+#define RGW_ATTR_CLOUD_TIER_TYPE    RGW_ATTR_PREFIX "cloud_tier_type"
+#define RGW_ATTR_CLOUD_TIER_CONFIG    RGW_ATTR_PREFIX "cloud_tier_config"
+
+#define RGW_ATTR_OBJ_REPLICATION_STATUS RGW_ATTR_PREFIX "amz-replication-status"
+#define RGW_ATTR_OBJ_REPLICATION_TRACE RGW_ATTR_PREFIX "replication-trace"
+
 /* IAM Policy */
 #define RGW_ATTR_IAM_POLICY    RGW_ATTR_PREFIX "iam-policy"
 #define RGW_ATTR_USER_POLICY    RGW_ATTR_PREFIX "user-policy"
@@ -153,10 +169,33 @@ using ceph::crypto::MD5;
 
 #define RGW_ATTR_TRACE RGW_ATTR_PREFIX "trace"
 
-#define RGW_FORMAT_PLAIN        0
-#define RGW_FORMAT_XML          1
-#define RGW_FORMAT_JSON         2
-#define RGW_FORMAT_HTML         3
+enum class RGWFormat : int8_t {
+  BAD_FORMAT = -1,
+  PLAIN = 0,
+  XML,
+  JSON,
+  HTML,
+};
+
+static inline const char* to_mime_type(const RGWFormat f)
+{
+  switch (f) {
+  case RGWFormat::XML:
+    return "application/xml";
+    break;
+  case RGWFormat::JSON:
+    return "application/json";
+    break;
+  case RGWFormat::HTML:
+    return "text/html";
+    break;
+  case RGWFormat::PLAIN:
+    return "text/plain";
+    break;
+  default:
+    return "invalid format";
+  }
+}
 
 #define RGW_CAP_READ            0x1
 #define RGW_CAP_WRITE           0x2
@@ -168,6 +207,7 @@ using ceph::crypto::MD5;
 #define RGW_REST_WEBSITE     0x8
 #define RGW_REST_STS            0x10
 #define RGW_REST_IAM            0x20
+#define RGW_REST_SNS            0x30
 
 #define RGW_SUSPENDED_USER_AUID (uint64_t)-2
 
@@ -279,35 +319,8 @@ using ceph::crypto::MD5;
 #define UINT32_MAX (0xffffffffu)
 #endif
 
-struct req_state;
-
 typedef void *RGWAccessHandle;
 
-enum RGWIntentEvent {
-  DEL_OBJ = 0,
-  DEL_DIR = 1,
-};
-
-enum HostStyle {
-  PathStyle = 0,
-  VirtualStyle = 1,
-};
-
-/** Store error returns for output at a different point in the program */
-struct rgw_err {
-  rgw_err();
-  void clear();
-  bool is_clear() const;
-  bool is_err() const;
-  friend std::ostream& operator<<(std::ostream& oss, const rgw_err &err);
-
-  int http_ret;
-  int ret;
-  std::string err_code;
-  std::string message;
-};
-
-
 /* Helper class used for RGWHTTPArgs parsing */
 class NameVal
 {
@@ -475,104 +488,11 @@ enum http_op {
 class RGWAccessControlPolicy;
 class JSONObj;
 
-struct RGWAccessKey {
-  std::string id; // AccessKey
-  std::string key; // SecretKey
-  std::string subuser;
-
-  RGWAccessKey() {}
-  RGWAccessKey(std::string _id, std::string _key)
-    : id(std::move(_id)), key(std::move(_key)) {}
-
-  void encode(bufferlist& bl) const {
-    ENCODE_START(2, 2, bl);
-    encode(id, bl);
-    encode(key, bl);
-    encode(subuser, bl);
-    ENCODE_FINISH(bl);
-  }
-
-  void decode(bufferlist::const_iterator& bl) {
-     DECODE_START_LEGACY_COMPAT_LEN_32(2, 2, 2, bl);
-     decode(id, bl);
-     decode(key, bl);
-     decode(subuser, bl);
-     DECODE_FINISH(bl);
-  }
-  void dump(Formatter *f) const;
-  void dump_plain(Formatter *f) const;
-  void dump(Formatter *f, const std::string& user, bool swift) const;
-  static void generate_test_instances(std::list<RGWAccessKey*>& o);
-
-  void decode_json(JSONObj *obj);
-  void decode_json(JSONObj *obj, bool swift);
-};
-WRITE_CLASS_ENCODER(RGWAccessKey)
-
-struct RGWSubUser {
-  std::string name;
-  uint32_t perm_mask;
-
-  RGWSubUser() : perm_mask(0) {}
-  void encode(bufferlist& bl) const {
-    ENCODE_START(2, 2, bl);
-    encode(name, bl);
-    encode(perm_mask, bl);
-    ENCODE_FINISH(bl);
-  }
-
-  void decode(bufferlist::const_iterator& bl) {
-     DECODE_START_LEGACY_COMPAT_LEN_32(2, 2, 2, bl);
-     decode(name, bl);
-     decode(perm_mask, bl);
-     DECODE_FINISH(bl);
-  }
-  void dump(Formatter *f) const;
-  void dump(Formatter *f, const std::string& user) const;
-  static void generate_test_instances(std::list<RGWSubUser*>& o);
-
-  void decode_json(JSONObj *obj);
-};
-WRITE_CLASS_ENCODER(RGWSubUser)
-
-class RGWUserCaps
-{
-  std::map<std::string, uint32_t> caps;
-
-  int get_cap(const std::string& cap, std::string& type, uint32_t *perm);
-  int add_cap(const std::string& cap);
-  int remove_cap(const std::string& cap);
-public:
-  static int parse_cap_perm(const std::string& str, uint32_t *perm);
-  int add_from_string(const std::string& str);
-  int remove_from_string(const std::string& str);
-
-  void encode(bufferlist& bl) const {
-     ENCODE_START(1, 1, bl);
-     encode(caps, bl);
-     ENCODE_FINISH(bl);
-  }
-  void decode(bufferlist::const_iterator& bl) {
-     DECODE_START(1, bl);
-     decode(caps, bl);
-     DECODE_FINISH(bl);
-  }
-  int check_cap(const std::string& cap, uint32_t perm) const;
-  bool is_valid_cap_type(const std::string& tp);
-  void dump(Formatter *f) const;
-  void dump(Formatter *f, const char *name) const;
-
-  void decode_json(JSONObj *obj);
-};
-WRITE_CLASS_ENCODER(RGWUserCaps)
-
 void encode_json(const char *name, const obj_version& v, Formatter *f);
 void encode_json(const char *name, const RGWUserCaps& val, Formatter *f);
 
 void decode_json_obj(obj_version& v, JSONObj *obj);
 
-
-
 enum RGWIdentityType
 {
   TYPE_NONE=0,
@@ -583,113 +503,6 @@ enum RGWIdentityType
   TYPE_WEB=5,
 };
 
-static std::string RGW_STORAGE_CLASS_STANDARD = "STANDARD";
-
-struct rgw_placement_rule {
-  std::string name;
-  std::string storage_class;
-
-  rgw_placement_rule() {}
-  rgw_placement_rule(const std::string& _n, const std::string& _sc) : name(_n), storage_class(_sc) {}
-  rgw_placement_rule(const rgw_placement_rule& _r, const std::string& _sc) : name(_r.name) {
-    if (!_sc.empty()) {
-      storage_class = _sc;
-    } else {
-      storage_class = _r.storage_class;
-    }
-  }
-
-  bool empty() const {
-    return name.empty() && storage_class.empty();
-  }
-
-  void inherit_from(const rgw_placement_rule& r) {
-    if (name.empty()) {
-      name = r.name;
-    }
-    if (storage_class.empty()) {
-      storage_class = r.storage_class;
-    }
-  }
-
-  void clear() {
-    name.clear();
-    storage_class.clear();
-  }
-
-  void init(const std::string& n, const std::string& c) {
-    name = n;
-    storage_class = c;
-  }
-
-  static const std::string& get_canonical_storage_class(const std::string& storage_class) {
-    if (storage_class.empty()) {
-      return RGW_STORAGE_CLASS_STANDARD;
-    }
-    return storage_class;
-  }
-
-  const std::string& get_storage_class() const {
-    return get_canonical_storage_class(storage_class);
-  }
-  
-  int compare(const rgw_placement_rule& r) const {
-    int c = name.compare(r.name);
-    if (c != 0) {
-      return c;
-    }
-    return get_storage_class().compare(r.get_storage_class());
-  }
-
-  bool operator==(const rgw_placement_rule& r) const {
-    return (name == r.name &&
-            get_storage_class() == r.get_storage_class());
-  }
-
-  bool operator!=(const rgw_placement_rule& r) const {
-    return !(*this == r);
-  }
-
-  void encode(bufferlist& bl) const {
-    /* no ENCODE_START/END due to backward compatibility */
-    std::string s = to_str();
-    ceph::encode(s, bl);
-  }
-
-  void decode(bufferlist::const_iterator& bl) {
-    std::string s;
-    ceph::decode(s, bl);
-    from_str(s);
-  } 
-
-  std::string to_str() const {
-    if (standard_storage_class()) {
-      return name;
-    }
-    return to_str_explicit();
-  }
-
-  std::string to_str_explicit() const {
-    return name + "/" + storage_class;
-  }
-
-  void from_str(const std::string& s) {
-    size_t pos = s.find("/");
-    if (pos == std::string::npos) {
-      name = s;
-      storage_class.clear();
-      return;
-    }
-    name = s.substr(0, pos);
-    storage_class = s.substr(pos + 1);
-  }
-
-  bool standard_storage_class() const {
-    return storage_class.empty() || storage_class == RGW_STORAGE_CLASS_STANDARD;
-  }
-};
-WRITE_CLASS_ENCODER(rgw_placement_rule)
-
 void encode_json(const char *name, const rgw_placement_rule& val, ceph::Formatter *f);
 void decode_json_obj(rgw_placement_rule& v, JSONObj *obj);
 
@@ -749,12 +562,10 @@ struct RGWUserInfo
   __u8 system;
   rgw_placement_rule default_placement;
   std::list<std::string> placement_tags;
-  RGWQuotaInfo bucket_quota;
   std::map<int, std::string> temp_url_keys;
-  RGWQuotaInfo user_quota;
+  RGWQuota quota;
   uint32_t type;
   std::set<std::string> mfa_ids;
-  std::string assumed_role_arn;
 
   RGWUserInfo()
     : suspended(0),
@@ -812,14 +623,17 @@ struct RGWUserInfo
      encode(system, bl);
      encode(default_placement, bl);
      encode(placement_tags, bl);
-     encode(bucket_quota, bl);
+     encode(quota.bucket_quota, bl);
      encode(temp_url_keys, bl);
-     encode(user_quota, bl);
+     encode(quota.user_quota, bl);
      encode(user_id.tenant, bl);
      encode(admin, bl);
      encode(type, bl);
      encode(mfa_ids, bl);
-     encode(assumed_role_arn, bl);
+     {
+       std::string assumed_role_arn; // removed
+       encode(assumed_role_arn, bl);
+     }
      encode(user_id.ns, bl);
      ENCODE_FINISH(bl);
   }
@@ -880,13 +694,13 @@ struct RGWUserInfo
       decode(placement_tags, bl); /* tags of allowed placement rules */
     }
     if (struct_v >= 14) {
-      decode(bucket_quota, bl);
+      decode(quota.bucket_quota, bl);
     }
     if (struct_v >= 15) {
      decode(temp_url_keys, bl);
     }
     if (struct_v >= 16) {
-      decode(user_quota, bl);
+      decode(quota.user_quota, bl);
     }
     if (struct_v >= 17) {
       decode(user_id.tenant, bl);
@@ -903,6 +717,7 @@ struct RGWUserInfo
       decode(mfa_ids, bl);
     }
     if (struct_v >= 21) {
+      std::string assumed_role_arn; // removed
       decode(assumed_role_arn, bl);
     }
     if (struct_v >= 22) {
@@ -919,121 +734,130 @@ struct RGWUserInfo
 };
 WRITE_CLASS_ENCODER(RGWUserInfo)
 
-struct rgw_raw_obj {
-  rgw_pool pool;
-  std::string oid;
-  std::string loc;
-
-  rgw_raw_obj() {}
-  rgw_raw_obj(const rgw_pool& _pool, const std::string& _oid) {
-    init(_pool, _oid);
-  }
-  rgw_raw_obj(const rgw_pool& _pool, const std::string& _oid, const std::string& _loc) : loc(_loc) {
-    init(_pool, _oid);
-  }
-
-  void init(const rgw_pool& _pool, const std::string& _oid) {
-    pool = _pool;
-    oid = _oid;
-  }
-
-  bool empty() const {
-    return oid.empty();
-  }
-
-  void encode(bufferlist& bl) const {
-     ENCODE_START(6, 6, bl);
-    encode(pool, bl);
-    encode(oid, bl);
-    encode(loc, bl);
-    ENCODE_FINISH(bl);
-  }
-
-  void decode_from_rgw_obj(bufferlist::const_iterator& bl);
-
-  void decode(bufferlist::const_iterator& bl) {
-    unsigned ofs = bl.get_off();
-    DECODE_START(6, bl);
-    if (struct_v < 6) {
-      /*
-       * this object was encoded as rgw_obj, prior to rgw_raw_obj been split out of it,
-       * let's decode it as rgw_obj and convert it
-       */
-      bl.seek(ofs);
-      decode_from_rgw_obj(bl);
-      return;
-    }
-    decode(pool, bl);
-    decode(oid, bl);
-    decode(loc, bl);
-    DECODE_FINISH(bl);
-  }
-
-  bool operator<(const rgw_raw_obj& o) const {
-    int r = pool.compare(o.pool);
-    if (r == 0) {
-      r = oid.compare(o.oid);
-      if (r == 0) {
-        r = loc.compare(o.loc);
-      }
-    }
-    return (r < 0);
-  }
-
-  bool operator==(const rgw_raw_obj& o) const {
-    return (pool == o.pool && oid == o.oid && loc == o.loc);
-  }
-
-  void dump(Formatter *f) const;
-  void decode_json(JSONObj *obj);
-};
-WRITE_CLASS_ENCODER(rgw_raw_obj)
-
-inline std::ostream& operator<<(std::ostream& out, const rgw_raw_obj& o) {
-  out << o.pool << ":" << o.oid;
-  return out;
-}
-
-struct rgw_bucket_placement {
-  rgw_placement_rule placement_rule;
-  rgw_bucket bucket;
-
-  void dump(Formatter *f) const;
-};
-
+/// `RGWObjVersionTracker`
+/// ======================
+///
+/// What and why is this?
+/// ---------------------
+///
+/// This is a wrapper around `cls_version` functionality. If two RGWs
+/// (or two non-synchronized threads in the same RGW) are accessing
+/// the same object, they may race and overwrite each other's work.
+///
+/// This class solves this issue by tracking and recording an object's
+/// version in the extended attributes. Operations are failed with
+/// ECANCELED if the version is not what we expect.
+///
+/// How to Use It
+/// -------------
+///
+/// When preparing a read operation, call `prepare_op_for_read`.
+/// For a write, call `prepare_op_for_write` when preparing the
+/// operation, and `apply_write` after it succeeds.
+///
+/// Adhere to the following guidelines:
+///
+/// - Each RGWObjVersionTracker should be used with only one object.
+///
+/// - If you receive `ECANCELED`, throw away whatever you were doing
+///   based on the content of the versioned object, re-read, and
+///   restart as appropriate.
+///
+/// - If one code path uses RGWObjVersionTracker, then they all
+///   should. In a situation where a writer should unconditionally
+///   overwrite an object, call `generate_new_write_ver` on a default
+///   constructed `RGWObjVersionTracker`.
+///
+/// - If we have a version from a previous read, we will check against
+///   it and fail the read if it doesn't match. Thus, if we want to
+///   re-read a new version of the object, call `clear()` on the
+///   `RGWObjVersionTracker`.
+///
+/// - This type is not thread-safe. Every thread must have its own
+///   instance.
+///
 struct RGWObjVersionTracker {
-  obj_version read_version;
-  obj_version write_version;
-
-  obj_version *version_for_read() {
+  obj_version read_version; //< The version read from an object. If
+                           //  set, this value is used to check the
+                           //  stored version.
+  obj_version write_version; //< Set the object to this version on
+                            //  write, if set.
+
+  /// Pointer to the read version.
+  obj_version* version_for_read() {
     return &read_version;
   }
 
-  obj_version *version_for_write() {
+  /// If we have a write version, return a pointer to it. Otherwise
+  /// return null. This is used in `prepare_op_for_write` to treat the
+  /// `write_version` as effectively an `option` type.
+  obj_version* version_for_write() {
     if (write_version.ver == 0)
-      return NULL;
+      return nullptr;
 
     return &write_version;
   }
 
-  obj_version *version_for_check() {
+  /// If read_version is non-empty, return a pointer to it, otherwise
+  /// null. This is used internally by `prepare_op_for_read` and
+  /// `prepare_op_for_write` to treat the `read_version` as
+  /// effectively an `option` type.
+  obj_version* version_for_check() {
     if (read_version.ver == 0)
-      return NULL;
+      return nullptr;
 
     return &read_version;
   }
 
-  void prepare_op_for_read(librados::ObjectReadOperation *op);
-  void prepare_op_for_write(librados::ObjectWriteOperation *op);
-
+  /// This function is to be called on any read operation. If we have
+  /// a non-empty `read_version`, assert on the OSD that the object
+  /// has the same version. Also reads the version into `read_version`.
+  ///
+  /// This function is defined in `rgw_rados.cc` rather than `rgw_common.cc`.
+  void prepare_op_for_read(librados::ObjectReadOperation* op);
+
+  /// This function is to be called on any write operation. If we have
+  /// a non-empty read operation, assert on the OSD that the object
+  /// has the same version. If we have a non-empty `write_version`,
+  /// set the object to it. Otherwise increment the version on the OSD.
+  ///
+  /// This function is defined in `rgw_rados.cc` rather than
+  /// `rgw_common.cc`.
+  void prepare_op_for_write(librados::ObjectWriteOperation* op);
+
+  /// This function is to be called after the completion of any write
+  /// operation on which `prepare_op_for_write` was called. If we did
+  /// not set the write version explicitly, it increments
+  /// `read_version`. If we did, it sets `read_version` to
+  /// `write_version`. In either case, it clears `write_version`.
+  ///
+  /// RADOS write operations, at least those not using the relatively
+  /// new RETURNVEC flag, cannot return more information than an error
+  /// code. Thus, write operations can't simply fill in the read
+  /// version the way read operations can, so prepare_op_for_write`
+  /// instructs the OSD to increment the object as stored in RADOS and
+  /// `apply_write` increments our `read_version` in RAM.
+  ///
+  /// This function is defined in `rgw_rados.cc` rather than
+  /// `rgw_common.cc`.
   void apply_write();
 
+  /// Clear `read_version` and `write_version`, making the instance
+  /// identical to a default-constructed instance.
   void clear() {
     read_version = obj_version();
     write_version = obj_version();
   }
 
-  void generate_new_write_ver(CephContext *cct);
+  /// Set `write_version` to a new, unique version.
+  ///
+  /// An `obj_version` contains an opaque, random tag and a
+  /// sequence. If the tags of two `obj_version`s don't match, the
+  /// versions are unordered and unequal. This function creates a
+  /// version with a new tag, ensuring that any other process
+  /// operating on the object will receive `ECANCELED` and will know
+  /// to re-read the object and restart whatever it was doing.
+  void generate_new_write_ver(CephContext* cct);
 };
 
 inline std::ostream& operator<<(std::ostream& out, const obj_version &v)
@@ -1073,11 +897,6 @@ struct RGWBucketInfo {
   // layout of bucket index objects
   rgw::BucketLayout layout;
 
-  // Represents the number of bucket index object shards:
-  //   - value of 0 indicates there is no sharding (this is by default
-  //     before this feature is implemented).
-  //   - value of UINT32_T::MAX indicates this is a blind bucket.
-
   // Represents the shard number for blind bucket.
   const static uint32_t NUM_SHARDS_BLIND_BUCKET;
 
@@ -1123,6 +942,16 @@ struct RGWBucketInfo {
 
   bool empty_sync_policy() const;
 
+  bool is_indexless() const {
+    return rgw::is_layout_indexless(layout.current_index);
+  }
+  const rgw::bucket_index_layout_generation& get_current_index() const {
+    return layout.current_index;
+  }
+  rgw::bucket_index_layout_generation& get_current_index() {
+    return layout.current_index;
+  }
+
   RGWBucketInfo();
   ~RGWBucketInfo();
 };
@@ -1243,299 +1072,6 @@ struct req_info {
   void init_meta_info(const DoutPrefixProvider *dpp, bool *found_bad_meta);
 };
 
-typedef cls_rgw_obj_key rgw_obj_index_key;
-
-struct rgw_obj_key {
-  std::string name;
-  std::string instance;
-  std::string ns;
-
-  rgw_obj_key() {}
-  // cppcheck-suppress noExplicitConstructor
-  rgw_obj_key(const std::string& n) : name(n) {}
-  rgw_obj_key(const std::string& n, const std::string& i) : name(n), instance(i) {}
-  rgw_obj_key(const std::string& n, const std::string& i, const std::string& _ns) : name(n), instance(i), ns(_ns) {}
-
-  rgw_obj_key(const rgw_obj_index_key& k) {
-    parse_index_key(k.name, &name, &ns);
-    instance = k.instance;
-  }
-
-  static void parse_index_key(const std::string& key, std::string *name, std::string *ns) {
-    if (key[0] != '_') {
-      *name = key;
-      ns->clear();
-      return;
-    }
-    if (key[1] == '_') {
-      *name = key.substr(1);
-      ns->clear();
-      return;
-    }
-    ssize_t pos = key.find('_', 1);
-    if (pos < 0) {
-      /* shouldn't happen, just use key */
-      *name = key;
-      ns->clear();
-      return;
-    }
-
-    *name = key.substr(pos + 1);
-    *ns = key.substr(1, pos -1);
-  }
-
-  void set(const std::string& n) {
-    name = n;
-    instance.clear();
-    ns.clear();
-  }
-
-  void set(const std::string& n, const std::string& i) {
-    name = n;
-    instance = i;
-    ns.clear();
-  }
-
-  void set(const std::string& n, const std::string& i, const std::string& _ns) {
-    name = n;
-    instance = i;
-    ns = _ns;
-  }
-
-  bool set(const rgw_obj_index_key& index_key) {
-    if (!parse_raw_oid(index_key.name, this)) {
-      return false;
-    }
-    instance = index_key.instance;
-    return true;
-  }
-
-  void set_instance(const std::string& i) {
-    instance = i;
-  }
-
-  const std::string& get_instance() const {
-    return instance;
-  }
-
-  void set_ns(const std::string& _ns) {
-    ns = _ns;
-  }
-
-  const std::string& get_ns() const {
-    return ns;
-  }
-
-  std::string get_index_key_name() const {
-    if (ns.empty()) {
-      if (name.size() < 1 || name[0] != '_') {
-        return name;
-      }
-      return std::string("_") + name;
-    };
-
-    char buf[ns.size() + 16];
-    snprintf(buf, sizeof(buf), "_%s_", ns.c_str());
-    return std::string(buf) + name;
-  };
-
-  void get_index_key(rgw_obj_index_key *key) const {
-    key->name = get_index_key_name();
-    key->instance = instance;
-  }
-
-  std::string get_loc() const {
-    /*
-     * For backward compatibility. Older versions used to have object locator on all objects,
-     * however, the name was the effective object locator. This had the same effect as not
-     * having object locator at all for most objects but the ones that started with underscore as
-     * these were escaped.
-     */
-    if (name[0] == '_' && ns.empty()) {
-      return name;
-    }
-
-    return {};
-  }
-
-  bool empty() const {
-    return name.empty();
-  }
-
-  bool have_null_instance() const {
-    return instance == "null";
-  }
-
-  bool have_instance() const {
-    return !instance.empty();
-  }
-
-  bool need_to_encode_instance() const {
-    return have_instance() && !have_null_instance();
-  }
-
-  std::string get_oid() const {
-    if (ns.empty() && !need_to_encode_instance()) {
-      if (name.size() < 1 || name[0] != '_') {
-        return name;
-      }
-      return std::string("_") + name;
-    }
-
-    std::string oid = "_";
-    oid.append(ns);
-    if (need_to_encode_instance()) {
-      oid.append(std::string(":") + instance);
-    }
-    oid.append("_");
-    oid.append(name);
-    return oid;
-  }
-
-  bool operator==(const rgw_obj_key& k) const {
-    return (name.compare(k.name) == 0) &&
-           (instance.compare(k.instance) == 0);
-  }
-
-  bool operator<(const rgw_obj_key& k) const {
-    int r = name.compare(k.name);
-    if (r == 0) {
-      r = instance.compare(k.instance);
-    }
-    return (r < 0);
-  }
-
-  bool operator<=(const rgw_obj_key& k) const {
-    return !(k < *this);
-  }
-
-  static void parse_ns_field(std::string& ns, std::string& instance) {
-    int pos = ns.find(':');
-    if (pos >= 0) {
-      instance = ns.substr(pos + 1);
-      ns = ns.substr(0, pos);
-    } else {
-      instance.clear();
-    }
-  }
-
-  // takes an oid and parses out the namespace (ns), name, and
-  // instance
-  static bool parse_raw_oid(const std::string& oid, rgw_obj_key *key) {
-    key->instance.clear();
-    key->ns.clear();
-    if (oid[0] != '_') {
-      key->name = oid;
-      return true;
-    }
-
-    if (oid.size() >= 2 && oid[1] == '_') {
-      key->name = oid.substr(1);
-      return true;
-    }
-
-    if (oid.size() < 3) // for namespace, min size would be 3: _x_
-      return false;
-
-    size_t pos = oid.find('_', 2); // oid must match ^_[^_].+$
-    if (pos == std::string::npos)
-      return false;
-
-    key->ns = oid.substr(1, pos - 1);
-    parse_ns_field(key->ns, key->instance);
-
-    key->name = oid.substr(pos + 1);
-    return true;
-  }
-
-  /**
-   * Translate a namespace-mangled object name to the user-facing name
-   * existing in the given namespace.
-   *
-   * If the object is part of the given namespace, it returns true
-   * and cuts down the name to the unmangled version. If it is not
-   * part of the given namespace, it returns false.
-   */
-  static bool oid_to_key_in_ns(const std::string& oid, rgw_obj_key *key, const std::string& ns) {
-    bool ret = parse_raw_oid(oid, key);
-    if (!ret) {
-      return ret;
-    }
-
-    return (ns == key->ns);
-  }
-
-  /**
-   * Given a mangled object name and an empty namespace std::string, this
-   * function extracts the namespace into the std::string and sets the object
-   * name to be the unmangled version.
-   *
-   * It returns true after successfully doing so, or
-   * false if it fails.
-   */
-  static bool strip_namespace_from_name(std::string& name, std::string& ns, std::string& instance) {
-    ns.clear();
-    instance.clear();
-    if (name[0] != '_') {
-      return true;
-    }
-
-    size_t pos = name.find('_', 1);
-    if (pos == std::string::npos) {
-      return false;
-    }
-
-    if (name[1] == '_') {
-      name = name.substr(1);
-      return true;
-    }
-
-    size_t period_pos = name.find('.');
-    if (period_pos < pos) {
-      return false;
-    }
-
-    ns = name.substr(1, pos-1);
-    name = name.substr(pos+1, std::string::npos);
-
-    parse_ns_field(ns, instance);
-    return true;
-  }
-
-  void encode(bufferlist& bl) const {
-    ENCODE_START(2, 1, bl);
-    encode(name, bl);
-    encode(instance, bl);
-    encode(ns, bl);
-    ENCODE_FINISH(bl);
-  }
-  void decode(bufferlist::const_iterator& bl) {
-    DECODE_START(2, bl);
-    decode(name, bl);
-    decode(instance, bl);
-    if (struct_v >= 2) {
-      decode(ns, bl);
-    }
-    DECODE_FINISH(bl);
-  }
-  void dump(Formatter *f) const;
-  void decode_json(JSONObj *obj);
-
-  std::string to_str() const {
-    if (instance.empty()) {
-      return name;
-    }
-    char buf[name.size() + instance.size() + 16];
-    snprintf(buf, sizeof(buf), "%s[%s]", name.c_str(), instance.c_str());
-    return buf;
-  }
-};
-WRITE_CLASS_ENCODER(rgw_obj_key)
-
-inline std::ostream& operator<<(std::ostream& out, const rgw_obj_key &o) {
-  return out << o.to_str();
-}
-
 struct req_init_state {
   /* Keeps [[tenant]:]bucket until we parse the token. */
   std::string url_bucket;
@@ -1545,11 +1081,11 @@ struct req_init_state {
 #include "rgw_auth.h"
 
 class RGWObjectCtx;
-class RGWSysObjectCtx;
 
 /** Store all the state necessary to complete and respond to an HTTP request*/
 struct req_state : DoutPrefixProvider {
   CephContext *cct;
+  const RGWProcessEnv& penv;
   rgw::io::BasicClient *cio{nullptr};
   http_op op{OP_UNKNOWN};
   RGWOpType op_type{};
@@ -1559,7 +1095,7 @@ struct req_state : DoutPrefixProvider {
   std::string ratelimit_bucket_marker;
   std::string ratelimit_user_name;
   bool content_started{false};
-  int format{0};
+  RGWFormat format{RGWFormat::PLAIN};
   ceph::Formatter *formatter{nullptr};
   std::string decoded_uri;
   std::string relative_uri;
@@ -1674,7 +1210,6 @@ struct req_state : DoutPrefixProvider {
 
   Clock::duration time_elapsed() const { return Clock::now() - time; }
 
-  RGWObjectCtx *obj_ctx{nullptr};
   std::string dialect;
   std::string req_id;
   std::string trans_id;
@@ -1693,11 +1228,12 @@ struct req_state : DoutPrefixProvider {
   std::vector<rgw::IAM::Policy> session_policies;
 
   jspan trace;
+  bool trace_enabled = false;
 
   //Principal tags that come in as part of AssumeRoleWithWebIdentity
   std::vector<std::pair<std::string, std::string>> principal_tags;
 
-  req_state(CephContext* _cct, RGWEnv* e, uint64_t id);
+  req_state(CephContext* _cct, const RGWProcessEnv& penv, RGWEnv* e, uint64_t id);
   ~req_state();
 
 
@@ -1710,10 +1246,10 @@ struct req_state : DoutPrefixProvider {
   unsigned get_subsys() const override { return ceph_subsys_rgw; }
 };
 
-void set_req_state_err(struct req_state*, int);
-void set_req_state_err(struct req_state*, int, const std::string&);
+void set_req_state_err(req_state*, int);
+void set_req_state_err(req_state*, int, const std::string&);
 void set_req_state_err(struct rgw_err&, int, const int);
-void dump(struct req_state*);
+void dump(req_state*);
 
 /** Store basic data on bucket */
 struct RGWBucketEnt {
@@ -1799,135 +1335,6 @@ struct RGWBucketEnt {
 };
 WRITE_CLASS_ENCODER(RGWBucketEnt)
 
-struct rgw_obj {
-  rgw_bucket bucket;
-  rgw_obj_key key;
-
-  bool in_extra_data{false}; /* in-memory only member, does not serialize */
-
-  // Represents the hash index source for this object once it is set (non-empty)
-  std::string index_hash_source;
-
-  rgw_obj() {}
-  rgw_obj(const rgw_bucket& b, const std::string& name) : bucket(b), key(name) {}
-  rgw_obj(const rgw_bucket& b, const rgw_obj_key& k) : bucket(b), key(k) {}
-  rgw_obj(const rgw_bucket& b, const rgw_obj_index_key& k) : bucket(b), key(k) {}
-
-  void init(const rgw_bucket& b, const std::string& name) {
-    bucket = b;
-    key.set(name);
-  }
-  void init(const rgw_bucket& b, const std::string& name, const std::string& i, const std::string& n) {
-    bucket = b;
-    key.set(name, i, n);
-  }
-  void init_ns(const rgw_bucket& b, const std::string& name, const std::string& n) {
-    bucket = b;
-    key.name = name;
-    key.instance.clear();
-    key.ns = n;
-  }
-
-  bool empty() const {
-    return key.empty();
-  }
-
-  void set_key(const rgw_obj_key& k) {
-    key = k;
-  }
-
-  std::string get_oid() const {
-    return key.get_oid();
-  }
-
-  const std::string& get_hash_object() const {
-    return index_hash_source.empty() ? key.name : index_hash_source;
-  }
-
-  void set_in_extra_data(bool val) {
-    in_extra_data = val;
-  }
-
-  bool is_in_extra_data() const {
-    return in_extra_data;
-  }
-
-  void encode(bufferlist& bl) const {
-    ENCODE_START(6, 6, bl);
-    encode(bucket, bl);
-    encode(key.ns, bl);
-    encode(key.name, bl);
-    encode(key.instance, bl);
-//    encode(placement_id, bl);
-    ENCODE_FINISH(bl);
-  }
-  void decode(bufferlist::const_iterator& bl) {
-    DECODE_START_LEGACY_COMPAT_LEN(6, 3, 3, bl);
-    if (struct_v < 6) {
-      std::string s;
-      decode(bucket.name, bl); /* bucket.name */
-      decode(s, bl); /* loc */
-      decode(key.ns, bl);
-      decode(key.name, bl);
-      if (struct_v >= 2)
-        decode(bucket, bl);
-      if (struct_v >= 4)
-        decode(key.instance, bl);
-      if (key.ns.empty() && key.instance.empty()) {
-        if (key.name[0] == '_') {
-          key.name = key.name.substr(1);
-        }
-      } else {
-        if (struct_v >= 5) {
-          decode(key.name, bl);
-        } else {
-          ssize_t pos = key.name.find('_', 1);
-          if (pos < 0) {
-            throw buffer::malformed_input();
-          }
-          key.name = key.name.substr(pos + 1);
-        }
-      }
-    } else {
-      decode(bucket, bl);
-      decode(key.ns, bl);
-      decode(key.name, bl);
-      decode(key.instance, bl);
-//      decode(placement_id, bl);
-    }
-    DECODE_FINISH(bl);
-  }
-  void dump(Formatter *f) const;
-  static void generate_test_instances(std::list<rgw_obj*>& o);
-
-  bool operator==(const rgw_obj& o) const {
-    return (key == o.key) &&
-           (bucket == o.bucket);
-  }
-  bool operator<(const rgw_obj& o) const {
-    int r = key.name.compare(o.key.name);
-    if (r == 0) {
-      r = bucket.bucket_id.compare(o.bucket.bucket_id); /* not comparing bucket.name, if bucket_id is equal so will be bucket.name */
-      if (r == 0) {
-        r = key.ns.compare(o.key.ns);
-        if (r == 0) {
-          r = key.instance.compare(o.key.instance);
-        }
-      }
-    }
-
-    return (r < 0);
-  }
-
-  const rgw_pool& get_explicit_data_pool() {
-    if (!in_extra_data || bucket.explicit_placement.data_extra_pool.empty()) {
-      return bucket.explicit_placement.data_pool;
-    }
-    return bucket.explicit_placement.data_extra_pool;
-  }
-};
-WRITE_CLASS_ENCODER(rgw_obj)
-
 struct rgw_cache_entry_info {
   std::string cache_locator;
   uint64_t gen;
@@ -2074,6 +1481,10 @@ parse_key_value(const std::string_view& in_str,
 extern boost::optional<std::pair<std::string_view,std::string_view>>
 parse_key_value(const std::string_view& in_str);
 
+struct rgw_name_to_flag {
+  const char *type_name;
+  uint32_t flag;
+};
 
 /** time parsing */
 extern int parse_time(const char *time_str, real_time *time);
@@ -2173,31 +1584,34 @@ bool verify_object_permission_no_policy(const DoutPrefixProvider* dpp,
 
 /** Check if the req_state's user has the necessary permissions
  * to do the requested action */
-rgw::IAM::Effect eval_identity_or_session_policies(const std::vector<rgw::IAM::Policy>& user_policies,
+rgw::IAM::Effect eval_identity_or_session_policies(const DoutPrefixProvider* dpp,
+                         const std::vector<rgw::IAM::Policy>& user_policies,
                           const rgw::IAM::Environment& env,
                           const uint64_t op,
                           const rgw::ARN& arn);
 bool verify_user_permission(const DoutPrefixProvider* dpp,
-                            struct req_state * const s,
+                            req_state * const s,
                             RGWAccessControlPolicy * const user_acl,
                             const std::vector<rgw::IAM::Policy>& user_policies,
                             const std::vector<rgw::IAM::Policy>& session_policies,
                             const rgw::ARN& res,
-                            const uint64_t op);
+                            const uint64_t op,
+                            bool mandatory_policy=true);
 bool verify_user_permission_no_policy(const DoutPrefixProvider* dpp,
-                                      struct req_state * const s,
+                                      req_state * const s,
                                       RGWAccessControlPolicy * const user_acl,
                                       const int perm);
 bool verify_user_permission(const DoutPrefixProvider* dpp,
-                            struct req_state * const s,
+                            req_state * const s,
                             const rgw::ARN& res,
-                            const uint64_t op);
+                            const uint64_t op,
+                            bool mandatory_policy=true);
 bool verify_user_permission_no_policy(const DoutPrefixProvider* dpp,
-                                      struct req_state * const s,
+                                      req_state * const s,
                                       int perm);
 bool verify_bucket_permission(
   const DoutPrefixProvider* dpp,
-  struct req_state * const s,
+  req_state * const s,
   const rgw_bucket& bucket,
   RGWAccessControlPolicy * const user_acl,
   RGWAccessControlPolicy * const bucket_acl,
@@ -2205,21 +1619,21 @@ bool verify_bucket_permission(
   const std::vector<rgw::IAM::Policy>& identity_policies,
   const std::vector<rgw::IAM::Policy>& session_policies,
   const uint64_t op);
-bool verify_bucket_permission(const DoutPrefixProvider* dpp, struct req_state * const s, const uint64_t op);
+bool verify_bucket_permission(const DoutPrefixProvider* dpp, req_state * const s, const uint64_t op);
 bool verify_bucket_permission_no_policy(
   const DoutPrefixProvider* dpp,
-  struct req_state * const s,
+  req_state * const s,
   RGWAccessControlPolicy * const user_acl,
   RGWAccessControlPolicy * const bucket_acl,
   const int perm);
 bool verify_bucket_permission_no_policy(const DoutPrefixProvider* dpp,
-                                        struct req_state * const s,
+                                        req_state * const s,
                                        const int perm);
-int verify_bucket_owner_or_policy(struct req_state* const s,
+int verify_bucket_owner_or_policy(req_state* const s,
                                  const uint64_t op);
 extern bool verify_object_permission(
   const DoutPrefixProvider* dpp,
-  struct req_state * const s,
+  req_state * const s,
   const rgw_obj& obj,
   RGWAccessControlPolicy * const user_acl,
   RGWAccessControlPolicy * const bucket_acl,
@@ -2228,15 +1642,15 @@ extern bool verify_object_permission(
   const std::vector<rgw::IAM::Policy>& identity_policies,
   const std::vector<rgw::IAM::Policy>& session_policies,
   const uint64_t op);
-extern bool verify_object_permission(const DoutPrefixProvider* dpp, struct req_state *s, uint64_t op);
+extern bool verify_object_permission(const DoutPrefixProvider* dpp, req_state *s, uint64_t op);
 extern bool verify_object_permission_no_policy(
   const DoutPrefixProvider* dpp,
-  struct req_state * const s,
+  req_state * const s,
   RGWAccessControlPolicy * const user_acl,
   RGWAccessControlPolicy * const bucket_acl,
   RGWAccessControlPolicy * const object_acl,
   int perm);
-extern bool verify_object_permission_no_policy(const DoutPrefixProvider* dpp, struct req_state *s,
+extern bool verify_object_permission_no_policy(const DoutPrefixProvider* dpp, req_state *s,
                                               int perm);
 extern int verify_object_lock(
   const DoutPrefixProvider* dpp,
@@ -2414,3 +1828,11 @@ int decode_bl(bufferlist& bl, T& t)
   }
   return 0;
 }
+
+extern int rgw_bucket_parse_bucket_instance(const std::string& bucket_instance, std::string *bucket_name, std::string *bucket_id, int *shard_id);
+
+boost::intrusive_ptr<CephContext>
+rgw_global_init(const std::map<std::string,std::string> *defaults,
+                   std::vector < const char* >& args,
+                   uint32_t module_type, code_environment_t code_env,
+                   int flags);