看一下 bypass-gc 的代码。
代码语言:javascript复制int rgw_remove_bucket_bypass_gc(rgw::sal::RGWRadosStore *store, rgw_bucket& bucket,
int concurrent_max, bool keep_index_consistent,
optional_yield y)
{
int ret;
map<RGWObjCategory, RGWStorageStats> stats;
std::vector<rgw_bucket_dir_entry> objs;
map<string, bool> common_prefixes;
RGWBucketInfo info;
RGWObjectCtx obj_ctx(store);
CephContext *cct = store->ctx();
string bucket_ver, master_ver;
ret = store->getRados()->get_bucket_info(store->svc(), bucket.tenant, bucket.name, info, NULL, null_yield);
if (ret < 0)
return ret;
ret = store->getRados()->get_bucket_stats(info, RGW_NO_SHARD, &bucket_ver, &master_ver, stats, NULL);
if (ret < 0)
return ret;
string prefix, delimiter;
ret = abort_bucket_multiparts(store, cct, info, prefix, delimiter);
if (ret < 0) {
return ret;
}
RGWRados::Bucket target(store->getRados(), info);
RGWRados::Bucket::List list_op(&target);
list_op.params.list_versions = true;
list_op.params.allow_unordered = true;
std::list<librados::AioCompletion*> handles;
int max_aio = concurrent_max;
bool is_truncated = true;
while (is_truncated) {
objs.clear();
ret = list_op.list_objects(listing_max_entries, &objs, &common_prefixes,
&is_truncated, null_yield);
if (ret < 0)
return ret;
std::vector<rgw_bucket_dir_entry>::iterator it = objs.begin();
for (; it != objs.end(); it) {
RGWObjState *astate = NULL;
rgw_obj obj(bucket, (*it).key);
ret = store->getRados()->get_obj_state(&obj_ctx, info, obj, &astate, false, y);
if (ret == -ENOENT) {
dout(1) << "WARNING: cannot find obj state for obj " << obj.get_oid() << dendl;
continue;
}
if (ret < 0) {
lderr(store->ctx()) << "ERROR: get obj state returned with error " << ret << dendl;
return ret;
}
if (astate->manifest) {
RGWObjManifest& manifest = *astate->manifest;
RGWObjManifest::obj_iterator miter = manifest.obj_begin();
rgw_obj head_obj = manifest.get_obj();
rgw_raw_obj raw_head_obj;
store->getRados()->obj_to_raw(info.placement_rule, head_obj, &raw_head_obj);
for (; miter != manifest.obj_end() && max_aio--; miter) {
if (!max_aio) {
ret = drain_handles(handles);
if (ret < 0) {
lderr(store->ctx()) << "ERROR: could not drain handles as aio completion returned with " << ret << dendl;
return ret;
}
max_aio = concurrent_max;
}
rgw_raw_obj last_obj = miter.get_location().get_raw_obj(store->getRados());
if (last_obj == raw_head_obj) {
// have the head obj deleted at the end
continue;
}
ret = store->getRados()->delete_raw_obj_aio(last_obj, handles);
if (ret < 0) {
lderr(store->ctx()) << "ERROR: delete obj aio failed with " << ret << dendl;
return ret;
}
} // for all shadow objs
ret = store->getRados()->delete_obj_aio(head_obj, info, astate, handles, keep_index_consistent, null_yield);
if (ret < 0) {
lderr(store->ctx()) << "ERROR: delete obj aio failed with " << ret << dendl;
return ret;
}
}
if (!max_aio) {
ret = drain_handles(handles);
if (ret < 0) {
lderr(store->ctx()) << "ERROR: could not drain handles as aio completion returned with " << ret << dendl;
return ret;
}
max_aio = concurrent_max;
}
obj_ctx.invalidate(obj);
} // for all RGW objects
}
ret = drain_handles(handles);
if (ret < 0) {
lderr(store->ctx()) << "ERROR: could not drain handles as aio completion returned with " << ret << dendl;
return ret;
}
ret = store->ctl()->bucket->sync_user_stats(info.owner, info);
if (ret < 0) {
dout(1) << "WARNING: failed sync user stats before bucket delete. ret=" << ret << dendl;
}
RGWObjVersionTracker objv_tracker;
// this function can only be run if caller wanted children to be
// deleted, so we can ignore the check for children as any that
// remain are detritus from a prior bug
ret = store->getRados()->delete_bucket(info, objv_tracker, y, false);
if (ret < 0) {
lderr(store->ctx()) << "ERROR: could not remove bucket " << bucket.name << dendl;
return ret;
}
ret = store->ctl()->bucket->unlink_bucket(info.owner, bucket, null_yield, false);
if (ret < 0) {
lderr(store->ctx()) << "ERROR: unable to remove user bucket information" << dendl;
}
return ret;
}