Skip to content

Commit

Permalink
librbd: use async image removal state machine
Browse files Browse the repository at this point in the history
Signed-off-by: Venky Shankar <vshankar@redhat.com>
  • Loading branch information
vshankar authored and yangdongsheng committed Nov 22, 2016
1 parent 23457a2 commit e8f1a96
Showing 1 changed file with 11 additions and 194 deletions.
205 changes: 11 additions & 194 deletions src/librbd/internal.cc
Expand Up @@ -26,6 +26,7 @@
#include "librbd/AioImageRequestWQ.h"
#include "librbd/AioObjectRequest.h"
#include "librbd/image/CreateRequest.h"
#include "librbd/image/RemoveRequest.h"
#include "librbd/DiffIterate.h"
#include "librbd/ExclusiveLock.h"
#include "librbd/ImageCtx.h"
Expand Down Expand Up @@ -1484,202 +1485,18 @@ int mirror_image_disable_internal(ImageCtx *ictx, bool force,
ldout(cct, 20) << "remove " << &io_ctx << " "
<< (image_id.empty() ? image_name : image_id) << dendl;

std::string name(image_name);
std::string id(image_id);
bool old_format = false;
bool unknown_format = true;
ImageCtx *ictx = new ImageCtx(
(id.empty() ? name : std::string()), id, nullptr, io_ctx, false);
int r = ictx->state->open();
if (r < 0) {
ldout(cct, 2) << "error opening image: " << cpp_strerror(-r) << dendl;
delete ictx;
} else {
string header_oid = ictx->header_oid;
old_format = ictx->old_format;
unknown_format = false;
name = ictx->name;
id = ictx->id;

ictx->owner_lock.get_read();
if (ictx->exclusive_lock != nullptr) {
if (force) {
// releasing read lock to avoid a deadlock when upgrading to
// write lock in the shut_down process
ictx->owner_lock.put_read();
if (ictx->exclusive_lock != nullptr) {
C_SaferCond ctx;
ictx->exclusive_lock->shut_down(&ctx);
r = ctx.wait();
if (r < 0) {
lderr(cct) << "error shutting down exclusive lock: "
<< cpp_strerror(r) << dendl;
ictx->state->close();
return r;
}
assert (ictx->exclusive_lock == nullptr);
ictx->owner_lock.get_read();
}
} else {
r = ictx->operations->prepare_image_update();
if (r < 0 || !ictx->exclusive_lock->is_lock_owner()) {
lderr(cct) << "cannot obtain exclusive lock - not removing" << dendl;
ictx->owner_lock.put_read();
ictx->state->close();
return -EBUSY;
}
}
}

if (ictx->snaps.size()) {
lderr(cct) << "image has snapshots - not removing" << dendl;
ictx->owner_lock.put_read();
ictx->state->close();
return -ENOTEMPTY;
}

std::list<obj_watch_t> watchers;
r = io_ctx.list_watchers(header_oid, &watchers);
if (r < 0) {
lderr(cct) << "error listing watchers" << dendl;
ictx->owner_lock.put_read();
ictx->state->close();
return r;
}
if (watchers.size() > 1) {
lderr(cct) << "image has watchers - not removing" << dendl;
ictx->owner_lock.put_read();
ictx->state->close();
return -EBUSY;
}

cls::rbd::GroupSpec s;
r = cls_client::image_get_group(&io_ctx, header_oid, &s);
if (r < 0 && r != -EOPNOTSUPP) {
lderr(cct) << "error querying consistency group" << dendl;
ictx->owner_lock.put_read();
ictx->state->close();
return r;
} else if (s.is_valid()) {
lderr(cct) << "image is in a consistency group - not removing" << dendl;
ictx->owner_lock.put_read();
ictx->state->close();
return -EMLINK;
}

trim_image(ictx, 0, prog_ctx);

ictx->parent_lock.get_read();
// struct assignment
parent_info parent_info = ictx->parent_md;
ictx->parent_lock.put_read();

r = cls_client::remove_child(&ictx->md_ctx, RBD_CHILDREN,
parent_info.spec, id);
if (r < 0 && r != -ENOENT) {
lderr(cct) << "error removing child from children list" << dendl;
ictx->owner_lock.put_read();
ictx->state->close();
return r;
}

if (!old_format) {
r = mirror_image_disable_internal(ictx, force, !force);
if (r < 0 && r != -EOPNOTSUPP) {
lderr(cct) << "error disabling image mirroring: " << cpp_strerror(r)
<< dendl;
ictx->owner_lock.put_read();
ictx->state->close();
return r;
}
}

ictx->owner_lock.put_read();
ictx->state->close();

ldout(cct, 2) << "removing header..." << dendl;
r = io_ctx.remove(header_oid);
if (r < 0 && r != -ENOENT) {
lderr(cct) << "error removing header: " << cpp_strerror(-r) << dendl;
return r;
}
}

if (old_format || unknown_format) {
ldout(cct, 2) << "removing rbd image from v1 directory..." << dendl;
r = tmap_rm(io_ctx, name);
old_format = (r == 0);
if (r < 0 && !unknown_format) {
if (r != -ENOENT) {
lderr(cct) << "error removing image from v1 directory: "
<< cpp_strerror(-r) << dendl;
}
return r;
}
}
if (!old_format) {
if (id.empty()) {
ldout(cct, 5) << "attempting to determine image id" << dendl;
r = cls_client::dir_get_id(&io_ctx, RBD_DIRECTORY, name, &id);
if (r < 0 && r != -ENOENT) {
lderr(cct) << "error getting id of image" << dendl;
return r;
}
} else if (name.empty()) {
ldout(cct, 5) << "attempting to determine image name" << dendl;
r = cls_client::dir_get_name(&io_ctx, RBD_DIRECTORY, id, &name);
if (r < 0 && r != -ENOENT) {
lderr(cct) << "error getting name of image" << dendl;
return r;
}
}

if (!id.empty()) {
ldout(cct, 10) << "removing journal..." << dendl;
r = Journal<>::remove(io_ctx, id);
if (r < 0 && r != -ENOENT) {
lderr(cct) << "error removing image journal" << dendl;
return r;
}

ldout(cct, 10) << "removing object map..." << dendl;
r = ObjectMap::remove(io_ctx, id);
if (r < 0 && r != -ENOENT) {
lderr(cct) << "error removing image object map" << dendl;
return r;
}

ldout(cct, 10) << "removing image from rbd_mirroring object..."
<< dendl;
r = cls_client::mirror_image_remove(&io_ctx, id);
if (r < 0 && r != -ENOENT && r != -EOPNOTSUPP) {
lderr(cct) << "failed to remove image from mirroring directory: "
<< cpp_strerror(r) << dendl;
return r;
}
}

ldout(cct, 2) << "removing id object..." << dendl;
r = io_ctx.remove(util::id_obj_name(name));
if (r < 0 && r != -ENOENT) {
lderr(cct) << "error removing id object: " << cpp_strerror(r)
<< dendl;
return r;
}
C_SaferCond cond;
ContextWQ op_work_queue("librbd::op_work_queue",
cct->_conf->rbd_op_thread_timeout,
ImageCtx::get_thread_pool_instance(cct));
librbd::image::RemoveRequest<> *req = librbd::image::RemoveRequest<>::create(
io_ctx, image_name, image_id, force, prog_ctx, &op_work_queue, &cond);
req->send();

ldout(cct, 2) << "removing rbd image from v2 directory..." << dendl;
r = cls_client::dir_remove_image(&io_ctx, RBD_DIRECTORY, name, id);
if (r < 0) {
if (r != -ENOENT) {
lderr(cct) << "error removing image from v2 directory: "
<< cpp_strerror(-r) << dendl;
}
return r;
}
}
int r = cond.wait();
op_work_queue.drain();

ldout(cct, 2) << "done." << dendl;
return 0;
return r;
}

int snap_list(ImageCtx *ictx, vector<snap_info_t>& snaps)
Expand Down

0 comments on commit e8f1a96

Please sign in to comment.