}
bool updated = false;
- for (uint64_t i = 0; i < object_map.size(); ++i) {
- if (object_map[i] == OBJECT_EXISTS) {
- object_map[i] = OBJECT_EXISTS_CLEAN;
+ auto it = object_map.begin();
+ auto end_it = object_map.end();
+ for (; it != end_it; ++it) {
+ if (*it == OBJECT_EXISTS) {
+ *it = OBJECT_EXISTS_CLEAN;
updated = true;
}
}
}
bool updated = false;
- for (uint64_t i = 0; i < dst_object_map.size(); ++i) {
- if (dst_object_map[i] == OBJECT_EXISTS_CLEAN &&
- (i >= src_object_map.size() || src_object_map[i] == OBJECT_EXISTS)) {
- dst_object_map[i] = OBJECT_EXISTS;
+ auto src_it = src_object_map.begin();
+ auto dst_it = dst_object_map.begin();
+ auto dst_it_end = dst_object_map.end();
+ uint64_t i = 0;
+ for (; dst_it != dst_it_end; ++dst_it) {
+ if (*dst_it == OBJECT_EXISTS_CLEAN &&
+ (i >= src_object_map.size() || *src_it == OBJECT_EXISTS)) {
+ *dst_it = OBJECT_EXISTS;
updated = true;
}
+ if (i < src_object_map.size())
+ ++src_it;
+ ++i;
}
if (updated) {
req->send();
}
+template <typename I>
+bool ObjectMap<I>::set_object_map(ceph::BitVector<2> &target_object_map) {
+ assert(m_image_ctx.owner_lock.is_locked());
+ assert(m_image_ctx.snap_lock.is_locked());
+ assert(m_image_ctx.test_features(RBD_FEATURE_OBJECT_MAP,
+ m_image_ctx.snap_lock));
+ RWLock::RLocker object_map_locker(m_image_ctx.object_map_lock);
+ m_object_map = target_object_map;
+ return true;
+}
+
template <typename I>
void ObjectMap<I>::rollback(uint64_t snap_id, Context *on_finish) {
assert(m_image_ctx.snap_lock.is_locked());
void open(Context *on_finish);
void close(Context *on_finish);
-
+ bool set_object_map(ceph::BitVector<2> &target_object_map);
bool object_may_exist(uint64_t object_no) const;
void aio_save(Context *on_finish);
void SnapshotCreateRequest::update_object_map() {
RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
RWLock::WLocker object_map_locker(m_image_ctx.object_map_lock);
-
- for (uint64_t i = 0; i < m_object_map.size(); ++i) {
- if (m_object_map[i] == OBJECT_EXISTS) {
- m_object_map[i] = OBJECT_EXISTS_CLEAN;
+
+ auto it = m_object_map.begin();
+ auto end_it = m_object_map.end();
+ for (; it != end_it; ++it) {
+ if (*it == OBJECT_EXISTS) {
+ *it = OBJECT_EXISTS_CLEAN;
}
}
}
if (m_next_snap_id == m_image_ctx.snap_id && m_next_snap_id == CEPH_NOSNAP) {
CephContext *cct = m_image_ctx.cct;
ldout(cct, 5) << this << " " << __func__ << dendl;
-
- for (uint64_t i = 0; i < m_object_map.size(); ++i) {
- if (m_object_map[i] == OBJECT_EXISTS_CLEAN &&
+
+ auto it = m_object_map.begin();
+ auto end_it = m_object_map.end();
+ auto snap_it = m_snap_object_map.begin();
+ uint64_t i = 0;
+ for (; it != end_it; ++it) {
+ if (*it == OBJECT_EXISTS_CLEAN &&
(i >= m_snap_object_map.size() ||
- m_snap_object_map[i] == OBJECT_EXISTS)) {
- m_object_map[i] = OBJECT_EXISTS;
+ *snap_it == OBJECT_EXISTS)) {
+ *it = OBJECT_EXISTS;
+ }
+ if (i < m_snap_object_map.size()) {
+ ++snap_it;
}
+ ++i;
}
}
}
-// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
#include "test/librbd/test_mock_fixture.h"
librbd::ImageCtx *ictx;
ASSERT_EQ(0, open_image(m_image_name, &ictx));
+ librbd::NoOpProgressContext prog_ctx;
+ uint64_t size = 4294967296; // 4GB = 1024 * 4MB
+ ASSERT_EQ(0, resize(ictx, size));
+
+ // update image objectmap for snap inherit
+ ceph::BitVector<2> object_map;
+ object_map.resize(1024);
+ for (uint64_t i = 512; i < object_map.size(); ++i) {
+ object_map[i] = i % 2 == 0 ? OBJECT_EXISTS : OBJECT_NONEXISTENT;
+ }
+
+ C_SaferCond cond_ctx1;
+ {
+ librbd::ObjectMap<> om(*ictx, ictx->snap_id);
+ RWLock::RLocker owner_locker(ictx->owner_lock);
+ RWLock::WLocker snap_locker(ictx->snap_lock);
+ om.set_object_map(object_map);
+ om.aio_save(&cond_ctx1);
+ }
+ ASSERT_EQ(0, cond_ctx1.wait());
ASSERT_EQ(0, snap_create(*ictx, "snap1"));
ASSERT_EQ(0, ictx->state->refresh_if_required());
- uint64_t snap_id = ictx->snap_info.rbegin()->first;
-
- ceph::BitVector<2> object_map;
- object_map.resize(1024);
+ // simutate the image objectmap state after creating snap
for (uint64_t i = 512; i < object_map.size(); ++i) {
object_map[i] = i % 2 == 0 ? OBJECT_EXISTS_CLEAN : OBJECT_NONEXISTENT;
}
- C_SaferCond cond_ctx;
+ C_SaferCond cond_ctx2;
+ uint64_t snap_id = ictx->snap_info.rbegin()->first;
AsyncRequest<> *request = new SnapshotRemoveRequest(
- *ictx, &object_map, snap_id, &cond_ctx);
+ *ictx, &object_map, snap_id, &cond_ctx2);
{
RWLock::RLocker owner_locker(ictx->owner_lock);
RWLock::WLocker snap_locker(ictx->snap_lock);
request->send();
}
- ASSERT_EQ(0, cond_ctx.wait());
+ ASSERT_EQ(0, cond_ctx2.wait());
for (uint64_t i = 512; i < object_map.size(); ++i) {
ASSERT_EQ(i % 2 == 0 ? OBJECT_EXISTS : OBJECT_NONEXISTENT,
return ictx.operations->flatten(prog_ctx);
}
+int TestFixture::resize(librbd::ImageCtx *ictx, uint64_t size){
+ librbd::NoOpProgressContext prog_ctx;
+ return ictx->operations->resize(size, prog_ctx);
+}
+
void TestFixture::close_image(librbd::ImageCtx *ictx) {
m_ictxs.erase(ictx);
int snap_protect(librbd::ImageCtx &ictx, const std::string &snap_name);
int flatten(librbd::ImageCtx &ictx, librbd::ProgressContext &prog_ctx);
+ int resize(librbd::ImageCtx *ictx, uint64_t size);
int lock_image(librbd::ImageCtx &ictx, ClsLockType lock_type,
const std::string &cookie);