rbd: make common options override krbd-specific options 37385/head
authorIlya Dryomov <idryomov@gmail.com>
Thu, 24 Sep 2020 08:50:24 +0000 (10:50 +0200)
committerIlya Dryomov <idryomov@gmail.com>
Thu, 24 Sep 2020 08:50:24 +0000 (10:50 +0200)
ceph-csi has added support for passing custom map and unmap options via
mapOptions and unmapOptions storage class parameters.  However, it also
uses --read-only for implementing ROX (ReadOnlyMany) PVs.  If the user
supplies "mapOptions: rw", they will get around the intended read-only
restriction (at least on the block device).

ceph-csi could be patched to use "-o ro", but it actually makes sense
for common options to win over device type-specific equivalents.

Fixes: https://tracker.ceph.com/issues/47625
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
doc/man/8/rbd.rst
qa/rbd/krbd_blkroset.t
src/tools/rbd/action/Kernel.cc

index b81b6a7087d1f68c1a44b4a7df9f6784b92a9e25..cc920a1af2de32657fc394d78ec5fbda1731c542 100644 (file)
@@ -762,7 +762,7 @@ Per client instance `rbd device map` options:
 
 Per mapping (block device) `rbd device map` options:
 
-* rw - Map the image read-write (default).
+* rw - Map the image read-write (default).  Overridden by --read-only.
 
 * ro - Map the image read-only.  Equivalent to --read-only.
 
@@ -772,6 +772,7 @@ Per mapping (block device) `rbd device map` options:
   discards (since 4.9).
 
 * exclusive - Disable automatic exclusive lock transitions (since 4.12).
+  Equivalent to --exclusive.
 
 * lock_timeout=x - A timeout on waiting for the acquisition of exclusive lock
   (since 4.17, default is 0 seconds, meaning no timeout).
index 893fcc4d44eb7dd2f278cae69c8ab8a9b3028ffa..e86c092f97003e1ea60b7983bb91e866c57cdf05 100644 (file)
@@ -343,6 +343,15 @@ rw -> ro with open_count > 0
   $ sudo rbd unmap $DEV
 
 
+"-o rw --read-only" should result in read-only mapping
+======================================================
+
+  $ DEV=$(sudo rbd map -o rw --read-only img)
+  $ blockdev --getro $DEV
+  1
+  $ sudo rbd unmap $DEV
+
+
 Teardown
 ========
 
index dcbca088ff75b9d05aa90abcbafd1dc513447ed2..deddcea3d01b55d5d6fc2f7d97e7aea1faa13a32 100644 (file)
@@ -499,30 +499,32 @@ int execute_map(const po::variables_map &vm,
   }
 
   MapOptions map_options;
-  if (vm["quiesce"].as<bool>()) {
-    std::cerr << "rbd: warning: quiesce is not supported" << std::endl;
+  if (vm.count("options")) {
+    for (auto &options : vm["options"].as<std::vector<std::string>>()) {
+      r = parse_map_options(options, &map_options);
+      if (r < 0) {
+        std::cerr << "rbd: couldn't parse map options" << std::endl;
+        return r;
+      }
+    }
   }
+
+  // parse options common to all device types after parsing krbd-specific
+  // options so that common options win (in particular "-o rw --read-only"
+  // should result in read-only mapping)
   if (vm["read-only"].as<bool>()) {
     put_map_option("rw", "ro", &map_options);
   }
   if (vm["exclusive"].as<bool>()) {
     put_map_option("exclusive", "exclusive", &map_options);
   }
-
+  if (vm["quiesce"].as<bool>()) {
+    std::cerr << "rbd: warning: quiesce is not supported" << std::endl;
+  }
   if (vm.count("quiesce-hook")) {
     std::cerr << "rbd: warning: quiesce-hook is not supported" << std::endl;
   }
 
-  if (vm.count("options")) {
-    for (auto &options : vm["options"].as<std::vector<std::string>>()) {
-      r = parse_map_options(options, &map_options);
-      if (r < 0) {
-        std::cerr << "rbd: couldn't parse map options" << std::endl;
-        return r;
-      }
-    }
-  }
-
   // connect to the cluster to get the default pool and the default map
   // options
   librados::Rados rados;