Skip to content

Commit

Permalink
librbd: guard object map against incompatible image sizes
Browse files Browse the repository at this point in the history
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
(cherry picked from commit 42d3d3a)
  • Loading branch information
Jason Dillaman committed May 10, 2016
1 parent 1649379 commit 3204d1c
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 3 deletions.
9 changes: 8 additions & 1 deletion src/librbd/ObjectMap.cc
Expand Up @@ -17,8 +17,10 @@
#include "common/dout.h"
#include "common/errno.h"
#include "common/WorkQueue.h"
#include "include/stringify.h"
#include "cls/lock/cls_lock_client.h"
#include "cls/rbd/cls_rbd_types.h"
#include "include/stringify.h"
#include "osdc/Striper.h"
#include <sstream>

#define dout_subsys ceph_subsys_rbd
Expand Down Expand Up @@ -48,6 +50,11 @@ std::string ObjectMap::object_map_name(const std::string &image_id,
return oid;
}

bool ObjectMap::is_compatible(const file_layout_t& layout, uint64_t size) {
uint64_t object_count = Striper::get_num_objects(layout, size);
return (object_count <= cls::rbd::MAX_OBJECT_MAP_OBJECT_COUNT);
}

ceph::BitVector<2u>::Reference ObjectMap::operator[](uint64_t object_no)
{
assert(m_image_ctx.object_map_lock.is_wlocked());
Expand Down
3 changes: 3 additions & 0 deletions src/librbd/ObjectMap.h
Expand Up @@ -4,6 +4,7 @@
#define CEPH_LIBRBD_OBJECT_MAP_H

#include "include/int_types.h"
#include "include/fs_types.h"
#include "include/rados/librados.hpp"
#include "include/rbd/object_map_types.h"
#include "common/bit_vector.hpp"
Expand All @@ -24,6 +25,8 @@ class ObjectMap {
static std::string object_map_name(const std::string &image_id,
uint64_t snap_id);

static bool is_compatible(const file_layout_t& layout, uint64_t size);

ceph::BitVector<2u>::Reference operator[](uint64_t object_no);
uint8_t operator[](uint64_t object_no) const;
inline uint64_t size() const {
Expand Down
15 changes: 13 additions & 2 deletions src/librbd/Operations.cc
Expand Up @@ -9,6 +9,7 @@
#include "librbd/ImageCtx.h"
#include "librbd/ImageState.h"
#include "librbd/ImageWatcher.h"
#include "librbd/ObjectMap.h"
#include "librbd/Utils.h"
#include "librbd/operation/FlattenRequest.h"
#include "librbd/operation/RebuildObjectMapRequest.h"
Expand Down Expand Up @@ -499,6 +500,12 @@ int Operations<I>::resize(uint64_t size, ProgressContext& prog_ctx) {
return r;
}

if (m_image_ctx.test_features(RBD_FEATURE_OBJECT_MAP) &&
!ObjectMap::is_compatible(m_image_ctx.layout, size)) {
lderr(cct) << "New size not compatible with object map" << dendl;
return -EINVAL;
}

uint64_t request_id = ++m_async_request_seq;
r = invoke_async_request("resize", false,
boost::bind(&Operations<I>::execute_resize, this,
Expand All @@ -525,13 +532,17 @@ void Operations<I>::execute_resize(uint64_t size, ProgressContext &prog_ctx,
ldout(cct, 5) << this << " " << __func__ << ": "
<< "size=" << m_image_ctx.size << ", "
<< "new_size=" << size << dendl;
m_image_ctx.snap_lock.put_read();

m_image_ctx.snap_lock.get_read();
if (m_image_ctx.snap_id != CEPH_NOSNAP || m_image_ctx.read_only) {
m_image_ctx.snap_lock.put_read();
on_finish->complete(-EROFS);
return;
} else if (m_image_ctx.test_features(RBD_FEATURE_OBJECT_MAP,
m_image_ctx.snap_lock) &&
!ObjectMap::is_compatible(m_image_ctx.layout, size)) {
m_image_ctx.snap_lock.put_read();
on_finish->complete(-EINVAL);
return;
}
m_image_ctx.snap_lock.put_read();

Expand Down
13 changes: 13 additions & 0 deletions src/librbd/internal.cc
Expand Up @@ -95,18 +95,26 @@ int remove_object_map(ImageCtx *ictx) {
}
return 0;
}

int create_object_map(ImageCtx *ictx) {
assert(ictx->snap_lock.is_locked());
CephContext *cct = ictx->cct;

int r;
uint64_t max_size = ictx->size;
std::vector<uint64_t> snap_ids;
snap_ids.push_back(CEPH_NOSNAP);
for (std::map<snap_t, SnapInfo>::iterator it = ictx->snap_info.begin();
it != ictx->snap_info.end(); ++it) {
max_size = MAX(max_size, it->second.size);
snap_ids.push_back(it->first);
}

if (!ObjectMap::is_compatible(ictx->layout, max_size)) {
lderr(cct) << "image size not compatible with object map" << dendl;
return -EINVAL;
}

for (std::vector<uint64_t>::iterator it = snap_ids.begin();
it != snap_ids.end(); ++it) {
librados::ObjectWriteOperation op;
Expand Down Expand Up @@ -1084,6 +1092,11 @@ int mirror_image_disable_internal(ImageCtx *ictx, bool force) {
layout.stripe_count = stripe_count;
}

if (!ObjectMap::is_compatible(layout, size)) {
lderr(cct) << "image size not compatible with object map" << dendl;
goto err_remove_header;
}

librados::ObjectWriteOperation op;
cls_client::object_map_resize(&op, Striper::get_num_objects(layout, size),
OBJECT_NONEXISTENT);
Expand Down

0 comments on commit 3204d1c

Please sign in to comment.