src/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
11 / 118
9.3%
Branches:
0 / 206
0.0%
Functions:
10 / 22
45.5%

memory/shm_file.h
Line Branch Exec Source
1 #pragma once
2
3 #include <fcntl.h>
4 #include <sys/mman.h>
5 #include <atomic>
6 #include <deque>
7 #include <fstream>
8 #include <memory>
9 #include <queue>
10 #include <string>
11 #include <utility>
12 #include <vector>
13
14 #include "base/base.h"
15 #include "base/factory.h"
16 #include "base/json.h"
17 #include "base/string.h"
18 #include "storage/nvm/pet_kv/persistence.h"
19
20 namespace base {
21
22 class PMMmapRegisterCenter {
23 struct MetaBlock {
24 static const int MM_META_NR = 1000;
25
26 ✗ MetaBlock() {
27 ✗ mmMetaNr_ = 0;
28 ✗ magic_ = 0xdeadbeef;
29
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ for (int i = 0; i < MetaBlock::MM_META_NR; i++)
30 ✗ mmMeta_[i].magic_ = 0x66666666;
31 ✗ }
32 struct MmMeta {
33 MmMeta() {}
34 char file_name_[64];
35 uint64_t offset_;
36 uint64_t size_;
37 int magic_ = 0x66666666;
38 };
39 union {
40 struct {
41 int magic_ = 0xdeadbeef;
42 int mmMetaNr_ = 0;
43 MmMeta mmMeta_[MM_META_NR];
44 };
45 char _[2 * 4096 * 4096LL];
46 };
47 };
48
49 public:
50 ✗ static PMMmapRegisterCenter* GetInstance() {
51
0/8
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ static PMMmapRegisterCenter instance;
52 ✗ return &instance;
53 }
54 static constexpr int64_t align = 2 * 1024 * 1024LL;
55 // static constexpr int64_t align = 4 * 1024LL;
56
57 ✗ void* Register(const std::string& name, uint64_t size) {
58
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ std::lock_guard<std::mutex> _(mutex_);
59
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ auto* item = FindIfExists(name);
60
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (item == nullptr) {
61
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ return append_register(name, size);
62
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ } else if (item->size_ != size) {
63 // reinit MMAP
64
0/6
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ LOG(INFO) << base::SFormat(
65 "PM mmap {} registered size{} != existing{}",
66 name,
67 size,
68
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ item->size_);
69
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ ReInitialize();
70
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ return append_register(name, size);
71 } else {
72
0/10
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ LOG(INFO) << base::SFormat("PM mmap {} use existing map", name);
73
74 ✗ shmfile_mmap_addr_ =
75 ✗ std::max(shmfile_mmap_addr_.load(),
76 ✗ shmfile_mmap_data_addr_start_ + item->offset_ + item->size_);
77 ✗ return (void*)(shmfile_mmap_data_addr_start_ + item->offset_);
78 }
79 ✗ }
80
81 std::pair<uint64_t, uint64_t> ForRDMAMemoryRegion() const {
82 return std::make_pair(
83 shmfile_mmap_data_addr_start_,
84 shmfile_mmap_addr_.load() - shmfile_mmap_data_addr_start_);
85 }
86 // this function is non-reentrant
87 ✗ void ReInitialize() {
88
0/4
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ LOG(WARNING) << "reinitialize the whole PM space";
89 static std::atomic_int flag{false};
90
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (!flag.fetch_or(true)) {
91
0/4
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ LOG(WARNING) << "memset whole meta block";
92 ✗ memset((void*)metaBlock_, 0, sizeof(MetaBlock));
93 ✗ new (metaBlock_) MetaBlock();
94 } else {
95
0/4
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ LOG(FATAL) << "ReInitialize is non-reentrant";
96 }
97
0/12
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ CHECK(Valid());
98 ✗ }
99
100 enum class Backend {
101 kAnonymousDram,
102 kDevDax,
103 };
104
105 struct Config {
106 Backend backend = Backend::kAnonymousDram;
107 int numa_id = 0;
108 };
109
110 2164 static Config& GetConfig() {
111 static Config config;
112 2164 return config;
113 }
114
115 ✗ static Backend BackendFromUseDram(bool use_dram) {
116
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ return use_dram ? Backend::kAnonymousDram : Backend::kDevDax;
117 }
118
119 private:
120 ✗ bool Valid() const {
121
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (metaBlock_->magic_ != 0xdeadbeef)
122 ✗ return false;
123
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ for (int i = 0; i < MetaBlock::MM_META_NR; i++)
124
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (metaBlock_->mmMeta_[i].magic_ != 0x66666666)
125 ✗ return false;
126 ✗ return true;
127 }
128
129 ✗ void* append_register(const std::string& name, uint64_t size) {
130
0/8
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ CHECK_NE(size, 0);
131 // LOG(INFO) << fmt::format("PM mmap register {}, size={}", name, size);
132 ✗ auto new_size = (size + align - 1) / align * align;
133 ✗ auto ret = shmfile_mmap_addr_.fetch_add(new_size);
134
0/4
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ LOG(ERROR) << "xmh "
135 ✗ << (shmfile_mmap_addr_ - shmfile_mmap_addr_start_) /
136
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ (1024 * 1024 * 1024LL);
137
0/8
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ CHECK_GE((uint64_t)ret, shmfile_mmap_data_addr_start_);
138
0/8
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ CHECK_LT((uint64_t)ret + size,
139 shmfile_mmap_data_addr_start_ + dax_mm_size_);
140 ✗ memset((void*)ret, 0, size);
141
142 // persist meta data
143 ✗ auto& item = metaBlock_->mmMeta_[metaBlock_->mmMetaNr_];
144 ✗ std::strncpy(item.file_name_, name.c_str(), 50);
145 ✗ item.offset_ = ret - shmfile_mmap_data_addr_start_;
146 ✗ item.size_ = size;
147 ✗ metaBlock_->mmMetaNr_++;
148
0/6
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ CHECK_LE(metaBlock_->mmMetaNr_, MetaBlock::MM_META_NR);
149 ✗ base::clflushopt_range(metaBlock_, sizeof(MetaBlock));
150 ✗ return (char*)ret;
151 }
152
153 ✗ MetaBlock::MmMeta* FindIfExists(const std::string& name) {
154
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ for (int i = 0; i < metaBlock_->mmMetaNr_; i++) {
155 ✗ auto& item = metaBlock_->mmMeta_[i];
156
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (std::strncmp(item.file_name_, name.c_str(), 64) == 0) {
157
0/6
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ CHECK_EQ(item.magic_, 0x66666666);
158 ✗ return &item;
159 }
160 }
161 ✗ return nullptr;
162 }
163
164 ✗ PMMmapRegisterCenter() {
165
0/8
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ CHECK_NE(GetConfig().numa_id, -1);
166
167 char* data;
168
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (GetConfig().backend == Backend::kAnonymousDram) {
169 // filename_ = folly::sformat("/dev/shm/big_file{}", GetConfig().numa_id);
170 ✗ fd_ = 0;
171
0/6
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ LOG(WARNING) << "use dram mmap for PMMmapRegisterCenter";
172 ✗ data = reinterpret_cast<char*>(mmap(
173 nullptr,
174 ✗ dax_mm_size_,
175 PROT_READ | PROT_WRITE,
176 MAP_PRIVATE | MAP_POPULATE | MAP_ANONYMOUS,
177 -1,
178 0));
179 ✗ metaBlock_ = (MetaBlock*)data;
180
0/10
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ CHECK_NE(data, MAP_FAILED) << "map failed";
181 ✗ mlock(data, dax_mm_size_);
182
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ ReInitialize();
183 } else {
184
0/4
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ filename_ = base::SFormat("/dev/dax{}.0", GetConfig().numa_id);
185
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ fd_ = open(filename_.c_str(), 0666);
186
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (fd_ < 0) {
187
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ LOG(FATAL) << "Failed to open file " << filename_ << ": "
188
0/8
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ << strerror(errno);
189 }
190 ✗ data = reinterpret_cast<char*>(mmap(
191 nullptr,
192 ✗ dax_mm_size_,
193 PROT_READ | PROT_WRITE,
194 MAP_SHARED | MAP_POPULATE,
195 fd_,
196 0));
197 }
198
199
0/12
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ LOG(INFO) << "mmap " << filename_ << " ; size = " << dax_mm_size_;
200
0/10
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ CHECK_NE(data, MAP_FAILED) << "map failed";
201 // read meta file
202 ✗ metaBlock_ = (MetaBlock*)data;
203
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (!Valid()) {
204 // first use this device
205
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ LOG(ERROR)
206 << "metadata of dax is not valid, maybe you first use this device;"
207
0/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ << " Please use pm_command to reinit";
208 // ReInitialize();
209 }
210
211 ✗ *(uint64_t*)&shmfile_mmap_addr_start_ = (uint64_t)data;
212 ✗ *(uint64_t*)&shmfile_mmap_data_addr_start_ =
213 ✗ (uint64_t)data + sizeof(MetaBlock);
214 ✗ shmfile_mmap_addr_.store(shmfile_mmap_data_addr_start_);
215 ✗ }
216 ✗ ~PMMmapRegisterCenter() {
217
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ if (fd_ >= 0) {
218 ✗ LOG(INFO) << "ummap shm file: " << filename_ << ", size: " << dax_mm_size_
219 ✗ << ", fd: " << fd_;
220 ✗ munmap((void*)shmfile_mmap_addr_start_, dax_mm_size_);
221 ✗ close(fd_);
222 ✗ fd_ = -1;
223 }
224 ✗ }
225
226 std::string filename_;
227 // const int64_t dax_mm_size_ = 300 * 1024 * 1024 * 1024LL;
228 const int64_t dax_mm_size_ = 140 * 1024 * 1024 * 1024LL;
229 // const int64_t dax_mm_size_ = 500 * 1024 * 1024 * 1024LL;
230 // const int64_t dax_mm_size_ = 75 * 1024 * 1024 * 1024LL;
231 int fd_;
232 const uint64_t shmfile_mmap_addr_start_ = 0;
233 const uint64_t shmfile_mmap_data_addr_start_ = 0;
234 // const uint64_t shmfile_mmap_addr_start_ = 0xeff4200000ull;
235 std::atomic<uint64_t> shmfile_mmap_addr_;
236
237 std::mutex mutex_;
238
239 MetaBlock* metaBlock_ = nullptr;
240 };
241
242 class ShmFile {
243 public:
244 1248 ShmFile() : data_(NULL), size_(0) {}
245 1248 virtual ~ShmFile() = default;
246
247 static std::unique_ptr<ShmFile> New(const json& config);
248 static json ConfigForMedium(
249 const std::string& medium, const std::string& filename, int64 size);
250
251 virtual bool Initialize(const json& config) = 0;
252 virtual void Clear() = 0;
253 691474 char* Data() const { return data_; }
254 4 int64 Size() const { return size_; }
255 2 const std::string& filename() const { return filename_; }
256
257 protected:
258 static std::string ConfigFilename(const json& config);
259 static int64 ConfigSize(const json& config);
260
261 std::string filename_;
262 char* data_;
263 int64 size_;
264
265 private:
266 DISALLOW_COPY_AND_ASSIGN(ShmFile);
267 };
268
269 class FsDaxShmFile : public ShmFile {
270 public:
271 6 explicit FsDaxShmFile(const json& config) : fd_(-1) {}
272 12 ~FsDaxShmFile() override { Clear(); }
273 bool Initialize(const json& config) override;
274 void Clear() override;
275
276 private:
277 int fd_;
278 DISALLOW_COPY_AND_ASSIGN(FsDaxShmFile);
279 };
280
281 class AnonyDramShmFile : public ShmFile {
282 public:
283 1242 explicit AnonyDramShmFile(const json& config) {}
284 2484 ~AnonyDramShmFile() override { Clear(); }
285 bool Initialize(const json& config) override;
286 void Clear() override;
287
288 private:
289 DISALLOW_COPY_AND_ASSIGN(AnonyDramShmFile);
290 };
291
292 class DevDaxShmFile : public ShmFile {
293 public:
294 ✗ explicit DevDaxShmFile(const json& config) {}
295 ✗ ~DevDaxShmFile() override { Clear(); }
296 bool Initialize(const json& config) override;
297 void Clear() override;
298
299 private:
300 DISALLOW_COPY_AND_ASSIGN(DevDaxShmFile);
301 };
302
303 } // namespace base
304