From: Jason Dillaman Date: Mon, 2 Feb 2015 14:21:13 +0000 (-0500) Subject: rbd: watch command should unwatch before exiting X-Git-Tag: v0.93~130^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F3578%2Fhead;p=ceph.git rbd: watch command should unwatch before exiting Switched the rbd CLI tool to use the new watch/unwatch API and properly unwatch the image before exiting. Additionally, the watch command opened the image twice -- once R/W and another R/O. This resulted in two watches being created for the image. Cleaned up old/new format detection by using the existing API methods. Fixes: #10709 Signed-off-by: Jason Dillaman --- diff --git a/src/rbd.cc b/src/rbd.cc index d17958e7e86c..dee1367c420a 100644 --- a/src/rbd.cc +++ b/src/rbd.cc @@ -2106,60 +2106,69 @@ static int do_copy(librbd::Image &src, librados::IoCtx& dest_pp, return 0; } -class RbdWatchCtx : public librados::WatchCtx { - string name; +class RbdWatchCtx : public librados::WatchCtx2 { public: - RbdWatchCtx(const char *imgname) : name(imgname) {} + RbdWatchCtx(librados::IoCtx& io_ctx, const char *image_name, + std::string header_oid) + : m_io_ctx(io_ctx), m_image_name(image_name), m_header_oid(header_oid) + { + } + virtual ~RbdWatchCtx() {} - virtual void notify(uint8_t opcode, uint64_t ver, bufferlist& bl) { - cout << name << " got notification opcode=" << (int)opcode << " ver=" - << ver << " bl.length=" << bl.length() << std::endl; + + virtual void handle_notify(uint64_t notify_id, + uint64_t cookie, + uint64_t notifier_id, + bufferlist& bl) { + cout << m_image_name << " received notification: notify_id=" << notify_id + << ", cookie=" << cookie << ", notifier_id=" << notifier_id + << ", bl.length=" << bl.length() << std::endl; + bufferlist reply; + m_io_ctx.notify_ack(m_header_oid, notify_id, cookie, reply); + } + + virtual void handle_error(uint64_t cookie, int err) { + cerr << m_image_name << " received error: cookie=" << cookie << ", err=" + << cpp_strerror(err) << std::endl; } +private: + librados::IoCtx m_io_ctx; + const char *m_image_name; + string m_header_oid; }; -static int do_watch(librados::IoCtx& pp, const char *imgname) +static int do_watch(librados::IoCtx& pp, librbd::Image &image, + const char *imgname) { - string md_oid, dest_md_oid; - uint64_t cookie; - RbdWatchCtx ctx(imgname); - - string old_header_oid = imgname; - old_header_oid += RBD_SUFFIX; - string new_id_oid = RBD_ID_PREFIX; - string new_header_oid = RBD_HEADER_PREFIX; - new_id_oid += imgname; - bool old_format = true; - - int r = pp.stat(old_header_oid, NULL, NULL); + uint8_t old_format; + int r = image.old_format(&old_format); if (r < 0) { - r = pp.stat(new_id_oid, NULL, NULL); - if (r < 0) - return r; - old_format = false; + cerr << "failed to query format" << std::endl; + return r; } - if (!old_format) { - librbd::RBD rbd; + string header_oid; + if (old_format != 0) { + header_oid = string(imgname) + RBD_SUFFIX; + } else { librbd::image_info_t info; - librbd::Image image; - - r = rbd.open_read_only(pp, image, imgname, NULL); - if (r < 0) - return r; - r = image.stat(info, sizeof(info)); - if (r < 0) + if (r < 0) { + cerr << "failed to stat image" << std::endl; return r; + } char prefix[RBD_MAX_BLOCK_NAME_SIZE + 1]; strncpy(prefix, info.block_name_prefix, RBD_MAX_BLOCK_NAME_SIZE); prefix[RBD_MAX_BLOCK_NAME_SIZE] = '\0'; - new_header_oid.append(prefix + strlen(RBD_DATA_PREFIX)); + string image_id(prefix + strlen(RBD_DATA_PREFIX)); + header_oid = RBD_HEADER_PREFIX + image_id; } - r = pp.watch(old_format ? old_header_oid : new_header_oid, - 0, &cookie, &ctx); + uint64_t cookie; + RbdWatchCtx ctx(pp, imgname, header_oid); + r = pp.watch2(header_oid, &cookie, &ctx); if (r < 0) { cerr << "rbd: watch failed" << std::endl; return r; @@ -2168,6 +2177,11 @@ static int do_watch(librados::IoCtx& pp, const char *imgname) cout << "press enter to exit..." << std::endl; getchar(); + r = pp.unwatch2(cookie); + if (r < 0) { + cerr << "rbd: unwatch failed" << std::endl; + return r; + } return 0; } @@ -3006,7 +3020,7 @@ if (!set_conf_param(v, p1, p2, p3)) { \ if (opt_cmd == OPT_INFO || opt_cmd == OPT_SNAP_LIST || opt_cmd == OPT_EXPORT || opt_cmd == OPT_EXPORT || opt_cmd == OPT_COPY || opt_cmd == OPT_CHILDREN || opt_cmd == OPT_LOCK_LIST || - opt_cmd == OPT_STATUS) { + opt_cmd == OPT_STATUS || opt_cmd == OPT_WATCH) { r = rbd.open_read_only(io_ctx, image, imgname, NULL); } else { r = rbd.open(io_ctx, image, imgname); @@ -3330,7 +3344,7 @@ if (!set_conf_param(v, p1, p2, p3)) { \ break; case OPT_WATCH: - r = do_watch(io_ctx, imgname); + r = do_watch(io_ctx, image, imgname); if (r < 0) { cerr << "rbd: watch failed: " << cpp_strerror(-r) << std::endl; return -r;