summaryrefslogtreecommitdiffstats
path: root/src/librbd/operation/SnapshotCreateRequest.h
blob: d306ee21b5b1f3f4aa6dbaa3d529d3f1752e7d89 (plain)
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab

#ifndef CEPH_LIBRBD_OPERATION_SNAPSHOT_CREATE_REQUEST_H
#define CEPH_LIBRBD_OPERATION_SNAPSHOT_CREATE_REQUEST_H

#include "cls/rbd/cls_rbd_types.h"
#include "librbd/Types.h"
#include "librbd/operation/Request.h"
#include <string>

class Context;

namespace librbd {

class ImageCtx;
class ProgressContext;

namespace operation {

template <typename ImageCtxT = ImageCtx>
class SnapshotCreateRequest : public Request<ImageCtxT> {
public:
  /**
   * Snap Create goes through the following state machine:
   *
   * @verbatim
   *
   *            <start>
   *               |
   *               v
   *           STATE_NOTIFY_QUIESCE  * * * * * * * * * * * * *
   *               |                                         *
   *               v                                         *
   *           STATE_SUSPEND_REQUESTS                        *
   *               |                                         *
   *               v                                         *
   *           STATE_SUSPEND_AIO * * * * * * * * * * * * * * *
   *               |                                         *
   *               v                                         *
   *           STATE_APPEND_OP_EVENT (skip if journal        *
   *               |                  disabled)              *
   *   (retry)     v                                         *
   *   . . . > STATE_ALLOCATE_SNAP_ID                        *
   *   .           |                                         *
   *   .           v                                         *
   *   . . . . STATE_CREATE_SNAP * * * * * * * * * * *       *
   *               |                                 *       *
   *               v                                 *       *
   *           STATE_CREATE_OBJECT_MAP (skip if      *       *
   *               |                    disabled)    *       *
   *               v                                 *       *
   *           STATE_CREATE_IMAGE_STATE (skip if     *       *
   *               |                     not mirror  *       *
   *               |                     snapshot)   *       *
   *               |                                 v       *
   *               |              STATE_RELEASE_SNAP_ID      *
   *               |                     |                   *
   *               |                     v                   *
   *               \------------> STATE_NOTIFY_UNQUIESCE < * *
   *                                     |
   *                                     v
   *                                  <finish>
   * @endverbatim
   *
   * The _CREATE_STATE state may repeat back to the _ALLOCATE_SNAP_ID state
   * if a stale snapshot context is allocated. If the create operation needs
   * to abort, the error path is followed to record the result in the journal
   * (if enabled) and bubble the originating error code back to the client.
   */
  SnapshotCreateRequest(ImageCtxT &image_ctx, Context *on_finish,
                        const cls::rbd::SnapshotNamespace &snap_namespace,
                        const std::string &snap_name, uint64_t journal_op_tid,
                        uint64_t flags, ProgressContext &prog_ctx);

protected:
  void send_op() override;
  bool should_complete(int r) override {
    return true;
  }
  bool can_affect_io() const override {
    return true;
  }
  journal::Event create_event(uint64_t op_tid) const override {
    return journal::SnapCreateEvent(op_tid, m_snap_namespace, m_snap_name);
  }

private:
  cls::rbd::SnapshotNamespace m_snap_namespace;
  std::string m_snap_name;
  bool m_skip_object_map;
  bool m_skip_notify_quiesce;
  bool m_ignore_notify_quiesce_error;
  ProgressContext &m_prog_ctx;

  uint64_t m_request_id = 0;
  int m_ret_val = 0;
  bool m_writes_blocked = false;

  uint64_t m_snap_id = CEPH_NOSNAP;
  uint64_t m_size;
  ParentImageInfo m_parent_info;

  void send_notify_quiesce();
  Context *handle_notify_quiesce(int *result);

  void send_suspend_requests();
  Context *handle_suspend_requests(int *result);

  void send_suspend_aio();
  Context *handle_suspend_aio(int *result);

  void send_append_op_event();
  Context *handle_append_op_event(int *result);

  void send_allocate_snap_id();
  Context *handle_allocate_snap_id(int *result);

  void send_create_snap();
  Context *handle_create_snap(int *result);

  Context *send_create_object_map();
  Context *handle_create_object_map(int *result);

  Context *send_create_image_state();
  Context *handle_create_image_state(int *result);

  void send_release_snap_id();
  Context *handle_release_snap_id(int *result);

  Context *send_notify_unquiesce();
  Context *handle_notify_unquiesce(int *result);

  void update_snap_context();

  void save_result(int *result) {
    if (m_ret_val == 0 && *result < 0) {
      m_ret_val = *result;
    }
  }
};

} // namespace operation
} // namespace librbd

extern template class librbd::operation::SnapshotCreateRequest<librbd::ImageCtx>;

#endif // CEPH_LIBRBD_OPERATION_SNAPSHOT_CREATE_REQUEST_H