Merge branch 'rbd-map-options'

Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
This commit is contained in:
Josh Durgin 2013-12-27 09:56:55 -08:00
commit 9c068939c4
6 changed files with 210 additions and 63 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

@ -249,8 +249,7 @@ bool ceph_argparse_binary_flag(std::vector<const char*> &args,
}
static bool va_ceph_argparse_witharg(std::vector<const char*> &args,
std::vector<const char*>::iterator &i, std::string *ret, bool cli,
va_list ap)
std::vector<const char*>::iterator &i, std::string *ret, va_list ap)
{
const char *first = *i;
char tmp[strlen(first)+1];
@ -274,12 +273,8 @@ static bool va_ceph_argparse_witharg(std::vector<const char*> &args,
else if (first[strlen_a] == '\0') {
// find second part (or not)
if (i+1 == args.end()) {
if (cli) {
cerr << "Option " << *i << " requires an argument." << std::endl;
_exit(1);
} else {
return false;
}
cerr << "Option " << *i << " requires an argument." << std::endl;
_exit(1);
}
i = args.erase(i);
*ret = *i;
@ -296,21 +291,11 @@ bool ceph_argparse_witharg(std::vector<const char*> &args,
bool r;
va_list ap;
va_start(ap, ret);
r = va_ceph_argparse_witharg(args, i, ret, false, ap);
r = va_ceph_argparse_witharg(args, i, ret, ap);
va_end(ap);
return r;
}
bool ceph_argparse_witharg_daemon(std::vector<const char*> &args,
std::vector<const char*>::iterator &i, std::string *ret, ...)
{
bool r;
va_list ap;
va_start(ap, ret);
r = va_ceph_argparse_witharg(args, i, ret, false, ap);
va_end(ap);
return r;
}
bool ceph_argparse_withint(std::vector<const char*> &args,
std::vector<const char*>::iterator &i, int *ret,
std::ostream *oss, ...)
@ -319,30 +304,7 @@ bool ceph_argparse_withint(std::vector<const char*> &args,
va_list ap;
std::string str;
va_start(ap, oss);
r = va_ceph_argparse_witharg(args, i, &str, true, ap);
va_end(ap);
if (!r) {
return false;
}
std::string err;
int myret = strict_strtol(str.c_str(), 10, &err);
*ret = myret;
if (!err.empty()) {
*oss << err;
}
return true;
}
bool ceph_argparse_withint_daemon(std::vector<const char*> &args,
std::vector<const char*>::iterator &i, int *ret,
std::ostream *oss, ...)
{
bool r;
va_list ap;
std::string str;
va_start(ap, oss);
r = va_ceph_argparse_witharg(args, i, &str, false, ap);
r = va_ceph_argparse_witharg(args, i, &str, ap);
va_end(ap);
if (!r) {
return false;
@ -365,7 +327,7 @@ bool ceph_argparse_withlonglong(std::vector<const char*> &args,
va_list ap;
std::string str;
va_start(ap, oss);
r = va_ceph_argparse_witharg(args, i, &str, false, ap);
r = va_ceph_argparse_witharg(args, i, &str, ap);
va_end(ap);
if (!r) {
return false;
@ -388,7 +350,7 @@ bool ceph_argparse_withfloat(std::vector<const char*> &args,
va_list ap;
std::string str;
va_start(ap, oss);
r = va_ceph_argparse_witharg(args, i, &str, false, ap);
r = va_ceph_argparse_witharg(args, i, &str, ap);
va_end(ap);
if (!r) {
return false;

View File

@ -57,8 +57,6 @@ bool ceph_argparse_flag(std::vector<const char*> &args,
std::vector<const char*>::iterator &i, ...);
bool ceph_argparse_witharg(std::vector<const char*> &args,
std::vector<const char*>::iterator &i, std::string *ret, ...);
bool ceph_argparse_witharg_daemon(std::vector<const char*> &args,
std::vector<const char*>::iterator &i, std::string *ret, ...);
bool ceph_argparse_binary_flag(std::vector<const char*> &args,
std::vector<const char*>::iterator &i, int *ret,
std::ostream *oss, ...);
@ -68,9 +66,6 @@ extern CephInitParameters ceph_argparse_early_args
extern bool ceph_argparse_withint(std::vector<const char*> &args,
std::vector<const char*>::iterator &i, int *ret,
std::ostream *oss, ...);
extern bool ceph_argparse_withint_daemon(std::vector<const char*> &args,
std::vector<const char*>::iterator &i, int *ret,
std::ostream *oss, ...);
extern bool ceph_argparse_withfloat(std::vector<const char*> &args,
std::vector<const char*>::iterator &i, float *ret,
std::ostream *oss, ...);

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