From 17d6a993fc17d533460c5f40f3908c708e057c18 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 23 May 2024 18:45:17 +0200 Subject: Merging upstream version 18.2.3. Signed-off-by: Daniel Baumann --- src/tools/ceph_objectstore_tool.cc | 2 +- src/tools/cephfs/shell/cephfs-shell | 15 ++++---- src/tools/cephfs/top/cephfs-top | 27 ++++++++++++-- src/tools/cephfs_mirror/FSMirror.cc | 40 ++++++++++++++++++++ src/tools/cephfs_mirror/FSMirror.h | 2 + src/tools/cephfs_mirror/Mirror.cc | 46 ++++++++++++++++++++++- src/tools/cephfs_mirror/Mirror.h | 2 + src/tools/cephfs_mirror/PeerReplayer.cc | 65 +++++++++++++++++++++++++++++++++ src/tools/cephfs_mirror/PeerReplayer.h | 2 + src/tools/rados/rados.cc | 18 +++++++-- src/tools/rbd/action/Children.cc | 21 +++++++++-- src/tools/rbd_nbd/rbd-nbd.cc | 30 +++++++++------ 12 files changed, 238 insertions(+), 32 deletions(-) (limited to 'src/tools') diff --git a/src/tools/ceph_objectstore_tool.cc b/src/tools/ceph_objectstore_tool.cc index 01c8722b4..27ac1cff9 100644 --- a/src/tools/ceph_objectstore_tool.cc +++ b/src/tools/ceph_objectstore_tool.cc @@ -105,7 +105,7 @@ int _action_on_all_objects_in_pg(ObjectStore *store, coll_t coll, action_on_obje obj != list.end(); ++obj) { object_info_t oi; - if (coll != coll_t::meta()) { + if (coll != coll_t::meta() && !obj->is_pgmeta()) { bufferlist attr; r = store->getattr(ch, *obj, OI_ATTR, attr); if (r < 0) { diff --git a/src/tools/cephfs/shell/cephfs-shell b/src/tools/cephfs/shell/cephfs-shell index 58884a275..9df4f71d8 100755 --- a/src/tools/cephfs/shell/cephfs-shell +++ b/src/tools/cephfs/shell/cephfs-shell @@ -16,13 +16,14 @@ import shlex import stat import errno -from distutils.version import LooseVersion +from pkg_resources import packaging # type: ignore from cmd2 import Cmd from cmd2 import __version__ as cmd2_version # XXX: In cmd2 versions < 1.0.1, we'll get SystemExit(2) instead of # Cmd2ArgparseError -if LooseVersion(cmd2_version) >= LooseVersion("1.0.1"): +Version = packaging.version.Version +if Version(cmd2_version) >= Version("1.0.1"): from cmd2.exceptions import Cmd2ArgparseError else: # HACK: so that we don't have check for version everywhere @@ -1699,11 +1700,11 @@ def read_shell_conf(shell, shell_conf_file): sec = 'cephfs-shell' opts = [] - if LooseVersion(cmd2_version) >= LooseVersion("0.10.0"): + if Version(cmd2_version) >= Version("0.10.0"): for attr in shell.settables.keys(): opts.append(attr) else: - if LooseVersion(cmd2_version) <= LooseVersion("0.9.13"): + if Version(cmd2_version) <= Version("0.9.13"): # hardcoding options for 0.7.9 because - # 1. we use cmd2 v0.7.9 with teuthology and # 2. there's no way distinguish between a shell setting and shell @@ -1712,7 +1713,7 @@ def read_shell_conf(shell, shell_conf_file): 'continuation_prompt', 'debug', 'echo', 'editor', 'feedback_to_output', 'locals_in_py', 'prompt', 'quiet', 'timing'] - elif LooseVersion(cmd2_version) >= LooseVersion("0.9.23"): + elif Version(cmd2_version) >= Version("0.9.23"): opts.append('allow_style') # no equivalent option was defined by cmd2. else: @@ -1767,7 +1768,7 @@ def manage_args(): args.exe_and_quit = False # Execute and quit, don't launch the shell. if args.batch: - if LooseVersion(cmd2_version) <= LooseVersion("0.9.13"): + if Version(cmd2_version) <= Version("0.9.13"): args.commands = ['load ' + args.batch, ',quit'] else: args.commands = ['run_script ' + args.batch, ',quit'] @@ -1812,7 +1813,7 @@ def execute_cmds_and_quit(args): # value to indicate whether the execution of the commands should stop, but # since 0.9.7 it returns the return value of do_* methods only if it's # not None. When it is None it returns False instead of None. - if LooseVersion(cmd2_version) <= LooseVersion("0.9.6"): + if Version(cmd2_version) <= Version("0.9.6"): stop_exec_val = None else: stop_exec_val = False diff --git a/src/tools/cephfs/top/cephfs-top b/src/tools/cephfs/top/cephfs-top index b39e815fa..ff02e2dd4 100755 --- a/src/tools/cephfs/top/cephfs-top +++ b/src/tools/cephfs/top/cephfs-top @@ -168,8 +168,8 @@ class FSTopBase(object): return False return True - def __build_clients(self, fs): - fs_meta = self.dump_json.setdefault(fs, {}) + def __build_clients(self, fs, clients_json): + fs_meta = clients_json.setdefault(fs, {}) fs_key = self.stats_json[GLOBAL_METRICS_KEY].get(fs, {}) clients = fs_key.keys() for client_id in clients: @@ -249,13 +249,32 @@ class FSTopBase(object): self.stats_json = self.perf_stats_query() if fs_name: # --dumpfs if fs_name in fs_list: - self.__build_clients(fs_name) + self.__build_clients(fs_name, clients_json=self.dump_json) else: sys.stdout.write(f"Filesystem {fs_name} not available\n") return else: # --dump + num_clients = num_mounts = num_kclients = num_libs = 0 + for fs_name in fs_list: + client_metadata = self.stats_json[CLIENT_METADATA_KEY].get(fs_name, {}) + client_cnt = len(client_metadata) + if client_cnt: + num_clients = num_clients + client_cnt + num_mounts = num_mounts + len( + [client for client, metadata in client_metadata.items() if + CLIENT_METADATA_MOUNT_POINT_KEY in metadata + and metadata[CLIENT_METADATA_MOUNT_POINT_KEY] != 'N/A']) + num_kclients = num_kclients + len( + [client for client, metadata in client_metadata.items() if + "kernel_version" in metadata]) + num_libs = num_clients - (num_mounts + num_kclients) + self.dump_json.update({'date': datetime.now().ctime()}) + client_count = self.dump_json.setdefault("client_count", {}) + client_count.update({'total_clients': num_clients, 'fuse': num_mounts, + 'kclient': num_kclients, 'libcephfs': num_libs}) + clients_json = self.dump_json.setdefault("filesystems", {}) for fs in fs_list: - self.__build_clients(fs) + self.__build_clients(fs, clients_json) sys.stdout.write(json.dumps(self.dump_json)) sys.stdout.write("\n") diff --git a/src/tools/cephfs_mirror/FSMirror.cc b/src/tools/cephfs_mirror/FSMirror.cc index 7ea798e6b..3d5bf2d1c 100644 --- a/src/tools/cephfs_mirror/FSMirror.cc +++ b/src/tools/cephfs_mirror/FSMirror.cc @@ -8,6 +8,8 @@ #include "common/debug.h" #include "common/errno.h" #include "common/WorkQueue.h" +#include "common/perf_counters.h" +#include "common/perf_counters_key.h" #include "include/stringify.h" #include "msg/Messenger.h" #include "FSMirror.h" @@ -25,6 +27,14 @@ using namespace std; +// Performance Counters +enum { + l_cephfs_mirror_fs_mirror_first = 5000, + l_cephfs_mirror_fs_mirror_peers, + l_cephfs_mirror_fs_mirror_dir_count, + l_cephfs_mirror_fs_mirror_last, +}; + namespace cephfs { namespace mirror { @@ -107,6 +117,18 @@ FSMirror::FSMirror(CephContext *cct, const Filesystem &filesystem, uint64_t pool m_asok_hook(new MirrorAdminSocketHook(cct, filesystem, this)) { m_service_daemon->add_or_update_fs_attribute(m_filesystem.fscid, SERVICE_DAEMON_DIR_COUNT_KEY, (uint64_t)0); + + std::string labels = ceph::perf_counters::key_create("cephfs_mirror_mirrored_filesystems", + {{"filesystem", m_filesystem.fs_name}}); + PerfCountersBuilder plb(m_cct, labels, l_cephfs_mirror_fs_mirror_first, + l_cephfs_mirror_fs_mirror_last); + auto prio = m_cct->_conf.get_val("cephfs_mirror_perf_stats_prio"); + plb.add_u64(l_cephfs_mirror_fs_mirror_peers, + "mirroring_peers", "Mirroring Peers", "mpee", prio); + plb.add_u64(l_cephfs_mirror_fs_mirror_dir_count, + "directory_count", "Directory Count", "dirc", prio); + m_perf_counters = plb.create_perf_counters(); + m_cct->get_perfcounters_collection()->add(m_perf_counters); } FSMirror::~FSMirror() { @@ -120,6 +142,12 @@ FSMirror::~FSMirror() { // outside the lock so that in-progress commands can acquire // lock and finish executing. delete m_asok_hook; + PerfCounters *perf_counters = nullptr; + std::swap(perf_counters, m_perf_counters); + if (perf_counters != nullptr) { + m_cct->get_perfcounters_collection()->remove(perf_counters); + delete perf_counters; + } } int FSMirror::init_replayer(PeerReplayer *peer_replayer) { @@ -355,6 +383,9 @@ void FSMirror::handle_acquire_directory(string_view dir_path) { peer_replayer->add_directory(dir_path); } } + if (m_perf_counters) { + m_perf_counters->set(l_cephfs_mirror_fs_mirror_dir_count, m_directories.size()); + } } void FSMirror::handle_release_directory(string_view dir_path) { @@ -372,6 +403,9 @@ void FSMirror::handle_release_directory(string_view dir_path) { peer_replayer->remove_directory(dir_path); } } + if (m_perf_counters) { + m_perf_counters->set(l_cephfs_mirror_fs_mirror_dir_count, m_directories.size()); + } } } @@ -395,6 +429,9 @@ void FSMirror::add_peer(const Peer &peer) { } m_peer_replayers.emplace(peer, std::move(replayer)); ceph_assert(m_peer_replayers.size() == 1); // support only a single peer + if (m_perf_counters) { + m_perf_counters->inc(l_cephfs_mirror_fs_mirror_peers); + } } void FSMirror::remove_peer(const Peer &peer) { @@ -415,6 +452,9 @@ void FSMirror::remove_peer(const Peer &peer) { dout(5) << ": shutting down replayers for peer=" << peer << dendl; shutdown_replayer(replayer.get()); } + if (m_perf_counters) { + m_perf_counters->dec(l_cephfs_mirror_fs_mirror_peers); + } } void FSMirror::mirror_status(Formatter *f) { diff --git a/src/tools/cephfs_mirror/FSMirror.h b/src/tools/cephfs_mirror/FSMirror.h index a9c1fab10..75fca7585 100644 --- a/src/tools/cephfs_mirror/FSMirror.h +++ b/src/tools/cephfs_mirror/FSMirror.h @@ -154,6 +154,8 @@ private: MountRef m_mount; + PerfCounters *m_perf_counters; + int init_replayer(PeerReplayer *peer_replayer); void shutdown_replayer(PeerReplayer *peer_replayer); void cleanup(); diff --git a/src/tools/cephfs_mirror/Mirror.cc b/src/tools/cephfs_mirror/Mirror.cc index edf903b92..fa2cf74be 100644 --- a/src/tools/cephfs_mirror/Mirror.cc +++ b/src/tools/cephfs_mirror/Mirror.cc @@ -9,6 +9,8 @@ #include "common/errno.h" #include "common/Timer.h" #include "common/WorkQueue.h" +#include "common/perf_counters.h" +#include "common/perf_counters_key.h" #include "include/types.h" #include "mon/MonClient.h" #include "msg/Messenger.h" @@ -20,6 +22,14 @@ #undef dout_prefix #define dout_prefix *_dout << "cephfs::mirror::Mirror " << __func__ +// Performance Counters +enum { + l_cephfs_mirror_first = 4000, + l_cephfs_mirror_file_systems_mirrorred, + l_cephfs_mirror_file_systems_mirror_enable_failures, + l_cephfs_mirror_last, +}; + namespace cephfs { namespace mirror { @@ -277,6 +287,17 @@ int Mirror::init(std::string &reason) { return r; } + std::string labels = ceph::perf_counters::key_create("cephfs_mirror"); + PerfCountersBuilder plb(m_cct, labels, l_cephfs_mirror_first, l_cephfs_mirror_last); + + auto prio = m_cct->_conf.get_val("cephfs_mirror_perf_stats_prio"); + plb.add_u64(l_cephfs_mirror_file_systems_mirrorred, + "mirrored_filesystems", "Filesystems mirrored", "mir", prio); + plb.add_u64_counter(l_cephfs_mirror_file_systems_mirror_enable_failures, + "mirror_enable_failures", "Mirroring enable failures", "mirf", prio); + m_perf_counters = plb.create_perf_counters(); + m_cct->get_perfcounters_collection()->add(m_perf_counters); + return 0; } @@ -285,6 +306,13 @@ void Mirror::shutdown() { m_stopping = true; m_cluster_watcher->shutdown(); m_cond.notify_all(); + + PerfCounters *perf_counters = nullptr; + std::swap(perf_counters, m_perf_counters); + if (perf_counters != nullptr) { + m_cct->get_perfcounters_collection()->remove(perf_counters); + delete perf_counters; + } } void Mirror::reopen_logs() { @@ -328,6 +356,9 @@ void Mirror::handle_enable_mirroring(const Filesystem &filesystem, m_service_daemon->add_or_update_fs_attribute(filesystem.fscid, SERVICE_DAEMON_MIRROR_ENABLE_FAILED_KEY, true); + if (m_perf_counters) { + m_perf_counters->inc(l_cephfs_mirror_file_systems_mirror_enable_failures); + } return; } @@ -336,6 +367,9 @@ void Mirror::handle_enable_mirroring(const Filesystem &filesystem, } dout(10) << ": Initialized FSMirror for filesystem=" << filesystem << dendl; + if (m_perf_counters) { + m_perf_counters->inc(l_cephfs_mirror_file_systems_mirrorred); + } } void Mirror::handle_enable_mirroring(const Filesystem &filesystem, int r) { @@ -353,10 +387,16 @@ void Mirror::handle_enable_mirroring(const Filesystem &filesystem, int r) { m_service_daemon->add_or_update_fs_attribute(filesystem.fscid, SERVICE_DAEMON_MIRROR_ENABLE_FAILED_KEY, true); + if (m_perf_counters) { + m_perf_counters->inc(l_cephfs_mirror_file_systems_mirror_enable_failures); + } return; } dout(10) << ": Initialized FSMirror for filesystem=" << filesystem << dendl; + if (m_perf_counters) { + m_perf_counters->inc(l_cephfs_mirror_file_systems_mirrorred); + } } void Mirror::enable_mirroring(const Filesystem &filesystem, uint64_t local_pool_id, @@ -412,6 +452,10 @@ void Mirror::handle_disable_mirroring(const Filesystem &filesystem, int r) { m_mirror_actions.erase(filesystem); } } + + if (m_perf_counters) { + m_perf_counters->dec(l_cephfs_mirror_file_systems_mirrorred); + } } void Mirror::disable_mirroring(const Filesystem &filesystem, Context *on_finish) { @@ -510,7 +554,7 @@ void Mirror::update_fs_mirrors() { if (!mirror_action.action_in_progress && !_is_restarting(filesystem)) { if (failed_restart || blocklisted_restart) { dout(5) << ": filesystem=" << filesystem << " failed mirroring (failed: " - << failed_restart << ", blocklisted: " << blocklisted_restart << dendl; + << failed_restart << ", blocklisted: " << blocklisted_restart << ")" << dendl; _set_restarting(filesystem); auto peers = mirror_action.fs_mirror->get_peers(); auto ctx = new C_RestartMirroring(this, filesystem, mirror_action.pool_id, peers); diff --git a/src/tools/cephfs_mirror/Mirror.h b/src/tools/cephfs_mirror/Mirror.h index 2081b5b53..5e37b5df4 100644 --- a/src/tools/cephfs_mirror/Mirror.h +++ b/src/tools/cephfs_mirror/Mirror.h @@ -104,6 +104,8 @@ private: RadosRef m_local; std::unique_ptr m_service_daemon; + PerfCounters *m_perf_counters; + int init_mon_client(); // called via listener diff --git a/src/tools/cephfs_mirror/PeerReplayer.cc b/src/tools/cephfs_mirror/PeerReplayer.cc index bd47046bb..6f3fb724a 100644 --- a/src/tools/cephfs_mirror/PeerReplayer.cc +++ b/src/tools/cephfs_mirror/PeerReplayer.cc @@ -12,6 +12,8 @@ #include "common/ceph_context.h" #include "common/debug.h" #include "common/errno.h" +#include "common/perf_counters.h" +#include "common/perf_counters_key.h" #include "FSMirror.h" #include "PeerReplayer.h" #include "Utils.h" @@ -26,6 +28,18 @@ using namespace std; +// Performance Counters +enum { + l_cephfs_mirror_peer_replayer_first = 6000, + l_cephfs_mirror_peer_replayer_snaps_synced, + l_cephfs_mirror_peer_replayer_snaps_deleted, + l_cephfs_mirror_peer_replayer_snaps_renamed, + l_cephfs_mirror_peer_replayer_snap_sync_failures, + l_cephfs_mirror_peer_replayer_avg_sync_time, + l_cephfs_mirror_peer_replayer_sync_bytes, + l_cephfs_mirror_peer_replayer_last, +}; + namespace cephfs { namespace mirror { @@ -161,10 +175,39 @@ PeerReplayer::PeerReplayer(CephContext *cct, FSMirror *fs_mirror, SERVICE_DAEMON_FAILED_DIR_COUNT_KEY, (uint64_t)0); m_service_daemon->add_or_update_peer_attribute(m_filesystem.fscid, m_peer, SERVICE_DAEMON_RECOVERED_DIR_COUNT_KEY, (uint64_t)0); + + std::string labels = ceph::perf_counters::key_create("cephfs_mirror_peers", + {{"source_fscid", stringify(m_filesystem.fscid)}, + {"source_filesystem", m_filesystem.fs_name}, + {"peer_cluster_name", m_peer.remote.cluster_name}, + {"peer_cluster_filesystem", m_peer.remote.fs_name}}); + PerfCountersBuilder plb(m_cct, labels, l_cephfs_mirror_peer_replayer_first, + l_cephfs_mirror_peer_replayer_last); + auto prio = m_cct->_conf.get_val("cephfs_mirror_perf_stats_prio"); + plb.add_u64_counter(l_cephfs_mirror_peer_replayer_snaps_synced, + "snaps_synced", "Snapshots Synchronized", "sync", prio); + plb.add_u64_counter(l_cephfs_mirror_peer_replayer_snaps_deleted, + "snaps_deleted", "Snapshots Deleted", "del", prio); + plb.add_u64_counter(l_cephfs_mirror_peer_replayer_snaps_renamed, + "snaps_renamed", "Snapshots Renamed", "ren", prio); + plb.add_u64_counter(l_cephfs_mirror_peer_replayer_snap_sync_failures, + "sync_failures", "Snapshot Sync Failures", "fail", prio); + plb.add_time_avg(l_cephfs_mirror_peer_replayer_avg_sync_time, + "avg_sync_time", "Average Sync Time", "asyn", prio); + plb.add_u64_counter(l_cephfs_mirror_peer_replayer_sync_bytes, + "sync_bytes", "Sync Bytes", "sbye", prio); + m_perf_counters = plb.create_perf_counters(); + m_cct->get_perfcounters_collection()->add(m_perf_counters); } PeerReplayer::~PeerReplayer() { delete m_asok_hook; + PerfCounters *perf_counters = nullptr; + std::swap(perf_counters, m_perf_counters); + if (perf_counters != nullptr) { + m_cct->get_perfcounters_collection()->remove(perf_counters); + delete perf_counters; + } } int PeerReplayer::init() { @@ -516,6 +559,9 @@ int PeerReplayer::propagate_snap_deletes(const std::string &dir_root, return r; } inc_deleted_snap(dir_root); + if (m_perf_counters) { + m_perf_counters->inc(l_cephfs_mirror_peer_replayer_snaps_deleted); + } } return 0; @@ -539,6 +585,9 @@ int PeerReplayer::propagate_snap_renames( return r; } inc_renamed_snap(dir_root); + if (m_perf_counters) { + m_perf_counters->inc(l_cephfs_mirror_peer_replayer_snaps_renamed); + } } return 0; @@ -694,6 +743,9 @@ int PeerReplayer::remote_file_op(const std::string &dir_root, const std::string derr << ": failed to copy path=" << epath << ": " << cpp_strerror(r) << dendl; return r; } + if (m_perf_counters) { + m_perf_counters->inc(l_cephfs_mirror_peer_replayer_sync_bytes, stx.stx_size); + } } else if (S_ISLNK(stx.stx_mode)) { // free the remote link before relinking r = ceph_unlinkat(m_remote_mount, fh.r_fd_dir_root, epath.c_str(), 0); @@ -1457,7 +1509,17 @@ int PeerReplayer::do_sync_snaps(const std::string &dir_root) { clear_current_syncing_snap(dir_root); return r; } + if (m_perf_counters) { + m_perf_counters->inc(l_cephfs_mirror_peer_replayer_snaps_synced); + } std::chrono::duration duration = clock::now() - start; + + utime_t d; + d.set_from_double(duration.count()); + if (m_perf_counters) { + m_perf_counters->tinc(l_cephfs_mirror_peer_replayer_avg_sync_time, d); + } + set_last_synced_stat(dir_root, it->first, it->second, duration.count()); if (--snaps_per_cycle == 0) { break; @@ -1481,6 +1543,9 @@ void PeerReplayer::sync_snaps(const std::string &dir_root, locker.lock(); if (r < 0) { _inc_failed_count(dir_root); + if (m_perf_counters) { + m_perf_counters->inc(l_cephfs_mirror_peer_replayer_snap_sync_failures); + } } else { _reset_failed_count(dir_root); } diff --git a/src/tools/cephfs_mirror/PeerReplayer.h b/src/tools/cephfs_mirror/PeerReplayer.h index 0511d154a..63e1bd9e8 100644 --- a/src/tools/cephfs_mirror/PeerReplayer.h +++ b/src/tools/cephfs_mirror/PeerReplayer.h @@ -269,6 +269,8 @@ private: ServiceDaemonStats m_service_daemon_stats; + PerfCounters *m_perf_counters; + void run(SnapshotReplayerThread *replayer); boost::optional pick_directory(); diff --git a/src/tools/rados/rados.cc b/src/tools/rados/rados.cc index 3d602e749..f2afe768c 100644 --- a/src/tools/rados/rados.cc +++ b/src/tools/rados/rados.cc @@ -2971,7 +2971,7 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, for (const auto& oid : oids) { ret = io_ctx.omap_clear(oid); if (ret < 0) { - cerr << "error clearing omap keys " << pool_name << "/" << prettify(*obj_name) << "/" + cerr << "error clearing omap keys " << pool_name << "/" << prettify(oid) << "/" << cpp_strerror(ret) << std::endl; return 1; } @@ -3120,7 +3120,12 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, cerr << "WARNING: pool copy does not preserve user_version, which some " << "apps may rely on." << std::endl; - if (rados.get_pool_is_selfmanaged_snaps_mode(src_pool)) { + ret = rados.pool_is_in_selfmanaged_snaps_mode(src_pool); + if (ret < 0) { + cerr << "failed to query pool " << src_pool << " for selfmanaged snaps: " + << cpp_strerror(ret) << std::endl; + return 1; + } else if (ret > 0) { cerr << "WARNING: pool " << src_pool << " has selfmanaged snaps, which are not preserved\n" << " by the cppool operation. This will break any snapshot user." << std::endl; @@ -3128,7 +3133,7 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, cerr << " If you insist on making a broken copy, you can pass\n" << " --yes-i-really-mean-it to proceed anyway." << std::endl; - exit(1); + return 1; } } @@ -3213,7 +3218,12 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts, return 1; } - if (rados.get_pool_is_selfmanaged_snaps_mode(pool_name)) { + ret = rados.pool_is_in_selfmanaged_snaps_mode(pool_name); + if (ret < 0) { + cerr << "failed to query pool " << pool_name << " for selfmanaged snaps: " + << cpp_strerror(ret) << std::endl; + return 1; + } else if (ret > 0) { cerr << "can't create snapshot: pool " << pool_name << " is in selfmanaged snaps mode" << std::endl; return 1; diff --git a/src/tools/rbd/action/Children.cc b/src/tools/rbd/action/Children.cc index 58e861b69..6881989ab 100644 --- a/src/tools/rbd/action/Children.cc +++ b/src/tools/rbd/action/Children.cc @@ -84,6 +84,7 @@ void get_arguments(po::options_description *positional, po::options_description *options) { at::add_image_or_snap_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE); + at::add_image_id_option(options); at::add_snap_id_option(options); options->add_options() ("all,a", po::bool_switch(), "list all children (include trash)"); @@ -104,14 +105,26 @@ int execute(const po::variables_map &vm, std::string namespace_name; std::string image_name; std::string snap_name; + std::string image_id; + + if (vm.count(at::IMAGE_ID)) { + image_id = vm[at::IMAGE_ID].as(); + } + int r = utils::get_pool_image_snapshot_names( vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &namespace_name, - &image_name, &snap_name, true, utils::SNAPSHOT_PRESENCE_PERMITTED, - utils::SPEC_VALIDATION_NONE); + &image_name, &snap_name, image_id.empty(), + utils::SNAPSHOT_PRESENCE_PERMITTED, utils::SPEC_VALIDATION_NONE); if (r < 0) { return r; } + if (!image_id.empty() && !image_name.empty()) { + std::cerr << "rbd: trying to access image using both name and id." + << std::endl; + return -EINVAL; + } + if (snap_id != LIBRADOS_SNAP_HEAD && !snap_name.empty()) { std::cerr << "rbd: trying to access snapshot using both name and id." << std::endl; @@ -127,8 +140,8 @@ int execute(const po::variables_map &vm, librados::Rados rados; librados::IoCtx io_ctx; librbd::Image image; - r = utils::init_and_open_image(pool_name, namespace_name, image_name, "", "", - true, &rados, &io_ctx, &image); + r = utils::init_and_open_image(pool_name, namespace_name, image_name, + image_id, "", true, &rados, &io_ctx, &image); if (r < 0) { return r; } diff --git a/src/tools/rbd_nbd/rbd-nbd.cc b/src/tools/rbd_nbd/rbd-nbd.cc index e348bd8fe..f2dfa1f66 100644 --- a/src/tools/rbd_nbd/rbd-nbd.cc +++ b/src/tools/rbd_nbd/rbd-nbd.cc @@ -194,7 +194,8 @@ static EventSocket terminate_event_sock; static int parse_args(vector& args, std::ostream *err_msg, Config *cfg); static int netlink_disconnect(int index); -static int netlink_resize(int nbd_index, uint64_t size); +static int netlink_resize(int nbd_index, const std::string& cookie, + uint64_t size); static int run_quiesce_hook(const std::string &quiesce_hook, const std::string &devpath, @@ -744,6 +745,7 @@ private: ceph::mutex lock = ceph::make_mutex("NBDWatchCtx::Locker"); bool notify = false; bool terminated = false; + std::string cookie; bool wait_notify() { dout(10) << __func__ << dendl; @@ -779,11 +781,11 @@ private: << dendl; } if (use_netlink) { - ret = netlink_resize(nbd_index, new_size); + ret = netlink_resize(nbd_index, cookie, new_size); } else { ret = ioctl(fd, NBD_SET_SIZE, new_size); if (ret < 0) { - derr << "resize failed: " << cpp_strerror(errno) << dendl; + derr << "ioctl resize failed: " << cpp_strerror(errno) << dendl; } } if (!ret) { @@ -805,13 +807,15 @@ public: bool _use_netlink, librados::IoCtx &_io_ctx, librbd::Image &_image, - unsigned long _size) + unsigned long _size, + std::string _cookie) : fd(_fd) , nbd_index(_nbd_index) , use_netlink(_use_netlink) , io_ctx(_io_ctx) , image(_image) , size(_size) + , cookie(std::move(_cookie)) { handle_notify_thread = make_named_thread("rbd_handle_notify", &NBDWatchCtx::handle_notify_entry, @@ -1319,7 +1323,8 @@ static int netlink_disconnect_by_path(const std::string& devpath) return netlink_disconnect(index); } -static int netlink_resize(int nbd_index, uint64_t size) +static int netlink_resize(int nbd_index, const std::string& cookie, + uint64_t size) { struct nl_sock *sock; struct nl_msg *msg; @@ -1327,30 +1332,33 @@ static int netlink_resize(int nbd_index, uint64_t size) sock = netlink_init(&nl_id); if (!sock) { - cerr << "rbd-nbd: Netlink interface not supported." << std::endl; - return 1; + derr << __func__ << ": netlink interface not supported" << dendl; + return -EINVAL; } nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, genl_handle_msg, NULL); msg = nlmsg_alloc(); if (!msg) { - cerr << "rbd-nbd: Could not allocate netlink message." << std::endl; + derr << __func__ << ": could not allocate netlink message" << dendl; goto free_sock; } if (!genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, nl_id, 0, 0, NBD_CMD_RECONFIGURE, 0)) { - cerr << "rbd-nbd: Could not setup message." << std::endl; + derr << __func__ << ": could not setup netlink message" << dendl; goto free_msg; } NLA_PUT_U32(msg, NBD_ATTR_INDEX, nbd_index); NLA_PUT_U64(msg, NBD_ATTR_SIZE_BYTES, size); + if (!cookie.empty()) + NLA_PUT_STRING(msg, NBD_ATTR_BACKEND_IDENTIFIER, cookie.c_str()); ret = nl_send_sync(sock, msg); if (ret < 0) { - cerr << "rbd-nbd: netlink resize failed: " << nl_geterror(ret) << std::endl; + derr << __func__ << ": netlink resize failed: " << nl_geterror(ret) + << dendl; goto free_sock; } @@ -1896,7 +1904,7 @@ static int do_map(int argc, const char *argv[], Config *cfg, bool reconnect) uint64_t handle; NBDWatchCtx watch_ctx(nbd, nbd_index, use_netlink, io_ctx, image, - info.size); + info.size, cfg->cookie); r = image.update_watch(&watch_ctx, &handle); if (r < 0) goto close_nbd; -- cgit v1.2.3