Skip to content

Commit e94e694

Browse files
igchorguptask
authored andcommitted
added 790c09f
1 parent ccc0dc1 commit e94e694

File tree

10 files changed

+207
-45
lines changed

10 files changed

+207
-45
lines changed

cachelib/allocator/CacheAllocator-inl.h

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ CacheAllocator<CacheTrait>::CacheAllocator(SharedMemNewT, Config config)
6666
AccessContainer::getRequiredSize(
6767
config_.accessConfig.getNumBuckets()),
6868
nullptr,
69-
ShmSegmentOpts(config_.accessConfig.getPageSize()))
69+
ShmSegmentOpts(config_.accessConfig.getPageSize(),
70+
false, config_.usePosixShm))
7071
.addr,
7172
compressor_,
7273
[this](Item* it) -> ItemHandle { return acquire(it); })),
@@ -77,7 +78,8 @@ CacheAllocator<CacheTrait>::CacheAllocator(SharedMemNewT, Config config)
7778
AccessContainer::getRequiredSize(
7879
config_.chainedItemAccessConfig.getNumBuckets()),
7980
nullptr,
80-
ShmSegmentOpts(config_.accessConfig.getPageSize()))
81+
ShmSegmentOpts(config_.accessConfig.getPageSize(),
82+
false, config_.usePosixShm))
8183
.addr,
8284
compressor_,
8385
[this](Item* it) -> ItemHandle { return acquire(it); })),
@@ -87,7 +89,8 @@ CacheAllocator<CacheTrait>::CacheAllocator(SharedMemNewT, Config config)
8789
nvmCacheState_{config_.cacheDir, config_.isNvmCacheEncryptionEnabled(),
8890
config_.isNvmCacheTruncateAllocSizeEnabled()} {
8991
initCommon(false);
90-
shmManager_->removeShm(detail::kShmInfoName);
92+
shmManager_->removeShm(detail::kShmInfoName,
93+
PosixSysVSegmentOpts(config_.usePosixShm));
9194
}
9295

9396
template <typename CacheTrait>
@@ -105,13 +108,15 @@ CacheAllocator<CacheTrait>::CacheAllocator(SharedMemAttachT, Config config)
105108
accessContainer_(std::make_unique<AccessContainer>(
106109
deserializer_->deserialize<AccessSerializationType>(),
107110
config_.accessConfig,
108-
shmManager_->attachShm(detail::kShmHashTableName),
111+
shmManager_->attachShm(detail::kShmHashTableName, nullptr,
112+
ShmSegmentOpts(PageSizeT::NORMAL, false, config_.usePosixShm)),
109113
compressor_,
110114
[this](Item* it) -> ItemHandle { return acquire(it); })),
111115
chainedItemAccessContainer_(std::make_unique<AccessContainer>(
112116
deserializer_->deserialize<AccessSerializationType>(),
113117
config_.chainedItemAccessConfig,
114-
shmManager_->attachShm(detail::kShmChainedItemHashTableName),
118+
shmManager_->attachShm(detail::kShmChainedItemHashTableName, nullptr,
119+
ShmSegmentOpts(PageSizeT::NORMAL, false, config_.usePosixShm)),
115120
compressor_,
116121
[this](Item* it) -> ItemHandle { return acquire(it); })),
117122
chainedItemLocks_(config_.chainedItemsLockPower,
@@ -128,7 +133,8 @@ CacheAllocator<CacheTrait>::CacheAllocator(SharedMemAttachT, Config config)
128133
// We will create a new info shm segment on shutDown(). If we don't remove
129134
// this info shm segment here and the new info shm segment's size is larger
130135
// than this one, creating new one will fail.
131-
shmManager_->removeShm(detail::kShmInfoName);
136+
shmManager_->removeShm(detail::kShmInfoName,
137+
PosixSysVSegmentOpts(config_.usePosixShm));
132138
}
133139

