]>
git.proxmox.com Git - ceph.git/blob - ceph/src/tools/rbd/action/List.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "tools/rbd/ArgumentTypes.h"
5 #include "tools/rbd/Shell.h"
6 #include "tools/rbd/Utils.h"
7 #include "include/Context.h"
8 #include "include/stringify.h"
9 #include "include/types.h"
10 #include "common/errno.h"
11 #include "common/Formatter.h"
12 #include "common/TextTable.h"
14 #include <boost/program_options.hpp>
15 #include "global/global_context.h"
22 namespace at
= argument_types
;
23 namespace po
= boost::program_options
;
33 librbd::RBD::AioCompletion
* completion
;
44 int list_process_image(librados::Rados
* rados
, WorkerEntry
* w
, bool lflag
, Formatter
*f
, TextTable
&tbl
)
47 librbd::image_info_t info
;
48 std::string pool
, image
, snap
, parent
;
50 // handle second-nth trips through loop
51 r
= w
->img
.parent_info(&pool
, &image
, &snap
);
52 if (r
< 0 && r
!= -ENOENT
)
54 bool has_parent
= false;
56 parent
= pool
+ "/" + image
+ "@" + snap
;
60 if (w
->img
.stat(info
, sizeof(info
)) < 0) {
65 w
->img
.old_format(&old_format
);
67 std::list
<librbd::locker_t
> lockers
;
69 r
= w
->img
.list_lockers(&lockers
, &exclusive
, NULL
);
73 if (!lockers
.empty()) {
74 lockstr
= (exclusive
) ? "excl" : "shr";
78 f
->open_object_section("image");
79 f
->dump_string("image", w
->name
);
80 f
->dump_unsigned("size", info
.size
);
82 f
->open_object_section("parent");
83 f
->dump_string("pool", pool
);
84 f
->dump_string("image", image
);
85 f
->dump_string("snapshot", snap
);
88 f
->dump_int("format", old_format
? 1 : 2);
90 f
->dump_string("lock_type", exclusive
? "exclusive" : "shared");
94 << stringify(byte_u_t(info
.size
))
96 << ((old_format
) ? '1' : '2')
97 << "" // protect doesn't apply to images
102 std::vector
<librbd::snap_info_t
> snaplist
;
103 if (w
->img
.snap_list(snaplist
) >= 0 && !snaplist
.empty()) {
104 for (std::vector
<librbd::snap_info_t
>::iterator s
= snaplist
.begin();
105 s
!= snaplist
.end(); ++s
) {
107 bool has_parent
= false;
109 w
->img
.snap_set(s
->name
.c_str());
110 r
= w
->img
.snap_is_protected(s
->name
.c_str(), &is_protected
);
113 if (w
->img
.parent_info(&pool
, &image
, &snap
) >= 0) {
114 parent
= pool
+ "/" + image
+ "@" + snap
;
118 f
->open_object_section("snapshot");
119 f
->dump_string("image", w
->name
);
120 f
->dump_string("snapshot", s
->name
);
121 f
->dump_unsigned("size", s
->size
);
123 f
->open_object_section("parent");
124 f
->dump_string("pool", pool
);
125 f
->dump_string("image", image
);
126 f
->dump_string("snapshot", snap
);
129 f
->dump_int("format", old_format
? 1 : 2);
130 f
->dump_string("protected", is_protected
? "true" : "false");
133 tbl
<< w
->name
+ "@" + s
->name
134 << stringify(byte_u_t(s
->size
))
136 << ((old_format
) ? '1' : '2')
137 << (is_protected
? "yes" : "")
138 << "" // locks don't apply to snaps
139 << TextTable::endrow
;
144 return r
< 0 ? r
: 0;
147 int do_list(std::string
&pool_name
, bool lflag
, int threads
, Formatter
*f
) {
148 std::vector
<WorkerEntry
*> workers
;
149 std::vector
<std::string
> names
;
150 librados::Rados rados
;
152 librados::IoCtx ioctx
;
161 int r
= utils::init(pool_name
, &rados
, &ioctx
);
166 r
= rbd
.list(ioctx
, names
);
172 f
->open_array_section("images");
173 for (std::vector
<std::string
>::const_iterator i
= names
.begin();
174 i
!= names
.end(); ++i
) {
176 f
->dump_string("name", *i
);
178 std::cout
<< *i
<< std::endl
;
190 f
->open_array_section("images");
192 tbl
.define_column("NAME", TextTable::LEFT
, TextTable::LEFT
);
193 tbl
.define_column("SIZE", TextTable::RIGHT
, TextTable::RIGHT
);
194 tbl
.define_column("PARENT", TextTable::LEFT
, TextTable::LEFT
);
195 tbl
.define_column("FMT", TextTable::RIGHT
, TextTable::RIGHT
);
196 tbl
.define_column("PROT", TextTable::LEFT
, TextTable::LEFT
);
197 tbl
.define_column("LOCK", TextTable::LEFT
, TextTable::LEFT
);
200 for (int left
= 0; left
< std::min(threads
, (int)names
.size()); left
++) {
201 workers
.push_back(new WorkerEntry());
204 auto i
= names
.begin();
206 size_t workers_idle
= 0;
207 for (auto comp
: workers
) {
208 switch (comp
->state
) {
210 comp
->completion
->wait_for_complete();
211 comp
->state
= STATE_IDLE
;
212 comp
->completion
->release();
213 comp
->completion
= nullptr;
214 // we want it to fall through in this case
216 if (i
== names
.end()) {
221 comp
->completion
= new librbd::RBD::AioCompletion(nullptr, nullptr);
222 r
= rbd
.aio_open_read_only(ioctx
, comp
->img
, i
->c_str(), NULL
, comp
->completion
);
224 comp
->state
= STATE_OPENED
;
227 comp
->completion
->wait_for_complete();
228 // image might disappear between rbd.list() and rbd.open(); ignore
229 // that, warn about other possible errors (EPERM, say, for opening
230 // an old-format image, because you need execute permission for the
232 r
= comp
->completion
->get_return_value();
233 comp
->completion
->release();
236 std::cerr
<< "rbd: error opening " << *i
<< ": " << cpp_strerror(r
)
239 // in any event, continue to next image
240 comp
->state
= STATE_IDLE
;
243 r
= list_process_image(&rados
, comp
, lflag
, f
, tbl
);
245 std::cerr
<< "rbd: error processing image " << comp
->name
<< ": " << cpp_strerror(r
)
248 comp
->completion
= new librbd::RBD::AioCompletion(nullptr, nullptr);
249 r
= comp
->img
.aio_close(comp
->completion
);
250 comp
->state
= STATE_DONE
;
254 if (workers_idle
== workers
.size()) {
262 } else if (!names
.empty()) {
268 for (auto comp
: workers
) {
272 return r
< 0 ? r
: 0;
275 void get_arguments(po::options_description
*positional
,
276 po::options_description
*options
) {
277 options
->add_options()
278 ("long,l", po::bool_switch(), "long listing format");
279 at::add_pool_options(positional
, options
);
280 at::add_format_options(options
);
283 int execute(const po::variables_map
&vm
) {
284 size_t arg_index
= 0;
285 std::string pool_name
= utils::get_pool_name(vm
, &arg_index
);
287 at::Format::Formatter formatter
;
288 int r
= utils::get_formatter(vm
, &formatter
);
293 r
= do_list(pool_name
, vm
["long"].as
<bool>(),
294 g_conf
->get_val
<int64_t>("rbd_concurrent_management_ops"),
297 std::cerr
<< "rbd: list: " << cpp_strerror(r
) << std::endl
;
304 Shell::SwitchArguments
switched_arguments({"long", "l"});
305 Shell::Action
action(
306 {"list"}, {"ls"}, "List rbd images.", "", &get_arguments
, &execute
);
309 } // namespace action