From d6a66fc8f49b5d6241ddec036f26e675ed0db8a1 Mon Sep 17 00:00:00 2001 From: lijing Date: Sun, 23 Jul 2017 20:52:40 +0800 Subject: [PATCH] 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 --- src/include/krbd.h | 4 +++ src/krbd.cc | 56 ++++++++++++++++++++++++++++++++++ src/tools/rbd/action/Kernel.cc | 12 +++++++- 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/include/krbd.h b/src/include/krbd.h index c6f3c9d037c..4f6da4fbfaf 100644 --- a/src/include/krbd.h +++ b/src/include/krbd.h @@ -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 */ diff --git a/src/krbd.cc b/src/krbd.cc index 4f8b671b429..7c5ade3dcec 100644 --- a/src/krbd.cc +++ b/src/krbd.cc @@ -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; +} diff --git a/src/tools/rbd/action/Kernel.cc b/src/tools/rbd/action/Kernel.cc index 1f1951fc884..a9ba709c93f 100644 --- a/src/tools/rbd/action/Kernel.cc +++ b/src/tools/rbd/action/Kernel.cc @@ -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); -- 2.39.5