template <typename I>
SnapshotCopyRequest<I>::SnapshotCopyRequest(I *src_image_ctx,
I *dst_image_ctx,
- librados::snap_t snap_id_end,
+ librados::snap_t src_snap_id_start,
+ librados::snap_t src_snap_id_end,
+ librados::snap_t dst_snap_id_start,
bool flatten, ContextWQ *work_queue,
SnapSeqs *snap_seqs,
Context *on_finish)
- : RefCountedObject(dst_image_ctx->cct, 1), m_src_image_ctx(src_image_ctx),
- m_dst_image_ctx(dst_image_ctx), m_snap_id_end(snap_id_end),
+ : RefCountedObject(dst_image_ctx->cct), m_src_image_ctx(src_image_ctx),
+ m_dst_image_ctx(dst_image_ctx), m_src_snap_id_start(src_snap_id_start),
+ m_src_snap_id_end(src_snap_id_end), m_dst_snap_id_start(dst_snap_id_start),
m_flatten(flatten), m_work_queue(work_queue), m_snap_seqs_result(snap_seqs),
m_snap_seqs(*snap_seqs), m_on_finish(on_finish), m_cct(dst_image_ctx->cct),
- m_lock(unique_lock_name("SnapshotCopyRequest::m_lock", this)) {
+ m_lock(ceph::make_mutex(unique_lock_name("SnapshotCopyRequest::m_lock", this))) {
+ ceph_assert((m_src_snap_id_start == 0 && m_dst_snap_id_start == 0) ||
+ (m_src_snap_id_start > 0 && m_dst_snap_id_start > 0));
+
// snap ids ordered from oldest to newest
+ m_src_image_ctx->image_lock.lock_shared();
m_src_snap_ids.insert(src_image_ctx->snaps.begin(),
src_image_ctx->snaps.end());
+ m_src_image_ctx->image_lock.unlock_shared();
+
+ m_dst_image_ctx->image_lock.lock_shared();
m_dst_snap_ids.insert(dst_image_ctx->snaps.begin(),
dst_image_ctx->snaps.end());
- if (m_snap_id_end != CEPH_NOSNAP) {
- m_src_snap_ids.erase(m_src_snap_ids.upper_bound(m_snap_id_end),
+ m_dst_image_ctx->image_lock.unlock_shared();
+
+ if (m_src_snap_id_end != CEPH_NOSNAP) {
+ m_src_snap_ids.erase(m_src_snap_ids.upper_bound(m_src_snap_id_end),
m_src_snap_ids.end());
}
}
template <typename I>
void SnapshotCopyRequest<I>::cancel() {
- Mutex::Locker locker(m_lock);
+ std::lock_guard locker{m_lock};
ldout(m_cct, 20) << dendl;
m_canceled = true;
SnapIdSet::iterator snap_id_it = m_dst_snap_ids.begin();
if (m_prev_snap_id != CEPH_NOSNAP) {
snap_id_it = m_dst_snap_ids.upper_bound(m_prev_snap_id);
+ } else if (m_dst_snap_id_start > 0) {
+ snap_id_it = m_dst_snap_ids.upper_bound(m_dst_snap_id_start);
}
for (; snap_id_it != m_dst_snap_ids.end(); ++snap_id_it) {
librados::snap_t dst_snap_id = *snap_id_it;
- m_dst_image_ctx->snap_lock.get_read();
+ m_dst_image_ctx->image_lock.lock_shared();
bool dst_unprotected;
int r = m_dst_image_ctx->is_snap_unprotected(dst_snap_id, &dst_unprotected);
if (r < 0) {
lderr(m_cct) << "failed to retrieve destination snap unprotect status: "
<< cpp_strerror(r) << dendl;
- m_dst_image_ctx->snap_lock.put_read();
+ m_dst_image_ctx->image_lock.unlock_shared();
finish(r);
return;
}
- m_dst_image_ctx->snap_lock.put_read();
+ m_dst_image_ctx->image_lock.unlock_shared();
if (dst_unprotected) {
// snap is already unprotected -- check next snap
});
if (snap_seq_it != m_snap_seqs.end()) {
- m_src_image_ctx->snap_lock.get_read();
+ m_src_image_ctx->image_lock.lock_shared();
bool src_unprotected;
r = m_src_image_ctx->is_snap_unprotected(snap_seq_it->first,
&src_unprotected);
if (r < 0) {
lderr(m_cct) << "failed to retrieve source snap unprotect status: "
<< cpp_strerror(r) << dendl;
- m_src_image_ctx->snap_lock.put_read();
+ m_src_image_ctx->image_lock.unlock_shared();
finish(r);
return;
}
- m_src_image_ctx->snap_lock.put_read();
+ m_src_image_ctx->image_lock.unlock_shared();
if (src_unprotected) {
// source is unprotected -- unprotect destination snap
return;
}
- auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
+ auto ctx = new LambdaContext([this, finish_op_ctx](int r) {
handle_snap_unprotect(r);
finish_op_ctx->complete(0);
});
- RWLock::RLocker owner_locker(m_dst_image_ctx->owner_lock);
+ std::shared_lock owner_locker{m_dst_image_ctx->owner_lock};
m_dst_image_ctx->operations->execute_snap_unprotect(
cls::rbd::UserSnapshotNamespace(), m_snap_name.c_str(), ctx);
}
if (r < 0) {
lderr(m_cct) << "failed to unprotect snapshot '" << m_snap_name << "': "
- << cpp_strerror(r) << dendl;
+ << cpp_strerror(r) << dendl;
finish(r);
return;
}
{
// avoid the need to refresh to delete the newly unprotected snapshot
- RWLock::RLocker snap_locker(m_dst_image_ctx->snap_lock);
+ std::shared_lock image_locker{m_dst_image_ctx->image_lock};
auto snap_info_it = m_dst_image_ctx->snap_info.find(m_prev_snap_id);
if (snap_info_it != m_dst_image_ctx->snap_info.end()) {
snap_info_it->second.protection_status =
SnapIdSet::iterator snap_id_it = m_dst_snap_ids.begin();
if (m_prev_snap_id != CEPH_NOSNAP) {
snap_id_it = m_dst_snap_ids.upper_bound(m_prev_snap_id);
+ } else if (m_dst_snap_id_start > 0) {
+ snap_id_it = m_dst_snap_ids.upper_bound(m_dst_snap_id_start);
}
for (; snap_id_it != m_dst_snap_ids.end(); ++snap_id_it) {
librados::snap_t dst_snap_id = *snap_id_it;
cls::rbd::SnapshotNamespace snap_namespace;
- m_dst_image_ctx->snap_lock.get_read();
+ m_dst_image_ctx->image_lock.lock_shared();
int r = m_dst_image_ctx->get_snap_namespace(dst_snap_id, &snap_namespace);
- m_dst_image_ctx->snap_lock.put_read();
+ m_dst_image_ctx->image_lock.unlock_shared();
if (r < 0) {
lderr(m_cct) << "failed to retrieve destination snap namespace: "
<< m_snap_name << dendl;
return;
}
- auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
+ auto ctx = new LambdaContext([this, finish_op_ctx](int r) {
handle_snap_remove(r);
finish_op_ctx->complete(0);
});
- RWLock::RLocker owner_locker(m_dst_image_ctx->owner_lock);
+ std::shared_lock owner_locker{m_dst_image_ctx->owner_lock};
m_dst_image_ctx->operations->execute_snap_remove(
cls::rbd::UserSnapshotNamespace(), m_snap_name.c_str(), ctx);
}
SnapIdSet::iterator snap_id_it = m_src_snap_ids.begin();
if (m_prev_snap_id != CEPH_NOSNAP) {
snap_id_it = m_src_snap_ids.upper_bound(m_prev_snap_id);
+ } else if (m_src_snap_id_start > 0) {
+ snap_id_it = m_src_snap_ids.upper_bound(m_src_snap_id_start);
}
for (; snap_id_it != m_src_snap_ids.end(); ++snap_id_it) {
librados::snap_t src_snap_id = *snap_id_it;
cls::rbd::SnapshotNamespace snap_namespace;
- m_src_image_ctx->snap_lock.get_read();
+ m_src_image_ctx->image_lock.lock_shared();
int r = m_src_image_ctx->get_snap_namespace(src_snap_id, &snap_namespace);
- m_src_image_ctx->snap_lock.put_read();
+ m_src_image_ctx->image_lock.unlock_shared();
if (r < 0) {
lderr(m_cct) << "failed to retrieve source snap namespace: "
<< m_snap_name << dendl;
return;
}
- // if the source snapshot isn't in our mapping table, create it
- if (m_snap_seqs.find(src_snap_id) == m_snap_seqs.end() &&
- boost::get<cls::rbd::UserSnapshotNamespace>(&snap_namespace) != nullptr) {
- break;
+ if (m_snap_seqs.find(src_snap_id) == m_snap_seqs.end()) {
+ // the source snapshot is not in our mapping table, ...
+ if (boost::get<cls::rbd::UserSnapshotNamespace>(&snap_namespace) !=
+ nullptr) {
+ // ... create it since it's a user snapshot
+ break;
+ } else if (src_snap_id == m_src_snap_id_end) {
+ // ... map it to destination HEAD since it's not a user snapshot that we
+ // will create (e.g. MirrorSnapshotNamespace)
+ m_snap_seqs[src_snap_id] = CEPH_NOSNAP;
+ }
}
}
m_prev_snap_id = *snap_id_it;
m_snap_name = get_snapshot_name(m_src_image_ctx, m_prev_snap_id);
- m_src_image_ctx->snap_lock.get_read();
+ m_src_image_ctx->image_lock.lock_shared();
auto snap_info_it = m_src_image_ctx->snap_info.find(m_prev_snap_id);
if (snap_info_it == m_src_image_ctx->snap_info.end()) {
- m_src_image_ctx->snap_lock.put_read();
+ m_src_image_ctx->image_lock.unlock_shared();
lderr(m_cct) << "failed to retrieve source snap info: " << m_snap_name
<< dendl;
finish(-ENOENT);
parent_spec = m_dst_parent_spec;
parent_overlap = snap_info_it->second.parent.overlap;
}
- m_src_image_ctx->snap_lock.put_read();
+ m_src_image_ctx->image_lock.unlock_shared();
ldout(m_cct, 20) << "snap_name=" << m_snap_name << ", "
<< "snap_id=" << m_prev_snap_id << ", "
return;
}
- auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
+ auto ctx = new LambdaContext([this, finish_op_ctx](int r) {
handle_snap_create(r);
finish_op_ctx->complete(0);
});
if (r < 0) {
lderr(m_cct) << "failed to create snapshot '" << m_snap_name << "': "
- << cpp_strerror(r) << dendl;
+ << cpp_strerror(r) << dendl;
finish(r);
return;
}
SnapIdSet::iterator snap_id_it = m_src_snap_ids.begin();
if (m_prev_snap_id != CEPH_NOSNAP) {
snap_id_it = m_src_snap_ids.upper_bound(m_prev_snap_id);
+ } else if (m_src_snap_id_start > 0) {
+ snap_id_it = m_src_snap_ids.upper_bound(m_src_snap_id_start);
}
for (; snap_id_it != m_src_snap_ids.end(); ++snap_id_it) {
librados::snap_t src_snap_id = *snap_id_it;
- m_src_image_ctx->snap_lock.get_read();
+ m_src_image_ctx->image_lock.lock_shared();
bool src_protected;
int r = m_src_image_ctx->is_snap_protected(src_snap_id, &src_protected);
if (r < 0) {
lderr(m_cct) << "failed to retrieve source snap protect status: "
<< cpp_strerror(r) << dendl;
- m_src_image_ctx->snap_lock.put_read();
+ m_src_image_ctx->image_lock.unlock_shared();
finish(r);
return;
}
- m_src_image_ctx->snap_lock.put_read();
+ m_src_image_ctx->image_lock.unlock_shared();
if (!src_protected) {
// snap is not protected -- check next snap
// if destination snapshot is not protected, protect it
auto snap_seq_it = m_snap_seqs.find(src_snap_id);
ceph_assert(snap_seq_it != m_snap_seqs.end());
+ if (snap_seq_it->second == CEPH_NOSNAP) {
+ // implies src end snapshot is mapped to a non-copyable snapshot
+ ceph_assert(src_snap_id == m_src_snap_id_end);
+ break;
+ }
- m_dst_image_ctx->snap_lock.get_read();
+ m_dst_image_ctx->image_lock.lock_shared();
bool dst_protected;
r = m_dst_image_ctx->is_snap_protected(snap_seq_it->second, &dst_protected);
if (r < 0) {
lderr(m_cct) << "failed to retrieve destination snap protect status: "
<< cpp_strerror(r) << dendl;
- m_dst_image_ctx->snap_lock.put_read();
+ m_dst_image_ctx->image_lock.unlock_shared();
finish(r);
return;
}
- m_dst_image_ctx->snap_lock.put_read();
+ m_dst_image_ctx->image_lock.unlock_shared();
if (!dst_protected) {
break;
return;
}
- auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
+ auto ctx = new LambdaContext([this, finish_op_ctx](int r) {
handle_snap_protect(r);
finish_op_ctx->complete(0);
});
- RWLock::RLocker owner_locker(m_dst_image_ctx->owner_lock);
+ std::shared_lock owner_locker{m_dst_image_ctx->owner_lock};
m_dst_image_ctx->operations->execute_snap_protect(
cls::rbd::UserSnapshotNamespace(), m_snap_name.c_str(), ctx);
}
template <typename I>
void SnapshotCopyRequest<I>::send_set_head() {
- if (m_snap_id_end != CEPH_NOSNAP) {
+ auto snap_seq_it = m_snap_seqs.find(m_src_snap_id_end);
+ if (m_src_snap_id_end != CEPH_NOSNAP &&
+ (snap_seq_it == m_snap_seqs.end() ||
+ snap_seq_it->second != CEPH_NOSNAP)) {
+ // not copying to src nor dst HEAD revision
finish(0);
return;
}
cls::rbd::ParentImageSpec parent_spec;
uint64_t parent_overlap = 0;
{
- RWLock::RLocker src_locker(m_src_image_ctx->snap_lock);
- size = m_src_image_ctx->size;
- if (!m_flatten) {
- parent_spec = m_src_image_ctx->parent_md.spec;
- parent_overlap = m_src_image_ctx->parent_md.overlap;
+ std::shared_lock src_locker{m_src_image_ctx->image_lock};
+ auto snap_info_it = m_src_image_ctx->snap_info.find(m_src_snap_id_end);
+ if (snap_info_it != m_src_image_ctx->snap_info.end()) {
+ auto& snap_info = snap_info_it->second;
+ size = snap_info.size;
+ if (!m_flatten && snap_info.parent.spec.pool_id != -1) {
+ parent_spec = m_dst_parent_spec;
+ parent_overlap = snap_info.parent.overlap;
+ }
+ } else {
+ size = m_src_image_ctx->size;
+ if (!m_flatten) {
+ parent_spec = m_dst_image_ctx->parent_md.spec;
+ parent_overlap = m_src_image_ctx->parent_md.overlap;
+ }
}
}
void SnapshotCopyRequest<I>::send_resize_object_map() {
int r = 0;
- if (m_snap_id_end == CEPH_NOSNAP &&
- m_dst_image_ctx->test_features(RBD_FEATURE_OBJECT_MAP)) {
- RWLock::RLocker owner_locker(m_dst_image_ctx->owner_lock);
- RWLock::RLocker snap_locker(m_dst_image_ctx->snap_lock);
+ if (m_dst_image_ctx->test_features(RBD_FEATURE_OBJECT_MAP)) {
+ std::shared_lock owner_locker{m_dst_image_ctx->owner_lock};
+ std::shared_lock image_locker{m_dst_image_ctx->image_lock};
if (m_dst_image_ctx->object_map != nullptr &&
Striper::get_num_objects(m_dst_image_ctx->layout,
auto finish_op_ctx = start_lock_op(m_dst_image_ctx->owner_lock, &r);
if (finish_op_ctx != nullptr) {
- auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
+ auto ctx = new LambdaContext([this, finish_op_ctx](int r) {
handle_resize_object_map(r);
finish_op_ctx->complete(0);
});
template <typename I>
bool SnapshotCopyRequest<I>::handle_cancellation() {
{
- Mutex::Locker locker(m_lock);
+ std::lock_guard locker{m_lock};
if (!m_canceled) {
return false;
}
void SnapshotCopyRequest<I>::error(int r) {
ldout(m_cct, 20) << "r=" << r << dendl;
- m_work_queue->queue(new FunctionContext([this, r](int r1) { finish(r); }));
+ m_work_queue->queue(new LambdaContext([this, r](int r1) { finish(r); }));
}
template <typename I>
int SnapshotCopyRequest<I>::validate_parent(I *image_ctx,
cls::rbd::ParentImageSpec *spec) {
- RWLock::RLocker owner_locker(image_ctx->owner_lock);
- RWLock::RLocker snap_locker(image_ctx->snap_lock);
+ std::shared_lock owner_locker{image_ctx->owner_lock};
+ std::shared_lock image_locker{image_ctx->image_lock};
// ensure source image's parent specs are still consistent
*spec = image_ctx->parent_md.spec;
template <typename I>
Context *SnapshotCopyRequest<I>::start_lock_op(int* r) {
- RWLock::RLocker owner_locker(m_dst_image_ctx->owner_lock);
+ std::shared_lock owner_locker{m_dst_image_ctx->owner_lock};
return start_lock_op(m_dst_image_ctx->owner_lock, r);
}
template <typename I>
-Context *SnapshotCopyRequest<I>::start_lock_op(RWLock &owner_lock, int* r) {
- ceph_assert(m_dst_image_ctx->owner_lock.is_locked());
+Context *SnapshotCopyRequest<I>::start_lock_op(ceph::shared_mutex &owner_lock, int* r) {
+ ceph_assert(ceph_mutex_is_locked(m_dst_image_ctx->owner_lock));
if (m_dst_image_ctx->exclusive_lock == nullptr) {
- return new FunctionContext([](int r) {});
+ return new LambdaContext([](int r) {});
}
return m_dst_image_ctx->exclusive_lock->start_op(r);
}