summaryrefslogtreecommitdiffstats
path: root/src/librbd/io/CopyupRequest.h
blob: e4b3a2e7ffceabf1b122099456c667d2081cdd9d (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
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab

#ifndef CEPH_LIBRBD_IO_COPYUP_REQUEST_H
#define CEPH_LIBRBD_IO_COPYUP_REQUEST_H

#include "include/int_types.h"
#include "include/rados/librados.hpp"
#include "include/buffer.h"
#include "common/Mutex.h"
#include "common/zipkin_trace.h"
#include "librbd/io/AsyncOperation.h"
#include "librbd/io/Types.h"

#include <string>
#include <vector>

namespace ZTracer { struct Trace; }

namespace librbd {

struct ImageCtx;

namespace io {

template <typename I> class AbstractObjectWriteRequest;

template <typename ImageCtxT = librbd::ImageCtx>
class CopyupRequest {
public:
  static CopyupRequest* create(ImageCtxT *ictx, const std::string &oid,
                               uint64_t objectno, Extents &&image_extents,
                               const ZTracer::Trace &parent_trace) {
    return new CopyupRequest(ictx, oid, objectno, std::move(image_extents),
                             parent_trace);
  }

  CopyupRequest(ImageCtxT *ictx, const std::string &oid, uint64_t objectno,
                Extents &&image_extents, const ZTracer::Trace &parent_trace);
  ~CopyupRequest();

  void append_request(AbstractObjectWriteRequest<ImageCtxT> *req);

  void send();

private:
  /**
   * Copyup requests go through the following state machine to read from the
   * parent image, update the object map, and copyup the object:
   *
   *
   * @verbatim
   *
   *              <start>
   *                 |
   *      /---------/ \---------\
   *      |                     |
   *      v                     v
   *  READ_FROM_PARENT      DEEP_COPY
   *      |                     |
   *      \---------\ /---------/
   *                 |
   *                 v (skip if not needed)
   *         UPDATE_OBJECT_MAPS
   *                 |
   *                 v (skip if not needed)
   *              COPYUP
   *                 |
   *                 v
   *              <finish>
   *
   * @endverbatim
   *
   * The OBJECT_MAP state is skipped if the object map isn't enabled or if
   * an object map update isn't required. The COPYUP state is skipped if
   * no data was read from the parent *and* there are no additional ops.
   */

  typedef std::vector<AbstractObjectWriteRequest<ImageCtxT> *> WriteRequests;

  ImageCtxT *m_image_ctx;
  std::string m_oid;
  uint64_t m_object_no;
  Extents m_image_extents;
  ZTracer::Trace m_trace;

  bool m_flatten = false;
  bool m_copyup_required = true;
  bool m_copyup_is_zero = true;

  ceph::bufferlist m_copyup_data;

  AsyncOperation m_async_op;

  std::vector<uint64_t> m_snap_ids;
  bool m_first_snap_is_clean = false;

  Mutex m_lock;
  WriteRequests m_pending_requests;
  unsigned m_pending_copyups = 0;

  WriteRequests m_restart_requests;
  bool m_append_request_permitted = true;

  void read_from_parent();
  void handle_read_from_parent(int r);

  void deep_copy();
  void handle_deep_copy(int r);

  void update_object_maps();
  void handle_update_object_maps(int r);

  void copyup();
  void handle_copyup(int r);

  void finish(int r);
  void complete_requests(bool override_restart_retval, int r);

  void disable_append_requests();
  void remove_from_list();

  bool is_copyup_required();
  bool is_update_object_map_required(int r);
  bool is_deep_copy() const;

  void compute_deep_copy_snap_ids();
};

} // namespace io
} // namespace librbd

extern template class librbd::io::CopyupRequest<librbd::ImageCtx>;

#endif // CEPH_LIBRBD_IO_COPYUP_REQUEST_H