134140
template <typename CacheTrait>
@@ -146,6 +152,7 @@ std::unique_ptr<MemoryAllocator>
146152
CacheAllocator<CacheTrait>::createNewMemoryAllocator() {
147153
ShmSegmentOpts opts;
148154
opts.alignment = sizeof(Slab);
155+
opts.typeOpts = PosixSysVSegmentOpts(config_.usePosixShm);
149156
return std::make_unique<MemoryAllocator>(
150157
getAllocatorConfig(config_),
151158
shmManager_
@@ -160,6 +167,7 @@ std::unique_ptr<MemoryAllocator>
160167
CacheAllocator<CacheTrait>::restoreMemoryAllocator() {
161168
ShmSegmentOpts opts;
162169
opts.alignment = sizeof(Slab);
170+
opts.typeOpts = PosixSysVSegmentOpts(config_.usePosixShm);
163171
return std::make_unique<MemoryAllocator>(
164172
deserializer_->deserialize<MemoryAllocator::SerializationType>(),
165173
shmManager_
@@ -267,7 +275,8 @@ void CacheAllocator<CacheTrait>::initWorkers() {
267275

268276
template <typename CacheTrait>
269277
std::unique_ptr<Deserializer> CacheAllocator<CacheTrait>::createDeserializer() {
270-
auto infoAddr = shmManager_->attachShm(detail::kShmInfoName);
278+
auto infoAddr = shmManager_->attachShm(detail::kShmInfoName, nullptr,
279+
ShmSegmentOpts(PageSizeT::NORMAL, false, config_.usePosixShm));
271280
return std::make_unique<Deserializer>(
272281
reinterpret_cast<uint8_t*>(infoAddr.addr),
273282
reinterpret_cast<uint8_t*>(infoAddr.addr) + infoAddr.size);
@@ -3129,8 +3138,11 @@ void CacheAllocator<CacheTrait>::saveRamCache() {
31293138
std::unique_ptr<folly::IOBuf> ioBuf = serializedBuf.move();
31303139
ioBuf->coalesce();
31313140

3132-
void* infoAddr =
3133-
shmManager_->createShm(detail::kShmInfoName, ioBuf->length()).addr;
3141+
ShmSegmentOpts opts;
3142+
opts.typeOpts = PosixSysVSegmentOpts(config_.usePosixShm);
3143+
3144+
void* infoAddr = shmManager_->createShm(detail::kShmInfoName, ioBuf->length(),
3145+
nullptr, opts).addr;
31343146
Serializer serializer(reinterpret_cast<uint8_t*>(infoAddr),
31353147
reinterpret_cast<uint8_t*>(infoAddr) + ioBuf->length());
31363148
serializer.writeToBuffer(std::move(ioBuf));
@@ -3481,7 +3493,7 @@ bool CacheAllocator<CacheTrait>::stopReaper(std::chrono::seconds timeout) {
34813493

34823494
template <typename CacheTrait>
34833495
bool CacheAllocator<CacheTrait>::cleanupStrayShmSegments(
3484-
const std::string& cacheDir, bool posix /*TODO(SHM_FILE): const std::vector<CacheMemoryTierConfig>& config */) {
3496+
const std::string& cacheDir, bool posix /*TODO(SHM_FILE): const std::vector<CacheMemoryTierConfig>& config */) {
34853497
if (util::getStatIfExists(cacheDir, nullptr) && util::isDir(cacheDir)) {
34863498
try {
34873499
// cache dir exists. clean up only if there are no other processes
@@ -3500,6 +3512,12 @@ bool CacheAllocator<CacheTrait>::cleanupStrayShmSegments(
35003512
ShmManager::removeByName(cacheDir, detail::kShmHashTableName, posix);
35013513
ShmManager::removeByName(cacheDir, detail::kShmChainedItemHashTableName,
35023514
posix);
3515+
3516+
// TODO(SHM_FILE): try to nuke segments of differente types (which require
3517+
// extra info)
3518+
// for (auto &tier : config) {
3519+
// ShmManager::removeByName(cacheDir, tierShmName, config_.memoryTiers[i].opts);
3520+
// }
35033521
}
35043522
return true;
35053523
}

cachelib/allocator/CacheAllocator.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1191,7 +1191,8 @@ class CacheAllocator : public CacheBase {
11911191
// returns true if there was no error in trying to cleanup the segment
11921192
// because another process was attached. False if the user tried to clean up
11931193
// and the cache was actually attached.
1194-
static bool cleanupStrayShmSegments(const std::string& cacheDir, bool posix);
1194+
static bool cleanupStrayShmSegments(const std::string& cacheDir, bool posix
1195+
/*TODO: const std::vector<CacheMemoryTierConfig>& config = {} */);
11951196

11961197
// gives a relative offset to a pointer within the cache.
11971198
uint64_t getItemPtrAsOffset(const void* ptr);

cachelib/allocator/TempShmMapping.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ TempShmMapping::TempShmMapping(size_t size)
3434
TempShmMapping::~TempShmMapping() {
3535
try {
3636
if (addr_) {
37-
shmManager_->removeShm(detail::kTempShmCacheName.str());
37+
shmManager_->removeShm(detail::kTempShmCacheName.str(),
38+
PosixSysVSegmentOpts(false /* posix */));
3839
}
3940
if (shmManager_) {
4041
shmManager_.reset();
@@ -77,7 +78,8 @@ void* TempShmMapping::createShmMapping(ShmManager& shmManager,
7778
return shmAddr;
7879
} catch (...) {
7980
if (shmAddr) {
80-
shmManager.removeShm(detail::kTempShmCacheName.str());
81+
shmManager.removeShm(detail::kTempShmCacheName.str(),
82+
PosixSysVSegmentOpts(false /* posix */));
8183
} else {
8284
munmap(addr, size);
8385
}

cachelib/shm/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ add_thrift_file(SHM shm.thrift frozen2)
1616

1717
add_library (cachelib_shm
1818
${SHM_THRIFT_FILES}
19+
FileShmSegment.cpp
1920
PosixShmSegment.cpp
2021
ShmCommon.cpp
2122
ShmManager.cpp

cachelib/shm/FileShmSegment.h

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#pragma once
18+
#include <string>
19+
20+
#include "cachelib/shm/ShmCommon.h"
21+
22+
namespace facebook {
23+
namespace cachelib {
24+
25+
/* This class lets you manage a pmem shared memory segment identified by
26+
* name. This is very similar to the Posix shared memory segment, except
27+
* that it allows for resizing of the segments on the fly. This can let the
28+
* application logic to grow/shrink the shared memory segment at its end.
29+
* Accessing the pages truncated on shrinking will result in SIGBUS.
30+
*
31+
* Segments can be created and attached to the process's address space.
32+
* Segments can be marked for removal, even while they are currently attached
33+
* to some process's address space. Upon which, any subsequent attach fails
34+
* until a new segment of the same name is created. Once the last process
35+
* attached to the segment unmaps the memory from its address space, the
36+
* physical memory associated with this segment is freed.
37+
*
38+
* At any given point of time, there is only ONE unique attachable segment by
39+
* name, but there could exist several unattachable segments which were once
40+
* referenced by the same name living in process address space while all of
41+
* them are marked for removal.
42+
*/
43+
44+
class FileShmSegment : public ShmBase {
45+
public:
46+
// attach to an existing pmem segment with the given name
47+
//
48+
// @param name Name of the segment
49+
// @param opts the options for attaching to the segment.
50+
FileShmSegment(ShmAttachT,
51+
const std::string& name,
52+
ShmSegmentOpts opts = {});
53+
54+
// create a new segment
55+
// @param name The name of the segment
56+
// @param size The size of the segment. This will be rounded up to the
57+
// nearest page size.
58+
FileShmSegment(ShmNewT,
59+
const std::string& name,
60+
size_t size,
61+
ShmSegmentOpts opts = {});
62+
63+
// destructor
64+
~FileShmSegment() override;
65+
66+
std::string getKeyStr() const noexcept override { return getPath(); }
67+
68+
// marks the current segment to be removed once it is no longer mapped
69+
// by any process in the kernel.
70+
void markForRemoval() override;
71+
72+
// return the current size of the segment. throws std::system_error
73+
// with EINVAL if the segment is invalid or appropriate errno if the
74+
// segment exists but we have a bad fd or kernel is out of memory.
75+
size_t getSize() const override;
76+
77+
// attaches the segment from the start to the address space of the
78+
// caller. the address must be page aligned.
79+
// @param addr the start of the address for attaching.
80+
//
81+
// @return the address where the segment was mapped to. This will be same
82+
// as addr if addr is not nullptr
83+
// @throw std::system_error with EINVAL if the segment is not valid or
84+
// address/length are not page aligned.
85+
void* mapAddress(void* addr) const override;
86+
87+
// unmaps the memory from addr up to the given length from the
88+
// address space.
89+
void unMap(void* addr) const override;
90+
91+
// useful for removing without attaching
92+
// @return true if the segment existed. false otherwise
93+
static bool removeByPath(const std::string& path);
94+
95+
private:
96+
static int createNewSegment(const std::string& name);
97+
static int getExisting(const std::string& name, const ShmSegmentOpts& opts);
98+
99+
// returns the key type corresponding to the given name.
100+
std::string getPath() const;
101+
102+
// resize the segment
103+
// @param size the new size
104+
// @return none
105+
// @throw Throws std::system_error with appropriate errno
106+
void resize(size_t size) const;
107+
108+
void createReferenceMapping();
109+
void deleteReferenceMapping() const;
110+
111+
// file descriptor associated with the shm. This has FD_CLOEXEC set
112+
// and once opened, we close this only on destruction of this object
113+
int fd_{kInvalidFD};
114+
};
115+
} // namespace cachelib
116+
} // namespace facebook

cachelib/shm/PosixShmSegment.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@
2222
namespace facebook {
2323
namespace cachelib {
2424

25-
constexpr int kInvalidFD = -1;
26-
2725
/* This class lets you manage a posix shared memory segment identified by
2826
* name. This is very similar to the System V shared memory segment, except
2927
* that it allows for resizing of the segments on the fly. This can let the

cachelib/shm/Shm.h

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <system_error>
2323

2424
#include "cachelib/common/Utils.h"
25+
#include "cachelib/shm/FileShmSegment.h"
2526
#include "cachelib/shm/PosixShmSegment.h"
2627
#include "cachelib/shm/ShmCommon.h"
2728
#include "cachelib/shm/SysVShmSegment.h"
@@ -50,14 +51,17 @@ class ShmSegment {
5051
ShmSegment(ShmNewT,
5152
std::string name,
5253
size_t size,
53-
bool usePosix,
5454
ShmSegmentOpts opts = {}) {
55-
if (usePosix) {
56-
segment_ = std::make_unique<PosixShmSegment>(ShmNew, std::move(name),
57-
size, opts);
58-
} else {
59-
segment_ =
60-
std::make_unique<SysVShmSegment>(ShmNew, std::move(name), size, opts);
55+
if (auto *v = std::get_if<FileShmSegmentOpts>(&opts.typeOpts)) {
56+
segment_ = std::make_unique<FileShmSegment>(
57+
ShmNew, std::move(name), size, opts);
58+
} else if (auto *v = std::get_if<PosixSysVSegmentOpts>(&opts.typeOpts)) {
59+
if (v->usePosix)
60+
segment_ = std::make_unique<PosixShmSegment>(
61+
ShmNew, std::move(name), size, opts);
62+
else
63+
segment_ = std::make_unique<SysVShmSegment>(
64+
ShmNew, std::move(name), size, opts);
6165
}
6266
}
6367

@@ -66,14 +70,17 @@ class ShmSegment {
6670
// @param opts the options for the segment.
6771
ShmSegment(ShmAttachT,
6872
std::string name,
69-
bool usePosix,
7073
ShmSegmentOpts opts = {}) {
71-
if (usePosix) {
72-
segment_ =
73-
std::make_unique<PosixShmSegment>(ShmAttach, std::move(name), opts);
74-
} else {
75-
segment_ =
76-
std::make_unique<SysVShmSegment>(ShmAttach, std::move(name), opts);
74+
if (std::get_if<FileShmSegmentOpts>(&opts.typeOpts)) {
75+
segment_ = std::make_unique<FileShmSegment>(
76+
ShmAttach, std::move(name), opts);
77+
} else if (auto *v = std::get_if<PosixSysVSegmentOpts>(&opts.typeOpts)) {
78+
if (v->usePosix)
79+
segment_ = std::make_unique<PosixShmSegment>(
80+
ShmAttach, std::move(name), opts);
81+
else
82+
segment_ = std::make_unique<SysVShmSegment>(
83+
ShmAttach, std::move(name), opts);
7784
}
7885
}
7986

cachelib/shm/ShmCommon.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <sys/stat.h>
2222

2323
#include <system_error>
24+
#include <variant>
2425

2526
#include "cachelib/common/Utils.h"
2627

@@ -92,9 +93,16 @@ struct ShmSegmentOpts {
9293
PageSizeT pageSize{PageSizeT::NORMAL};
9394
bool readOnly{false};
9495
size_t alignment{1}; // alignment for mapping.
96+
ShmTypeOpts typeOpts{}; // opts specific to segment type
9597

9698
explicit ShmSegmentOpts(PageSizeT p) : pageSize(p) {}
9799
explicit ShmSegmentOpts(PageSizeT p, bool ro) : pageSize(p), readOnly(ro) {}
100+
explicit ShmSegmentOpts(PageSizeT p, bool ro, const std::string& path) :
101+
pageSize(p), readOnly(ro),
102+
typeOpts(path) {}
103+
explicit ShmSegmentOpts(PageSizeT p, bool ro, bool posix) :
104+
pageSize(p), readOnly(ro),
105+
typeOpts(posix) {}
98106
ShmSegmentOpts() : pageSize(PageSizeT::NORMAL) {}
99107
};
100108

0 commit comments

Comments
 (0)