rbd: before rbd map, warn if the image is already mapped

RBD should check if an image is already mapped before mapping one image as serveral devices.

Fixes: http://tracker.ceph.com/issues/20580
Signed-off-by: Jing Li <lijing@gohighsec.com>
This commit is contained in:
lijing 2017-07-23 20:52:40 +08:00
parent 27c1d62ae9
commit d6a66fc8f4
3 changed files with 71 additions and 1 deletions

View File

@ -45,6 +45,10 @@ namespace ceph {
int krbd_showmapped(struct krbd_ctx *ctx, ceph::Formatter *f);
int krbd_is_image_mapped(struct krbd_ctx *ctx, const char *poolname,
const char *imgname, const char *snapname,
std::ostringstream &mapped_info, bool &is_mapped);
#endif /* __cplusplus */
#endif /* CEPH_KRBD_H */

View File

@ -764,3 +764,59 @@ int krbd_showmapped(struct krbd_ctx *ctx, Formatter *f)
{
return dump_images(ctx, f);
}
int krbd_is_image_mapped(struct krbd_ctx *ctx, const char *poolname,
const char *imgname, const char *snapname,
std::ostringstream &mapped_info, bool &is_mapped) {
struct udev_enumerate *enm;
struct udev_list_entry *l;
struct udev *udev = ctx->udev;
const char *mapped_id, *mapped_pool, *mapped_image, *mapped_snap;
int r;
is_mapped = false;
enm = udev_enumerate_new(udev);
if(!enm)
return -ENOMEM;
r = udev_enumerate_add_match_subsystem(enm, "rbd");
if (r < 0)
goto out_enm;
r = udev_enumerate_scan_devices(enm);
if (r < 0)
goto out_enm;
udev_list_entry_foreach(l, udev_enumerate_get_list_entry(enm)) {
struct udev_device *dev;
dev = udev_device_new_from_syspath(udev, udev_list_entry_get_name(l));
if (dev) {
mapped_id = udev_device_get_sysname(dev);
mapped_pool = udev_device_get_sysattr_value(dev, "pool");
mapped_image = udev_device_get_sysattr_value(dev, "name");
mapped_snap = udev_device_get_sysattr_value(dev, "current_snap");
string kname = get_kernel_rbd_name(mapped_id);
udev_device_unref(dev);
if (mapped_pool && poolname && strcmp(mapped_pool, poolname) == 0 &&
mapped_image && imgname && strcmp(mapped_image, imgname) == 0) {
if (!snapname || snapname[0] == '\0') {
mapped_info << "image " << *poolname << "/" << *imgname
<< " already mapped as " << kname;
is_mapped = true;
goto out_enm;
} else if (snapname && mapped_snap &&
strcmp(snapname, mapped_snap) == 0) {
mapped_info << "image " << *poolname << "/" << *imgname << "@"
<< *snapname << " already mapped as " << kname;
is_mapped = true;
goto out_enm;
}
}
}
}
out_enm:
udev_enumerate_unref(enm);
return r;
}

View File

@ -289,9 +289,10 @@ static int do_kernel_map(const char *poolname, const char *imgname,
{
#if defined(WITH_KRBD)
struct krbd_ctx *krbd;
std::ostringstream oss;
std::ostringstream oss, mapped_info;
char *devnode;
int r;
bool img_mapped;
r = krbd_create_from_context(g_ceph_context, &krbd);
if (r < 0)
@ -312,6 +313,15 @@ static int do_kernel_map(const char *poolname, const char *imgname,
}
}
r = krbd_is_image_mapped(krbd, poolname, imgname, snapname,
mapped_info, img_mapped);
if (r < 0) {
std::cerr << "rbd: warning: can't get image map infomation: "
<< cpp_strerror(r) << std::endl;
} else if (img_mapped) {
std::cerr << "rbd: warning: " << mapped_info.str() << std::endl;
}
r = krbd_map(krbd, poolname, imgname, snapname, oss.str().c_str(), &devnode);
if (r < 0) {
print_error_description(poolname, imgname, snapname, r);