template <typename I>
bool ImageState<I>::is_refresh_required() const {
Mutex::Locker locker(m_lock);
- return (m_last_refresh != m_refresh_seq);
+ return (m_last_refresh != m_refresh_seq || find_pending_refresh() != nullptr);
}
template <typename I>
C_SaferCond ctx;
{
m_lock.Lock();
- if (m_last_refresh == m_refresh_seq) {
+ Action action(ACTION_TYPE_REFRESH);
+ action.refresh_seq = m_refresh_seq;
+
+ auto refresh_action = find_pending_refresh();
+ if (refresh_action != nullptr) {
+ // if a refresh is in-flight, delay until it is finished
+ action = *refresh_action;
+ } else if (m_last_refresh == m_refresh_seq) {
m_lock.Unlock();
return 0;
} else if (is_closed()) {
return -ESHUTDOWN;
}
- Action action(ACTION_TYPE_REFRESH);
- action.refresh_seq = m_refresh_seq;
execute_action_unlock(action, &ctx);
}
return ctx.wait();
}
+template <typename I>
+const typename ImageState<I>::Action *
+ImageState<I>::find_pending_refresh() const {
+ assert(m_lock.is_locked());
+
+ auto it = std::find_if(m_actions_contexts.rbegin(),
+ m_actions_contexts.rend(),
+ [](const ActionContexts& action_contexts) {
+ return (action_contexts.first == ACTION_TYPE_REFRESH);
+ });
+ if (it != m_actions_contexts.rend()) {
+ return &it->first;
+ }
+ return nullptr;
+}
+
template <typename I>
void ImageState<I>::snap_set(const std::string &snap_name, Context *on_finish) {
CephContext *cct = m_image_ctx->cct;
bool is_transition_state() const;
bool is_closed() const;
+ const Action *find_pending_refresh() const;
+
void append_context(const Action &action, Context *context);
void execute_next_action_unlock();
void execute_action_unlock(const Action &action, Context *context);