]>
git.proxmox.com Git - ceph.git/blob - ceph/src/rbd_replay/actions.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2014 Adam Crume <adamcrume@gmail.com>
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
15 #include "actions.hpp"
16 #include <boost/foreach.hpp>
18 #include "PendingIO.hpp"
19 #include "rbd_replay_debug.hpp"
21 #define dout_context g_ceph_context
24 using namespace rbd_replay
;
28 std::string
create_fake_data() {
29 char data
[1 << 20]; // 1 MB
30 for (unsigned int i
= 0; i
< sizeof(data
); i
++) {
33 return std::string(data
, sizeof(data
));
36 struct ConstructVisitor
: public boost::static_visitor
<Action::ptr
> {
37 inline Action::ptr
operator()(const action::StartThreadAction
&action
) const {
38 return Action::ptr(new StartThreadAction(action
));
41 inline Action::ptr
operator()(const action::StopThreadAction
&action
) const{
42 return Action::ptr(new StopThreadAction(action
));
45 inline Action::ptr
operator()(const action::ReadAction
&action
) const {
46 return Action::ptr(new ReadAction(action
));
49 inline Action::ptr
operator()(const action::AioReadAction
&action
) const {
50 return Action::ptr(new AioReadAction(action
));
53 inline Action::ptr
operator()(const action::WriteAction
&action
) const {
54 return Action::ptr(new WriteAction(action
));
57 inline Action::ptr
operator()(const action::AioWriteAction
&action
) const {
58 return Action::ptr(new AioWriteAction(action
));
61 inline Action::ptr
operator()(const action::DiscardAction
&action
) const {
62 return Action::ptr(new DiscardAction(action
));
65 inline Action::ptr
operator()(const action::AioDiscardAction
&action
) const {
66 return Action::ptr(new AioDiscardAction(action
));
69 inline Action::ptr
operator()(const action::OpenImageAction
&action
) const {
70 return Action::ptr(new OpenImageAction(action
));
73 inline Action::ptr
operator()(const action::CloseImageAction
&action
) const {
74 return Action::ptr(new CloseImageAction(action
));
77 inline Action::ptr
operator()(const action::AioOpenImageAction
&action
) const {
78 return Action::ptr(new AioOpenImageAction(action
));
81 inline Action::ptr
operator()(const action::AioCloseImageAction
&action
) const {
82 return Action::ptr(new AioCloseImageAction(action
));
85 inline Action::ptr
operator()(const action::UnknownAction
&action
) const {
90 } // anonymous namespace
92 std::ostream
& rbd_replay::operator<<(std::ostream
& o
, const Action
& a
) {
96 Action::ptr
Action::construct(const action::ActionEntry
&action_entry
) {
97 return boost::apply_visitor(ConstructVisitor(), action_entry
.action
);
100 void StartThreadAction::perform(ActionCtx
&ctx
) {
101 cerr
<< "StartThreadAction should never actually be performed" << std::endl
;
105 void StopThreadAction::perform(ActionCtx
&ctx
) {
106 dout(ACTION_LEVEL
) << "Performing " << *this << dendl
;
110 void AioReadAction::perform(ActionCtx
&worker
) {
111 dout(ACTION_LEVEL
) << "Performing " << *this << dendl
;
112 librbd::Image
*image
= worker
.get_image(m_action
.imagectx_id
);
114 PendingIO::ptr
io(new PendingIO(pending_io_id(), worker
));
115 worker
.add_pending(io
);
116 int r
= image
->aio_read(m_action
.offset
, m_action
.length
, io
->bufferlist(), &io
->completion());
117 assertf(r
>= 0, "id = %d, r = %d", id(), r
);
120 void ReadAction::perform(ActionCtx
&worker
) {
121 dout(ACTION_LEVEL
) << "Performing " << *this << dendl
;
122 librbd::Image
*image
= worker
.get_image(m_action
.imagectx_id
);
123 PendingIO::ptr
io(new PendingIO(pending_io_id(), worker
));
124 worker
.add_pending(io
);
125 ssize_t r
= image
->read(m_action
.offset
, m_action
.length
, io
->bufferlist());
126 assertf(r
>= 0, "id = %d, r = %d", id(), r
);
127 worker
.remove_pending(io
);
130 void AioWriteAction::perform(ActionCtx
&worker
) {
131 static const std::string
fake_data(create_fake_data());
132 dout(ACTION_LEVEL
) << "Performing " << *this << dendl
;
133 librbd::Image
*image
= worker
.get_image(m_action
.imagectx_id
);
134 PendingIO::ptr
io(new PendingIO(pending_io_id(), worker
));
135 uint64_t remaining
= m_action
.length
;
136 while (remaining
> 0) {
137 uint64_t n
= std::min(remaining
, (uint64_t)fake_data
.length());
138 io
->bufferlist().append(fake_data
.data(), n
);
141 worker
.add_pending(io
);
142 if (worker
.readonly()) {
143 worker
.remove_pending(io
);
145 int r
= image
->aio_write(m_action
.offset
, m_action
.length
, io
->bufferlist(), &io
->completion());
146 assertf(r
>= 0, "id = %d, r = %d", id(), r
);
150 void WriteAction::perform(ActionCtx
&worker
) {
151 dout(ACTION_LEVEL
) << "Performing " << *this << dendl
;
152 librbd::Image
*image
= worker
.get_image(m_action
.imagectx_id
);
153 PendingIO::ptr
io(new PendingIO(pending_io_id(), worker
));
154 worker
.add_pending(io
);
155 io
->bufferlist().append_zero(m_action
.length
);
156 if (!worker
.readonly()) {
157 ssize_t r
= image
->write(m_action
.offset
, m_action
.length
, io
->bufferlist());
158 assertf(r
>= 0, "id = %d, r = %d", id(), r
);
160 worker
.remove_pending(io
);
163 void AioDiscardAction::perform(ActionCtx
&worker
) {
164 dout(ACTION_LEVEL
) << "Performing " << *this << dendl
;
165 librbd::Image
*image
= worker
.get_image(m_action
.imagectx_id
);
166 PendingIO::ptr
io(new PendingIO(pending_io_id(), worker
));
167 worker
.add_pending(io
);
168 if (worker
.readonly()) {
169 worker
.remove_pending(io
);
171 int r
= image
->aio_discard(m_action
.offset
, m_action
.length
, &io
->completion());
172 assertf(r
>= 0, "id = %d, r = %d", id(), r
);
176 void DiscardAction::perform(ActionCtx
&worker
) {
177 dout(ACTION_LEVEL
) << "Performing " << *this << dendl
;
178 librbd::Image
*image
= worker
.get_image(m_action
.imagectx_id
);
179 PendingIO::ptr
io(new PendingIO(pending_io_id(), worker
));
180 worker
.add_pending(io
);
181 if (!worker
.readonly()) {
182 ssize_t r
= image
->discard(m_action
.offset
, m_action
.length
);
183 assertf(r
>= 0, "id = %d, r = %d", id(), r
);
185 worker
.remove_pending(io
);
188 void OpenImageAction::perform(ActionCtx
&worker
) {
189 dout(ACTION_LEVEL
) << "Performing " << *this << dendl
;
190 PendingIO::ptr
io(new PendingIO(pending_io_id(), worker
));
191 worker
.add_pending(io
);
192 librbd::Image
*image
= new librbd::Image();
193 librbd::RBD
*rbd
= worker
.rbd();
194 rbd_loc
name(worker
.map_image_name(m_action
.name
, m_action
.snap_name
));
196 if (m_action
.read_only
|| worker
.readonly()) {
197 r
= rbd
->open_read_only(*worker
.ioctx(), *image
, name
.image
.c_str(), name
.snap
.c_str());
199 r
= rbd
->open(*worker
.ioctx(), *image
, name
.image
.c_str(), name
.snap
.c_str());
202 cerr
<< "Unable to open image '" << m_action
.name
203 << "' with snap '" << m_action
.snap_name
204 << "' (mapped to '" << name
.str()
205 << "') and readonly " << m_action
.read_only
206 << ": (" << -r
<< ") " << strerror(-r
) << std::endl
;
209 worker
.put_image(m_action
.imagectx_id
, image
);
210 worker
.remove_pending(io
);
213 void CloseImageAction::perform(ActionCtx
&worker
) {
214 dout(ACTION_LEVEL
) << "Performing " << *this << dendl
;
215 worker
.erase_image(m_action
.imagectx_id
);
216 worker
.set_action_complete(pending_io_id());
219 void AioOpenImageAction::perform(ActionCtx
&worker
) {
220 dout(ACTION_LEVEL
) << "Performing " << *this << dendl
;
221 // TODO: Make it async
222 PendingIO::ptr
io(new PendingIO(pending_io_id(), worker
));
223 worker
.add_pending(io
);
224 librbd::Image
*image
= new librbd::Image();
225 librbd::RBD
*rbd
= worker
.rbd();
226 rbd_loc
name(worker
.map_image_name(m_action
.name
, m_action
.snap_name
));
228 if (m_action
.read_only
|| worker
.readonly()) {
229 r
= rbd
->open_read_only(*worker
.ioctx(), *image
, name
.image
.c_str(), name
.snap
.c_str());
231 r
= rbd
->open(*worker
.ioctx(), *image
, name
.image
.c_str(), name
.snap
.c_str());
234 cerr
<< "Unable to open image '" << m_action
.name
235 << "' with snap '" << m_action
.snap_name
236 << "' (mapped to '" << name
.str()
237 << "') and readonly " << m_action
.read_only
238 << ": (" << -r
<< ") " << strerror(-r
) << std::endl
;
241 worker
.put_image(m_action
.imagectx_id
, image
);
242 worker
.remove_pending(io
);
245 void AioCloseImageAction::perform(ActionCtx
&worker
) {
246 dout(ACTION_LEVEL
) << "Performing " << *this << dendl
;
247 // TODO: Make it async
248 worker
.erase_image(m_action
.imagectx_id
);
249 worker
.set_action_complete(pending_io_id());