From 8abc46a157e4c1431a92a1e52ab694dccff5d514 Mon Sep 17 00:00:00 2001 From: wuxingyi Date: Wed, 10 Jun 2015 06:57:57 +0000 Subject: [PATCH] rgw: fix data corruption when race condition We should delete the object in the multipart namespace lastly to prevent a previous upload wrongly deleting objects belong to the following upload. Fixes: #11749 Signed-off-by: wuxingyi (cherry picked from commit ac1e729a75b5d995028bbc223bcf5ecce0d112cc) --- src/rgw/rgw_rados.cc | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 38718b44bb5fb..a8257b00c29be 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -915,11 +915,36 @@ RGWPutObjProcessor_Aio::~RGWPutObjProcessor_Aio() return; list::iterator iter; + bool is_multipart_obj = false; + rgw_obj multipart_obj; + + /** + * We should delete the object in the "multipart" namespace to avoid race condition. + * Such race condition is caused by the fact that the multipart object is the gatekeeper of a multipart + * upload, when it is deleted, a second upload would start with the same suffix("2/"), therefore, objects + * written by the second upload may be deleted by the first upload. + * details is describled on #11749 + */ for (iter = written_objs.begin(); iter != written_objs.end(); ++iter) { - rgw_obj& obj = *iter; + rgw_obj &obj = *iter; + if (RGW_OBJ_NS_MULTIPART == obj.ns) { + ldout(store->ctx(), 5) << "NOTE: we should not process the multipart object (" << obj << ") here" << dendl; + multipart_obj = *iter; + is_multipart_obj = true; + continue; + } + int r = store->delete_obj(obj_ctx, bucket_info, obj, 0, 0); if (r < 0 && r != -ENOENT) { - ldout(store->ctx(), 0) << "WARNING: failed to remove obj (" << obj << "), leaked" << dendl; + ldout(store->ctx(), 5) << "WARNING: failed to remove obj (" << obj << "), leaked" << dendl; + } + } + + if (true == is_multipart_obj) { + ldout(store->ctx(), 5) << "NOTE: we are going to process the multipart obj (" << multipart_obj << dendl; + int r = store->delete_obj(obj_ctx, bucket_info, multipart_obj, 0, 0); + if (r < 0 && r != -ENOENT) { + ldout(store->ctx(), 0) << "WARNING: failed to remove obj (" << multipart_obj << "), leaked" << dendl; } } } -- 2.39.5