summaryrefslogtreecommitdiffstats
path: root/src/librbd/ObjectMap.h
blob: c930a5b554a353dcf224c99f66999a177da5ae37 (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
149
150
151
152
153
154
155
156
157
158
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab

#ifndef CEPH_LIBRBD_OBJECT_MAP_H
#define CEPH_LIBRBD_OBJECT_MAP_H

#include "include/int_types.h"
#include "include/fs_types.h"
#include "include/rados/librados_fwd.hpp"
#include "include/rbd/object_map_types.h"
#include "common/bit_vector.hpp"
#include "librbd/Utils.h"
#include <boost/optional.hpp>

class Context;
class RWLock;
namespace ZTracer { struct Trace; }

namespace librbd {

template <typename Op> class BlockGuard;
struct BlockGuardCell;
class ImageCtx;

template <typename ImageCtxT = ImageCtx>
class ObjectMap {
public:
  static ObjectMap *create(ImageCtxT &image_ctx, uint64_t snap_id) {
    return new ObjectMap(image_ctx, snap_id);
  }

  ObjectMap(ImageCtxT &image_ctx, uint64_t snap_id);
  ~ObjectMap();

  static int aio_remove(librados::IoCtx &io_ctx, const std::string &image_id, librados::AioCompletion *c);
  static std::string object_map_name(const std::string &image_id,
				     uint64_t snap_id);

  static bool is_compatible(const file_layout_t& layout, uint64_t size);

  ceph::BitVector<2u>::Reference operator[](uint64_t object_no);
  uint8_t operator[](uint64_t object_no) const;
  inline uint64_t size() const {
    return m_object_map.size();
  }

  void open(Context *on_finish);
  void close(Context *on_finish);
  bool set_object_map(ceph::BitVector<2> &target_object_map);
  bool object_may_exist(uint64_t object_no) const;
  bool object_may_not_exist(uint64_t object_no) const;

  void aio_save(Context *on_finish);
  void aio_resize(uint64_t new_size, uint8_t default_object_state,
		  Context *on_finish);

  template <typename T, void(T::*MF)(int) = &T::complete>
  bool aio_update(uint64_t snap_id, uint64_t start_object_no, uint8_t new_state,
                  const boost::optional<uint8_t> &current_state,
                  const ZTracer::Trace &parent_trace, bool ignore_enoent,
                  T *callback_object) {
    return aio_update<T, MF>(snap_id, start_object_no, start_object_no + 1,
                             new_state, current_state, parent_trace,
                             ignore_enoent, callback_object);
  }

  template <typename T, void(T::*MF)(int) = &T::complete>
  bool aio_update(uint64_t snap_id, uint64_t start_object_no,
                  uint64_t end_object_no, uint8_t new_state,
                  const boost::optional<uint8_t> &current_state,
                  const ZTracer::Trace &parent_trace, bool ignore_enoent,
                  T *callback_object) {
    ceph_assert(start_object_no < end_object_no);
    if (snap_id == CEPH_NOSNAP) {
      end_object_no = std::min(end_object_no, m_object_map.size());
      if (start_object_no >= end_object_no) {
        return false;
      }

      auto it = m_object_map.begin() + start_object_no;
      auto end_it = m_object_map.begin() + end_object_no;
      for (; it != end_it; ++it) {
        if (update_required(it, new_state)) {
          break;
        }
      }

      if (it == end_it) {
        return false;
      }

      UpdateOperation update_operation(start_object_no, end_object_no,
                                       new_state, current_state, parent_trace,
                                       ignore_enoent,
                                       util::create_context_callback<T, MF>(
                                         callback_object));
      detained_aio_update(std::move(update_operation));
    } else {
      aio_update(snap_id, start_object_no, end_object_no, new_state,
                 current_state, parent_trace, ignore_enoent,
                 util::create_context_callback<T, MF>(callback_object));
    }
    return true;
  }

  void rollback(uint64_t snap_id, Context *on_finish);
  void snapshot_add(uint64_t snap_id, Context *on_finish);
  void snapshot_remove(uint64_t snap_id, Context *on_finish);

private:
  struct UpdateOperation {
    uint64_t start_object_no;
    uint64_t end_object_no;
    uint8_t new_state;
    boost::optional<uint8_t> current_state;
    ZTracer::Trace parent_trace;
    bool ignore_enoent;
    Context *on_finish;

    UpdateOperation(uint64_t start_object_no, uint64_t end_object_no,
                    uint8_t new_state,
                    const boost::optional<uint8_t> &current_state,
                    const ZTracer::Trace &parent_trace,
                    bool ignore_enoent, Context *on_finish)
      : start_object_no(start_object_no), end_object_no(end_object_no),
        new_state(new_state), current_state(current_state),
        parent_trace(parent_trace), ignore_enoent(ignore_enoent),
        on_finish(on_finish) {
    }
  };

  typedef BlockGuard<UpdateOperation> UpdateGuard;

  ImageCtxT &m_image_ctx;
  ceph::BitVector<2> m_object_map;
  uint64_t m_snap_id;

  UpdateGuard *m_update_guard = nullptr;

  void detained_aio_update(UpdateOperation &&update_operation);
  void handle_detained_aio_update(BlockGuardCell *cell, int r,
                                  Context *on_finish);

  void aio_update(uint64_t snap_id, uint64_t start_object_no,
                  uint64_t end_object_no, uint8_t new_state,
                  const boost::optional<uint8_t> &current_state,
                  const ZTracer::Trace &parent_trace, bool ignore_enoent,
                  Context *on_finish);
  bool update_required(const ceph::BitVector<2>::Iterator &it,
                       uint8_t new_state);

};

} // namespace librbd

extern template class librbd::ObjectMap<librbd::ImageCtx>;

#endif // CEPH_LIBRBD_OBJECT_MAP_H