return store->gc_aio_operate(obj_names[i], &op);
}
-int RGWGC::remove(int index, const std::list<string>& tags)
+int RGWGC::remove(int index, const std::list<string>& tags, AioCompletion **pc)
{
ObjectWriteOperation op;
cls_rgw_gc_remove(op, tags);
- return store->gc_operate(obj_names[index], &op);
+ return store->gc_aio_operate(obj_names[index], &op, pc);
}
int RGWGC::list(int *index, string& marker, uint32_t max, bool expired_only, std::list<cls_rgw_gc_obj_info>& result, bool *truncated)
RGWGC *gc;
struct IO {
+ enum Type {
+ UnknownIO = 0,
+ TailIO = 1,
+ IndexIO = 2,
+ } type{UnknownIO};
librados::AioCompletion *c{nullptr};
string oid;
int index{-1};
string tag;
+
+ IO() = default;
+
+ IO(IO::Type type, librados::AioCompletion *c,
+ const std::string& oid, int index, const std::string& tag)
+ : type(type), c(c), oid(oid), index(index), tag(tag)
+ {}
};
list<IO> ios;
if (ret < 0) {
return ret;
}
- ios.push_back(IO{c, oid, index, tag});
+ ios.push_back(IO(IO::TailIO, c, oid, index, tag));
return 0;
}
if (ret == -ENOENT) {
ret = 0;
}
+
+ if (io.type == IO::IndexIO) {
+ if (ret < 0) {
+ ldout(cct, 0) << "WARNING: gc cleanup of tags on gc shard index=" << io.index << " returned error, ret=" << ret << dendl;
+ }
+ goto done;
+ }
+
if (ret < 0) {
ldout(cct, 0) << "WARNING: could not remove oid=" << io.oid << ", ret=" << ret << dendl;
goto done;
rt.push_back(io.tag);
#define MAX_REMOVE_CHUNK 16
if (rt.size() > MAX_REMOVE_CHUNK) {
- drain_remove_tags(io.index, rt);
+ flush_remove_tags(io.index, rt);
}
done:
ios.pop_front();
}
- void drain() {
+ void drain_ios() {
while (!ios.empty()) {
if (gc->going_down()) {
return;
}
handle_next_completion();
}
+ }
- drain_remove_tags();
+ void drain() {
+ drain_ios();
+ flush_remove_tags();
+ /* the tags draining might have generated more ios, drain those too */
+ drain_ios();
}
- void drain_remove_tags(int index, list<string>& rt) {
- gc->remove(index, rt);
+ void flush_remove_tags(int index, list<string>& rt) {
+ IO index_io;
+ index_io.type = IO::IndexIO;
+ index_io.index = index;
+
+ int ret = gc->remove(index, rt, &index_io.c);
rt.clear();
+ if (ret < 0) {
+ /* we already cleared list of tags, this prevents us from ballooning in case of
+ * a persistent problem
+ */
+ ldout(cct, 0) << "WARNING: failed to remove tags on gc shard index=" << index << " ret=" << ret << dendl;
+ return;
+ }
+ ios.push_back(index_io);
}
- void drain_remove_tags() {
+ void flush_remove_tags() {
for (auto iter : remove_tags) {
- drain_remove_tags(iter.first, iter.second);
+ flush_remove_tags(iter.first, iter.second);
}
}
};
void add_chain(librados::ObjectWriteOperation& op, cls_rgw_obj_chain& chain, const string& tag);
int send_chain(cls_rgw_obj_chain& chain, const string& tag, bool sync);
int defer_chain(const string& tag, bool sync);
- int remove(int index, const std::list<string>& tags);
+ int remove(int index, const std::list<string>& tags, librados::AioCompletion **pc);
void initialize(CephContext *_cct, RGWRados *_store);
void finalize();
void update_gc_chain(rgw_obj& head_obj, RGWObjManifest& manifest, cls_rgw_obj_chain *chain);
int send_chain_to_gc(cls_rgw_obj_chain& chain, const string& tag, bool sync);
int gc_operate(string& oid, librados::ObjectWriteOperation *op);
- int gc_aio_operate(string& oid, librados::ObjectWriteOperation *op);
+ int gc_aio_operate(string& oid, librados::ObjectWriteOperation *op, librados::AioCompletion **pc = nullptr);
int gc_operate(string& oid, librados::ObjectReadOperation *op, bufferlist *pbl);
int list_gc_objs(int *index, string& marker, uint32_t max, bool expired_only, std::list<cls_rgw_gc_obj_info>& result, bool *truncated);