Skip to content

Commit 0f2a0b2

Browse files
committed
Add emerge jobs tmpdir blocks and files threshold options
--jobs-tmpdir-blocks-threshold[=RATIO] Specifies the maximum ratio of used blocks allowed (a floating-point number between 0.0 and 1.0) in PORTAGE_TMPDIR when starting a new job. With no argument, removes a previous blocks ratio threshold. For example, use a ratio of 0.85 to stop starting new jobs when the blocks usage in PORTAGE_TMPDIR exceeds 85%. This option conflicts with FEATURES="keepwork". --jobs-tmpdir-files-threshold[=RATIO] Specifies the maximum ratio of used files (inodes) allowed (a floating-point number between 0.0 and 1.0) in PORTAGE_TMPDIR when starting a new job. With no argument, removes a previous files ratio threshold. For example, use a ratio of 0.85 to stop starting new jobs when the files usage in PORTAGE_TMPDIR exceeds 85%. This option conflicts with FEATURES="keepwork". Bug: https://bugs.gentoo.org/934382 Signed-off-by: Zac Medico <[email protected]>
1 parent 819c863 commit 0f2a0b2

File tree

3 files changed

+137
-4
lines changed

3 files changed

+137
-4
lines changed

Diff for: lib/_emerge/Scheduler.py

+52-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from portage._sets.base import InternalPackageSet
2727
from portage.util import ensure_dirs, writemsg, writemsg_level
2828
from portage.util.futures import asyncio
29+
from portage.util.path import first_existing
2930
from portage.util.SlotObject import SlotObject
3031
from portage.util._async.SchedulerInterface import SchedulerInterface
3132
from portage.package.ebuild.digestcheck import digestcheck
@@ -64,7 +65,7 @@
6465

6566

6667
class Scheduler(PollScheduler):
67-
# max time between loadavg checks (seconds)
68+
# max time between loadavg and tmpdir statvfs checks (seconds)
6869
_loadavg_latency = 30
6970

