]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd-nbd: check /sys/block/nbdX/size to ensure kernel mapped correctly
authorMykola Golub <mgolub@mirantis.com>
Thu, 2 Feb 2017 10:11:35 +0000 (11:11 +0100)
committerNathan Cutler <ncutler@suse.com>
Mon, 3 Jul 2017 10:48:25 +0000 (12:48 +0200)
Fixes: http://tracker.ceph.com/issues/18335
Signed-off-by: Mykola Golub <mgolub@mirantis.com>
(cherry picked from commit 596e5ea8a5df72002672eef0a6d20572ca6f60f0)

qa/workunits/rbd/rbd-nbd.sh
src/tools/rbd_nbd/rbd-nbd.cc

index 513b6dacb10eee33995c884bdc34e9ab7f3bacac..348d9c177f95d4ee0c5ee02b70d24a933ec71e93 100755 (executable)
@@ -4,7 +4,6 @@
 
 POOL=rbd
 IMAGE=testrbdnbd$$
-TOO_LARGE_IMAGE=${IMAGE}_large
 SIZE=64
 DATA=
 DEV=
@@ -50,7 +49,6 @@ setup()
     DATA=${TEMPDIR}/data
     dd if=/dev/urandom of=${DATA} bs=1M count=${SIZE}
     rbd --dest-pool ${POOL} --no-progress import ${DATA} ${IMAGE}
-    rbd -p ${POOL} create ${TOO_LARGE_IMAGE} --size 3T
 }
 
 function cleanup()
@@ -68,7 +66,6 @@ function cleanup()
        done
        rbd -p ${POOL} remove ${IMAGE}
     fi
-    rbd -p ${POOL} remove ${TOO_LARGE_IMAGE}
 }
 
 function expect_false()
@@ -91,7 +88,6 @@ then
 fi
 expect_false _sudo rbd-nbd map INVALIDIMAGE
 expect_false _sudo rbd-nbd --device INVALIDDEV map ${IMAGE}
-expect_false _sudo rbd-nbd map ${TOO_LARGE_IMAGE}
 
 # map test using the first unused device
 DEV=`_sudo rbd-nbd map ${POOL}/${IMAGE}`
index 04a747cbf9a67ff310a8ddea0e39a620bcd73ab4..006cc54cc1fd5bcb0d6bb6e94c414c69a8889114 100644 (file)
@@ -49,6 +49,7 @@
 
 #include "include/rados/librados.hpp"
 #include "include/rbd/librbd.hpp"
+#include "include/stringify.h"
 #include "include/xlist.h"
 
 #define dout_subsys ceph_subsys_rbd
@@ -76,6 +77,8 @@ static int nbds_max = 0;
 static int max_part = 255;
 static bool exclusive = false;
 
+#define RBD_NBD_BLKSIZE 512UL
+
 #ifdef CEPH_BIG_ENDIAN
 #define ntohll(a) (a)
 #elif defined(CEPH_LITTLE_ENDIAN)
@@ -466,6 +469,28 @@ static int open_device(const char* path, bool try_load_moudle = false)
   return nbd;
 }
 
+static int check_device_size(int nbd_index, unsigned long expected_size)
+{
+  unsigned long size = 0;
+  std::string path = "/sys/block/nbd" + stringify(nbd_index) + "/size";
+  std::ifstream ifs;
+  ifs.open(path.c_str(), std::ifstream::in);
+  if (!ifs.is_open()) {
+    cerr << "rbd-nbd: failed to open " << path << std::endl;
+    return -EINVAL;
+  }
+  ifs >> size;
+  size *= RBD_NBD_BLKSIZE;
+
+  if (size != expected_size) {
+    cerr << "rbd-nbd: kernel reported invalid device size (" << size
+         << ", expected " << expected_size << ")" << std::endl;
+    return -EINVAL;
+  }
+
+  return 0;
+}
+
 static int do_map()
 {
   int r;
@@ -479,6 +504,7 @@ static int do_map()
   unsigned long flags;
   unsigned long size;
 
+  int index = 0;
   int fd[2];
   int nbd;
 
@@ -514,7 +540,6 @@ static int do_map()
 
   if (devpath.empty()) {
     char dev[64];
-    int index = 0;
     while (true) {
       snprintf(dev, sizeof(dev), "/dev/nbd%d", index);
 
@@ -536,6 +561,12 @@ static int do_map()
       break;
     }
   } else {
+    r = sscanf(devpath.c_str(), "/dev/nbd%d", &index);
+    if (r < 0) {
+      cerr << "rbd-nbd: invalid device path: " << devpath
+           << " (expected /dev/nbd{num})" << std::endl;
+      goto close_fd;
+    }
     nbd = open_device(devpath.c_str(), true);
     if (nbd < 0) {
       r = nbd;
@@ -591,27 +622,32 @@ static int do_map()
   if (r < 0)
     goto close_nbd;
 
-  r = ioctl(nbd, NBD_SET_BLKSIZE, 512UL);
+  r = ioctl(nbd, NBD_SET_BLKSIZE, RBD_NBD_BLKSIZE);
   if (r < 0) {
     r = -errno;
     goto close_nbd;
   }
 
-  size = info.size;
-
-  if (size > (1UL << 32) * 512) {
+  if (info.size > ULONG_MAX) {
     r = -EFBIG;
-    cerr << "rbd-nbd: image is too large (" << prettybyte_t(size) << ", max is "
-         << prettybyte_t((1UL << 32) * 512) << ")" << std::endl;
+    cerr << "rbd-nbd: image is too large (" << prettybyte_t(info.size)
+         << ", max is " << prettybyte_t(ULONG_MAX) << ")" << std::endl;
     goto close_nbd;
   }
 
+  size = info.size;
+
   r = ioctl(nbd, NBD_SET_SIZE, size);
   if (r < 0) {
     r = -errno;
     goto close_nbd;
   }
 
+  r = check_device_size(index, size);
+  if (r < 0) {
+    goto close_nbd;
+  }
+
   ioctl(nbd, NBD_SET_FLAGS, flags);
 
   read_only = snapname.empty() ? 0 : 1;