From: Jason Dillaman Date: Wed, 15 Mar 2017 18:49:13 +0000 (-0400) Subject: librbd: image create validates that pool supports overwrites X-Git-Tag: v12.0.1~69^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F13986%2Fhead;p=ceph.git librbd: image create validates that pool supports overwrites Fixes: http://tracker.ceph.com/issues/19081 Signed-off-by: Jason Dillaman --- diff --git a/src/librbd/image/CreateRequest.cc b/src/librbd/image/CreateRequest.cc index 9f3bcc9d8e2c..f9e43e79c6af 100644 --- a/src/librbd/image/CreateRequest.cc +++ b/src/librbd/image/CreateRequest.cc @@ -281,6 +281,7 @@ void CreateRequest::validate_pool() { librados::ObjectReadOperation op; op.stat(NULL, NULL, NULL); + m_outbl.clear(); int r = m_ioctx.aio_operate(RBD_DIRECTORY, comp, &op, &m_outbl); assert(r == 0); comp->release(); @@ -291,7 +292,7 @@ void CreateRequest::handle_validate_pool(int r) { ldout(m_cct, 20) << "r=" << r << dendl; if (r == 0) { - create_id_object(); + validate_overwrite(); return; } else if ((r < 0) && (r != -ENOENT)) { lderr(m_cct) << "failed to stat RBD directory: " << cpp_strerror(r) @@ -328,6 +329,73 @@ void CreateRequest::handle_validate_pool(int r) { << ": " << cpp_strerror(r) << dendl; } + validate_overwrite(); +} + +template +void CreateRequest::validate_overwrite() { + ldout(m_cct, 20) << dendl; + + m_data_io_ctx = m_ioctx; + if (m_data_pool_id != -1) { + librados::Rados rados(m_ioctx); + int r = rados.ioctx_create2(m_data_pool_id, m_data_io_ctx); + if (r < 0) { + lderr(m_cct) << "data pool " << m_data_pool << " does not exist" << dendl; + complete(r); + return; + } + } + + using klass = CreateRequest; + librados::AioCompletion *comp = + create_rados_callback(this); + + librados::ObjectReadOperation op; + op.read(0, 0, nullptr, nullptr); + + m_outbl.clear(); + int r = m_data_io_ctx.aio_operate(RBD_INFO, comp, &op, &m_outbl); + assert(r == 0); + comp->release(); +} + +template +void CreateRequest::handle_validate_overwrite(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; + + bufferlist bl; + bl.append("overwrite validated"); + + if (r == 0 && m_outbl.contents_equal(bl)) { + create_id_object(); + return; + } else if ((r < 0) && (r != -ENOENT)) { + lderr(m_cct) << "failed to read RBD info: " << cpp_strerror(r) << dendl; + complete(r); + return; + } + + // validate the pool supports overwrites. We cannot use rbd_directory + // since the v1 images store the directory as tmap data within the object. + ldout(m_cct, 10) << "validating overwrite support" << dendl; + bufferlist initial_bl; + initial_bl.append("validate"); + r = m_data_io_ctx.write(RBD_INFO, initial_bl, initial_bl.length(), 0); + if (r >= 0) { + r = m_data_io_ctx.write(RBD_INFO, bl, bl.length(), 0); + } + if (r == -EOPNOTSUPP) { + lderr(m_cct) << "pool missing required overwrite support" << dendl; + complete(-EINVAL); + return; + } else if (r < 0) { + lderr(m_cct) << "failed to validate overwrite support: " << cpp_strerror(r) + << dendl; + complete(r); + return; + } + create_id_object(); } @@ -406,6 +474,8 @@ void CreateRequest::negotiate_features() { using klass = CreateRequest; librados::AioCompletion *comp = create_rados_callback(this); + + m_outbl.clear(); int r = m_ioctx.aio_operate(RBD_DIRECTORY, comp, &op, &m_outbl); assert(r == 0); comp->release(); diff --git a/src/librbd/image/CreateRequest.h b/src/librbd/image/CreateRequest.h index 8a3464b5f3a3..9d77838dd318 100644 --- a/src/librbd/image/CreateRequest.h +++ b/src/librbd/image/CreateRequest.h @@ -54,8 +54,11 @@ private: * . . . . > . . . . . * | . * v . - * VALIDATE POOL v (pool validation - * | . disabled) + * VALIDATE POOL v (pool validation + * | . disabled) + * v . + * VALIDATE OVERWRITE . + * | . * v . * (error: bottom up) CREATE ID OBJECT. . < . . . . . * _______<_______ | @@ -99,6 +102,7 @@ private: ContextWQ *op_work_queue, Context *on_finish); IoCtx &m_ioctx; + IoCtx m_data_io_ctx; std::string m_image_name; std::string m_image_id; uint64_t m_size; @@ -132,6 +136,9 @@ private: void validate_pool(); void handle_validate_pool(int r); + void validate_overwrite(); + void handle_validate_overwrite(int r); + void create_id_object(); void handle_create_id_object(int r);