sculpt: allow RAM fs to grow up to 2 GiB

The hard resource limit introduced by "sculpt: upper limit for automatic
quota upgrading" is too conservative for typical use cases of the RAM
fs. This commit makes the limit adjustable per managed component and
relaxes the limit for the RAM fs and depot_rom from 256 MiB to 2 GiB.

Issue #5174
This commit is contained in:
Norman Feske 2024-04-11 12:19:15 +02:00 committed by Christian Helmuth
parent 5d56340568
commit a1e3f9a73e
3 changed files with 66 additions and 37 deletions

View File

@ -62,12 +62,16 @@ struct Sculpt::Deploy
Arch _arch { }; Arch _arch { };
Child_state cached_depot_rom_state { Child_state cached_depot_rom_state {
_child_states, "depot_rom", Priority::STORAGE, _child_states, { .name = "depot_rom",
Ram_quota{24*1024*1024}, Cap_quota{200} }; .priority = Priority::STORAGE,
.initial = { Ram_quota{24*1024*1024}, Cap_quota{200} },
.max = { Ram_quota{2*1024*1024*1024UL}, { } } } };
Child_state uncached_depot_rom_state { Child_state uncached_depot_rom_state {
_child_states, "dynamic_depot_rom", Priority::STORAGE, _child_states, { .name = "dynamic_depot_rom",
Ram_quota{8*1024*1024}, Cap_quota{200} }; .priority = Priority::STORAGE,
.initial = { Ram_quota{8*1024*1024}, Cap_quota{200} },
.max = { Ram_quota{2*1024*1024*1024UL}, { } } } };
/* /*
* Report written to '/config/managed/deploy' * Report written to '/config/managed/deploy'

View File

@ -30,43 +30,58 @@ struct Sculpt::Child_state : Noncopyable
struct Version { unsigned value; }; struct Version { unsigned value; };
struct Attr
{
Start_name name;
Priority priority;
struct Initial { Ram_quota ram; Cap_quota caps; } initial;
struct Max { Ram_quota ram; Cap_quota caps; } max;
static constexpr Max DEFAULT_MAX = { .ram = { 256*1024*1024 },
.caps = { 5000 } };
};
private: private:
Registry<Child_state>::Element _element; Registry<Child_state>::Element _element;
Start_name const _name; Attr const _attr;
Priority const _priority; static Attr _init_attr(Attr const attr)
{
Attr result = attr;
if (!result.max.ram .value) result.max.ram = Attr::DEFAULT_MAX.ram;
if (!result.max.caps.value) result.max.caps = Attr::DEFAULT_MAX.caps;
return result;
}
Ram_quota const _initial_ram_quota; Ram_quota _ram_quota = _attr.initial.ram;
Cap_quota const _initial_cap_quota; Cap_quota _cap_quota = _attr.initial.caps;
Ram_quota _ram_quota = _initial_ram_quota; struct Warned_once { bool ram, caps; } _warned_once { };
Cap_quota _cap_quota = _initial_cap_quota;
Version _version { 0 }; Version _version { 0 };
public: public:
/** Child_state(Registry<Child_state> &registry, Attr const attr)
* Constructor : _element(registry, *this), _attr(_init_attr(attr)) { }
*
* \param ram_quota initial RAM quota Child_state(Registry<Child_state> &registry, auto const &name,
* \param cap_quota initial capability quota Priority priority, Ram_quota initial_ram, Cap_quota initial_caps)
*/
Child_state(Registry<Child_state> &registry, Start_name const &name,
Priority priority, Ram_quota ram_quota, Cap_quota cap_quota)
: :
_element(registry, *this), Child_state(registry, { .name = name,
_name(name), _priority(priority), .priority = priority,
_initial_ram_quota(ram_quota), _initial_cap_quota(cap_quota) .initial = { initial_ram, initial_caps },
.max = { } })
{ } { }
void trigger_restart() void trigger_restart()
{ {
_version.value++; _version.value++;
_ram_quota = _initial_ram_quota; _ram_quota = _attr.initial.ram;
_cap_quota = _initial_cap_quota; _cap_quota = _attr.initial.caps;
} }
void gen_start_node_version(Xml_generator &xml) const void gen_start_node_version(Xml_generator &xml) const
@ -77,12 +92,12 @@ struct Sculpt::Child_state : Noncopyable
void gen_start_node_content(Xml_generator &xml) const void gen_start_node_content(Xml_generator &xml) const
{ {
xml.attribute("name", _name); xml.attribute("name", _attr.name);
gen_start_node_version(xml); gen_start_node_version(xml);
xml.attribute("caps", _cap_quota.value); xml.attribute("caps", _cap_quota.value);
xml.attribute("priority", (int)_priority); xml.attribute("priority", (int)_attr.priority);
gen_named_node(xml, "resource", "RAM", [&] { gen_named_node(xml, "resource", "RAM", [&] {
Number_of_bytes const bytes(_ram_quota.value); Number_of_bytes const bytes(_ram_quota.value);
xml.attribute("quantum", String<64>(bytes)); }); xml.attribute("quantum", String<64>(bytes)); });
@ -102,25 +117,33 @@ struct Sculpt::Child_state : Noncopyable
{ {
bool result = false; bool result = false;
if (child.attribute_value("name", Start_name()) != _name) if (child.attribute_value("name", Start_name()) != _attr.name)
return false; return false;
if (child.has_sub_node("ram") && child.sub_node("ram").has_attribute("requested")) { auto upgrade = [&] (auto const &msg, auto &quota, auto &max_quota, bool &warned_once)
_ram_quota.value = min(_ram_quota.value*2, 256*1024*1024u); {
result = true; if (quota.value == max_quota.value) {
} if (!warned_once)
warning(msg, " consumption of ", _attr.name, " exceeeded maximum of ", max_quota);
warned_once = true;
} else {
quota.value = min(quota.value*2, max_quota.value);
result = true;
}
};
if (child.has_sub_node("caps") && child.sub_node("caps").has_attribute("requested")) { if (child.has_sub_node("ram") && child.sub_node("ram").has_attribute("requested"))
_cap_quota.value = min(_cap_quota.value + 100, 5000u); upgrade("RAM", _ram_quota, _attr.max.ram, _warned_once.ram);
result = true;
} if (child.has_sub_node("caps") && child.sub_node("caps").has_attribute("requested"))
upgrade("caps", _cap_quota, _attr.max.caps, _warned_once.caps);
return result; return result;
} }
Ram_quota ram_quota() const { return _ram_quota; } Ram_quota ram_quota() const { return _ram_quota; }
Start_name name() const { return _name; } Start_name name() const { return _attr.name; }
}; };
#endif /* _MODEL__CHILD_STATE_H_ */ #endif /* _MODEL__CHILD_STATE_H_ */

View File

@ -34,8 +34,10 @@ struct Sculpt::Ram_fs_state : Child_state, File_system
Ram_fs_state(Registry<Child_state> &registry, Start_name const &name) Ram_fs_state(Registry<Child_state> &registry, Start_name const &name)
: :
Child_state(registry, name, Priority::LEITZENTRALE, Child_state(registry, { .name = name,
Ram_quota{1024*1024}, Cap_quota{300}), .priority = Priority::LEITZENTRALE,
.initial = { Ram_quota{1024*1024}, Cap_quota{300} },
.max = { Ram_quota{2*1024*1024*1024UL}, { } } }),
File_system(File_system::UNKNOWN) File_system(File_system::UNKNOWN)
{ } { }
}; };