1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
#include <errno.h>
#include "common/ceph_context.h"
#include "common/debug.h"
#include "librbd/AioRequest.h"
#include "librbd/internal.h"
#include "librbd/AioCompletion.h"
#define dout_subsys ceph_subsys_rbd
#undef dout_prefix
#define dout_prefix *_dout << "librbd::AioCompletion: "
namespace librbd {
void AioCompletion::finish_adding_requests(CephContext *cct)
{
ldout(cct, 20) << "AioCompletion::finish_adding_requests " << (void*)this << " pending " << pending_count << dendl;
lock.Lock();
assert(building);
building = false;
if (!pending_count) {
finalize(cct, rval);
complete();
}
lock.Unlock();
}
void AioCompletion::finalize(CephContext *cct, ssize_t rval)
{
ldout(cct, 20) << "AioCompletion::finalize() " << (void*)this << " rval " << rval << " read_buf " << (void*)read_buf
<< " read_bl " << (void*)read_bl << dendl;
if (rval >= 0 && aio_type == AIO_TYPE_READ) {
// FIXME: make the destriper write directly into a buffer so
// that we avoid shuffling pointers and copying zeros around.
bufferlist bl;
destriper.assemble_result(cct, bl, true);
if (read_buf) {
assert(bl.length() == read_buf_len);
bl.copy(0, read_buf_len, read_buf);
ldout(cct, 20) << "AioCompletion::finalize() copied resulting " << bl.length()
<< " bytes to " << (void*)read_buf << dendl;
}
if (read_bl) {
ldout(cct, 20) << "AioCompletion::finalize() moving resulting " << bl.length()
<< " bytes to bl " << (void*)read_bl << dendl;
read_bl->claim(bl);
}
}
}
void AioCompletion::complete_request(CephContext *cct, ssize_t r)
{
ldout(cct, 20) << "AioCompletion::complete_request() "
<< (void *)this << " complete_cb=" << (void *)complete_cb
<< " pending " << pending_count << dendl;
lock.Lock();
if (rval >= 0) {
if (r < 0 && r != -EEXIST)
rval = r;
else if (r > 0)
rval += r;
}
assert(pending_count);
int count = --pending_count;
if (!count && !building) {
finalize(cct, rval);
complete();
}
put_unlock();
}
void C_AioRead::finish(int r)
{
ldout(m_cct, 10) << "C_AioRead::finish() " << this << " r = " << r << dendl;
if (r >= 0 || r == -ENOENT) { // this was a sparse_read operation
ldout(m_cct, 10) << " got " << m_req->m_ext_map
<< " for " << m_req->m_buffer_extents
<< " bl " << m_req->data().length() << dendl;
// reads from the parent don't populate the m_ext_map and the overlap
// may not be the full buffer. compensate here by filling in m_ext_map
// with the read extent when it is empty.
if (m_req->m_ext_map.empty())
m_req->m_ext_map[m_req->m_object_off] = m_req->data().length();
m_completion->lock.Lock();
m_completion->destriper.add_partial_sparse_result(
m_cct, m_req->data(), m_req->m_ext_map, m_req->m_object_off,
m_req->m_buffer_extents);
m_completion->lock.Unlock();
r = m_req->m_object_len;
}
m_completion->complete_request(m_cct, r);
}
void C_CacheRead::finish(int r)
{
m_req->complete(r);
}
}
|