]>
git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_process.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
4 #include "common/errno.h"
5 #include "common/Throttle.h"
6 #include "common/WorkQueue.h"
7 #include "include/scope_guard.h"
9 #include "rgw_dmclock_scheduler.h"
11 #include "rgw_frontend.h"
12 #include "rgw_request.h"
13 #include "rgw_process.h"
14 #include "rgw_loadgen.h"
15 #include "rgw_client_io.h"
17 #include "rgw_perf_counters.h"
19 #include "rgw_lua_request.h"
21 #include "services/svc_zone_utils.h"
23 #define dout_subsys ceph_subsys_rgw
25 using rgw::dmclock::Scheduler
;
27 void RGWProcess::RGWWQ::_dump_queue()
29 if (!g_conf()->subsys
.should_gather
<ceph_subsys_rgw
, 20>()) {
32 deque
<RGWRequest
*>::iterator iter
;
33 if (process
->m_req_queue
.empty()) {
34 dout(20) << "RGWWQ: empty" << dendl
;
37 dout(20) << "RGWWQ:" << dendl
;
38 for (iter
= process
->m_req_queue
.begin();
39 iter
!= process
->m_req_queue
.end(); ++iter
) {
40 dout(20) << "req: " << hex
<< *iter
<< dec
<< dendl
;
42 } /* RGWProcess::RGWWQ::_dump_queue */
44 auto schedule_request(Scheduler
*scheduler
, req_state
*s
, RGWOp
*op
)
46 using rgw::dmclock::SchedulerCompleter
;
48 return std::make_pair(0,SchedulerCompleter
{});
50 const auto client
= op
->dmclock_client();
51 const auto cost
= op
->dmclock_cost();
52 if (s
->cct
->_conf
->subsys
.should_gather(ceph_subsys_rgw
, 10)) {
53 ldpp_dout(op
,10) << "scheduling with "
54 << s
->cct
->_conf
.get_val
<std::string
>("rgw_scheduler_type")
55 << " client=" << static_cast<int>(client
)
56 << " cost=" << cost
<< dendl
;
58 return scheduler
->schedule_request(client
, {},
59 req_state::Clock::to_double(s
->time
),
64 bool RGWProcess::RGWWQ::_enqueue(RGWRequest
* req
) {
65 process
->m_req_queue
.push_back(req
);
66 perfcounter
->inc(l_rgw_qlen
);
67 dout(20) << "enqueued request req=" << hex
<< req
<< dec
<< dendl
;
72 RGWRequest
* RGWProcess::RGWWQ::_dequeue() {
73 if (process
->m_req_queue
.empty())
75 RGWRequest
*req
= process
->m_req_queue
.front();
76 process
->m_req_queue
.pop_front();
77 dout(20) << "dequeued request req=" << hex
<< req
<< dec
<< dendl
;
79 perfcounter
->inc(l_rgw_qlen
, -1);
83 void RGWProcess::RGWWQ::_process(RGWRequest
*req
, ThreadPool::TPHandle
&) {
84 perfcounter
->inc(l_rgw_qactive
);
85 process
->handle_request(this, req
);
86 process
->req_throttle
.put(1);
87 perfcounter
->inc(l_rgw_qactive
, -1);
90 int rgw_process_authenticated(RGWHandler_REST
* const handler
,
92 RGWRequest
* const req
,
95 const bool skip_retarget
)
97 ldpp_dout(op
, 2) << "init permissions" << dendl
;
98 int ret
= handler
->init_permissions(op
, y
);
104 * Only some accesses support website mode, and website mode does NOT apply
105 * if you are using the REST endpoint either (ergo, no authenticated access)
107 if (! skip_retarget
) {
108 ldpp_dout(op
, 2) << "recalculating target" << dendl
;
109 ret
= handler
->retarget(op
, &op
, y
);
115 ldpp_dout(op
, 2) << "retargeting skipped because of SubOp mode" << dendl
;
118 /* If necessary extract object ACL and put them into req_state. */
119 ldpp_dout(op
, 2) << "reading permissions" << dendl
;
120 ret
= handler
->read_permissions(op
, y
);
125 ldpp_dout(op
, 2) << "init op" << dendl
;
126 ret
= op
->init_processing(y
);
131 ldpp_dout(op
, 2) << "verifying op mask" << dendl
;
132 ret
= op
->verify_op_mask();
137 /* Check if OPA is used to authorize requests */
138 if (s
->cct
->_conf
->rgw_use_opa_authz
) {
139 ret
= rgw_opa_authorize(op
, s
);
145 ldpp_dout(op
, 2) << "verifying op permissions" << dendl
;
146 ret
= op
->verify_permission(y
);
148 if (s
->system_request
) {
149 dout(2) << "overriding permissions due to system operation" << dendl
;
150 } else if (s
->auth
.identity
->is_admin_of(s
->user
->get_id())) {
151 dout(2) << "overriding permissions due to admin operation" << dendl
;
157 ldpp_dout(op
, 2) << "verifying op params" << dendl
;
158 ret
= op
->verify_params();
163 ldpp_dout(op
, 2) << "pre-executing" << dendl
;
166 ldpp_dout(op
, 2) << "executing" << dendl
;
169 ldpp_dout(op
, 2) << "completing" << dendl
;
175 int process_request(rgw::sal::RGWRadosStore
* const store
,
177 RGWRequest
* const req
,
178 const std::string
& frontend_prefix
,
179 const rgw_auth_registry_t
& auth_registry
,
180 RGWRestfulIO
* const client_io
,
181 OpsLogSink
* const olog
,
182 optional_yield yield
,
183 rgw::dmclock::Scheduler
*scheduler
,
185 ceph::coarse_real_clock::duration
* latency
,
188 int ret
= client_io
->init(g_ceph_context
);
190 dout(1) << "====== starting new request req=" << hex
<< req
<< dec
191 << " =====" << dendl
;
192 perfcounter
->inc(l_rgw_req
);
194 RGWEnv
& rgw_env
= client_io
->get_env();
196 struct req_state
rstate(g_ceph_context
, &rgw_env
, req
->id
);
197 struct req_state
*s
= &rstate
;
199 std::unique_ptr
<rgw::sal::RGWUser
> u
= store
->get_user(rgw_user());
202 RGWObjectCtx
rados_ctx(store
, s
);
203 s
->obj_ctx
= &rados_ctx
;
205 auto sysobj_ctx
= store
->svc()->sysobj
->init_obj_ctx();
206 s
->sysobj_ctx
= &sysobj_ctx
;
210 abort_early(s
, nullptr, ret
, nullptr, yield
);
214 s
->req_id
= store
->svc()->zone_utils
->unique_id(req
->id
);
215 s
->trans_id
= store
->svc()->zone_utils
->unique_trans_id(req
->id
);
216 s
->host_id
= store
->getRados()->host_id
;
219 ldpp_dout(s
, 2) << "initializing for trans_id = " << s
->trans_id
<< dendl
;
223 bool should_log
= false;
225 RGWHandler_REST
*handler
= rest
->get_handler(store
, s
,
228 client_io
, &mgr
, &init_error
);
229 rgw::dmclock::SchedulerCompleter c
;
231 if (init_error
!= 0) {
232 abort_early(s
, nullptr, init_error
, nullptr, yield
);
235 ldpp_dout(s
, 10) << "handler=" << typeid(*handler
).name() << dendl
;
237 should_log
= mgr
->get_logging();
239 ldpp_dout(s
, 2) << "getting op " << s
->op
<< dendl
;
240 op
= handler
->get_op();
242 abort_early(s
, NULL
, -ERR_METHOD_NOT_ALLOWED
, handler
, yield
);
247 auto rc
= rgw::lua::read_script(store
, s
->bucket_tenant
, s
->yield
, rgw::lua::context::preRequest
, script
);
249 // no script, nothing to do
251 ldpp_dout(op
, 5) << "WARNING: failed to read pre request script. error: " << rc
<< dendl
;
253 rc
= rgw::lua::request::execute(store
, rest
, olog
, s
, op
->name(), script
);
255 ldpp_dout(op
, 5) << "WARNING: failed to execute pre request script. error: " << rc
<< dendl
;
259 std::tie(ret
,c
) = schedule_request(scheduler
, s
, op
);
261 if (ret
== -EAGAIN
) {
262 ret
= -ERR_RATE_LIMITED
;
264 ldpp_dout(op
,0) << "Scheduling request failed with " << ret
<< dendl
;
265 abort_early(s
, op
, ret
, handler
, yield
);
269 ldpp_dout(op
, 10) << "op=" << typeid(*op
).name() << dendl
;
271 s
->op_type
= op
->get_type();
274 ldpp_dout(op
, 2) << "verifying requester" << dendl
;
275 ret
= op
->verify_requester(auth_registry
, yield
);
277 dout(10) << "failed to authorize request" << dendl
;
278 abort_early(s
, op
, ret
, handler
, yield
);
282 /* FIXME: remove this after switching all handlers to the new authentication
284 if (nullptr == s
->auth
.identity
) {
285 s
->auth
.identity
= rgw::auth::transform_old_authinfo(s
);
288 ldpp_dout(op
, 2) << "normalizing buckets and tenants" << dendl
;
289 ret
= handler
->postauth_init(yield
);
291 dout(10) << "failed to run post-auth init" << dendl
;
292 abort_early(s
, op
, ret
, handler
, yield
);
296 if (s
->user
->get_info().suspended
) {
297 dout(10) << "user is suspended, uid=" << s
->user
->get_id() << dendl
;
298 abort_early(s
, op
, -ERR_USER_SUSPENDED
, handler
, yield
);
302 ret
= rgw_process_authenticated(handler
, op
, req
, s
, yield
);
304 abort_early(s
, op
, ret
, handler
, yield
);
307 } catch (const ceph::crypto::DigestException
& e
) {
308 dout(0) << "authentication failed" << e
.what() << dendl
;
309 abort_early(s
, op
, -ERR_INVALID_SECRET_KEY
, handler
, yield
);
315 auto rc
= rgw::lua::read_script(store
, s
->bucket_tenant
, s
->yield
, rgw::lua::context::postRequest
, script
);
317 // no script, nothing to do
319 ldpp_dout(op
, 5) << "WARNING: failed to read post request script. error: " << rc
<< dendl
;
321 rc
= rgw::lua::request::execute(store
, rest
, olog
, s
, op
->name(), script
);
323 ldpp_dout(op
, 5) << "WARNING: failed to execute post request script. error: " << rc
<< dendl
;
329 client_io
->complete_request();
330 } catch (rgw::io::Exception
& e
) {
331 dout(0) << "ERROR: client_io->complete_request() returned "
332 << e
.what() << dendl
;
336 rgw_log_op(rest
, s
, (op
? op
->name() : "unknown"), olog
);
339 if (http_ret
!= nullptr) {
340 *http_ret
= s
->err
.http_ret
;
344 if (user
&& !rgw::sal::RGWUser::empty(s
->user
.get())) {
345 *user
= s
->user
->get_id().to_str();
349 op_ret
= op
->get_ret();
350 ldpp_dout(op
, 2) << "op status=" << op_ret
<< dendl
;
351 ldpp_dout(op
, 2) << "http status=" << s
->err
.http_ret
<< dendl
;
353 ldpp_dout(s
, 2) << "http status=" << s
->err
.http_ret
<< dendl
;
357 rest
->put_handler(handler
);
359 const auto lat
= s
->time_elapsed();
364 dout(1) << "====== req done req=" << hex
<< req
<< dec
365 << " op status=" << op_ret
366 << " http_status=" << s
->err
.http_ret
367 << " latency=" << lat
371 return (ret
< 0 ? ret
: s
->err
.ret
);
372 } /* process_request */