Skip to content

Conversation

@filbranden
Copy link
Member

@filbranden filbranden commented Jul 16, 2018

This new setting allows configuration of CFS period on the CPU cgroup, instead of using a hardcoded default of 100ms.

Tested:

  • Legacy cgroup + Unified cgroup
  • systemctl set-property
  • systemctl show
  • Confirmed that the cgroup settings (such as cpu.cfs_period_ns) were set appropriately, including updating the CPU quota (cpu.cfs_quota_ns) when CPUQuotaPeriodSec= is updated.
  • Checked that clamping works properly when either period or (quota * period) is out of the [1ms, 1s] range.

Fixes #9081
/cc @derekwaynecarr

Copy link
Member

@poettering poettering left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, just minro nitpicks.

cc @htejun

/* Valid range for period in cpu.max is [1ms, 1s]:
* https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/sched/core.c?h=v4.18-rc5#n6545 */
if (u < 1 * USEC_PER_MSEC || u > 1 * USEC_PER_SEC) {
log_syntax(unit, LOG_ERR, filename, line, r, "CPU quota period '%s' outside of the valid range [1ms, 1s], ignoring.", rvalue);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should pass 0 instead of r as 5th argument. (is not actually going to make a difference during runtime, since r is 0, but is semantically more correct)

usec_t u = 0;

if (!isempty(eq)) {
r = parse_time(eq, &u, MSEC_PER_SEC);
Copy link
Member

@poettering poettering Jul 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, I am not sure about using ms as default unit here. Currently there's exactly one spot where we deviate from the default unit of seconds which we otherwise universally use: the parsing of RLIMIT_RTTIME values. And the primary reason we parse with a default unit if µs there is for "downwards compat", i.e. simply because setting RLIMIT_RTTIME is widely supported in various tools (think: shell's ulimit command), where it always exposes the raw kernel unit of µs, and we should remain compatible to that. Now, i don't think CPUQuotaPeriod= is a similar case though, it's relatively exotic, and people seldom will echo these values directly to cgroupfs...

Or to say this differently: to deviate from the default unit of seconds for time values needs some major reasons, and I don't think this case qualifies. Having uniformity within the systemd codebase regarding time units is more important here...

Or in shorter words: please just use parse_sec() here!

r = parse_time(eq, &u, MSEC_PER_SEC);
if (r < 0) {
log_error_errno(r, "CPU quota period '%s' invalid.", eq);
return -EINVAL;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not merge these two lines into: return log_error_errno(r, …...

/* Valid range for period in cpu.max is [1ms, 1s]:
* https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/sched/core.c?h=v4.18-rc5#n6545 */
if (u < 1 * USEC_PER_MSEC || u > 1 * USEC_PER_SEC)
return log_error_errno(-ERANGE, "CPU quota period '%s' outside of the valid range [1ms, 1s].", eq);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so far we had the rule, that our logging calls would only log error codes that have been received from somewhere else, rather than error codes that are generated here. (@keszybz disagrees with that rule however, and maybe we should revisit this) However for now I think we should stick to this rule, hence please rework this bit to:

if (…) {
        log_error("CPU quota…
        return -ERANGE;
}

@poettering poettering added pid1 reviewed/needs-rework 🔨 PR has been reviewed and needs another round of reworks cgroups labels Jul 16, 2018
@poettering
Copy link
Member

(btw, i am fully aware the define drange is [1ms…1s] and hence using seconds as default unit on the first look makes little sense. However, do note that we support a syntax such as "0.5" too, which I think should mean 500ms...

@poettering
Copy link
Member

I am wonder if this is one of the cases where clamping the value to the defined range plus warning is better than warning and ignoring the whole setting. I mean, this is a very "soft tune" value, i.e. it's not something that makes or breaks stuff, but rather a fine tune thing that just slightly optimizes behaviour for stuff that works anyway. Hence I think being permissive here and apply the closest we can apply makes sense I think

$1.CPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context.cpu_shares)
$1.StartupCPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context.startup_cpu_shares)
$1.CPUQuota, config_parse_cpu_quota, 0, offsetof($1, cgroup_context)
$1.CPUQuotaPeriod, config_parse_cpu_quota_period, 0, offsetof($1, cgroup_context)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, in light of the other discussions this should probably be called CPUQuotaPeriodSec= or so

else
unit_write_settingf(u, flags, "CPUQuotaPeriod",
"CPUQuotaPeriod=%lums",
(unsigned long) (c->cpu_quota_period_usec / USEC_PER_MSEC));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

USEC_FMT rather than %lu please

@filbranden
Copy link
Member Author

Yes, clamping sounds right, since in further testing this I realized that if CPUQuota= gets outside of the range than the setting will fail too, so need to make sure both settings are hand-in-hand and then clamp them when they get out-of-range. (This will potentially make this a bit more complex, since we probably want to store the configured value, but we might also want to store the clamped values as well...)

Anyways, I'll address that and also your other comments, I'll let you know when I have an updated version for you to look into.

Cheers!
Filipe

@poettering
Copy link
Member

since in further testing this I realized that if CPUQuota= gets outside of the range than the setting will fail too, so need to make sure both settings are hand-in-hand and then clamp them when they get out-of-range.

Nah, note that CPUQuota= takes a percentage value, i.e. a value relative to 100. Internally we then store that relative to 1s, for greater granularity. But this means it's CPUQuota= and CPUQuotaPeriodSec= can be stored fully independently, as conversion of CPUQuota= to µs only happens right at the time we write it to cgroupfs

@filbranden
Copy link
Member Author

Updated the PR.

I'm now using seconds by default.

I added some code to time-util to handle clamping the pair (period, quota*period) to the [1ms, 1s] interval, including extensive testing of those functions.

I tested everything again (on unified hierarchy) and everything seems to work fine. The one bit I couldn't manage to trigger is the code in src/core/dbus-cgroup.c that does a unit_write_setting() to update a unit in /run/systemd/system... Should systemctl set-property trigger that code? I didn't see that happening... What would be the best way to trigger it?

All the comments from the previous revision are no longer relevant (since that code is gone) or have been addressed.

PTAL.

@filbranden filbranden changed the title core: add CPUQuotaPeriod core: add CPUQuotaPeriodSec= Jul 20, 2018
@filbranden filbranden removed the reviewed/needs-rework 🔨 PR has been reviewed and needs another round of reworks label Jul 23, 2018
@filbranden
Copy link
Member Author

This has been updated (on Friday) and it's ready for a new review. Please take another look.

<para>Assign the duration over which the CPU time quota specified by <varname>CPUQuota=</varname> is measured.
Takes a time duration value in seconds, with an optional suffix such as "ms" for milliseconds (or "s" for seconds.)
The default setting is 100ms. The period and the time calculated for the quota need to be in the range of
[1ms, 1000ms], so they will be clamped to that interval if any of them are outside it, while still preserving the ratio.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think there's some confusion around CPUQuota here... Note that CPUQuota= takes a percentage from the user, i.e. already a ratio (i.e. relative to 100). Internally, to maintain a larger granularity it is stored relative to 1,000,000 however, but still as a ratio.

i.e.:

  • if the user specifies CPUQuota=3%, then we'll store it intrenally as 30,000 instead.
  • if the user specifies CPUQuota=60%, then we'll store it internally as 600,000 instead.
  • if the user specifies CPUQuota=75%, then we'll store it internally as 750,000 instead.
  • if the user specifies CPUQuota=99%, then we'll store it internally as 990,000 instead.
  • if hte user specifies CPUQuota=100%, then we'll store it internally as 1,000,000 instead.

Moreover, it's actually entirely OK to assign a service 200% CPU time, as the time spend on each CPU is counted individually, and hence 200% means effectively "100% on max 2 cpus", if you follow...

This then means:

  • if the user specifies CPUQuota=234%, then we'll store it internally as 2,340,000 instead.
  • if the user specifies CPUQuota=4567%, then we'll store it internally as 45,670,000 instead. (which means the user could get full CPU time on a whopping 45 cpus before he maxes out!)

This also means that CPUQuota= never needs clamping (as it's a ratio anyway, and is fine with values > 100%)

To make this even more interesting, with #9484 we start supporting permille values too for this(either suffixed by or with a single fractional digit), in that case:

  • if the user specifies CPUQuota=134‰ we store this as 134,000
  • if the user specifies CPUQuota=17.8% we store this as 178,000

Given that we store things internally like this (i.e. as a ratio, and not as a time) things become a lot easier, and clamping is only necessary for the value configured with CPUQuotaPeriodSec=, but not for the value configured with CPUQuota=.

Hope this makes sense?

}

if (streq(field, "CPUQuotaPeriodSec")) {
usec_t u = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we usually use the maximum value for resetting properties, not zero. Hence, please set this to u = USEC_INFINITY here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I was thinking about this one in particular, and I'm not sure I agree in this case... I can see how using USEC_INFINITY makes sense for something like WatchdogSec= or TimeoutSec=, where setting it to infinity is essentially the same as disabling it... So I can see the logic in that.

But in this case, the default value is actually in the middle of the interval, so I'm not that convinced that 0 is not as good a choice as USEC_INFINITY would be.

In fact, I think someone setting CPUQuotaPeriodSec=infinity explicitly would expect to get the maximum allowed value in the interval (in other words, 1 second) rather than the default one (100 ms), no?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but following this logic, you could also say that "0" should result in the smallest period, no, i.e. 1ms?

} else if (streq(name, "CPUQuotaPeriodUSec")) {
uint64_t u64;

r = sd_bus_message_read(message, "t", &u64);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so, we usually use the the maximum value of the type as indicator for "unset", hence we should refuse u64 == 0 here (as zero-length periods are not defined)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good. But is it OK for me to keep using parse_time to parse the time from the config file? That one accepts 0 as a valid value... What should I do with that case?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for the unit files, filter it out right after calling parse_time(). for the bus API filter out server side where we receive the time value, i.e. at this place here.

if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->cpu_quota_period_usec = u64;
unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
if (c->cpu_quota_period_usec == 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in accordance with the comment above, this should check if (c->cpu_quota_period_usec == USEC_INFINITY)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not addressed yet

static void cgroup_apply_legacy_cpu_config(Unit *u, uint64_t shares, uint64_t quota) {
static void cgroup_apply_legacy_cpu_config(Unit *u, uint64_t shares, uint64_t quota, uint64_t period) {
char buf[MAX(DECIMAL_STR_MAX(uint64_t), DECIMAL_STR_MAX(usec_t)) + 1];
usec_t bandwidth;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not actually used, is it?

"%sCPUShares=%" PRIu64 "\n"
"%sStartupCPUShares=%" PRIu64 "\n"
"%sCPUQuotaPerSecSec=%s\n"
"%sCPUQuotaPeriodUSec=%s\n"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

USec → Sec

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So here I was trying to keep the DBus names, which typically use USec suffix on settings that use Sec in the config file...

Though I see the one for CPUQuota doesn't really match exactly the one from DBus, since it's PerSecUSec there and PerSecSec here... What would be correct here do you think?

Should I adjust the CPUQuotaPerSecSec= here to become CPUQuotaPerSecUSec=? (and stop using format_timespan there) or should I use CPUQuotaPeriodSec= here? (If the former, then why not report CPUQuota= with a percentage value here, since that would match the actual configuration?)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we try to keep the prop names in unit files and on the bus objects in sync, but the former usually leans more to the "user friendly" side, while the latter to the "normalized" side. This means the unit file usually lists stuff with seconds as default unit, while the latter exposes stuff normalized to usec like we use everyhere else.

the "dump" calls exist only for debugging, hence we are a bit sloppy there, but usually we show the user friendly version, except where we don't. If in doubt we should probably show the user friendly version there, unless there's a good reason to show the low-level version...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this hasn't been addressed yet...

/* Always use default period for infinity quota. */
*period = CGROUP_CPU_QUOTA_DEFAULT_PERIOD_USEC;
else {
if (*period == 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as mentioned elsewhere we should really use == USEC_INFINITY as marker for "default period" not zero, for the only reason that we tend to standardize using a type's max value for marking "undefined"

* Returns true if some clamping has been performed, in which case
* *a and *b will be updated with the new values.
*/
bool clamp_time_interval(usec_t *a, usec_t *b, usec_t min, usec_t max) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i am not sure i grok why we need this function... the ratio is stored as ratio anyway, hence when the period is altered the ratio doesn't have to be changed.

We should simply clamp the period early (i.e. while parsing) and then at the time we write to cgroupfs calculate the time value from the period and the ratio.

This also means the ratio never has to be clamped.

i.e. if you say 76% quota, then it means mostly the same regardless if you operate with a 100ms period or a 500ms period: as long as we calculate 76% of the period at the instant we write to cgroupfs we are fine.

Also note quota above 100% is completely OK, as the value is counted per CPU, hence 200% means 2 cpus full time.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we need this because both period and quota * period (not sure what to call this one... bandwidth?) need to be within the [1ms, 1s] interval.

So if I have CPUQuota=40% and CPUQuotaPeriodSec=10ms, then the first field will be set to 4ms and everything is fine (no clamping needed.) However, if I have the same CPUQuota=40% but CPUQuotaPeriodSec=2ms, then this needs clamping, even though the period is in the allowed interval! But quota * period = 0.8ms is out of it, so this needs to be clamped to 1ms (for the quota * period product, minimum in the range) and 2.5ms for the period, in order to keep the ratio of 40%.

Does this make sense now?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, so this is just about ensuring the value never becomes 0 after scaling?

I think to deal with that a scaling that rounds up would make sense (which I think would be wise anyway). I.e.

(quota * period + 999999) / 1000000

With that logic we'd never go to zero, given that neither quota nor period can be zero...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it's not about zero... It's about making sure that the calculated slice quota * period is also in the [1ms, 1s] range. Otherwise, writing to the cgroup file (at least in cgroupv2) fails.

Like, with this example, CPUQuota=40% and CPUQuotaPeriodSec=2ms, the calculated slice quota * period = 0.8ms, but setting cpu.max to 800 2000 fails. So this needs to be scaled up to 1000 2500, which is the smallest possible period that satisfies both period and quota * period being within the valid interval.

I hope this makes sense?

I'll definitely add more comments here...

I think other than the check for division by zero, this function should be OK. But I'm open to using a slightly different prototype, perhaps sending the quota as is (a percentage) and then just returning the calculated period back... But I think this prototype works fine as is, it's pretty generic and avoids us having to calculate that more than once...

What do you think would be a good name for quota * period? I thought of bandwidth or slice...

One part that is confusing in this code is this other function (cgroup_cpu_adjust_quota_period) which takes quota as an argument (by reference) but returns quota * period (i.e. slice or bandwidth) in that same argument... Perhaps that could use some improvement.

Cheers,
Filipe

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ping? Please see this comment here, I think that's the main point of contention that needs clarification now. Thanks!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so the range is actually only 1ms…1s for the period but for quota*period there is no upper limit, only 1ms lower limit.

now, i am not entirely sure what the right approach to clamping here is if these limits are breached. if i understand you correctly then you opted for a scheme where the quota is kept in effect and the period and the period adjusted if needed. i.e. you consider quota more relevant than period. I figure that makes sense indeed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think would be a good name for quota * period? I thought of bandwidth or slice...

the kernel calls that quota too...

maybe call it "quota_absolute" or so?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah indeed I didn't realize that setting quota_absolute > 1s actually worked... That makes this a bit more complicated, but I'll take a look and see if I can make it nicer.

(And yes, I like quota_absolute, will use that.)

if (*a > *b)
return clamp_time_interval(b, a, min, max);
if (*a < min) {
usec_t new_high = min * (*b) / (*a);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs division by zero check

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw, this check can be an assert() if we filtered out zero already during parsing and hence know the value can't be zero here anyway...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good.

@filbranden
Copy link
Member Author

What about the default for period... Do you insist on USEC_INFINITY (I can do that change then), or do you agree with my previous argument that using 0 for that is acceptable here?

@poettering
Copy link
Member

What about the default for period... Do you insist on USEC_INFINITY (I can do that change then), or do you agree with my previous argument that using 0 for that is acceptable here?

Yeah, I'd prefer that. Pretty much everywhere else we use UINT64_MAX (or its aliases (uint64_t) -1, USEC_INFINITY, …) as marker for "does not apply" or "not set", and I think we should stick to that here too

@filbranden
Copy link
Member Author

Sounds good. I'll address these pointers and ask you to take another look when it's ready... Thanks!

@poettering
Copy link
Member

any update? (also needs rebase)

@filbranden
Copy link
Member Author

any update?

I updated the code a while ago, but didn't have time to test it thoroughly... Will try to come back to this next week if I find a bit of time...

@filbranden filbranden force-pushed the cpu_quota_period1 branch 2 times, most recently from 2745cc3 to 6e610a1 Compare November 2, 2018 16:22
@poettering
Copy link
Member

Ah, I totally missed that you pushed a new version. For some reason github more often than not doesn't notify us about that, hence whenever you push a new version please also add a quick comment, so that we know

Copy link
Member

@poettering poettering left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks excellent, just some minor notes

"%sCPUShares=%" PRIu64 "\n"
"%sStartupCPUShares=%" PRIu64 "\n"
"%sCPUQuotaPerSecSec=%s\n"
"%sCPUQuotaPeriodUSec=%s\n"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this hasn't been addressed yet...

}

if (streq(field, "CPUQuotaPeriodSec")) {
usec_t u = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but following this logic, you could also say that "0" should result in the smallest period, no, i.e. 1ms?

if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->cpu_quota_period_usec = u64;
unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
if (c->cpu_quota_period_usec == 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not addressed yet

log_unit_full(u, LOG_WARNING, 0,
"Clamping CPU interval for cpu.max: period is now %s",
format_timespan(v, sizeof(v), new_period, 1));
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, so this way we'll log at LOG_WARNING whenever we realize the cgroup, which might be quite often. We really should generate this message only once though I think (and downgrade to LOG_DEBUG from then on). Maybe add a bool flag to the unit stores whether we already warned, and if so, doesn't warn again?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one hasn't been addressed yet. The problem with "already warned" is how to clear it every time the value is updated... I've been thinking of storing the last clamped value instead, that way I can compare to it and skip warning if it still matches. Will update with a separate commit on top once I figure out how to fix this.

@filbranden filbranden force-pushed the cpu_quota_period1 branch 2 times, most recently from 3e2bc70 to fb090a3 Compare December 12, 2018 22:37
@filbranden
Copy link
Member Author

I just pushed a new version that uses USEC_INFINITY for the default (100ms) and doesn't clamp quota to 1s (only period can be at most 1s.) It also addresses the case where quota * period rounds down below 1ms, with some more clamping to use at least 1ms for that product.

I still haven't addressed the issue with LOG_WARNING being too frequent, I'll investigate that and push a separate commit to fix that.

Otherwise, I think this should be ready for review and possibly merge.

Cheers!
Filipe

@filbranden
Copy link
Member Author

Hmmm, config_parse_sec_fix_0 doesn't seem to like an empty string, so setting CPUQuotaPeriodSec= doesn't really work to reset it... I get Failed to parse CPUQuotaPeriodSec= parameter, ignoring. Suggestions?

This works like parse_sec() but defaults to USEC_INFINITY when passed an
empty string or only whitespace.

Also introduce config_parse_sec_def_infinity, which can be used to parse
config options using this function.

This is useful for time options that use "infinity" for default and that
can be reset by unsetting them.

Introduce a test case to ensure it works as expected.
This new setting allows configuration of CFS period on the CPU cgroup, instead
of using a hardcoded default of 100ms.

Tested:
- Legacy cgroup + Unified cgroup
- systemctl set-property
- systemctl show
- Confirmed that the cgroup settings (such as cpu.cfs_period_ns) were set
  appropriately, including updating the CPU quota (cpu.cfs_quota_ns) when
  CPUQuotaPeriodSec= is updated.
- Checked that clamping works properly when either period or (quota * period)
  are below the resolution of 1ms, or if period is above the max of 1s.
After the first warning log, further messages are downgraded to LOG_DEBUG.
@filbranden
Copy link
Member Author

@poettering Please take a look, I believe this one is ready to go or very close to it... I think I have addressed all the items you mentioned.

I just retested this on top of v241 and everything seems to be working as expected.

There are some quirks with the logs, for instance running systemctl daemon-reload will repeat the Clamping CPU interval for cpu.max: ... log line in warning level. Also, when starting a unit that has the quote period clamped, the message is printed before the Started ... service. so it does not always show up in systemctl status ....service output. Not sure if you would have a good recommendation of what to do about those? (Perhaps skipping this "warning" log and just logging it on debug mode might be enough?)

Anyways, let me know if you think this still needs changes or if it's good to go.

Cheers!
Filipe

@poettering
Copy link
Member

There are some quirks with the logs, for instance running systemctl daemon-reload will repeat the Clamping CPU interval for cpu.max: ... log line in warning level.

I think this is fine. In fact, even desirable. Whenever we reread config we should warn again.

Also, when starting a unit that has the quote period clamped, the message is printed before the Started ... service. so it does not always show up in systemctl status ....service output.

Hmm, so this is a general problem, not specific to this new setting, but applies to all settings. I don't really have a good answer for this. Might be worth filing a new issue about this.

Not sure if you would have a good recommendation of what to do about those? (Perhaps skipping this "warning" log and just logging it on debug mode might be enough?)

I think the PR is good to go in, let's see if people complain before we tweak the log level further.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

2 participants