From: Adam C. Emerson Date: Wed, 24 Aug 2022 19:24:09 +0000 (-0400) Subject: rgw: `SimpleRadosWriteAttrsCR` uses an async RADOS call X-Git-Tag: v18.1.0~499^2~10 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=900068ef93ce5d3d2aa54e79a89d3ada10d90b89;p=ceph-ci.git rgw: `SimpleRadosWriteAttrsCR` uses an async RADOS call Don't go through the 'system object' cache. This also saves us the use of the RADOS async completion processor. Signed-off-by: Adam C. Emerson --- diff --git a/src/rgw/driver/rados/rgw_cr_rados.h b/src/rgw/driver/rados/rgw_cr_rados.h index f4362e6b2f2..778f66fa253 100644 --- a/src/rgw/driver/rados/rgw_cr_rados.h +++ b/src/rgw/driver/rados/rgw_cr_rados.h @@ -572,51 +572,69 @@ public: }; class RGWSimpleRadosWriteAttrsCR : public RGWSimpleCoroutine { - const DoutPrefixProvider *dpp; - RGWAsyncRadosProcessor *async_rados; - RGWSI_SysObj *svc; - RGWObjVersionTracker *objv_tracker; - + const DoutPrefixProvider* dpp; + rgw::sal::RadosStore* const store; + RGWObjVersionTracker* objv_tracker; rgw_raw_obj obj; std::map attrs; bool exclusive; - RGWAsyncPutSystemObjAttrs *req = nullptr; + + rgw_rados_ref ref; + boost::intrusive_ptr cn; + public: - RGWSimpleRadosWriteAttrsCR(const DoutPrefixProvider *_dpp, - RGWAsyncRadosProcessor *_async_rados, - RGWSI_SysObj *_svc, const rgw_raw_obj& _obj, - std::map _attrs, - RGWObjVersionTracker *objv_tracker = nullptr, + RGWSimpleRadosWriteAttrsCR(const DoutPrefixProvider* dpp, + rgw::sal::RadosStore* const store, + rgw_raw_obj obj, + std::map attrs, + RGWObjVersionTracker* objv_tracker = nullptr, bool exclusive = false) - : RGWSimpleCoroutine(_svc->ctx()), dpp(_dpp), async_rados(_async_rados), - svc(_svc), objv_tracker(objv_tracker), obj(_obj), - attrs(std::move(_attrs)), exclusive(exclusive) { - } - ~RGWSimpleRadosWriteAttrsCR() override { - request_cleanup(); - } + : RGWSimpleCoroutine(store->ctx()), dpp(dpp), + store(store), objv_tracker(objv_tracker), + obj(std::move(obj)), attrs(std::move(attrs)), + exclusive(exclusive) {} - void request_cleanup() override { - if (req) { - req->finish(); - req = NULL; + int send_request(const DoutPrefixProvider *dpp) override { + int r = store->getRados()->get_raw_obj_ref(dpp, obj, &ref); + if (r < 0) { + ldpp_dout(dpp, -1) << "ERROR: failed to get ref for (" << obj << ") ret=" + << r << dendl; + return r; } - } - int send_request(const DoutPrefixProvider *dpp) override { - req = new RGWAsyncPutSystemObjAttrs(dpp, this, stack->create_completion_notifier(), - svc, objv_tracker, obj, std::move(attrs), - exclusive); - async_rados->queue(req); - return 0; + set_status() << "sending request"; + + librados::ObjectWriteOperation op; + if (exclusive) { + op.create(true); + } + if (objv_tracker) { + objv_tracker->prepare_op_for_write(&op); + } + + for (const auto& [name, bl] : attrs) { + if (!bl.length()) + continue; + op.setxattr(name.c_str(), bl); + } + + cn = stack->create_completion_notifier(); + if (!op.size()) { + cn->cb(); + return 0; + } + + return ref.pool.ioctx().aio_operate(ref.obj.oid, cn->completion(), &op); } int request_complete() override { - if (objv_tracker) { // copy the updated version - *objv_tracker = req->objv_tracker; + int ret = cn->completion()->get_return_value(); + set_status() << "request complete; ret=" << ret; + if (ret >= 0 && objv_tracker) { + objv_tracker->apply_write(); } - return req->get_ret_status(); + return ret; } }; diff --git a/src/rgw/driver/rados/rgw_data_sync.cc b/src/rgw/driver/rados/rgw_data_sync.cc index c030d6ddc4d..1b5ad619bef 100644 --- a/src/rgw/driver/rados/rgw_data_sync.cc +++ b/src/rgw/driver/rados/rgw_data_sync.cc @@ -3212,7 +3212,7 @@ public: map attrs; status.encode_all_attrs(attrs); - call(new RGWSimpleRadosWriteAttrsCR(dpp, sync_env->async_rados, sync_env->svc->sysobj, + call(new RGWSimpleRadosWriteAttrsCR(dpp, sync_env->driver, obj, attrs, &objv_tracker, exclusive)); } @@ -4065,7 +4065,7 @@ class RGWWriteBucketShardIncSyncStatus : public RGWCoroutine { reenter(this) { sync_marker.encode_attr(attrs); - yield call(new RGWSimpleRadosWriteAttrsCR(sync_env->dpp, sync_env->async_rados, sync_env->svc->sysobj, + yield call(new RGWSimpleRadosWriteAttrsCR(sync_env->dpp, sync_env->driver, obj, attrs, &objv_tracker)); if (retcode < 0) { return set_cr_error(retcode); diff --git a/src/test/rgw/rgw_cr_test.cc b/src/test/rgw/rgw_cr_test.cc index 957c625574f..b53d0655923 100644 --- a/src/test/rgw/rgw_cr_test.cc +++ b/src/test/rgw/rgw_cr_test.cc @@ -267,6 +267,42 @@ TEST(Write, ObjV) { ASSERT_EQ(-ECANCELED, r); } +TEST(WriteAttrs, Attrs) { + TempPool pool; + auto oid = "object"s; + bufferlist bl; + bl.append("I'm some data."); + std::map wrattrs { + { "foo", bl }, { "bar", bl }, { "baz", bl } + }; + auto r = run(new RGWSimpleRadosWriteAttrsCR(dpp(), store, {pool, oid}, + wrattrs, nullptr, true)); + ASSERT_EQ(0, r); + std::map rdattrs; + librados::IoCtx ioctx(pool); + r = ioctx.getxattrs(oid, rdattrs); + ASSERT_EQ(0, r); + ASSERT_EQ(wrattrs, rdattrs); +} + +TEST(WriteAttrs, Empty) { + TempPool pool; + auto oid = "object"s; + bufferlist bl; + std::map wrattrs { + { "foo", bl }, { "bar", bl }, { "baz", bl } + }; + // With an empty bufferlist all attributes should be skipped. + auto r = run(new RGWSimpleRadosWriteAttrsCR(dpp(), store, {pool, oid}, + wrattrs, nullptr, true)); + ASSERT_EQ(0, r); + std::map rdattrs; + librados::IoCtx ioctx(pool); + r = ioctx.getxattrs(oid, rdattrs); + ASSERT_EQ(0, r); + ASSERT_TRUE(rdattrs.empty()); +} + int main(int argc, const char **argv) { auto args = argv_to_vec(argc, argv);