Make json or xml formatted output more human-readable.
-.. option:: -o map-options, --options map-options
+.. option:: -o krbd-options, --options krbd-options
- Specifies which options to use when mapping an image. map-options is
- a comma-separated string of options (similar to mount(8) mount options).
- See map options section below for more details.
+ Specifies which options to use when mapping or unmapping an image via the
+ rbd kernel driver. krbd-options is a comma-separated list of options
+ (similar to mount(8) mount options). See kernel rbd (krbd) options section
+ below for more details.
.. option:: --read-only
This requires image format 2.
-:command:`map` [-o | --options *map-options* ] [--read-only] *image-spec* | *snap-spec*
+:command:`map` [-o | --options *krbd-options* ] [--read-only] *image-spec* | *snap-spec*
Maps the specified image to a block device via the rbd kernel module.
-:command:`unmap` *image-spec* | *snap-spec* | *device-path*
+:command:`unmap` [-o | --options *krbd-options* ] *image-spec* | *snap-spec* | *device-path*
Unmaps the block device that was mapped via the rbd kernel module.
:command:`showmapped`
used.
-Map options
-===========
+Kernel rbd (krbd) options
+=========================
Most of these options are useful mainly for debugging and benchmarking. The
default values are set in the kernel and may therefore depend on the version of
the running kernel.
-libceph (per client instance) options:
+Per client instance `rbd map` options:
* fsid=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee - FSID that should be assumed by
the client.
* osd_idle_ttl=x - OSD idle TTL (default is 60 seconds).
-Mapping (per block device) options:
+Per mapping (block device) `rbd map` options:
* rw - Map the image read-write (default).
* lock_on_read - Acquire exclusive lock on reads, in addition to writes and
discards (since 4.9).
+`rbd unmap` options:
+
+* force - Force the unmapping of a block device that is open (since 4.9). The
+ driver will wait for running requests to complete and then unmap; requests
+ sent to the driver after initiating the unmap will be failed.
+
Examples
========
int krbd_map(struct krbd_ctx *ctx, const char *pool, const char *image,
const char *snap, const char *options, char **pdevnode);
-int krbd_unmap(struct krbd_ctx *ctx, const char *devnode);
+int krbd_unmap(struct krbd_ctx *ctx, const char *devnode,
+ const char *options);
int krbd_unmap_by_spec(struct krbd_ctx *ctx, const char *pool,
- const char *image, const char *snap);
+ const char *image, const char *snap,
+ const char *options);
#ifdef __cplusplus
}
return r;
}
+static string build_unmap_buf(const string& id, const char *options)
+{
+ string buf(id);
+ if (strcmp(options, "") != 0) {
+ buf += " ";
+ buf += options;
+ }
+ return buf;
+}
+
static int wait_for_udev_remove(struct udev_monitor *mon, dev_t devno)
{
for (;;) {
return 0;
}
-static int do_unmap(struct udev *udev, dev_t devno, const string& id)
+static int do_unmap(struct udev *udev, dev_t devno, const string& buf)
{
struct udev_monitor *mon;
int r;
* Try to circumvent this with a retry before turning to udev.
*/
for (int tries = 0; ; tries++) {
- r = sysfs_write_rbd_remove(id);
+ r = sysfs_write_rbd_remove(buf);
if (r >= 0) {
break;
} else if (r == -EBUSY && tries < 2) {
return r;
}
-static int unmap_image(struct krbd_ctx *ctx, const char *devnode)
+static int unmap_image(struct krbd_ctx *ctx, const char *devnode,
+ const char *options)
{
struct stat sb;
dev_t wholedevno;
return r;
}
- return do_unmap(ctx->udev, wholedevno, id);
+ return do_unmap(ctx->udev, wholedevno, build_unmap_buf(id, options));
}
static int unmap_image(struct krbd_ctx *ctx, const char *pool,
- const char *image, const char *snap)
-
+ const char *image, const char *snap,
+ const char *options)
{
dev_t devno;
string id;
return r;
}
- return do_unmap(ctx->udev, devno, id);
+ return do_unmap(ctx->udev, devno, build_unmap_buf(id, options));
}
static bool dump_one_image(Formatter *f, TextTable *tbl,
return r;
}
-extern "C" int krbd_unmap(struct krbd_ctx *ctx, const char *devnode)
+extern "C" int krbd_unmap(struct krbd_ctx *ctx, const char *devnode,
+ const char *options)
{
- return unmap_image(ctx, devnode);
+ return unmap_image(ctx, devnode, options);
}
extern "C" int krbd_unmap_by_spec(struct krbd_ctx *ctx, const char *pool,
- const char *image, const char *snap)
+ const char *image, const char *snap,
+ const char *options)
{
- return unmap_image(ctx, pool, image, snap);
+ return unmap_image(ctx, pool, image, snap, options);
}
int krbd_showmapped(struct krbd_ctx *ctx, Formatter *f)
rbd help unmap
usage: rbd unmap [--pool <pool>] [--image <image>] [--snap <snap>]
+ [--options <options>]
<image-or-snap-or-device-spec>
Unmap a rbd device that was used by the kernel.
-p [ --pool ] arg pool name
--image arg image name
--snap arg snapshot name
+ -o [ --options ] arg unmap options
rbd help watch
usage: rbd watch [--pool <pool>] [--image <image>]
return ret;
}
- ret = krbd_unmap(krbd, ctx->krbd_name);
+ ret = krbd_unmap(krbd, ctx->krbd_name, "");
if (ret < 0) {
prt("krbd_unmap(%s) failed\n", ctx->krbd_name);
return ret;
namespace {
-std::map<std::string, std::string> map_options;
+std::map<std::string, std::string> map_options; // used for both map and unmap
} // anonymous namespace
return 0;
}
+static int parse_unmap_options(char *options)
+{
+ for (char *this_char = strtok(options, ", ");
+ this_char != NULL;
+ this_char = strtok(NULL, ",")) {
+ char *value_char;
+
+ if ((value_char = strchr(this_char, '=')) != NULL)
+ *value_char++ = '\0';
+
+ if (!strcmp(this_char, "force")) {
+ put_map_option("force", this_char);
+ } else {
+ std::cerr << "rbd: unknown unmap option '" << this_char << "'" << std::endl;
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
static int do_kernel_showmapped(Formatter *f)
{
struct krbd_ctx *krbd;
const char *imgname, const char *snapname)
{
struct krbd_ctx *krbd;
+ std::ostringstream oss;
int r;
r = krbd_create_from_context(g_ceph_context, &krbd);
if (r < 0)
return r;
+ for (auto it = map_options.cbegin(); it != map_options.cend(); ++it) {
+ if (it != map_options.cbegin())
+ oss << ",";
+ oss << it->second;
+ }
+
if (dev)
- r = krbd_unmap(krbd, dev);
+ r = krbd_unmap(krbd, dev, oss.str().c_str());
else
- r = krbd_unmap_by_spec(krbd, poolname, imgname, snapname);
+ r = krbd_unmap_by_spec(krbd, poolname, imgname, snapname,
+ oss.str().c_str());
krbd_destroy(krbd);
return r;
at::add_pool_option(options, at::ARGUMENT_MODIFIER_NONE);
at::add_image_option(options, at::ARGUMENT_MODIFIER_NONE);
at::add_snap_option(options, at::ARGUMENT_MODIFIER_NONE);
+ options->add_options()
+ ("options,o", po::value<std::string>(), "unmap options");
}
int execute_unmap(const po::variables_map &vm) {
return -EINVAL;
}
+ if (vm.count("options")) {
+ char *cli_unmap_options = strdup(vm["options"].as<std::string>().c_str());
+ BOOST_SCOPE_EXIT( (cli_unmap_options) ) {
+ free(cli_unmap_options);
+ } BOOST_SCOPE_EXIT_END;
+
+ if (parse_unmap_options(cli_unmap_options)) {
+ std::cerr << "rbd: couldn't parse unmap options" << std::endl;
+ return -EINVAL;
+ }
+ }
+
utils::init_context();
r = do_kernel_unmap(device_name.empty() ? nullptr : device_name.c_str(),