Merge pull request #13229 from trociny/wip-18335

rbd-nbd: check /sys/block/nbdX/size to ensure kernel mapped correctly

Reviewed-by: Jason Dillaman <dillaman@redhat.com>
This commit is contained in:
Jason Dillaman 2017-02-11 09:29:23 -05:00 committed by GitHub
commit e95fe0dfad
2 changed files with 45 additions and 13 deletions

View File

@ -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}`

View 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_context g_ceph_context
@ -77,6 +78,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)
@ -468,6 +471,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;
@ -481,6 +506,7 @@ static int do_map()
unsigned long flags;
unsigned long size;
int index = 0;
int fd[2];
int nbd;
@ -516,7 +542,6 @@ static int do_map()
if (devpath.empty()) {
char dev[64];
int index = 0;
while (true) {
snprintf(dev, sizeof(dev), "/dev/nbd%d", index);
@ -538,6 +563,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;
@ -593,27 +624,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;
}
if (info.size > ULONG_MAX) {
r = -EFBIG;
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;
if (size > (1UL << 32) * 512) {
r = -EFBIG;
cerr << "rbd-nbd: image is too large (" << prettybyte_t(size) << ", max is "
<< prettybyte_t((1UL << 32) * 512) << ")" << std::endl;
goto close_nbd;
}
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;