rbd: expose options available to rbd map

Add a -o / --options option, which would allow users to specify
rbd-specific and generic ceph client and osd options available at
mapping time in a comma separated list (similar to mount(8) mount
options).

Exposed options are:

- fsid=%s
- ip=%s
- share
- noshare
- crc
- nocrc
- osdkeepalive=%d
- osd_idle_ttl=%d
- rw
- ro (equivalent to existing --read-only flag)

The rw/ro < 3.7 kernels compatibility kludge added in commit
fb0f198644 is preserved.

Signed-off-by: Ilya Dryomov <ilya.dryomov@inktank.com>
This commit is contained in:
Ilya Dryomov 2013-12-27 19:40:59 +02:00 committed by Josh Durgin
parent 87b8e54fae
commit 9b7364d245
4 changed files with 203 additions and 13 deletions

View File

@ -113,9 +113,15 @@ Parameters
Make json or xml formatted output more human-readable.
.. option:: -o map-options, --options map-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.
.. option:: --read-only
Set device readonly when mapping image.
Map the image read-only. Equivalent to -o ro.
Commands
@ -235,7 +241,7 @@ Commands
This requires image format 2.
:command:`map` [*image-name*]
:command:`map` [*image-name*] [-o | --options *map-options* ] [--read-only]
Maps the specified image to a block device via the rbd kernel module.
:command:`unmap` [*device-path*]
@ -306,6 +312,35 @@ By default, [*stripe_unit*] is the same as the object size and [*stripe_count*]
used.
Map 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.
* fsid=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee - FSID that should be assumed by
the client.
* ip=a.b.c.d[:p] - IP and, optionally, port the client should use.
* share - Enable sharing of client instances with other mappings (default).
* noshare - Disable sharing of client instances with other mappings.
* crc - Enable CRC32C checksumming for data writes (default).
* nocrc - Disable CRC32C checksumming for data writes.
* osdkeepalive=x - OSD keepalive timeout (default is 5 seconds).
* osd_idle_ttl=x - OSD idle TTL (default is 60 seconds).
* rw - Map the image read-write (default).
* ro - Map the image read-only. Equivalent to --read-only.
Examples
========

View File

