template <typename I>
bool CopyupRequest<I>::send_copyup() {
- bool copy_on_read = m_pending_requests.empty();
- bool add_copyup_op = !m_copyup_data.is_zero();
- if (!add_copyup_op) {
- m_copyup_data.clear();
- }
-
ldout(m_ictx->cct, 20) << "oid " << m_oid << dendl;
m_state = STATE_COPYUP;
std::vector<librados::snap_t> snaps;
+ bool copy_on_read = m_pending_requests.empty();
+ bool deep_copyup = !snapc.snaps.empty() && !m_copyup_data.is_zero();
+ if (m_copyup_data.is_zero()) {
+ m_copyup_data.clear();
+ }
+
Mutex::Locker locker(m_lock);
int r;
- if (copy_on_read || (!snapc.snaps.empty() && add_copyup_op)) {
-
+ if (copy_on_read || deep_copyup) {
librados::ObjectWriteOperation copyup_op;
copyup_op.exec("rbd", "copyup", m_copyup_data);
- m_copyup_data.clear();
-
ObjectRequest<I>::add_write_hint(*m_ictx, ©up_op);
// send only the copyup request with a blank snapshot context so that
if (!copy_on_read) {
librados::ObjectWriteOperation write_op;
- write_op.exec("rbd", "copyup", m_copyup_data);
+ if (!deep_copyup) {
+ write_op.exec("rbd", "copyup", m_copyup_data);
+ ObjectRequest<I>::add_write_hint(*m_ictx, &write_op);
+ }
// merge all pending write ops into this single RADOS op
- ObjectRequest<I>::add_write_hint(*m_ictx, &write_op);
for (auto req : m_pending_requests) {
ldout(m_ictx->cct, 20) << "add_copyup_ops " << req << dendl;
req->add_copyup_ops(&write_op);
}
+ // compare-and-write doesn't add any write ops (copyup+cmpext+write
+ // can't be executed in the same RADOS op because, unless the object
+ // was already present in the clone, cmpext wouldn't see it)
+ if (!write_op.size()) {
+ return false;
+ }
+
m_pending_copyups++;
+ ldout(m_ictx->cct, 20) << (!deep_copyup && write_op.size() > 2 ?
+ "copyup + ops" : !deep_copyup ?
+ "copyup" : "ops")
+ << " with current snapshot context" << dendl;
snaps.insert(snaps.end(), snapc.snaps.begin(), snapc.snaps.end());
librados::AioCompletion *comp = util::create_rados_callback(this);