]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd-nbd: check /sys/block/nbdX/size to ensure kernel mapped correctly 13932/head
authorMykola Golub <mgolub@mirantis.com>
Thu, 2 Feb 2017 10:11:35 +0000 (11:11 +0100)
committerAlexey Sheplyakov <asheplyakov@mirantis.com>
Mon, 13 Mar 2017 04:13:29 +0000 (08:13 +0400)
Fixes: http://tracker.ceph.com/issues/18335
Signed-off-by: Mykola Golub <mgolub@mirantis.com>
(cherry picked from commit 596e5ea8a5df72002672eef0a6d20572ca6f60f0)

Conflicts:
qa/workunits/rbd/rbd-nbd.sh: the original commit removes
  TOO_LARGE_IMAGE test, do the same thing
src/tools/rbd_nbd/rbd-nbd.cc: help git to add
  "include/stringify.h"

Other changes:
src/tools/rbd_nbd/rbd-nbd.cc: #include <fstream> so
  the code compiles

Signed-off-by: Alexey Sheplyakov <asheplyakov@mirantis.com>
qa/workunits/rbd/rbd-nbd.sh
src/tools/rbd_nbd/rbd-nbd.cc

index a414c4d0d641e07cbe266a820ea4120afc5e0ec3..1e08adee81fa964f936f5c9707d1b0adf6069c26 100755 (executable)
@@ -4,7 +4,6 @@
 
 POOL=rbd
 IMAGE=testrbdnbd$$
-TOO_LARGE_IMAGE=${IMAGE}_large
 SUDO=sudo
 SIZE=64
 DATA=
@@ -17,7 +16,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
 
     if [ `id -u` = 0 ]
     then
@@ -40,7 +38,6 @@ function cleanup()
        done
        rbd -p ${POOL} remove ${IMAGE}
     fi
-    rbd -p ${POOL} remove ${TOO_LARGE_IMAGE}
 }
 
 function expect_false()
@@ -63,7 +60,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 9d38cf1382b8ed43ae830acf2a97fe41cba352f0..4479e31d5680f6c4de668f5ffae6334a604c85f8 100644 (file)
@@ -34,6 +34,7 @@
 #include <sys/socket.h>
 
 #include <iostream>
+#include <fstream>
 #include <boost/regex.hpp>
 
 #include "mon/MonClient.h"
@@ -49,6 +50,7 @@
 
 #include "include/rados/librados.hpp"
 #include "include/rbd/librbd.hpp"
+#include "include/stringify.h"
 
 #define dout_subsys ceph_subsys_rbd
 #undef dout_prefix
@@ -73,6 +75,8 @@ static bool readonly = false;
 static int nbds_max = 0;
 static int max_part = 255;
 
+#define RBD_NBD_BLKSIZE 512UL
+
 #ifdef CEPH_BIG_ENDIAN
 #define ntohll(a) (a)
 #elif defined(CEPH_LITTLE_ENDIAN)
@@ -463,6 +467,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;
@@ -476,6 +502,7 @@ static int do_map()
   unsigned long flags;
   unsigned long size;
 
+  int index = 0;
   int fd[2];
   int nbd;
 
@@ -510,7 +537,6 @@ static int do_map()
 
   if (devpath.empty()) {
     char dev[64];
-    int index = 0;
     while (true) {
       snprintf(dev, sizeof(dev), "/dev/nbd%d", index);
 
@@ -532,6 +558,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;
@@ -578,27 +610,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;