Skip to content

Commit

Permalink
librbd: fix when rbd close hang due to contineous rewatch
Browse files Browse the repository at this point in the history
  fix when rbd close hang due to contineous rewatch

Signed-off-by: Song Shun <song.shun3@zte.com.cn>
  • Loading branch information
shun-s committed Mar 30, 2018
1 parent 9e8af3e commit dca59ca
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 19 deletions.
5 changes: 3 additions & 2 deletions src/librbd/ImageState.h
Expand Up @@ -31,6 +31,7 @@ class ImageState {

int close();
void close(Context *on_finish);
bool is_closed() const;

void handle_update_notification();

Expand All @@ -49,6 +50,8 @@ class ImageState {
int unregister_update_watcher(uint64_t handle);
void flush_update_watchers(Context *on_finish);
void shut_down_update_watchers(Context *on_finish);

mutable Mutex m_lock;

private:
enum State {
Expand Down Expand Up @@ -102,7 +105,6 @@ class ImageState {
ImageCtxT *m_image_ctx;
State m_state;

mutable Mutex m_lock;
ActionsContexts m_actions_contexts;

uint64_t m_last_refresh;
Expand All @@ -113,7 +115,6 @@ class ImageState {
bool m_skip_open_parent_image;

bool is_transition_state() const;
bool is_closed() const;

const Action *find_pending_refresh() const;

Expand Down
7 changes: 7 additions & 0 deletions src/librbd/ImageWatcher.cc
Expand Up @@ -89,6 +89,13 @@ void ImageWatcher<I>::unregister_watch(Context *on_finish) {
FunctionContext *ctx = new FunctionContext([this, on_finish](int r) {
m_task_finisher->cancel_all(on_finish);
});
{
m_image_ctx.state->m_lock.Lock();
if (m_image_ctx.state->is_closed()) {
m_image_closing = true;
}
m_image_ctx.state->m_lock.Unlock();
}
Watcher::unregister_watch(ctx);
}

Expand Down
19 changes: 14 additions & 5 deletions src/librbd/Watcher.cc
Expand Up @@ -250,13 +250,22 @@ void Watcher::rewatch() {
}

void Watcher::handle_rewatch(int r) {
ldout(m_cct, 10) "r=" << r << dendl;

ldout(m_cct, 10) << "r=" << r << dendl;
WatchState next_watch_state = WATCH_STATE_REGISTERED;
if (r < 0) {
// only EBLACKLISTED or ENOENT can be returned
assert(r == -EBLACKLISTED || r == -ENOENT);

if (r == -EBLACKLISTED) {
lderr(m_cct) << "client blacklisted" << dendl;
next_watch_state = WATCH_STATE_UNREGISTERED;
} else if (r == -ENOENT) {
lderr(m_cct) << "failed to unwatch: " << cpp_strerror(r) << dendl;
next_watch_state = WATCH_STATE_UNREGISTERED;
} else if (r < 0) {
next_watch_state = WATCH_STATE_ERROR;
if (m_image_closing) {
ldout(m_cct, 10) << "image is closing, skip rewatch" << dendl;
} else {
rewatch();
}
}

Context *unregister_watch_ctx = nullptr;
Expand Down
1 change: 1 addition & 0 deletions src/librbd/Watcher.h
Expand Up @@ -79,6 +79,7 @@ class Watcher {
watcher::Notifier m_notifier;
WatchState m_watch_state;
AsyncOpTracker m_async_op_tracker;
bool m_image_closing = false;

void send_notify(bufferlist &payload,
watcher::NotifyResponse *response = nullptr,
Expand Down
13 changes: 1 addition & 12 deletions src/librbd/watcher/RewatchRequest.cc
Expand Up @@ -78,20 +78,9 @@ void RewatchRequest::rewatch() {
void RewatchRequest::handle_rewatch(int r) {
CephContext *cct = reinterpret_cast<CephContext *>(m_ioctx.cct());
ldout(cct, 10) << "r=" << r << dendl;

if (r == -EBLACKLISTED) {
lderr(cct) << "client blacklisted" << dendl;
if (r < 0) {
finish(r);
return;
} else if (r == -ENOENT) {
ldout(cct, 5) << "object deleted" << dendl;
finish(r);
return;
} else if (r < 0) {
lderr(cct) << "failed to watch object: " << cpp_strerror(r)
<< dendl;
rewatch();
return;
}

{
Expand Down

0 comments on commit dca59ca

Please sign in to comment.