commit: 084f76dbbc0c7b238375d094ced3f957941825d6
Author: Michał Górny <mgorny <AT> gentoo <DOT> org>
AuthorDate: Tue Dec 30 19:57:53 2025 +0000
Commit: Michał Górny <mgorny <AT> gentoo <DOT> org>
CommitDate: Tue Dec 30 19:57:53 2025 +0000
URL: https://gitweb.gentoo.org/proj/steve.git/commit/?id=084f76db
Add sanity checks for --min-memory-avail
Signed-off-by: Michał Górny <mgorny <AT> gentoo.org>
src/steve.cxx | 28 ++++++++++++++++++++++++++--
1 file changed, 26 insertions(+), 2 deletions(-)
diff --git a/src/steve.cxx b/src/steve.cxx
index 1751fe7..dd89412 100644
--- a/src/steve.cxx
+++ b/src/steve.cxx
@@ -121,6 +121,7 @@ struct steve_state {
double load_avg{-1};
int64_t min_memory_avail{-1}; /* <= 0 implies none */
int64_t memory_avail{-1};
+ int64_t memory_total{-1};
int64_t tokens;
std::deque<steve_waiter> waiters;
std::unordered_map<uint64_t, steve_process> processes;
@@ -199,7 +200,7 @@ static std::optional<long> steve_get_meminfo(int fd,
std::string_view label)
buf[rd + 1] = 0;
char *match = strstr(buf, label.data());
if (!match) {
- std::print(stderr, "Parsing /proc/meminfo failed: no {}\n",
label);
+ std::print(stderr, "Parsing /proc/meminfo failed: no {}\n",
label.substr(1));
return {};
}
match += label.size();
@@ -494,7 +495,8 @@ static void steve_init(void *userdata, struct
fuse_conn_info *)
if (state->max_load_avg > 0)
std::print(stderr, " tokens will be served with load average <
{:.3}\n", state->max_load_avg);
if (state->min_memory_avail > 0)
- std::print(stderr, " tokens will be served with memory
available >= {} MiB\n", state->min_memory_avail);
+ std::print(stderr, " tokens will be served with memory
available >= {} MiB (out of {} MiB)\n",
+ state->min_memory_avail, state->memory_total);
if (state->max_load_avg > 0 || state->min_memory_avail > 0)
std::print(stderr, " with a recheck timeout of {} s {} us\n",
state->recheck_timeout.tv_sec,
state->recheck_timeout.tv_usec);
@@ -899,6 +901,15 @@ static void steve_ioctl(
steve_wake_waiters(state);
break;
case STEVE_IOC_SET_MIN_MEMORY_AVAIL:
+ if (state->memory_total == -1) {
+ auto memtotal = steve_get_meminfo(state,
"\nMemTotal:");
+ if (memtotal.has_value())
+ state->memory_total = memtotal.value()
/ 1024;
+ }
+ if (val > state->memory_total) {
+ fuse_reply_err(req, EINVAL);
+ return;
+ }
state->min_memory_avail = val;
std::print(stderr, "{} set min. available memory to {}
MiB\n", steve_process_id(fi->fh, process), state->min_memory_avail);
fuse_reply_ioctl(req, 0, nullptr, 0);
@@ -1170,6 +1181,19 @@ int main(int argc, char **argv)
state.min_jobs, state.jobs);
return 1;
}
+ if (state.min_memory_avail != -1) {
+ auto memtotal = steve_get_meminfo(&state, "\nMemTotal:");
+ if (!memtotal.has_value()) {
+ std::print(stderr, "--min-memory-avail specified but
memory info not available\n");
+ return 1;
+ }
+ state.memory_total = memtotal.value() / 1024;
+ if (state.memory_total < state.min_memory_avail) {
+ std::print(stderr, "--min-memory-avail requests {} MiB
available, but the system has only {} MiB memory\n",
+ state.min_memory_avail,
state.memory_total);
+ return 1;
+ }
+ }
std::unique_ptr<struct event_base, std::function<void(struct
event_base*)>>
evb{event_base_new(), event_base_free};