]>
git.proxmox.com Git - ceph.git/blob - ceph/src/tools/rbd/action/Lock.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 "common/errno.h"
8 #include "common/Formatter.h"
9 #include "common/TextTable.h"
11 #include <boost/program_options.hpp>
17 namespace at
= argument_types
;
18 namespace po
= boost::program_options
;
22 void add_id_option(po::options_description
*positional
) {
23 positional
->add_options()
24 ("lock-id", "unique lock id");
27 int get_id(const po::variables_map
&vm
, std::string
*id
) {
28 *id
= utils::get_positional_argument(vm
, 1);
30 std::cerr
<< "rbd: lock id was not specified" << std::endl
;
36 } // anonymous namespace
38 static int do_lock_list(librbd::Image
& image
, Formatter
*f
)
40 std::list
<librbd::locker_t
> lockers
;
46 r
= image
.list_lockers(&lockers
, &exclusive
, &tag
);
51 f
->open_array_section("locks");
53 tbl
.define_column("Locker", TextTable::LEFT
, TextTable::LEFT
);
54 tbl
.define_column("ID", TextTable::LEFT
, TextTable::LEFT
);
55 tbl
.define_column("Address", TextTable::LEFT
, TextTable::LEFT
);
59 bool one
= (lockers
.size() == 1);
62 std::cout
<< "There " << (one
? "is " : "are ") << lockers
.size()
63 << (exclusive
? " exclusive" : " shared")
64 << " lock" << (one
? "" : "s") << " on this image.\n";
66 std::cout
<< "Lock tag: " << tag
<< "\n";
69 for (std::list
<librbd::locker_t
>::const_iterator it
= lockers
.begin();
70 it
!= lockers
.end(); ++it
) {
72 f
->open_object_section("lock");
73 f
->dump_string("id", it
->cookie
);
74 f
->dump_string("locker", it
->client
);
75 f
->dump_string("address", it
->address
);
78 tbl
<< it
->client
<< it
->cookie
<< it
->address
<< TextTable::endrow
;
92 static int do_lock_add(librbd::Image
& image
, const char *cookie
,
96 return image
.lock_shared(cookie
, tag
);
98 return image
.lock_exclusive(cookie
);
101 static int do_lock_remove(librbd::Image
& image
, const char *client
,
104 return image
.break_lock(client
, cookie
);
107 void get_list_arguments(po::options_description
*positional
,
108 po::options_description
*options
) {
109 at::add_image_spec_options(positional
, options
, at::ARGUMENT_MODIFIER_NONE
);
110 at::add_format_options(options
);
113 int execute_list(const po::variables_map
&vm
,
114 const std::vector
<std::string
> &ceph_global_init_args
) {
115 size_t arg_index
= 0;
116 std::string pool_name
;
117 std::string namespace_name
;
118 std::string image_name
;
119 std::string snap_name
;
120 int r
= utils::get_pool_image_snapshot_names(
121 vm
, at::ARGUMENT_MODIFIER_NONE
, &arg_index
, &pool_name
, &namespace_name
,
122 &image_name
, &snap_name
, true, utils::SNAPSHOT_PRESENCE_NONE
,
123 utils::SPEC_VALIDATION_NONE
);
128 at::Format::Formatter formatter
;
129 r
= utils::get_formatter(vm
, &formatter
);
134 librados::Rados rados
;
135 librados::IoCtx io_ctx
;
137 r
= utils::init_and_open_image(pool_name
, namespace_name
, image_name
, "", "",
138 true, &rados
, &io_ctx
, &image
);
143 r
= do_lock_list(image
, formatter
.get());
145 std::cerr
<< "rbd: listing locks failed: " << cpp_strerror(r
) << std::endl
;
151 void get_add_arguments(po::options_description
*positional
,
152 po::options_description
*options
) {
153 at::add_image_spec_options(positional
, options
, at::ARGUMENT_MODIFIER_NONE
);
154 add_id_option(positional
);
155 options
->add_options()
156 ("shared", po::value
<std::string
>(), "shared lock tag");
159 int execute_add(const po::variables_map
&vm
,
160 const std::vector
<std::string
> &ceph_global_init_args
) {
161 size_t arg_index
= 0;
162 std::string pool_name
;
163 std::string namespace_name
;
164 std::string image_name
;
165 std::string snap_name
;
166 int r
= utils::get_pool_image_snapshot_names(
167 vm
, at::ARGUMENT_MODIFIER_NONE
, &arg_index
, &pool_name
, &namespace_name
,
168 &image_name
, &snap_name
, true, utils::SNAPSHOT_PRESENCE_NONE
,
169 utils::SPEC_VALIDATION_NONE
);
174 std::string lock_cookie
;
175 r
= get_id(vm
, &lock_cookie
);
180 std::string lock_tag
;
181 if (vm
.count("shared")) {
182 lock_tag
= vm
["shared"].as
<std::string
>();
185 librados::Rados rados
;
186 librados::IoCtx io_ctx
;
188 r
= utils::init_and_open_image(pool_name
, namespace_name
, image_name
, "", "",
189 false, &rados
, &io_ctx
, &image
);
194 r
= do_lock_add(image
, lock_cookie
.c_str(),
195 lock_tag
.empty() ? nullptr : lock_tag
.c_str());
197 if (r
== -EBUSY
|| r
== -EEXIST
) {
198 if (!lock_tag
.empty()) {
199 std::cerr
<< "rbd: lock is already held by someone else"
200 << " with a different tag" << std::endl
;
202 std::cerr
<< "rbd: lock is already held by someone else" << std::endl
;
205 std::cerr
<< "rbd: taking lock failed: " << cpp_strerror(r
) << std::endl
;
212 void get_remove_arguments(po::options_description
*positional
,
213 po::options_description
*options
) {
214 at::add_image_spec_options(positional
, options
, at::ARGUMENT_MODIFIER_NONE
);
215 add_id_option(positional
);
216 positional
->add_options()
217 ("locker", "locker client");
220 int execute_remove(const po::variables_map
&vm
,
221 const std::vector
<std::string
> &ceph_global_init_args
) {
222 size_t arg_index
= 0;
223 std::string pool_name
;
224 std::string namespace_name
;
225 std::string image_name
;
226 std::string snap_name
;
227 int r
= utils::get_pool_image_snapshot_names(
228 vm
, at::ARGUMENT_MODIFIER_NONE
, &arg_index
, &pool_name
, &namespace_name
,
229 &image_name
, &snap_name
, true, utils::SNAPSHOT_PRESENCE_NONE
,
230 utils::SPEC_VALIDATION_NONE
);
235 std::string lock_cookie
;
236 r
= get_id(vm
, &lock_cookie
);
241 std::string lock_client
= utils::get_positional_argument(vm
, 2);
242 if (lock_client
.empty()) {
243 std::cerr
<< "rbd: locker was not specified" << std::endl
;
247 librados::Rados rados
;
248 librados::IoCtx io_ctx
;
250 r
= utils::init_and_open_image(pool_name
, namespace_name
, image_name
, "", "",
251 false, &rados
, &io_ctx
, &image
);
256 r
= do_lock_remove(image
, lock_client
.c_str(), lock_cookie
.c_str());
258 std::cerr
<< "rbd: releasing lock failed: " << cpp_strerror(r
) << std::endl
;
264 Shell::Action
action_list(
265 {"lock", "list"}, {"lock", "ls"}, "Show locks held on an image.", "",
266 &get_list_arguments
, &execute_list
);
267 Shell::Action
action_add(
268 {"lock", "add"}, {}, "Take a lock on an image.", "",
269 &get_add_arguments
, &execute_add
);
270 Shell::Action
action_remove(
271 {"lock", "remove"}, {"lock", "rm"}, "Release a lock on an image.", "",
272 &get_remove_arguments
, &execute_remove
);
275 } // namespace action