]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd: expose rbd unmap options 11400/head
authorIlya Dryomov <idryomov@gmail.com>
Fri, 7 Oct 2016 10:32:43 +0000 (12:32 +0200)
committerIlya Dryomov <idryomov@gmail.com>
Tue, 11 Oct 2016 08:52:34 +0000 (10:52 +0200)
Reuse rbd map -o infrastructure to expose rbd unmap options in
a similar fashion.  Currently it's just one bool option, but we may
need more in the future.

Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
(cherry picked from commit 620f5e1455fdcb05cd3873c1e260141849829e35)

Conflicts:
doc/man/8/rbd.rst [ PR #9151 ("rbd: add methods to set and get
  snapshot limits") not in jewel ]

doc/man/8/rbd.rst
src/include/krbd.h
src/krbd.cc
src/test/cli/rbd/help.t
src/test/librbd/fsx.cc
src/tools/rbd/action/Kernel.cc

index 218b41d3b31b45c9dc20b575982cda697539ca96..cfe3b6e1230a178cdd6e36db4ca5dd4e7e2682f3 100644 (file)
@@ -122,11 +122,12 @@ Parameters
 
    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
 
@@ -315,10 +316,10 @@ Commands
 
   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`
@@ -410,14 +411,14 @@ By default, [*stripe_unit*] is the same as the object size and [*stripe_count*]
 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.
@@ -456,7 +457,7 @@ libceph (per client instance) options:
 
 * 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).
 
@@ -467,6 +468,12 @@ Mapping (per block device) options:
 * 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
 ========
index 75206cded658dd46ba2500e65c4ccb0ac69cb3e9..c6f3c9d037c03c55fb5bcf540c47dce8d5158ece 100644 (file)
@@ -27,9 +27,11 @@ void krbd_destroy(struct krbd_ctx *ctx);
 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
 }
index fff6a3cc763f2db03a76280a8c16d4666a8d636e..a0e546fa7f6f58ee951a4da43bec2bc877678d34 100644 (file)
@@ -453,6 +453,16 @@ out_enm:
   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 (;;) {
@@ -480,7 +490,7 @@ static int wait_for_udev_remove(struct udev_monitor *mon, dev_t devno)
   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;
@@ -504,7 +514,7 @@ static int do_unmap(struct udev *udev, dev_t devno, const string& id)
    * 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) {
@@ -536,7 +546,8 @@ out_mon:
   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;
@@ -568,12 +579,12 @@ static int unmap_image(struct krbd_ctx *ctx, const char *devnode)
     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;
@@ -592,7 +603,7 @@ static int unmap_image(struct krbd_ctx *ctx, const char *pool,
     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,
@@ -730,15 +741,17 @@ extern "C" int krbd_map(struct krbd_ctx *ctx, const char *pool,
   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)
index 10cee52353f03133bf730b2ca5d35e2ddeb69d26..346345c7d97fa146d6df19f5371b71a37f613753 100644 (file)
   
   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>] 
index 95a2f899480b1e024010be8011fdc58c8378f0dc..fe2d4adc12a93545acc75c0d6449421f70c73d13 100644 (file)
@@ -827,7 +827,7 @@ krbd_close(struct rbd_ctx *ctx)
                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;
index 0777f211cde33c6bcb72764ac571016e2ac408f7..a829c8bb0255e9474fe0f791390eefca5d5c077b 100644 (file)
@@ -27,7 +27,7 @@ namespace po = boost::program_options;
 
 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
 
@@ -140,6 +140,27 @@ static int parse_map_options(char *options)
   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;
@@ -239,16 +260,24 @@ static int do_kernel_unmap(const char *dev, const char *poolname,
                            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;
@@ -345,6 +374,8 @@ void get_unmap_arguments(po::options_description *positional,
   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) {
@@ -374,6 +405,18 @@ 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(),