@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "RBD" "8" "December 09, 2013" "dev" "Ceph"
.TH "RBD" "8" "December 27, 2013" "dev" "Ceph"
.SH NAME
rbd \- manage rados block device (RBD) images
.
@ -177,8 +177,15 @@ Make json or xml formatted output more human\-readable.
.UNINDENT
.INDENT 0.0
.TP
.B \-o map\-options, \-\-options map\-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.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-read\-only
Set device readonly when mapping image.
Map the image read\-only. Equivalent to \-o ro.
.UNINDENT
.SH COMMANDS
.INDENT 0.0
@ -295,7 +302,7 @@ in different pools than the parent snapshot.)
.sp
This requires image format 2.
.TP
.B \fBmap\fP [\fIimage\-name\fP]
.B \fBmap\fP [\fIimage\-name\fP] [\-o | \-\-options \fImap\-options\fP ] [\-\-read\-only]
Maps the specified image to a block device via the rbd kernel module.
.TP
.B \fBunmap\fP [\fIdevice\-path\fP]
@ -381,6 +388,34 @@ The striping is controlled by three parameters:
By default, [\fIstripe_unit\fP] is the same as the object size and [\fIstripe_count\fP] is 1. Specifying a different
[\fIstripe_unit\fP] requires that the STRIPINGV2 feature be supported (added in Ceph v0.53) and format 2 images be
used.
.SH MAP OPTIONS
.sp
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.
.INDENT 0.0
.IP \(bu 2
fsid=aaaaaaaa\-bbbb\-cccc\-dddd\-eeeeeeeeeeee \- FSID that should be assumed by
the client.
.IP \(bu 2
ip=a.b.c.d[:p] \- IP and, optionally, port the client should use.
.IP \(bu 2
share \- Enable sharing of client instances with other mappings (default).
.IP \(bu 2
noshare \- Disable sharing of client instances with other mappings.
.IP \(bu 2
crc \- Enable CRC32C checksumming for data writes (default).
.IP \(bu 2
nocrc \- Disable CRC32C checksumming for data writes.
.IP \(bu 2
osdkeepalive=x \- OSD keepalive timeout (default is 5 seconds).
.IP \(bu 2
osd_idle_ttl=x \- OSD idle TTL (default is 60 seconds).
.IP \(bu 2
rw \- Map the image read\-write (default).
.IP \(bu 2
ro \- Map the image read\-only. Equivalent to \-\-read\-only.
.UNINDENT
.SH EXAMPLES
.sp
To create a new rbd image that is 100 GB:

View File

@ -70,7 +70,8 @@ static string dir_info_oid = RBD_INFO;
bool udevadm_settle = true;
bool progress = true;
bool resize_allow_shrink = false;
bool read_only = false;
map<string, string> map_options; // -o / --options map
#define dout_subsys ceph_subsys_rbd
@ -154,6 +155,7 @@ void usage()
" --pretty-format make json or xml output more readable\n"
" --no-settle do not wait for udevadm to settle on map/unmap\n"
" --no-progress do not show progress for long-running commands\n"
" -o, --options <map-options> options to use when mapping an image\n"
" --read-only set device readonly when mapping image\n"
" --allow-shrink allow shrinking of an image when resizing\n";
}
@ -1649,13 +1651,8 @@ static int do_kernel_add(const char *poolname, const char *imgname,
oss << ",";
}
if (read_only)
oss << " ro,";
else
oss << " ";
const char *user = g_conf->name.get_id().c_str();
oss << "name=" << user;
oss << " name=" << user;
char key_name[strlen(user) + strlen("client.") + 1];
snprintf(key_name, sizeof(key_name), "client.%s", user);
@ -1691,6 +1688,18 @@ static int do_kernel_add(const char *poolname, const char *imgname,
oss << ",key=" << key_name;
}
for (map<string, string>::const_iterator it = map_options.begin();
it != map_options.end();
++it) {
// for compatibility with < 3.7 kernels, assume that rw is on by
// default and omit it even if it was specified by the user
// (see ceph.git commit fb0f1986449b)
if (it->first == "rw" && it->second == "rw")
continue;
oss << "," << it->second;
}
oss << " " << poolname << " " << imgname;
if (snapname) {
@ -2056,6 +2065,109 @@ static int do_kernel_rm(const char *dev)
return r;
}
static string map_option_uuid_cb(const char *value_char)
{
uuid_d u;
if (!u.parse(value_char))
return "";
ostringstream oss;
oss << u;
return oss.str();
}
static string map_option_ip_cb(const char *value_char)
{
entity_addr_t a;
const char *endptr;
if (!a.parse(value_char, &endptr) ||
endptr != value_char + strlen(value_char)) {
return "";
}
ostringstream oss;
oss << a.addr;
return oss.str();
}
static string map_option_int_cb(const char *value_char)
{
string err;
int d = strict_strtol(value_char, 10, &err);
if (!err.empty() || d < 0)
return "";
ostringstream oss;
oss << d;
return oss.str();
}
static void put_map_option(const string key, string val)
{
map<string, string>::const_iterator it = map_options.find(key);
if (it != map_options.end()) {
cerr << "rbd: warning: redefining map option " << key << ": '"
<< it->second << "' -> '" << val << "'" << std::endl;
}
map_options[key] = val;
}
static int put_map_option_value(const string opt, const char *value_char,
string (*parse_cb)(const char *))
{
if (!value_char || *value_char == '\0') {
cerr << "rbd: " << opt << " option requires a value" << std::endl;
return 1;
}
string value = parse_cb(value_char);
if (value.empty()) {
cerr << "rbd: invalid " << opt << " value '" << value_char << "'"
<< std::endl;
return 1;
}
put_map_option(opt, opt + "=" + value);
return 0;
}
static int parse_map_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, "fsid")) {
if (put_map_option_value("fsid", value_char, map_option_uuid_cb))
return 1;
} else if (!strcmp(this_char, "ip")) {
if (put_map_option_value("ip", value_char, map_option_ip_cb))
return 1;
} else if (!strcmp(this_char, "share") || !strcmp(this_char, "noshare")) {
put_map_option("share", this_char);
} else if (!strcmp(this_char, "crc") || !strcmp(this_char, "nocrc")) {
put_map_option("crc", this_char);
} else if (!strcmp(this_char, "osdkeepalive")) {
if (put_map_option_value("osdkeepalive", value_char, map_option_int_cb))
return 1;
} else if (!strcmp(this_char, "osd_idle_ttl")) {
if (put_map_option_value("osd_idle_ttl", value_char, map_option_int_cb))
return 1;
} else if (!strcmp(this_char, "rw") || !strcmp(this_char, "ro")) {
put_map_option("rw", this_char);
} else {
cerr << "rbd: unknown map option '" << this_char << "'" << std::endl;
return 1;
}
}
return 0;
}
enum {
OPT_NO_CMD = 0,
OPT_LIST,
@ -2291,8 +2403,15 @@ int main(int argc, const char **argv)
lock_tag = strdup(val.c_str());
} else if (ceph_argparse_flag(args, i, "--no-settle", (char *)NULL)) {
udevadm_settle = false;
} else if (ceph_argparse_witharg(args, i, &val, "-o", "--options", (char*)NULL)) {
char *map_options = strdup(val.c_str());
if (parse_map_options(map_options)) {
cerr << "rbd: couldn't parse map options" << std::endl;
return EXIT_FAILURE;
}
} else if (ceph_argparse_flag(args, i, "--read-only", (char *)NULL)) {
read_only = true;
// --read-only is equivalent to -o ro
put_map_option("rw", "ro");
} else if (ceph_argparse_flag(args, i, "--no-progress", (char *)NULL)) {
progress = false;
} else if (ceph_argparse_flag(args, i , "--allow-shrink", (char *)NULL)) {

View File

@ -76,5 +76,6 @@
--pretty-format make json or xml output more readable
--no-settle do not wait for udevadm to settle on map/unmap
--no-progress do not show progress for long-running commands
-o, --options <map-options> options to use when mapping an image
--read-only set device readonly when mapping image
--allow-shrink allow shrinking of an image when resizing