]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/AsyncObjectThrottle.cc
import 14.2.4 nautilus point release
[ceph.git] / ceph / src / librbd / AsyncObjectThrottle.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3#include "librbd/AsyncObjectThrottle.h"
4#include "common/RWLock.h"
5#include "common/WorkQueue.h"
6#include "librbd/AsyncRequest.h"
7#include "librbd/ImageCtx.h"
8#include "librbd/Utils.h"
9
10namespace librbd
11{
12
13template <typename T>
14AsyncObjectThrottle<T>::AsyncObjectThrottle(
15 const AsyncRequest<T>* async_request, T &image_ctx,
16 const ContextFactory& context_factory, Context *ctx,
17 ProgressContext *prog_ctx, uint64_t object_no, uint64_t end_object_no)
18 : m_lock(util::unique_lock_name("librbd::AsyncThrottle::m_lock", this)),
19 m_async_request(async_request), m_image_ctx(image_ctx),
20 m_context_factory(context_factory), m_ctx(ctx), m_prog_ctx(prog_ctx),
21 m_object_no(object_no), m_end_object_no(end_object_no), m_current_ops(0),
22 m_ret(0)
23{
24}
25
26template <typename T>
27void AsyncObjectThrottle<T>::start_ops(uint64_t max_concurrent) {
11fdf7f2 28 ceph_assert(m_image_ctx.owner_lock.is_locked());
7c673cae
FG
29 bool complete;
30 {
31 Mutex::Locker l(m_lock);
32 for (uint64_t i = 0; i < max_concurrent; ++i) {
33 start_next_op();
34 if (m_ret < 0 && m_current_ops == 0) {
35 break;
36 }
37 }
38 complete = (m_current_ops == 0);
39 }
40 if (complete) {
41 // avoid re-entrant callback
42 m_image_ctx.op_work_queue->queue(m_ctx, m_ret);
43 delete this;
44 }
45}
46
47template <typename T>
48void AsyncObjectThrottle<T>::finish_op(int r) {
49 bool complete;
50 {
51 RWLock::RLocker owner_locker(m_image_ctx.owner_lock);
52 Mutex::Locker locker(m_lock);
53 --m_current_ops;
54 if (r < 0 && r != -ENOENT && m_ret == 0) {
55 m_ret = r;
56 }
57
58 start_next_op();
59 complete = (m_current_ops == 0);
60 }
61 if (complete) {
62 m_ctx->complete(m_ret);
63 delete this;
64 }
65}
66
67template <typename T>
68void AsyncObjectThrottle<T>::start_next_op() {
69 bool done = false;
70 while (!done) {
71 if (m_async_request != NULL && m_async_request->is_canceled() &&
72 m_ret == 0) {
73 // allow in-flight ops to complete, but don't start new ops
74 m_ret = -ERESTART;
75 return;
76 } else if (m_ret != 0 || m_object_no >= m_end_object_no) {
77 return;
78 }
79
80 uint64_t ono = m_object_no++;
81 C_AsyncObjectThrottle<T> *ctx = m_context_factory(*this, ono);
82
83 int r = ctx->send();
84 if (r < 0) {
85 m_ret = r;
86 delete ctx;
87 return;
88 } else if (r > 0) {
89 // op completed immediately
90 delete ctx;
91 } else {
92 ++m_current_ops;
93 done = true;
94 }
95 if (m_prog_ctx != NULL) {
494da23a
TL
96 r = m_prog_ctx->update_progress(ono, m_end_object_no);
97 if (r < 0) {
98 m_ret = r;
99 }
7c673cae
FG
100 }
101 }
102}
103
104} // namespace librbd
105
106#ifndef TEST_F
107template class librbd::AsyncObjectThrottle<librbd::ImageCtx>;
108#endif