New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
rgw: improve handling of Swift's error messages and limits #15369
Changes from all commits
e851614
1845e41
593d656
64b7923
06b1f25
9e53c14
21ad80a
308c8d3
9b06985
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1884,38 +1884,73 @@ static inline void format_xattr(std::string &xattr) | |
* map(<attr_name, attr_contents>, where attr_name is RGW_ATTR_PREFIX.HTTP_NAME) | ||
* s: The request state | ||
* attrs: will be filled up with attrs mapped as <attr_name, attr_contents> | ||
* On success returns 0. | ||
* On failure returns a negative error code. | ||
* | ||
*/ | ||
static inline void rgw_get_request_metadata(CephContext *cct, | ||
struct req_info& info, | ||
map<string, bufferlist>& attrs, | ||
const bool allow_empty_attrs = true) | ||
static inline int rgw_get_request_metadata(CephContext* const cct, | ||
struct req_info& info, | ||
std::map<std::string, ceph::bufferlist>& attrs, | ||
const bool allow_empty_attrs = true) | ||
{ | ||
static const std::set<std::string> blacklisted_headers = { | ||
"x-amz-server-side-encryption-customer-algorithm", | ||
"x-amz-server-side-encryption-customer-key", | ||
"x-amz-server-side-encryption-customer-key-md5" | ||
}; | ||
map<string, string>::iterator iter; | ||
for (iter = info.x_meta_map.begin(); iter != info.x_meta_map.end(); ++iter) { | ||
const string &name(iter->first); | ||
string &xattr(iter->second); | ||
|
||
size_t valid_meta_count = 0; | ||
for (auto& kv : info.x_meta_map) { | ||
const std::string& name = kv.first; | ||
std::string& xattr = kv.second; | ||
|
||
if (blacklisted_headers.count(name) == 1) { | ||
lsubdout(cct, rgw, 10) << "skipping x>> " << name << dendl; | ||
continue; | ||
} | ||
if (allow_empty_attrs || !xattr.empty()) { | ||
} else if (allow_empty_attrs || !xattr.empty()) { | ||
lsubdout(cct, rgw, 10) << "x>> " << name << ":" << xattr << dendl; | ||
format_xattr(xattr); | ||
string attr_name(RGW_ATTR_PREFIX); | ||
|
||
std::string attr_name(RGW_ATTR_PREFIX); | ||
attr_name.append(name); | ||
map<string, bufferlist>::value_type v(attr_name, bufferlist()); | ||
std::pair < map<string, bufferlist>::iterator, bool > | ||
rval(attrs.insert(v)); | ||
bufferlist& bl(rval.first->second); | ||
|
||
/* Check roughly whether we aren't going behind the limit on attribute | ||
* name. Passing here doesn't guarantee that an OSD will accept that | ||
* as ObjectStore::get_max_attr_name_length() can set the limit even | ||
* lower than the "osd_max_attr_name_len" configurable. */ | ||
const size_t max_attr_name_len = \ | ||
cct->_conf->get_val<size_t>("rgw_max_attr_name_len"); | ||
if (max_attr_name_len && attr_name.length() > max_attr_name_len) { | ||
return -ENAMETOOLONG; | ||
} | ||
|
||
/* Similar remarks apply to the check for value size. We're veryfing | ||
* it early at the RGW's side as it's being claimed in /info. */ | ||
const size_t max_attr_size = \ | ||
cct->_conf->get_val<size_t>("rgw_max_attr_size"); | ||
if (max_attr_size && xattr.length() > max_attr_size) { | ||
return -EFBIG; | ||
} | ||
|
||
/* Swift allows administrators to limit the number of metadats items | ||
* send _in a single request_. */ | ||
const auto rgw_max_attrs_num_in_req = \ | ||
cct->_conf->get_val<size_t>("rgw_max_attrs_num_in_req"); | ||
if (rgw_max_attrs_num_in_req && | ||
++valid_meta_count > rgw_max_attrs_num_in_req) { | ||
return -E2BIG; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's logic elsewhere in this commit that turns E2BIG into an error message. It would be much better to generate that error message here. That would result in simpler and easier to understand logic with less chance of breakage - less brittle! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm afraid there is a reason for not doing that. IIRC the |
||
} | ||
|
||
auto rval = attrs.emplace(std::move(attr_name), ceph::bufferlist()); | ||
/* At the moment the value of the freshly created attribute key-value | ||
* pair is an empty bufferlist. */ | ||
|
||
ceph::bufferlist& bl = rval.first->second; | ||
bl.append(xattr.c_str(), xattr.size() + 1); | ||
} | ||
} | ||
|
||
return 0; | ||
} /* rgw_get_request_metadata */ | ||
|
||
static inline void encode_delete_at_attr(boost::optional<ceph::real_time> delete_at, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thank you