7071
# max time between display status updates (seconds)
@@ -229,6 +230,10 @@ def __init__(
229230
if max_jobs is None:
230231
max_jobs = 1
231232
self._set_max_jobs(max_jobs)
233+
self._jobs_tmpdir_blocks_threshold = myopts.get(
234+
"--jobs-tmpdir-blocks-threshold"
235+
)
236+
self._jobs_tmpdir_files_threshold = myopts.get("--jobs-tmpdir-files-threshold")
232237
self._running_root = trees[trees._running_eroot]["root_config"]
233238
self.edebug = 0
234239
if settings.get("PORTAGE_DEBUG", "") == "1":
@@ -1573,7 +1578,11 @@ def _main_loop(self):
15731578
self._main_exit = self._event_loop.create_future()
15741579

15751580
if (
1576-
self._max_load is not None
1581+
(
1582+
self._max_load is not None
1583+
or self._jobs_tmpdir_blocks_threshold is not None
1584+
or self._jobs_tmpdir_files_threshold is not None
1585+
)
15771586
and self._loadavg_latency is not None
15781587
and (self._max_jobs is True or self._max_jobs > 1)
15791588
):
@@ -1792,6 +1801,47 @@ def _is_work_scheduled(self):
17921801
def _running_job_count(self):
17931802
return self._jobs
17941803

1804+
def _can_add_job(self):
1805+
if not super()._can_add_job():
1806+
return False
1807+
1808+
if (
1809+
self._jobs_tmpdir_blocks_threshold is not None
1810+
or self._jobs_tmpdir_files_threshold is not None
1811+
) and hasattr(os, "statvfs"):
1812+
tmpdirs = set()
1813+
for root in self.trees:
1814+
settings = self.trees[root]["root_config"].settings
1815+
if settings["PORTAGE_TMPDIR"] in tmpdirs:
1816+
continue
1817+
tmpdirs.add(settings["PORTAGE_TMPDIR"])
1818+
tmpdir = first_existing(
1819+
os.path.join(settings["PORTAGE_TMPDIR"], "portage")
1820+
)
1821+
try:
1822+
vfs_stat = os.statvfs(tmpdir)
1823+
except OSError as e:
1824+
writemsg_level(
1825+
f"!!! statvfs('{tmpdir}'): {e}\n",
1826+
noiselevel=-1,
1827+
level=logging.ERROR,
1828+
)
1829+
else:
1830+
if (
1831+
self._jobs_tmpdir_blocks_threshold is not None
1832+
and (vfs_stat.f_blocks - vfs_stat.f_bavail) / vfs_stat.f_blocks
1833+
) >= self._jobs_tmpdir_blocks_threshold:
1834+
return False
1835+
if (
1836+
self._jobs_tmpdir_files_threshold is not None
1837+
and vfs_stat.f_files > 0
1838+
and ((vfs_stat.f_files - vfs_stat.f_favail) / vfs_stat.f_files)
1839+
>= self._jobs_tmpdir_files_threshold
1840+
):
1841+
return False
1842+
1843+
return True
1844+
17951845
def _schedule_tasks(self):
17961846
while True:
17971847
state_change = 0

Diff for: lib/_emerge/main.py

+68-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 1999-2023 Gentoo Authors
1+
# Copyright 1999-2024 Gentoo Authors
22
# Distributed under the terms of the GNU General Public License v2
33

44
import argparse
@@ -165,6 +165,8 @@ def __contains__(self, s):
165165
"--getbinpkgonly": y_or_n,
166166
"--ignore-world": y_or_n,
167167
"--jobs": valid_integers,
168+
"--jobs-tmpdir-blocks-threshold": valid_floats,
169+
"--jobs-tmpdir-files-threshold": valid_floats,
168170
"--keep-going": y_or_n,
169171
"--load-average": valid_floats,
170172
"--onlydeps-with-ideps": y_or_n,
@@ -523,6 +525,14 @@ def parse_opts(tmpcmdline, silent=False):
523525
"help": "Specifies the number of packages to build " + "simultaneously.",
524526
"action": "store",
525527
},
528+
"--jobs-tmpdir-blocks-threshold": {
529+
"help": "Specifies maximum used blocks ratio when starting a new job.",
530+
"action": "store",
531+
},
532+
"--jobs-tmpdir-files-threshold": {
533+
"help": "Specifies maximum used files ratio when starting a new job.",
534+
"action": "store",
535+
},
526536
"--keep-going": {
527537
"help": "continue as much as possible after an error",
528538
"choices": true_y_or_n,
@@ -1033,6 +1043,42 @@ def parse_opts(tmpcmdline, silent=False):
10331043

10341044
myoptions.jobs = jobs
10351045

1046+
if myoptions.jobs_tmpdir_blocks_threshold == "True":
1047+
myoptions.jobs_tmpdir_blocks_threshold = None
1048+
1049+
if myoptions.jobs_tmpdir_blocks_threshold:
1050+
try:
1051+
jobs_tmpdir_blocks_threshold = float(myoptions.jobs_tmpdir_blocks_threshold)
1052+
except ValueError:
1053+
jobs_tmpdir_blocks_threshold = 0.0
1054+
1055+
if jobs_tmpdir_blocks_threshold <= 0.0 or jobs_tmpdir_blocks_threshold > 1.0:
1056+
jobs_tmpdir_blocks_threshold = None
1057+
if not silent:
1058+
parser.error(
1059+
f"Invalid --jobs-tmpdir-blocks-threshold: '{myoptions.jobs_tmpdir_blocks_threshold}'\n"
1060+
)
1061+
1062+
myoptions.jobs_tmpdir_blocks_threshold = jobs_tmpdir_blocks_threshold
1063+
1064+
if myoptions.jobs_tmpdir_files_threshold == "True":
1065+
myoptions.jobs_tmpdir_files_threshold = None
1066+
1067+
if myoptions.jobs_tmpdir_files_threshold:
1068+
try:
1069+
jobs_tmpdir_files_threshold = float(myoptions.jobs_tmpdir_files_threshold)
1070+
except ValueError:
1071+
jobs_tmpdir_files_threshold = 0.0
1072+
1073+
if jobs_tmpdir_files_threshold <= 0.0 or jobs_tmpdir_files_threshold > 1.0:
1074+
jobs_tmpdir_files_threshold = None
1075+
if not silent:
1076+
parser.error(
1077+
f"Invalid --jobs-tmpdir-files-threshold: '{myoptions.jobs_tmpdir_files_threshold}'\n"
1078+
)
1079+
1080+
myoptions.jobs_tmpdir_files_threshold = jobs_tmpdir_files_threshold
1081+
10361082
if myoptions.load_average == "True":
10371083
myoptions.load_average = None
10381084

@@ -1304,6 +1350,27 @@ def emerge_main(args: Optional[list[str]] = None):
13041350
emerge_config.action, emerge_config.opts, emerge_config.args = parse_opts(
13051351
tmpcmdline
13061352
)
1353+
if (
1354+
"--jobs-tmpdir-blocks-threshold" in emerge_config.opts
1355+
and "keepwork" in emerge_config.running_config.settings.features
1356+
):
1357+
writemsg_level(
1358+
"--jobs-tmpdir-blocks-threshold conflicts with FEATURES=keepwork\n",
1359+
level=logging.ERROR,
1360+
noiselevel=-1,
1361+
)
1362+
return 1
1363+
1364+
if (
1365+
"--jobs-tmpdir-files-threshold" in emerge_config.opts
1366+
and "keepwork" in emerge_config.running_config.settings.features
1367+
):
1368+
writemsg_level(
1369+
"--jobs-tmpdir-files-threshold conflicts with FEATURES=keepwork\n",
1370+
level=logging.ERROR,
1371+
noiselevel=-1,
1372+
)
1373+
return 1
13071374

13081375
try:
13091376
return run_action(emerge_config)

Diff for: man/emerge.1

+17-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.TH "EMERGE" "1" "May 2024" "Portage @VERSION@" "Portage"
1+
.TH "EMERGE" "1" "Jun 2024" "Portage @VERSION@" "Portage"
22
.SH "NAME"
33
emerge \- Command\-line interface to the Portage system
44
.SH "SYNOPSIS"
@@ -693,6 +693,22 @@ Note that interactive packages currently force a setting
693693
of \fI\-\-jobs=1\fR. This issue can be temporarily avoided
694694
by specifying \fI\-\-accept\-properties=\-interactive\fR.
695695
.TP
696+
.BR \-\-jobs\-tmpdir\-blocks\-threshold[=RATIO]
697+
Specifies the maximum ratio of used blocks allowed (a floating\-point
698+
number between \fI0.0\fR and \fI1.0\fR) in \fBPORTAGE_TMPDIR\fR when
699+
starting a new job. With noargument, removes a previous blocks ratio
700+
threshold. For example, use a ratio of \fI0.85\fR to stop starting new
701+
jobs when the blocks usage in \fBPORTAGE_TMPDIR\fR exceeds \fI85%\fR.
702+
This option conflicts with \fBFEATURES="keepwork"\fR.
703+
.TP
704+
.BR \-\-jobs\-tmpdir\-files\-threshold[=RATIO]
705+
Specifies the maximum ratio of used files (inodes) allowed (a
706+
floating\-point number between \fI0.0\fR and \fI1.0\fR) in
707+
\fBPORTAGE_TMPDIR\fR when starting a new job. With no argument, removes
708+
a previous files ratio threshold. For example, use a ratio of \fI0.85\fR
709+
to stop starting new jobs when the files usage in \fBPORTAGE_TMPDIR\fR
710+
exceeds \fI85%\fR. This option conflicts with \fBFEATURES="keepwork"\fR.
711+
.TP
696712
.BR "\-\-keep\-going [ y | n ]"
697713
Continue as much as possible after an error. When an error occurs,
698714
dependencies are recalculated for remaining packages and any with

0 commit comments

Comments
 (0)