summaryrefslogtreecommitdiffstats
path: root/src/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/ceph_objectstore_tool.cc2
-rwxr-xr-xsrc/tools/cephfs/shell/cephfs-shell15
-rwxr-xr-xsrc/tools/cephfs/top/cephfs-top27
-rw-r--r--src/tools/cephfs_mirror/FSMirror.cc40
-rw-r--r--src/tools/cephfs_mirror/FSMirror.h2
-rw-r--r--src/tools/cephfs_mirror/Mirror.cc46
-rw-r--r--src/tools/cephfs_mirror/Mirror.h2
-rw-r--r--src/tools/cephfs_mirror/PeerReplayer.cc65
-rw-r--r--src/tools/cephfs_mirror/PeerReplayer.h2
-rw-r--r--src/tools/rados/rados.cc18
-rw-r--r--src/tools/rbd/action/Children.cc21
-rw-r--r--src/tools/rbd_nbd/rbd-nbd.cc30
12 files changed, 238 insertions, 32 deletions
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<int64_t>("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<int64_t>("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<ServiceDaemon> 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<int64_t>("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<double> 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<std::string> 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<std::string>();
+ }
+
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<const char*>& 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;