summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Mick <dan.mick@inktank.com>2012-12-05 17:39:17 -0800
committerDan Mick <dan.mick@inktank.com>2012-12-05 17:39:17 -0800
commit7f906b5afd5f28a3df93c31ea738e8dca8ce7992 (patch)
tree8388ae07f6f41cd0b884156125c3400fc07d8d03
parent930bb55006aff45f717462b95690d6d0d0fb8150 (diff)
parenta55700cc0aea0ff79e55c6bf78e9757b81fe9425 (diff)
downloadceph-7f906b5afd5f28a3df93c31ea738e8dca8ce7992.tar.gz
Merge branch 'next'
Pull in fixes for 3567 and 3524
-rw-r--r--src/librbd/AioCompletion.cc9
-rw-r--r--src/librbd/AioRequest.cc44
-rw-r--r--src/osdc/Striper.cc2
3 files changed, 44 insertions, 11 deletions
diff --git a/src/librbd/AioCompletion.cc b/src/librbd/AioCompletion.cc
index 082a08eb651..86b5b504ebd 100644
--- a/src/librbd/AioCompletion.cc
+++ b/src/librbd/AioCompletion.cc
@@ -88,10 +88,11 @@ namespace librbd {
if (m_req->m_ext_map.empty())
m_req->m_ext_map[m_req->m_object_off] = m_req->data().length();
- m_completion->destriper.add_partial_sparse_result(m_cct,
- m_req->data(),
- m_req->m_ext_map, m_req->m_object_off,
- m_req->m_buffer_extents);
+ m_completion->lock.Lock();
+ m_completion->destriper.add_partial_sparse_result(
+ m_cct, m_req->data(), m_req->m_ext_map, m_req->m_object_off,
+ m_req->m_buffer_extents);
+ m_completion->lock.Unlock();
r = m_req->m_object_len;
}
m_completion->complete_request(m_cct, r);
diff --git a/src/librbd/AioRequest.cc b/src/librbd/AioRequest.cc
index 63424e397fc..b9a76e48e0a 100644
--- a/src/librbd/AioRequest.cc
+++ b/src/librbd/AioRequest.cc
@@ -157,15 +157,47 @@ namespace librbd {
ldout(m_ictx->cct, 20) << "WRITE_CHECK_GUARD" << dendl;
if (r == -ENOENT) {
+
Mutex::Locker l(m_ictx->snap_lock);
Mutex::Locker l2(m_ictx->parent_lock);
- // copyup the entire object up to the overlap point
- ldout(m_ictx->cct, 20) << "reading from parent " << m_object_image_extents << dendl;
- assert(m_object_image_extents.size());
-
- m_state = LIBRBD_AIO_WRITE_COPYUP;
- read_from_parent(m_object_image_extents);
+ /*
+ * Parent may have disappeared; if so, recover by using
+ * send_copyup() to send the original write req (the copyup
+ * operation itself will be a no-op, since someone must have
+ * populated the child object while we weren't looking).
+ * Move to WRITE_FLAT state as we'll be done with the
+ * operation once the null copyup completes.
+ */
+
+ if (m_ictx->parent == NULL) {
+ ldout(m_ictx->cct, 20) << "parent is gone; do null copyup " << dendl;
+ m_state = LIBRBD_AIO_WRITE_FLAT;
+ send_copyup();
+ finished = false;
+ break;
+ }
+
+ // If parent still exists, overlap might also have changed.
+ uint64_t newlen = m_ictx->prune_parent_extents(
+ m_object_image_extents, m_ictx->parent_md.overlap);
+
+ // copyup the entire object up to the overlap point, if any
+ if (newlen != 0) {
+ ldout(m_ictx->cct, 20) << "should_complete(" << this << ") overlap "
+ << m_ictx->parent_md.overlap << " newlen "
+ << newlen << " image_extents"
+ << m_object_image_extents << dendl;
+
+ m_state = LIBRBD_AIO_WRITE_COPYUP;
+ read_from_parent(m_object_image_extents);
+ } else {
+ ldout(m_ictx->cct, 20) << "should_complete(" << this
+ << "): parent overlap now 0" << dendl;
+ m_object_image_extents.clear();
+ m_state = LIBRBD_AIO_WRITE_FLAT;
+ send_copyup();
+ }
finished = false;
break;
}
diff --git a/src/osdc/Striper.cc b/src/osdc/Striper.cc
index 26e2b917bb7..7b5a402893f 100644
--- a/src/osdc/Striper.cc
+++ b/src/osdc/Striper.cc
@@ -284,7 +284,7 @@ void Striper::StripedReadResult::assemble_result(CephContext *cct, bufferlist& b
size_t len = p->second.first.length();
if (len < p->second.second) {
if (zero_tail || bl.length()) {
- bufferptr bp(p->second.second - p->second.first.length());
+ bufferptr bp(p->second.second - len);
bp.zero();
bl.push_front(bp);
bl.claim_prepend(p->second.first);