#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
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());
#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"
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 {
#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"
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,
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();
}
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;
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);