]>
git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/operation/Request.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "librbd/operation/Request.h"
5 #include "common/dout.h"
6 #include "common/errno.h"
7 #include "common/WorkQueue.h"
8 #include "librbd/ImageCtx.h"
10 #define dout_subsys ceph_subsys_rbd
12 #define dout_prefix *_dout << "librbd::Request: "
18 Request
<I
>::Request(I
&image_ctx
, Context
*on_finish
, uint64_t journal_op_tid
)
19 : AsyncRequest
<I
>(image_ctx
, on_finish
), m_op_tid(journal_op_tid
) {
23 void Request
<I
>::send() {
24 I
&image_ctx
= this->m_image_ctx
;
25 assert(image_ctx
.owner_lock
.is_locked());
27 // automatically create the event if we don't need to worry
28 // about affecting concurrent IO ops
29 if (can_affect_io() || !append_op_event()) {
35 Context
*Request
<I
>::create_context_finisher(int r
) {
36 // automatically commit the event if required (delete after commit)
37 if (m_appended_op_event
&& !m_committed_op_event
&&
42 I
&image_ctx
= this->m_image_ctx
;
43 CephContext
*cct
= image_ctx
.cct
;
44 ldout(cct
, 10) << this << " " << __func__
<< dendl
;
45 return util::create_context_callback
<Request
<I
>, &Request
<I
>::finish
>(this);
49 void Request
<I
>::finish_and_destroy(int r
) {
50 I
&image_ctx
= this->m_image_ctx
;
51 CephContext
*cct
= image_ctx
.cct
;
52 ldout(cct
, 10) << this << " " << __func__
<< ": r=" << r
<< dendl
;
54 // automatically commit the event if required (delete after commit)
55 if (m_appended_op_event
&& !m_committed_op_event
&&
60 AsyncRequest
<I
>::finish_and_destroy(r
);
64 void Request
<I
>::finish(int r
) {
65 I
&image_ctx
= this->m_image_ctx
;
66 CephContext
*cct
= image_ctx
.cct
;
67 ldout(cct
, 10) << this << " " << __func__
<< ": r=" << r
<< dendl
;
69 assert(!m_appended_op_event
|| m_committed_op_event
);
70 AsyncRequest
<I
>::finish(r
);
74 bool Request
<I
>::append_op_event() {
75 I
&image_ctx
= this->m_image_ctx
;
77 assert(image_ctx
.owner_lock
.is_locked());
78 RWLock::RLocker
snap_locker(image_ctx
.snap_lock
);
79 if (image_ctx
.journal
!= nullptr &&
80 image_ctx
.journal
->is_journal_appending()) {
81 append_op_event(util::create_context_callback
<
82 Request
<I
>, &Request
<I
>::handle_op_event_safe
>(this));
89 bool Request
<I
>::commit_op_event(int r
) {
90 I
&image_ctx
= this->m_image_ctx
;
91 RWLock::RLocker
snap_locker(image_ctx
.snap_lock
);
93 if (!m_appended_op_event
) {
97 assert(m_op_tid
!= 0);
98 assert(!m_committed_op_event
);
99 m_committed_op_event
= true;
101 if (image_ctx
.journal
!= nullptr &&
102 image_ctx
.journal
->is_journal_appending()) {
103 CephContext
*cct
= image_ctx
.cct
;
104 ldout(cct
, 10) << this << " " << __func__
<< ": r=" << r
<< dendl
;
106 // ops will be canceled / completed before closing journal
107 assert(image_ctx
.journal
->is_journal_ready());
108 image_ctx
.journal
->commit_op_event(m_op_tid
, r
,
109 new C_CommitOpEvent(this, r
));
115 template <typename I
>
116 void Request
<I
>::handle_commit_op_event(int r
, int original_ret_val
) {
117 I
&image_ctx
= this->m_image_ctx
;
118 CephContext
*cct
= image_ctx
.cct
;
119 ldout(cct
, 10) << this << " " << __func__
<< ": r=" << r
<< dendl
;
122 lderr(cct
) << "failed to commit op event to journal: " << cpp_strerror(r
)
125 if (original_ret_val
< 0) {
126 r
= original_ret_val
;
131 template <typename I
>
132 void Request
<I
>::replay_op_ready(Context
*on_safe
) {
133 I
&image_ctx
= this->m_image_ctx
;
134 assert(image_ctx
.owner_lock
.is_locked());
135 assert(image_ctx
.snap_lock
.is_locked());
136 assert(m_op_tid
!= 0);
138 m_appended_op_event
= true;
139 image_ctx
.journal
->replay_op_ready(
140 m_op_tid
, util::create_async_context_callback(image_ctx
, on_safe
));
143 template <typename I
>
144 void Request
<I
>::append_op_event(Context
*on_safe
) {
145 I
&image_ctx
= this->m_image_ctx
;
146 assert(image_ctx
.owner_lock
.is_locked());
147 assert(image_ctx
.snap_lock
.is_locked());
149 CephContext
*cct
= image_ctx
.cct
;
150 ldout(cct
, 10) << this << " " << __func__
<< dendl
;
152 m_op_tid
= image_ctx
.journal
->allocate_op_tid();
153 image_ctx
.journal
->append_op_event(
154 m_op_tid
, journal::EventEntry
{create_event(m_op_tid
)},
155 new C_AppendOpEvent(this, on_safe
));
158 template <typename I
>
159 void Request
<I
>::handle_op_event_safe(int r
) {
160 I
&image_ctx
= this->m_image_ctx
;
161 CephContext
*cct
= image_ctx
.cct
;
162 ldout(cct
, 10) << this << " " << __func__
<< ": r=" << r
<< dendl
;
165 lderr(cct
) << "failed to commit op event to journal: " << cpp_strerror(r
)
170 assert(!can_affect_io());
172 // haven't started the request state machine yet
173 RWLock::RLocker
owner_locker(image_ctx
.owner_lock
);
178 } // namespace operation
179 } // namespace librbd
182 template class librbd::operation::Request
<librbd::ImageCtx
>;