POOL=rbd
IMAGE=testrbdnbd$$
-TOO_LARGE_IMAGE=${IMAGE}_large
SIZE=64
DATA=
DEV=
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()
done
rbd -p ${POOL} remove ${IMAGE}
fi
- rbd -p ${POOL} remove ${TOO_LARGE_IMAGE}
}
function expect_false()
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}`
#include "include/rados/librados.hpp"
#include "include/rbd/librbd.hpp"
+#include "include/stringify.h"
#include "include/xlist.h"
#define dout_subsys ceph_subsys_rbd
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)
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;
unsigned long flags;
unsigned long size;
+ int index = 0;
int fd[2];
int nbd;
if (devpath.empty()) {
char dev[64];
- int index = 0;
while (true) {
snprintf(dev, sizeof(dev), "/dev/nbd%d", index);
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;
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;