rgw: prevent spurious/lost notifications in the index completion thread#45131
rgw: prevent spurious/lost notifications in the index completion thread#45131yuvalif wants to merge 1 commit intoceph:wip-rgw-multisite-reshardfrom
Conversation
src/rgw/rgw_rados.cc
Outdated
| entry->bilog_op = bilog_op; | ||
| std::ostringstream oss; | ||
| dpp->gen_prefix(oss); | ||
| entry->original_prefix = oss.str(); |
There was a problem hiding this comment.
i suggested doing this for debugging, but i'd prefer not to merge it
this adds overhead (allocations and a global lock for iostream locale support) to every index operation, but is only relevant to a small subset of those (writes that prepared before reshard started, but completed after)
There was a problem hiding this comment.
i added debug logs to handle_completion() even for the non-reshard cases.
since these are async callbacks where the original dpp context is not lost (they are synchronous with the op)
i can probably pass in the original dpp, without copying the prefix string
src/rgw/rgw_rados.cc
Outdated
|
|
||
| void RGWIndexCompletionManager::process() | ||
| { | ||
| auto dpp = std::make_unique<DoutPrefix>(store->ctx(), dout_subsys, "rgw index completion thread: "); |
There was a problem hiding this comment.
can't this live on the stack?
src/rgw/rgw_rados.cc
Outdated
| const int num_shards; | ||
| ceph::containers::tiny_vector<ceph::mutex> locks; | ||
| std::vector<set<complete_op_data*>> completions; | ||
| std::vector<complete_op_data*> async_completions; |
There was a problem hiding this comment.
the async_ piece is a bit misleading here? it's completions that were submitted asynchronously with aio_operate(). the completions in this vector failed with ERR_BUSY_RESHARDING and need to be retried synchronously. maybe call this retry_completions?
what was the motivation for collapsing RGWIndexCompletionThread into RGWIndexCompletionManager? i think it's better to keep the Thread class and encapsulate its state/locking there. that way we don't mix completions/locks and async_completions/async_completions_lock together in one place
There was a problem hiding this comment.
the
async_piece is a bit misleading here? it'scompletionsthat were submitted asynchronously withaio_operate(). the completions in this vector failed with ERR_BUSY_RESHARDING and need to be retried synchronously. maybe call thisretry_completions?
sure, will rename
what was the motivation for collapsing
RGWIndexCompletionThreadintoRGWIndexCompletionManager? i think it's better to keep theThreadclass and encapsulate its state/locking there. that way we don't mixcompletions/locksandasync_completions/async_completions_locktogether in one place
there is no thread class. it is just a function called from the manager class inside its own thread.
both the async_completion_lock is used inside functions called from different thread contexts, os it belongs to the manager class
src/rgw/rgw_rados.cc
Outdated
| std::unique_lock l{async_completions_lock}; | ||
| cond.wait(l, [this](){return _stop || !async_completions.empty();}); | ||
| if (_stop) { | ||
| return; | ||
| } | ||
| async_completions.swap(comps); |
|
2918b9b to
359db94
Compare
src/rgw/rgw_rados.h
Outdated
| int cls_obj_complete_op(const DoutPrefixProvider *dpp, BucketShard& bs, const rgw_obj& obj, RGWModifyOp op, std::string& tag, int64_t pool, uint64_t epoch, | ||
| rgw_bucket_dir_entry& ent, RGWObjCategory category, std::list<rgw_obj_index_key> *remove_objs, uint16_t bilog_flags, rgw_zone_set *zones_trace = nullptr); | ||
| int cls_obj_complete_add(BucketShard& bs, const rgw_obj& obj, std::string& tag, int64_t pool, uint64_t epoch, rgw_bucket_dir_entry& ent, | ||
| int cls_obj_complete_add(const DoutPrefixProvider *dpp, BucketShard& bs, const rgw_obj& obj, std::string& tag, int64_t pool, uint64_t epoch, rgw_bucket_dir_entry& ent, | ||
| RGWObjCategory category, std::list<rgw_obj_index_key> *remove_objs, uint16_t bilog_flags, rgw_zone_set *zones_trace = nullptr); | ||
| int cls_obj_complete_del(BucketShard& bs, std::string& tag, int64_t pool, uint64_t epoch, rgw_obj& obj, | ||
| int cls_obj_complete_del(const DoutPrefixProvider *dpp, BucketShard& bs, std::string& tag, int64_t pool, uint64_t epoch, rgw_obj& obj, | ||
| ceph::real_time& removed_mtime, std::list<rgw_obj_index_key> *remove_objs, uint16_t bilog_flags, rgw_zone_set *zones_trace = nullptr); | ||
| int cls_obj_complete_cancel(BucketShard& bs, std::string& tag, rgw_obj& obj, | ||
| int cls_obj_complete_cancel(const DoutPrefixProvider *dpp, BucketShard& bs, std::string& tag, rgw_obj& obj, |
There was a problem hiding this comment.
this adds a dpp to lots of functions, apparently for RGWIndexCompletionManager::create_completion(), but the new dpp argument is unused there. can we safely remove these now? that would simplify backports
There was a problem hiding this comment.
ok. removing dpp. as it is too expensive to cache it inside the callback args
this was happening when asyn completions happened during reshard. more information about testing: https://gist.github.com/yuvalif/d526c0a3a4c5b245b9e951a6c5a10517 we also add more logs to the completion manager. should allow finding unhandled completions due to reshards. Signed-off-by: Yuval Lifshitz <ylifshit@redhat.com>
359db94 to
1cc5fdf
Compare
|
merged, thanks @yuvalif! |
this was happening when async completions happened during reshard.
more information about testing:
https://gist.github.com/yuvalif/d526c0a3a4c5b245b9e951a6c5a10517
to trace possible issues, dpp was added to the completion thread.
this should allow finding unhandled completions due to reshards. for example:
https://0x0.st/oKQ1.log
Signed-off-by: Yuval Lifshitz ylifshit@redhat.com
Checklist
Show available Jenkins commands
jenkins retest this pleasejenkins test classic perfjenkins test crimson perfjenkins test signedjenkins test make checkjenkins test make check arm64jenkins test submodulesjenkins test dashboardjenkins test dashboard cephadmjenkins test apijenkins test docsjenkins render docsjenkins test ceph-volume alljenkins test ceph-volume tox