commit:     c096a5d5d07c464d787a77c44725ac22f2ea731b
Author:     Michał Górny <mgorny <AT> gentoo <DOT> org>
AuthorDate: Fri Nov 28 19:13:54 2025 +0000
Commit:     Michał Górny <mgorny <AT> gentoo <DOT> org>
CommitDate: Fri Nov 28 19:13:54 2025 +0000
URL:        https://gitweb.gentoo.org/proj/steve.git/commit/?id=c096a5d5

Add a --min-jobs option for --load-average

Signed-off-by: Michał Górny <mgorny <AT> gentoo.org>

 steve.cxx | 26 +++++++++++++++++++++++---
 1 file changed, 23 insertions(+), 3 deletions(-)

diff --git a/steve.cxx b/steve.cxx
index 50d9f50..4c49e3f 100644
--- a/steve.cxx
+++ b/steve.cxx
@@ -68,6 +68,7 @@ struct steve_process {
 struct steve_state {
        bool verbose;
        size_t jobs;
+       size_t min_jobs;
        double max_load_avg{-1};  /* < 0 implies no load average */
        double load_avg;
        size_t tokens;
@@ -93,6 +94,8 @@ static steve_token_availability 
steve_can_give_token(steve_state *state)
        if (state->tokens == 0)
                return steve_token_availability::no_tokens;
        if (state->max_load_avg > 0) {
+               if (state->jobs < state->min_jobs + state->tokens)
+                       return steve_token_availability::available;
                if (getloadavg(&state->load_avg, 1) == -1) {
                        static bool warned = false;
                        if (!warned) {
@@ -112,7 +115,7 @@ static void steve_give_token(steve_state *state, fuse_req_t 
req, uint64_t pid)
        state->processes[pid].tokens_held++;
        if (state->verbose) {
                if (state->max_load_avg > 0)
-                       std::print(stderr, "Giving job token to PID {}, {} 
left, {} tokens held by process, load average = {:.3} < {}\n",
+                       std::print(stderr, "Giving job token to PID {}, {} 
left, {} tokens held by process, load average = {:.3} (limit: {})\n",
                                        pid, state->tokens, 
state->processes[pid].tokens_held, state->load_avg, state->max_load_avg);
                else
                        std::print(stderr, "Giving job token to PID {}, {} 
left, {} tokens held by process\n",
@@ -169,6 +172,8 @@ static void steve_init(void *userdata, struct 
fuse_conn_info *)
        std::print(stderr, "steve running on /dev/steve for {} jobs\n", 
state->jobs);
        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_jobs > 0)
+               std::print(stderr, "  at least {} jobs will be always 
available\n", state->min_jobs);
 }
 
 static void steve_destroy(void *userdata)
@@ -427,6 +432,8 @@ static constexpr char steve_usage[] =
 "    --jobs=JOBS, -j JOBS   jobs to use (default: nproc)\n"
 "    --load-average=LOAD_AVG, -l LOAD_AVG\n"
 "                           do not serve tokens unless load is below 
LOAD_AVG\n"
+"    --min-jobs=MIN_JOBS, -m MIN_JOBS\n"
+"                           min. jobs to serve even if load average is 
exceeded\n"
 "    --verbose, -v          enable verbose logging\n"
 "    --debug, -d            enable FUSE debug output\n";
 
@@ -435,12 +442,13 @@ static const struct option steve_long_opts[] = {
        { "version", no_argument, 0, 'V' },
        { "jobs", required_argument, 0, 'j' },
        { "load-average", required_argument, 0, 'l' },
+       { "min-jobs", required_argument, 0, 'm' },
        { "verbose", no_argument, 0, 'v' },
        { "debug", no_argument, 0, 'd' },
        {},
 };
 
-static const char *steve_short_opts = "hVj:l:vd";
+static const char *steve_short_opts = "hVj:l:m:vd";
 
 struct fd_guard {
        int fd;
@@ -462,6 +470,7 @@ int main(int argc, char **argv)
                                std::print("steve {}\n", STEVE_VERSION);
                                return 0;
                        case 'j':
+                       case 'm':
                                {
                                        char *endptr;
                                        errno = 0;
@@ -470,7 +479,12 @@ int main(int argc, char **argv)
                                                std::print(stderr, "invalid job 
number: {}\n", optarg);
                                                return 1;
                                        }
-                                       state.jobs = jobs_arg;
+                                       if (opt == 'j')
+                                               state.jobs = jobs_arg;
+                                       else if (opt == 'm')
+                                               state.min_jobs = jobs_arg;
+                                       else
+                                               assert(0 && "not reached");
                                }
                                break;
                        case 'l':
@@ -497,6 +511,12 @@ int main(int argc, char **argv)
                }
        }
 
+       if (state.min_jobs > state.jobs) {
+               std::print(stderr, "--min-jobs ({}) must be smaller than --jobs 
({})\n",
+                               state.min_jobs, state.jobs);
+               return 1;
+       }
+
        std::unique_ptr<struct event_base, std::function<void(struct 
event_base*)>>
                evb{event_base_new(), event_base_free};
        if (!evb) {

Reply via email to