mirror of
https://github.com/ceph/ceph
synced 2025-03-25 11:48:05 +00:00
rgw-admin: a tool to fix object locator issue
Objects that start with underscore need to have an object locator, this is due to an old behavior that we need to retain. Some objects might have been created without the locator. This tool creates a new rados object with the appropriate locator. Syntax: $ ./radosgw-admin bucket check --check-head-obj-locator \ --bucket=<bucket> [--fix] Signed-off-by: Yehuda Sadeh <yehuda@redhat.com>
This commit is contained in:
parent
3d4a1d20b8
commit
be4355ad8e
@ -907,6 +907,118 @@ int check_min_obj_stripe_size(RGWRados *store, RGWBucketInfo& bucket_info, rgw_o
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int check_obj_locator_underscore(RGWBucketInfo& bucket_info, rgw_obj& obj, rgw_obj_key& key, bool fix, Formatter *f) {
|
||||
f->open_object_section("object");
|
||||
f->open_object_section("key");
|
||||
f->dump_string("name", key.name);
|
||||
f->dump_string("instance", key.instance);
|
||||
f->close_section();
|
||||
|
||||
string oid;
|
||||
string locator;
|
||||
|
||||
get_obj_bucket_and_oid_loc(obj, obj.bucket, oid, locator);
|
||||
|
||||
f->dump_string("oid", oid);
|
||||
f->dump_string("locator", locator);
|
||||
|
||||
|
||||
RGWObjectCtx obj_ctx(store);
|
||||
|
||||
RGWRados::Object op_target(store, bucket_info, obj_ctx, obj);
|
||||
RGWRados::Object::Read read_op(&op_target);
|
||||
|
||||
int ret = read_op.prepare(NULL, NULL);
|
||||
bool needs_fixing = (ret == -ENOENT);
|
||||
|
||||
f->dump_bool("needs_fixing", needs_fixing);
|
||||
|
||||
string status = (needs_fixing ? "needs_fixing" : "ok");
|
||||
|
||||
if (needs_fixing && fix) {
|
||||
ret = store->fix_head_obj_locator(obj.bucket, key);
|
||||
if (ret < 0) {
|
||||
cerr << "ERROR: fix_head_object_locator() returned ret=" << ret << std::endl;
|
||||
goto done;
|
||||
}
|
||||
status = "fixed";
|
||||
}
|
||||
|
||||
done:
|
||||
f->dump_string("status", status);
|
||||
|
||||
f->close_section();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_check_object_locator(const string& bucket_name, bool fix, Formatter *f)
|
||||
{
|
||||
RGWBucketInfo bucket_info;
|
||||
rgw_bucket bucket;
|
||||
string bucket_id;
|
||||
|
||||
f->open_object_section("bucket");
|
||||
f->dump_string("bucket", bucket_name);
|
||||
int ret = init_bucket(bucket_name, bucket_id, bucket_info, bucket);
|
||||
if (ret < 0) {
|
||||
cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
|
||||
return ret;
|
||||
}
|
||||
bool truncated;
|
||||
int count = 0;
|
||||
|
||||
int max_entries = 1000;
|
||||
|
||||
string prefix;
|
||||
string delim;
|
||||
vector<RGWObjEnt> result;
|
||||
map<string, bool> common_prefixes;
|
||||
string ns;
|
||||
|
||||
RGWRados::Bucket target(store, bucket);
|
||||
RGWRados::Bucket::List list_op(&target);
|
||||
|
||||
string marker;
|
||||
|
||||
list_op.params.prefix = prefix;
|
||||
list_op.params.delim = delim;
|
||||
list_op.params.marker = rgw_obj_key(marker);
|
||||
list_op.params.ns = ns;
|
||||
list_op.params.enforce_ns = false;
|
||||
list_op.params.list_versions = true;
|
||||
|
||||
f->open_array_section("check_objects");
|
||||
do {
|
||||
ret = list_op.list_objects(max_entries - count, &result, &common_prefixes, &truncated);
|
||||
if (ret < 0) {
|
||||
cerr << "ERROR: store->list_objects(): " << cpp_strerror(-ret) << std::endl;
|
||||
return -ret;
|
||||
}
|
||||
|
||||
count += result.size();
|
||||
|
||||
list<rgw_obj> objs;
|
||||
for (vector<RGWObjEnt>::iterator iter = result.begin(); iter != result.end(); ++iter) {
|
||||
rgw_obj_key key = iter->key;
|
||||
rgw_obj obj(bucket, key);
|
||||
|
||||
if (key.name[0] == '_') {
|
||||
ret = check_obj_locator_underscore(bucket_info, obj, key, fix, f);
|
||||
/* ignore return code, move to the next one */
|
||||
}
|
||||
}
|
||||
f->flush(cout);
|
||||
} while (truncated && count < max_entries);
|
||||
f->close_section();
|
||||
f->close_section();
|
||||
|
||||
f->flush(cout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
vector<const char*> args;
|
||||
@ -944,6 +1056,7 @@ int main(int argc, char **argv)
|
||||
int yes_i_really_mean_it = false;
|
||||
int delete_child_objects = false;
|
||||
int fix = false;
|
||||
int check_head_obj_locator = false;
|
||||
int max_buckets = -1;
|
||||
map<string, bool> categories;
|
||||
string caps;
|
||||
@ -1128,6 +1241,8 @@ int main(int argc, char **argv)
|
||||
// do nothing
|
||||
} else if (ceph_argparse_binary_flag(args, i, &fix, NULL, "--fix", (char*)NULL)) {
|
||||
// do nothing
|
||||
} else if (ceph_argparse_binary_flag(args, i, &check_head_obj_locator, NULL, "--check-head-obj-locator", (char*)NULL)) {
|
||||
// do nothing
|
||||
} else if (ceph_argparse_binary_flag(args, i, &check_objects, NULL, "--check-objects", (char*)NULL)) {
|
||||
// do nothing
|
||||
} else if (ceph_argparse_binary_flag(args, i, &sync_stats, NULL, "--sync-stats", (char*)NULL)) {
|
||||
@ -2348,7 +2463,15 @@ next:
|
||||
}
|
||||
|
||||
if (opt_cmd == OPT_BUCKET_CHECK) {
|
||||
RGWBucketAdminOp::check_index(store, bucket_op, f);
|
||||
if (check_head_obj_locator) {
|
||||
if (bucket_name.empty()) {
|
||||
cerr << "ERROR: need to specify bucket name" << std::endl;
|
||||
return EINVAL;
|
||||
}
|
||||
do_check_object_locator(bucket_name, fix, formatter);
|
||||
} else {
|
||||
RGWBucketAdminOp::check_index(store, bucket_op, f);
|
||||
}
|
||||
}
|
||||
|
||||
if (opt_cmd == OPT_BUCKET_RM) {
|
||||
|
@ -2967,6 +2967,77 @@ int RGWRados::get_obj_ref(const rgw_obj& obj, rgw_rados_ref *ref, rgw_bucket *bu
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* fixes an issue where head objects were supposed to have a locator created, but ended
|
||||
* up without one
|
||||
*/
|
||||
int RGWRados::fix_head_obj_locator(rgw_bucket& bucket, rgw_obj_key& key)
|
||||
{
|
||||
string oid;
|
||||
string locator;
|
||||
|
||||
rgw_obj obj(bucket, key);
|
||||
|
||||
get_obj_bucket_and_oid_loc(obj, bucket, oid, locator);
|
||||
|
||||
if (locator.empty()) {
|
||||
ldout(cct, 20) << "object does not have a locator, nothing to fix" << dendl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
librados::IoCtx ioctx;
|
||||
|
||||
int ret = get_obj_ioctx(obj, &ioctx);
|
||||
if (ret < 0) {
|
||||
cerr << "ERROR: get_obj_ioctx() returned ret=" << ret << std::endl;
|
||||
return ret;
|
||||
}
|
||||
ioctx.locator_set_key(string()); /* override locator for this object, use empty locator */
|
||||
|
||||
uint64_t size;
|
||||
time_t mtime;
|
||||
bufferlist data;
|
||||
|
||||
map<string, bufferlist> attrs;
|
||||
librados::ObjectReadOperation op;
|
||||
op.getxattrs(&attrs, NULL);
|
||||
op.stat(&size, &mtime, NULL);
|
||||
#define HEAD_SIZE 512 * 1024
|
||||
op.read(0, HEAD_SIZE, &data, NULL);
|
||||
|
||||
ret = ioctx.operate(oid, &op, NULL);
|
||||
if (ret < 0) {
|
||||
lderr(cct) << "ERROR: ioctx.operate(oid=" << oid << ") returned ret=" << ret << dendl;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (size > HEAD_SIZE) {
|
||||
lderr(cct) << "ERROR: returned object size (" << size << ") > HEAD_SIZE (" << HEAD_SIZE << ")" << dendl;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (size != data.length()) {
|
||||
lderr(cct) << "ERROR: returned object size (" << size << ") != data.length() (" << data.length() << ")" << dendl;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
librados::ObjectWriteOperation wop;
|
||||
|
||||
wop.mtime(&mtime);
|
||||
|
||||
map<string, bufferlist>::iterator iter;
|
||||
for (iter = attrs.begin(); iter != attrs.end(); ++iter) {
|
||||
wop.setxattr(iter->first.c_str(), iter->second);
|
||||
}
|
||||
|
||||
wop.write(0, data);
|
||||
|
||||
ioctx.locator_set_key(locator);
|
||||
ioctx.operate(oid, &wop);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RGWRados::BucketShard::init(rgw_bucket& _bucket, rgw_obj& obj)
|
||||
{
|
||||
bucket = _bucket;
|
||||
|
@ -2027,6 +2027,7 @@ public:
|
||||
map<RGWObjCategory, RGWStorageStats> *calculated_stats);
|
||||
int bucket_rebuild_index(rgw_bucket& bucket);
|
||||
int remove_objs_from_index(rgw_bucket& bucket, list<rgw_obj_key>& oid_list);
|
||||
int fix_head_obj_locator(rgw_bucket& bucket, rgw_obj_key& key);
|
||||
|
||||
int cls_user_get_header(const string& user_id, cls_user_header *header);
|
||||
int cls_user_get_header_async(const string& user_id, RGWGetUserHeader_CB *ctx);
|
||||
|
Loading…
Reference in New Issue
Block a user