Skip to content

Commit cf62ba8

Browse files
committed
common: MemoryModel: do not issue error messages directly
leave error reporting to the caller. This change achieves two targets: - no need for a context when creating the MemoryModel object; and - (more importantly) the error messages are now reported in the context of the caller, and can be made to appear only once in the logs. The existing client of the MemoryModel is modified to reflect the changes to its API. Signed-off-by: Ronen Friedman <[email protected]>
1 parent 6ed3038 commit cf62ba8

File tree

4 files changed

+63
-33
lines changed

4 files changed

+63
-33
lines changed

src/common/MemoryModel.cc

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717
using namespace std;
1818
using mem_snap_t = MemoryModel::mem_snap_t;
1919

20-
MemoryModel::MemoryModel(CephContext *cct_) : cct(cct_) {}
21-
2220
inline bool MemoryModel::cmp_against(
2321
const std::string &ln,
2422
std::string_view param,
@@ -41,14 +39,10 @@ inline bool MemoryModel::cmp_against(
4139
}
4240

4341

44-
std::optional<int64_t> MemoryModel::get_mapped_heap()
42+
tl::expected<int64_t, std::string> MemoryModel::get_mapped_heap()
4543
{
4644
if (!proc_maps.is_open()) {
47-
ldout(cct, 0) << fmt::format(
48-
"MemoryModel::get_mapped_heap() unable to open {}",
49-
proc_maps_fn)
50-
<< dendl;
51-
return std::nullopt;
45+
return tl::unexpected("unable to open proc/maps");
5246
}
5347
// always rewind before reading
5448
proc_maps.clear();
@@ -99,14 +93,10 @@ std::optional<int64_t> MemoryModel::get_mapped_heap()
9993
}
10094

10195

102-
std::optional<mem_snap_t> MemoryModel::full_sample()
96+
tl::expected<mem_snap_t, std::string> MemoryModel::full_sample()
10397
{
10498
if (!proc_status.is_open()) {
105-
ldout(cct, 0) << fmt::format(
106-
"MemoryModel::sample() unable to open {}",
107-
proc_stat_fn)
108-
<< dendl;
109-
return std::nullopt;
99+
return tl::unexpected("unable to open proc/status");
110100
}
111101
// always rewind before reading
112102
proc_status.clear();

src/common/MemoryModel.h

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@
1616
#define CEPH_MEMORYMODEL_H
1717

1818
#include <fstream>
19-
#include <optional>
19+
#include <string>
2020
#include <string_view>
2121
#include "include/common_fwd.h"
2222
#include "include/compat.h"
23+
#include "include/expected.hpp"
2324

2425

2526
class MemoryModel {
@@ -50,8 +51,14 @@ class MemoryModel {
5051
std::ifstream proc_status{proc_stat_fn};
5152
std::ifstream proc_maps{proc_maps_fn};
5253

53-
CephContext *cct;
54-
std::optional<int64_t> get_mapped_heap();
54+
/**
55+
* @brief Get the mapped heap size
56+
*
57+
* Read /proc/self/maps to get the heap size.
58+
* \retval the mapped heap size, or an error message if the file had not been opened
59+
* when the object was constructed.
60+
*/
61+
tl::expected<int64_t, std::string> get_mapped_heap();
5562

5663
/**
5764
* @brief Compare a line against an expected data label
@@ -62,8 +69,19 @@ class MemoryModel {
6269
bool cmp_against(const std::string& ln, std::string_view param, long& v) const;
6370

6471
public:
65-
explicit MemoryModel(CephContext *cct);
66-
std::optional<mem_snap_t> full_sample();
72+
/**
73+
* @brief extract memory usage information from /proc/self/status &
74+
* /proc/self/maps
75+
*
76+
* Read /proc/self/status and /proc/self/maps to get memory usage information.
77+
* \retval a structure containing the memory usage information, or an error
78+
* message if /proc/status had not been opened when the object was
79+
* constructed.
80+
* Note that no error is returned if only /proc/maps is not open (the heap
81+
* size will be reported as 0).
82+
*/
83+
tl::expected<mem_snap_t, std::string> full_sample();
84+
6785
void sample(mem_snap_t *p = nullptr);
6886
};
6987

src/mds/MDCache.cc

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7812,10 +7812,17 @@ void MDCache::trim_client_leases()
78127812
}
78137813
}
78147814

7815-
void MDCache::check_memory_usage(const MemoryModel::mem_snap_t &baseline)
7815+
void MDCache::check_memory_usage()
78167816
{
7817-
MemoryModel mm(g_ceph_context);
7818-
mm.sample();
7817+
MemoryModel::mem_snap_t memory_snap;
7818+
7819+
if (upkeep_memory_stats) {
7820+
auto maybe_memory_snap = upkeep_memory_stats->full_sample();
7821+
if (maybe_memory_snap) {
7822+
memory_snap = *maybe_memory_snap;
7823+
}
7824+
}
7825+
// else - no access to memory stats. The problem was already reported at thread's init.
78197826

78207827
// check client caps
78217828
ceph_assert(CInode::count() == inode_map.size() + snap_inode_map.size() + num_shadow_inodes);
@@ -7824,17 +7831,17 @@ void MDCache::check_memory_usage(const MemoryModel::mem_snap_t &baseline)
78247831
caps_per_inode = (double)Capability::count() / (double)CInode::count();
78257832

78267833
dout(2) << "Memory usage: "
7827-
<< " total " << mm.last.get_total()
7828-
<< ", rss " << mm.last.get_rss()
7829-
<< ", heap " << mm.last.get_heap()
7830-
<< ", baseline " << baseline.get_heap()
7834+
<< " total " << memory_snap.get_total()
7835+
<< ", rss " << memory_snap.get_rss()
7836+
<< ", heap " << memory_snap.get_heap()
7837+
<< ", baseline " << upkeep_mem_baseline.get_heap()
78317838
<< ", " << num_inodes_with_caps << " / " << CInode::count() << " inodes have caps"
78327839
<< ", " << Capability::count() << " caps, " << caps_per_inode << " caps per inode"
78337840
<< dendl;
78347841

78357842
mds->update_mlogger();
7836-
mds->mlogger->set(l_mdm_rss, mm.last.get_rss());
7837-
mds->mlogger->set(l_mdm_heap, mm.last.get_heap());
7843+
mds->mlogger->set(l_mdm_rss, memory_snap.get_rss());
7844+
mds->mlogger->set(l_mdm_heap, memory_snap.get_heap());
78387845
}
78397846

78407847

@@ -14171,11 +14178,24 @@ void MDCache::upkeep_main(void)
1417114178
{
1417214179
std::unique_lock lock(upkeep_mutex);
1417314180

14181+
// create a "memory model" for the upkeep thread. The object maintains
14182+
// the relevant '/proc' files open. We only check for a failure to open
14183+
// the files once, and then we'll just keep the object around.
14184+
upkeep_memory_stats = MemoryModel{};
14185+
1417414186
// get initial sample upon thread creation
14175-
MemoryModel::mem_snap_t baseline;
1417614187
{
14177-
MemoryModel mm(g_ceph_context);
14178-
mm.sample(&baseline);
14188+
auto maybe_base = upkeep_memory_stats->full_sample();
14189+
if (!maybe_base) {
14190+
dout(1) << fmt::format(
14191+
"{}: Failed to get initial memory sample ({}). No more "
14192+
"sampling will be attempted",
14193+
__func__, maybe_base.error())
14194+
<< dendl;
14195+
upkeep_memory_stats = std::nullopt;
14196+
} else {
14197+
upkeep_mem_baseline = *maybe_base;
14198+
}
1417914199
}
1418014200

1418114201
while (!upkeep_trim_shutdown.load()) {
@@ -14188,7 +14208,7 @@ void MDCache::upkeep_main(void)
1418814208
lock.lock();
1418914209
if (upkeep_trim_shutdown.load())
1419014210
return;
14191-
check_memory_usage(baseline);
14211+
check_memory_usage();
1419214212
if (mds->is_cache_trimmable()) {
1419314213
dout(20) << "upkeep thread trimming cache; last trim " << since << " ago" << dendl;
1419414214
bool active_with_clients = mds->is_active() || mds->is_clientreplay() || mds->is_stopping();

src/mds/MDCache.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -776,7 +776,7 @@ class MDCache {
776776
bool expire_recursive(CInode *in, expiremap& expiremap);
777777

778778
void trim_client_leases();
779-
void check_memory_usage(const MemoryModel::mem_snap_t &baseline);
779+
void check_memory_usage();
780780

781781
void shutdown_start();
782782
void shutdown_check();
@@ -1540,6 +1540,8 @@ class MDCache {
15401540
time upkeep_last_trim = clock::zero();
15411541
time upkeep_last_release = clock::zero();
15421542
std::atomic<bool> upkeep_trim_shutdown{false};
1543+
std::optional<MemoryModel> upkeep_memory_stats;
1544+
MemoryModel::mem_snap_t upkeep_mem_baseline;
15431545

15441546
uint64_t kill_shutdown_at = 0;
15451547

0 commit comments

Comments
 (0)