1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "librbd/io/AioCompletion.h"
7 #include "common/ceph_context.h"
8 #include "common/dout.h"
9 #include "common/errno.h"
10 #include "common/perf_counters.h"
11 #include "common/WorkQueue.h"
13 #include "librbd/ImageCtx.h"
14 #include "librbd/internal.h"
16 #include "librbd/Journal.h"
19 #include "tracing/librbd.h"
21 #define tracepoint(...)
24 #define dout_subsys ceph_subsys_rbd
26 #define dout_prefix *_dout << "librbd::io::AioCompletion: " << this \
27 << " " << __func__ << ": "
32 int AioCompletion::wait_for_complete() {
33 tracepoint(librbd
, aio_wait_for_complete_enter
, this);
35 while (state
!= AIO_STATE_COMPLETE
)
38 tracepoint(librbd
, aio_wait_for_complete_exit
, 0);
42 void AioCompletion::finalize(ssize_t rval
)
44 assert(lock
.is_locked());
45 assert(ictx
!= nullptr);
46 CephContext
*cct
= ictx
->cct
;
48 ldout(cct
, 20) << "r=" << rval
<< dendl
;
49 if (rval
>= 0 && aio_type
== AIO_TYPE_READ
) {
50 read_result
.assemble_result(cct
);
54 void AioCompletion::complete() {
55 assert(lock
.is_locked());
56 assert(ictx
!= nullptr);
57 CephContext
*cct
= ictx
->cct
;
59 tracepoint(librbd
, aio_complete_enter
, this, rval
);
61 elapsed
= ceph_clock_now() - start_time
;
63 case AIO_TYPE_GENERIC
:
68 ictx
->perfcounter
->tinc(l_librbd_rd_latency
, elapsed
); break;
70 ictx
->perfcounter
->tinc(l_librbd_wr_latency
, elapsed
); break;
71 case AIO_TYPE_DISCARD
:
72 ictx
->perfcounter
->tinc(l_librbd_discard_latency
, elapsed
); break;
74 ictx
->perfcounter
->tinc(l_librbd_aio_flush_latency
, elapsed
); break;
75 case AIO_TYPE_WRITESAME
:
76 ictx
->perfcounter
->tinc(l_librbd_ws_latency
, elapsed
); break;
78 lderr(cct
) << "completed invalid aio_type: " << aio_type
<< dendl
;
82 // inform the journal that the op has successfully committed
83 if (journal_tid
!= 0) {
84 assert(ictx
->journal
!= NULL
);
85 ictx
->journal
->commit_io_event(journal_tid
, rval
);
88 state
= AIO_STATE_CALLBACK
;
91 complete_cb(rbd_comp
, complete_arg
);
95 if (ictx
&& event_notify
&& ictx
->event_socket
.is_valid()) {
96 ictx
->completed_reqs_lock
.Lock();
97 ictx
->completed_reqs
.push_back(&m_xlist_item
);
98 ictx
->completed_reqs_lock
.Unlock();
99 ictx
->event_socket
.notify();
102 state
= AIO_STATE_COMPLETE
;
105 // note: possible for image to be closed after op marked finished
106 if (async_op
.started()) {
107 async_op
.finish_op();
109 tracepoint(librbd
, aio_complete_exit
);
112 void AioCompletion::init_time(ImageCtx
*i
, aio_type_t t
) {
113 Mutex::Locker
locker(lock
);
114 if (ictx
== nullptr) {
117 start_time
= ceph_clock_now();
121 void AioCompletion::start_op(bool ignore_type
) {
122 Mutex::Locker
locker(lock
);
123 assert(ictx
!= nullptr);
124 assert(!async_op
.started());
125 if (state
== AIO_STATE_PENDING
&&
126 (ignore_type
|| aio_type
!= AIO_TYPE_FLUSH
)) {
127 async_op
.start_op(*ictx
);
131 void AioCompletion::fail(int r
)
134 assert(ictx
!= nullptr);
135 CephContext
*cct
= ictx
->cct
;
137 lderr(cct
) << cpp_strerror(r
) << dendl
;
138 assert(pending_count
== 0);
144 void AioCompletion::set_request_count(uint32_t count
) {
146 assert(ictx
!= nullptr);
147 CephContext
*cct
= ictx
->cct
;
149 ldout(cct
, 20) << "pending=" << count
<< dendl
;
150 assert(pending_count
== 0);
151 pending_count
= count
;
154 // if no pending requests, completion will fire now
158 void AioCompletion::complete_request(ssize_t r
)
161 assert(ictx
!= nullptr);
162 CephContext
*cct
= ictx
->cct
;
165 if (r
< 0 && r
!= -EEXIST
)
170 assert(pending_count
);
171 int count
= --pending_count
;
173 ldout(cct
, 20) << "cb=" << complete_cb
<< ", "
174 << "pending=" << pending_count
<< dendl
;
175 if (!count
&& blockers
== 0) {
182 void AioCompletion::associate_journal_event(uint64_t tid
) {
183 Mutex::Locker
l(lock
);
184 assert(state
== AIO_STATE_PENDING
);
188 bool AioCompletion::is_complete() {
189 tracepoint(librbd
, aio_is_complete_enter
, this);
192 Mutex::Locker
l(lock
);
193 done
= this->state
== AIO_STATE_COMPLETE
;
195 tracepoint(librbd
, aio_is_complete_exit
, done
);
199 ssize_t
AioCompletion::get_return_value() {
200 tracepoint(librbd
, aio_get_return_value_enter
, this);
204 tracepoint(librbd
, aio_get_return_value_exit
, r
);
209 } // namespace librbd