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"
15 #include "librbd/Journal.h"
16 #include "librbd/Types.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;
77 case AIO_TYPE_COMPARE_AND_WRITE
:
78 ictx
->perfcounter
->tinc(l_librbd_cmp_latency
, elapsed
); break;
80 lderr(cct
) << "completed invalid aio_type: " << aio_type
<< dendl
;
84 // inform the journal that the op has successfully committed
85 if (journal_tid
!= 0) {
86 assert(ictx
->journal
!= NULL
);
87 ictx
->journal
->commit_io_event(journal_tid
, rval
);
90 state
= AIO_STATE_CALLBACK
;
93 complete_cb(rbd_comp
, complete_arg
);
97 if (ictx
&& event_notify
&& ictx
->event_socket
.is_valid()) {
98 ictx
->completed_reqs_lock
.Lock();
99 ictx
->completed_reqs
.push_back(&m_xlist_item
);
100 ictx
->completed_reqs_lock
.Unlock();
101 ictx
->event_socket
.notify();
104 state
= AIO_STATE_COMPLETE
;
107 // note: possible for image to be closed after op marked finished
108 if (async_op
.started()) {
109 async_op
.finish_op();
111 tracepoint(librbd
, aio_complete_exit
);
114 void AioCompletion::init_time(ImageCtx
*i
, aio_type_t t
) {
115 Mutex::Locker
locker(lock
);
116 if (ictx
== nullptr) {
119 start_time
= ceph_clock_now();
123 void AioCompletion::start_op(bool ignore_type
) {
124 Mutex::Locker
locker(lock
);
125 assert(ictx
!= nullptr);
126 assert(!async_op
.started());
127 if (state
== AIO_STATE_PENDING
&&
128 (ignore_type
|| aio_type
!= AIO_TYPE_FLUSH
)) {
129 async_op
.start_op(*ictx
);
133 void AioCompletion::fail(int r
)
136 assert(ictx
!= nullptr);
137 CephContext
*cct
= ictx
->cct
;
139 lderr(cct
) << cpp_strerror(r
) << dendl
;
140 assert(pending_count
== 0);
146 void AioCompletion::set_request_count(uint32_t count
) {
148 assert(ictx
!= nullptr);
149 CephContext
*cct
= ictx
->cct
;
151 ldout(cct
, 20) << "pending=" << count
<< dendl
;
152 assert(pending_count
== 0);
153 pending_count
= count
;
156 // if no pending requests, completion will fire now
160 void AioCompletion::complete_request(ssize_t r
)
163 assert(ictx
!= nullptr);
164 CephContext
*cct
= ictx
->cct
;
167 if (r
< 0 && r
!= -EEXIST
)
172 assert(pending_count
);
173 int count
= --pending_count
;
175 ldout(cct
, 20) << "cb=" << complete_cb
<< ", "
176 << "pending=" << pending_count
<< dendl
;
177 if (!count
&& blockers
== 0) {
184 void AioCompletion::associate_journal_event(uint64_t tid
) {
185 Mutex::Locker
l(lock
);
186 assert(state
== AIO_STATE_PENDING
);
190 bool AioCompletion::is_complete() {
191 tracepoint(librbd
, aio_is_complete_enter
, this);
194 Mutex::Locker
l(lock
);
195 done
= this->state
== AIO_STATE_COMPLETE
;
197 tracepoint(librbd
, aio_is_complete_exit
, done
);
201 ssize_t
AioCompletion::get_return_value() {
202 tracepoint(librbd
, aio_get_return_value_enter
, this);
206 tracepoint(librbd
, aio_get_return_value_exit
, r
);
211 } // namespace librbd