]> git.proxmox.com Git - ceph.git/blame - ceph/src/tools/rbd/action/Diff.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / tools / rbd / action / Diff.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
4#include "tools/rbd/ArgumentTypes.h"
5#include "tools/rbd/Shell.h"
6#include "tools/rbd/Utils.h"
7#include "common/errno.h"
8#include "common/Formatter.h"
9#include "common/TextTable.h"
10#include <iostream>
11#include <boost/program_options.hpp>
12
13namespace rbd {
14namespace action {
15namespace diff {
16
17namespace at = argument_types;
18namespace po = boost::program_options;
19
20struct output_method {
21 output_method() : f(NULL), t(NULL), empty(true) {}
22 Formatter *f;
23 TextTable *t;
24 bool empty;
25};
26
27static int diff_cb(uint64_t ofs, size_t len, int exists, void *arg)
28{
29 output_method *om = static_cast<output_method *>(arg);
30 om->empty = false;
31 if (om->f) {
32 om->f->open_object_section("extent");
33 om->f->dump_unsigned("offset", ofs);
34 om->f->dump_unsigned("length", len);
35 om->f->dump_string("exists", exists ? "true" : "false");
36 om->f->close_section();
37 } else {
11fdf7f2 38 ceph_assert(om->t);
7c673cae
FG
39 *(om->t) << ofs << len << (exists ? "data" : "zero") << TextTable::endrow;
40 }
41 return 0;
42}
43
44static int do_diff(librbd::Image& image, const char *fromsnapname,
45 bool whole_object, Formatter *f)
46{
47 int r;
48 librbd::image_info_t info;
49
50 r = image.stat(info, sizeof(info));
51 if (r < 0)
52 return r;
53
54 output_method om;
55 if (f) {
56 om.f = f;
57 f->open_array_section("extents");
58 } else {
59 om.t = new TextTable();
60 om.t->define_column("Offset", TextTable::LEFT, TextTable::LEFT);
61 om.t->define_column("Length", TextTable::LEFT, TextTable::LEFT);
62 om.t->define_column("Type", TextTable::LEFT, TextTable::LEFT);
63 }
64
65 r = image.diff_iterate2(fromsnapname, 0, info.size, true, whole_object,
66 diff_cb, &om);
67 if (f) {
68 f->close_section();
69 f->flush(std::cout);
70 } else {
71 if (!om.empty)
72 std::cout << *om.t;
73 delete om.t;
74 }
75 return r;
76}
77
78void get_arguments(po::options_description *positional,
79 po::options_description *options) {
80 at::add_image_or_snap_spec_options(positional, options,
81 at::ARGUMENT_MODIFIER_NONE);
82 options->add_options()
83 (at::FROM_SNAPSHOT_NAME.c_str(), po::value<std::string>(),
84 "snapshot starting point")
85 (at::WHOLE_OBJECT.c_str(), po::bool_switch(), "compare whole object");
86 at::add_format_options(options);
87}
88
11fdf7f2
TL
89int execute(const po::variables_map &vm,
90 const std::vector<std::string> &ceph_global_init_args) {
7c673cae
FG
91 size_t arg_index = 0;
92 std::string pool_name;
11fdf7f2 93 std::string namespace_name;
7c673cae
FG
94 std::string image_name;
95 std::string snap_name;
96 int r = utils::get_pool_image_snapshot_names(
11fdf7f2
TL
97 vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &namespace_name,
98 &image_name, &snap_name, true, utils::SNAPSHOT_PRESENCE_PERMITTED,
7c673cae
FG
99 utils::SPEC_VALIDATION_NONE);
100 if (r < 0) {
101 return r;
102 }
103
104 std::string from_snap_name;
105 if (vm.count(at::FROM_SNAPSHOT_NAME)) {
106 from_snap_name = vm[at::FROM_SNAPSHOT_NAME].as<std::string>();
107 }
108
109 bool diff_whole_object = vm[at::WHOLE_OBJECT].as<bool>();
110
111 at::Format::Formatter formatter;
112 r = utils::get_formatter(vm, &formatter);
113 if (r < 0) {
114 return r;
115 }
116
117 librados::Rados rados;
118 librados::IoCtx io_ctx;
119 librbd::Image image;
11fdf7f2
TL
120 r = utils::init_and_open_image(pool_name, namespace_name, image_name, "",
121 snap_name, true, &rados, &io_ctx, &image);
7c673cae
FG
122 if (r < 0) {
123 return r;
124 }
125
126 r = do_diff(image, from_snap_name.empty() ? nullptr : from_snap_name.c_str(),
127 diff_whole_object, formatter.get());
128 if (r < 0) {
129 std::cerr << "rbd: diff error: " << cpp_strerror(r) << std::endl;
130 return -r;
131 }
132 return 0;
133}
134
7c673cae
FG
135Shell::Action action(
136 {"diff"}, {},
137 "Print extents that differ since a previous snap, or image creation.", "",
138 &get_arguments, &execute);
139
140} // namespace diff
141} // namespace action
142} // namespace rbd