Compare commits

..

18 Commits

Author SHA1 Message Date
Lennart Poettering f6358f8931
Merge pull request #17427 from poettering/v247-bump
preparation for v247-rc1
2020-10-23 17:50:04 +02:00
Lennart Poettering 3b8a216045 update TODO 2020-10-23 15:46:29 +02:00
Lennart Poettering a53225670d build-sys: prepare 247-rc1
Interestingly, the libudev so version was already bumped.
2020-10-23 13:44:33 +02:00
Lennart Poettering b2a9e4d0ed update hwdb 2020-10-23 13:44:33 +02:00
Lennart Poettering 17d99f95c2
Merge pull request #16859 from poettering/loop-eagain
loop: handle EAGAIN on LOOP_SET_STATUS64
2020-10-23 13:15:04 +02:00
Zbigniew Jędrzejewski-Szmek 15a6c4bf8b
Merge pull request #17417 from anitazha/more_systoomd
More systemd-oomd tweaks
2020-10-23 13:06:51 +02:00
Anita Zhang 532855bead oomd: make start up swap check more robust 2020-10-22 17:04:26 -07:00
Anita Zhang e4ff80404a test: add basic memory pressure extended test for oomd
Simple test to generate a lot of pressure in one unit and assert that
systemd-oomd kills the right one.
2020-10-22 17:04:22 -07:00
Lennart Poettering f93ba37530 test: add heavy load loopback block device test 2020-10-22 15:10:03 +02:00
Lennart Poettering b202ec2068 loop-util: wait a random time before trying again
Let's try to make collisions when multiple clients want to use the same
device less likely, by sleeping a random time on collision.

The loop device allocation protocol is inherently collision prone:
first, a program asks which is the next free loop device, then it tries
to acquire it, in a separate, unsynchronized setp. If many peers do this
all at the same time, they'll likely all collide when trying to
acquire the device, so that they need to ask for a free device again and
again.

Let's make this a little less prone to collisions, reducing the number
of failing attempts: whenever we notice a collision we'll now wait
short and randomized time, making it more likely another peer succeeds.

(This also adds a similar logic when retrying LOOP_SET_STATUS64, but
with a slightly altered calculation, since there we definitely want to
wait a bit, under all cases)
2020-10-22 14:58:28 +02:00
Lennart Poettering 786e3a52a2 dissect: retrigger devices if we missed uevents
On systems that have a udev before
a7fdc6cbd3 uevents would sometimes be
eaten because of device node collisions that caused the ruleset to fail.
Let's add an (ugly) work-around for this, so that we can even work with
such an older udev.
2020-10-22 14:58:28 +02:00
Lennart Poettering 9e3d90671e udev-util: use absolute rather than relative timeout when waiting for devices
This makes it easier to accurately wait for a overall deadline.
2020-10-22 14:58:28 +02:00
Lennart Poettering 021bf17528 loop-util: if a loopback device we want to use still has partitions, do something about it
On current kernels (5.8 for example) under some conditions I don't fully
grok it might happen that a detached loopback block device still has
partition block devices around. Accessing these partition block devices
results in EIO errors (that also fill up dmesg). These devices cannot be
claned up with LOOP_CLR_FD (since the main device already is officially
detached), nor with LOOP_CTL_DELETE (returns EBUSY as long as the
partitions still exist). This is a kernel bug. But it appears to apply
to all recent kernels. I cannot really pin down what triggers this,
suffice to say our heavy-duty test can trigger it.

Either way, let's do something about it: when we notice this state we'll
attach an empty file to it, which is guaranteed to have to part table.
This makes the partitions go away. After closing/reoping the device we
hence are good to go again. ugly workaround, but I think OK enough to
use.

The net result is: with this commit, we'll guarantee that by the time we
attach a file to the loopback device we have zero kernel partitions
associated with it. Thus if we then wait for the kernel partitions we
need to appear we should have entirely reliable behaviour even if
loopback devices by the name are heavily recycled and udev events reach
us very late.

Fixes: #16858
2020-10-22 14:58:27 +02:00
Lennart Poettering 4ba86848c9 dissect-image: rework how we wait for partitions
Previously, we'd just wait for the first moment where the kernel exposes
the same numbre of partitions as libblkid tells us. After that point we
enumerate kernel partitions and look for matching libblkid partitions.

With this change we'll instead enumerate with libblkid only, and then
wait for each kernel partition to show up with the exact parameters we
expect them to show up. Once that happens we are happy.

Care is taken to use the udev device notification messages only as hint
to recheck what the kernel actually says. That's because we are
otherwise subject to a race: we might see udev events from an earlier
use of a loopback device. After all these devices are heavily recycled.
Under the assumption that we'll get udev events for *at least* all
partitions we care about (but possibly more) we can fix the race
entirely with one more fix coming in a later commit: if we make sure
that a loopback block device has zero kernel partitions when we take
possession of it, it doesn't matter anymore if we get spurious udev
events from a previous use. All we have to do is notice when the devices
we need all popped up.
2020-10-22 14:58:27 +02:00
Lennart Poettering 6c544d14d9 dissect-image: wait for udev device to be initialized early
If we allocate the sd_device early we can already use it as path when
looking at whole-device fs images.
2020-10-22 14:58:27 +02:00
Lennart Poettering 95c5009248 loop-util: LOOP_CLR_FD is async, don't retry to reuse a device right after issuing it
When we fall back to classic LOOP_SET_FD logic in case LOOP_CONFIGURE
didn't work we issue LOOP_CLR_FD first. But that call turns out to be
potentially async in the kernel: if something else (let's say
udev/blkid) is accessing the device the ioctl just sets the autoclear
flag and exits. Hence quite often the LOOP_SET_FD will subsequently
fail. Let's avoid the trouble, and immediately exit with EBUSY if
LOOP_CONFIGURE fails, and but remember that LOOP_CONFIGURE is not
available so that on the next iteration we go directly for LOOP_SET_FD
instead.
2020-10-22 14:58:27 +02:00
Lennart Poettering 738f29cb53 loop-util: handle EAGAIN on LOOP_SET_STATUS64
Since
5db470e229 (i.e. kernel 5.0)
changing the .lo_offset field via LOOP_SET_STATUS64 might result in
EAGAIN. Let's handle that.

Fixes: #16858
2020-10-22 14:58:27 +02:00
Anita Zhang 018b6f4548 oomd: use ERRNO_IS_NOT_SUPPORTED and ERRNO_IS_PRIVILEGE 2020-10-21 22:37:30 -07:00
24 changed files with 7116 additions and 5420 deletions

31
NEWS
View File

@ -587,6 +587,37 @@ CHANGES WITH 247 in spe:
* "systemctl edit" has been updated to show the original effective unit
contents in commented form in the text editor.
Contributions from: Adolfo Jayme Barrientos, afg, Alec Moskvin, Alyssa
Ross, Amitanand.Chikorde, Andrew Hangsleben, Anita Zhang, Ansgar
Burchardt, Arian van Putten, Aurelien Jarno, Axel Rasmussen, bauen1,
Beniamino Galvani, Benjamin Berg, Bjørn Mork, brainrom, Chandradeep
Dey, Charles Lee, Chris Down, Christian Göttsche, Clemens Gruber, Daan
De Meyer, Daniele Medri, Daniel Mack, Dan Streetman, David Tardon,
Dimitri John Ledkov, Dmitry Borodaenko, Elisei Roca, ErrantSpore,
Etienne Doms, Fabrice Fontaine, fangxiuning, Felix Riemann, Florian
Klink, Franck Bui, Frantisek Sumsal, George Rawlinson, germanztz,
Gibeom Gwon, Glen Whitney, Gogo Gogsi, Göran Uddeborg, Grant Mathews,
Hans de Goede, Hans Ulrich Niedermann, Haochen Tong, Harald Seiler,
huangyong, Hubert Kario, Ikey Doherty, Jan Chren, Jan Schlüter, Jérémy
Nouhaud, Joerg Behrmann, Jonathan Lebon, Juergen Hoetzel, Julien
Humbert, Kai-Chuan Hsieh, Kairui Song, Kamil Dudka, Kir Kolyshkin, Kyle
Huey, Kyle Russell, Lennart Poettering, lichangze, Luca Boccassi, Lucas
Werkmeister, Marc Kleine-Budde, Marco Wang, Marti Raudsepp,
masmullin2000, Máté Pozsgay, Matt Fenwick, Michael Biebl, Michael
Scherer, Michal Koutný, Michal Sekletár, Michal Suchanek, Mikael
Szreder, Milo Casagrande, mirabilos, Mitsuha_QuQ, mog422, Nazar
Vinnichuk, Nicholas Narsing, Nicolas Fella, Njibhu, nl6720, Oğuz Ersen,
Olivier Le Moal, Ondrej Kozina, Pass Automated Testing Suite, Pedro
Ruiz, Peter Hutterer, Phaedrus Leeds, PhoenixDiscord, Piotr Drąg, Plan
C, Renaud Métrich, Robert Marko, Ronan Pigott, Roy Chen (陳彥廷),
RussianNeuroMancer, Samanta Navarro, Samuel BF, scootergrisen, Steve
Dodd, Susant Sahani, Tobias Hunger, Tobias Kaufmann, Topi Miettinen,
Vito Caputo, Weblate, Wen Yang, williamvds, Yuri Chornoivan, Yu
Watanabe, Zbigniew Jędrzejewski-Szmek, Zmicer Turok, Дамјан
Георгиевски
???, 2020-10-XX
CHANGES WITH 246:
* The service manager gained basic support for cgroup v2 freezer. Units

3
TODO
View File

@ -20,6 +20,9 @@ Janitorial Clean-ups:
Features:
* teach LoadCredential= the ability to load all files from a specfied dir as
individual creds
* systemd-analyze netif that explains predictable interface (or networkctl)
* port selinux code from mallinfo() to mallinfo2() once added to glibc

View File

@ -14265,7 +14265,7 @@ OUI:0012AC*
ID_OUI_FROM_DATABASE=ONTIMETEK INC.
OUI:0012AD*
ID_OUI_FROM_DATABASE=IDS GmbH
ID_OUI_FROM_DATABASE=VIVAVIS AG
OUI:0012AE*
ID_OUI_FROM_DATABASE=HLS HARD-LINE Solutions Inc.
@ -26052,7 +26052,7 @@ OUI:00213D*
ID_OUI_FROM_DATABASE=Cermetek Microelectronics, Inc.
OUI:00213E*
ID_OUI_FROM_DATABASE=TomTom
ID_OUI_FROM_DATABASE=TomTom International BV
OUI:00213F*
ID_OUI_FROM_DATABASE=A-Team Technology Ltd.
@ -29592,7 +29592,7 @@ OUI:0025DE*
ID_OUI_FROM_DATABASE=Probits Co., LTD.
OUI:0025DF*
ID_OUI_FROM_DATABASE=Private
ID_OUI_FROM_DATABASE=Taser International Inc.
OUI:0025E0*
ID_OUI_FROM_DATABASE=CeedTec Sdn Bhd
@ -33977,6 +33977,9 @@ OUI:006967D*
OUI:006967E*
ID_OUI_FROM_DATABASE=Tianjin Lianwu Technology Co., Ltd.
OUI:006B6F*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:006B8E*
ID_OUI_FROM_DATABASE=Shanghai Feixun Communication Co.,Ltd.
@ -43901,6 +43904,9 @@ OUI:14B126*
OUI:14B1C8*
ID_OUI_FROM_DATABASE=InfiniWing, Inc.
OUI:14B2E5*
ID_OUI_FROM_DATABASE=Shenzhen iComm Semiconductor CO.,LTD
OUI:14B31F*
ID_OUI_FROM_DATABASE=Dell Inc.
@ -44144,6 +44150,9 @@ OUI:181420*
OUI:181456*
ID_OUI_FROM_DATABASE=Nokia Corporation
OUI:18146C*
ID_OUI_FROM_DATABASE=Zhejiang Tmall Technology Co., Ltd.
OUI:1816C9*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
@ -45209,6 +45218,9 @@ OUI:1C36BB*
OUI:1C37BF*
ID_OUI_FROM_DATABASE=Cloudium Systems Ltd.
OUI:1C3929*
ID_OUI_FROM_DATABASE=OHSUNG
OUI:1C3947*
ID_OUI_FROM_DATABASE=COMPAL INFORMATION (KUNSHAN) CO., LTD.
@ -46034,6 +46046,9 @@ OUI:1CCCD6*
OUI:1CCDE5*
ID_OUI_FROM_DATABASE=Shanghai Wind Technologies Co.,Ltd
OUI:1CD1BA*
ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
OUI:1CD40C*
ID_OUI_FROM_DATABASE=Kriwan Industrie-Elektronik GmbH
@ -46250,6 +46265,9 @@ OUI:200A5E*
OUI:200BC7*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:200BCF*
ID_OUI_FROM_DATABASE=Nintendo Co.,Ltd
OUI:200CC8*
ID_OUI_FROM_DATABASE=NETGEAR
@ -46961,6 +46979,9 @@ OUI:20FECD*
OUI:20FEDB*
ID_OUI_FROM_DATABASE=M2M Solution S.A.S.
OUI:20FF36*
ID_OUI_FROM_DATABASE=IFLYTEK CO.,LTD.
OUI:2400BA*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
@ -47687,6 +47708,9 @@ OUI:24E314*
OUI:24E43F*
ID_OUI_FROM_DATABASE=Wenzhou Kunmei Communication Technology Co.,Ltd.
OUI:24E4C8*
ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
OUI:24E5AA*
ID_OUI_FROM_DATABASE=Philips Oral Healthcare, Inc.
@ -49445,6 +49469,9 @@ OUI:2CA30E*
OUI:2CA539*
ID_OUI_FROM_DATABASE=Parallel Wireless, Inc
OUI:2CA59C*
ID_OUI_FROM_DATABASE=Hangzhou Hikvision Digital Technology Co.,Ltd.
OUI:2CA780*
ID_OUI_FROM_DATABASE=True Technologies Inc.
@ -51233,6 +51260,9 @@ OUI:34ADE4*
OUI:34AF2C*
ID_OUI_FROM_DATABASE=Nintendo Co., Ltd.
OUI:34AFB3*
ID_OUI_FROM_DATABASE=Amazon Technologies Inc.
OUI:34B1F7*
ID_OUI_FROM_DATABASE=Texas Instruments
@ -51311,6 +51341,9 @@ OUI:34C731*
OUI:34C803*
ID_OUI_FROM_DATABASE=Nokia Corporation
OUI:34C93D*
ID_OUI_FROM_DATABASE=Intel Corporate
OUI:34C99D*
ID_OUI_FROM_DATABASE=EIDOLON COMMUNICATIONS TECHNOLOGY CO. LTD.
@ -51587,6 +51620,9 @@ OUI:34FCEF*
OUI:34FD6A*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:34FEC5*
ID_OUI_FROM_DATABASE=Shenzhen Sunwoda intelligent hardware Co.,Ltd
OUI:380025*
ID_OUI_FROM_DATABASE=Intel Corporate
@ -51824,6 +51860,9 @@ OUI:383F10*
OUI:383FB3*
ID_OUI_FROM_DATABASE=Technicolor CH USA Inc.
OUI:38420B*
ID_OUI_FROM_DATABASE=Sonos, Inc.
OUI:384233*
ID_OUI_FROM_DATABASE=Wildeboer Bauteile GmbH
@ -52067,6 +52106,9 @@ OUI:388E7A*
OUI:388EE7*
ID_OUI_FROM_DATABASE=Fanhattan LLC
OUI:389052*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:3890A5*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@ -52688,6 +52730,9 @@ OUI:3C1E04*
OUI:3C1E13*
ID_OUI_FROM_DATABASE=HANGZHOU SUNRISE TECHNOLOGY CO., LTD
OUI:3C2093*
ID_OUI_FROM_DATABASE=GD Midea Air-Conditioning Equipment Co.,Ltd.
OUI:3C20F6*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
@ -52949,6 +52994,9 @@ OUI:3C5282*
OUI:3C53D7*
ID_OUI_FROM_DATABASE=CEDES AG
OUI:3C5447*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:3C5731*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@ -54056,6 +54104,9 @@ OUI:40882F*
OUI:4088E0*
ID_OUI_FROM_DATABASE=Beijing Ereneben Information Technology Limited Shenzhen Branch
OUI:4089A8*
ID_OUI_FROM_DATABASE=WiredIQ, LLC
OUI:408A9A*
ID_OUI_FROM_DATABASE=TITENG CO., Ltd.
@ -54071,6 +54122,9 @@ OUI:408C4C*
OUI:408D5C*
ID_OUI_FROM_DATABASE=GIGA-BYTE TECHNOLOGY CO.,LTD.
OUI:408F9D*
ID_OUI_FROM_DATABASE=Juniper Networks
OUI:409505*
ID_OUI_FROM_DATABASE=ACOINFO TECHNOLOGY CO.,LTD
@ -55097,6 +55151,9 @@ OUI:44ADB1*
OUI:44ADD9*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:44AE25*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:44AEAB*
ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
@ -58421,6 +58478,9 @@ OUI:54666C*
OUI:546751*
ID_OUI_FROM_DATABASE=Compal Broadband Networks, Inc.
OUI:5467E6*
ID_OUI_FROM_DATABASE=SHENZHEN MTC CO LTD
OUI:546AD8*
ID_OUI_FROM_DATABASE=Elster Water Metering
@ -59423,6 +59483,9 @@ OUI:58B035*
OUI:58B0D4*
ID_OUI_FROM_DATABASE=ZuniData Systems Inc.
OUI:58B0FE*
ID_OUI_FROM_DATABASE=Team EPS GmbH
OUI:58B10F*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
@ -60011,6 +60074,9 @@ OUI:5C6D20*
OUI:5C6F4F*
ID_OUI_FROM_DATABASE=S.A. SISTEL
OUI:5C6F69*
ID_OUI_FROM_DATABASE=Broadcom Limited
OUI:5C70A3*
ID_OUI_FROM_DATABASE=LG Electronics (Mobile Communications)
@ -60944,6 +61010,9 @@ OUI:608CE6*
OUI:608D17*
ID_OUI_FROM_DATABASE=Sentrus Government Systems Division, Inc
OUI:608D26*
ID_OUI_FROM_DATABASE=Arcadyan Corporation
OUI:608E08*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
@ -61406,6 +61475,9 @@ OUI:64037F*
OUI:6405BE*
ID_OUI_FROM_DATABASE=NEW LIGHT LED
OUI:6405E4*
ID_OUI_FROM_DATABASE=ALPSALPINE CO .,LTD
OUI:6405E9*
ID_OUI_FROM_DATABASE=Shenzhen WayOS Technology Crop., Ltd.
@ -62432,6 +62504,9 @@ OUI:683EEC*
OUI:683F1E*
ID_OUI_FROM_DATABASE=EFFECT Photonics B.V.
OUI:683F7D*
ID_OUI_FROM_DATABASE=INGRAM MICRO SERVICES
OUI:684352*
ID_OUI_FROM_DATABASE=Bhuu Limited
@ -62558,6 +62633,9 @@ OUI:6872C3*
OUI:6872DC*
ID_OUI_FROM_DATABASE=CETORY.TV Company Limited
OUI:687627*
ID_OUI_FROM_DATABASE=Zhuhai Dingzhi Electronic Technology Co., Ltd
OUI:68764F*
ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
@ -66404,6 +66482,9 @@ OUI:70B3D528E*
OUI:70B3D528F*
ID_OUI_FROM_DATABASE=Overline Systems
OUI:70B3D5290*
ID_OUI_FROM_DATABASE=GETT Geraetetechnik GmbH
OUI:70B3D5291*
ID_OUI_FROM_DATABASE=Sequent AG
@ -67508,6 +67589,9 @@ OUI:70B3D541A*
OUI:70B3D541B*
ID_OUI_FROM_DATABASE=SYS TEC electronic GmbH
OUI:70B3D541C*
ID_OUI_FROM_DATABASE=Twoway Communications, Inc.
OUI:70B3D541D*
ID_OUI_FROM_DATABASE=Azmoon Keifiat
@ -68043,7 +68127,7 @@ OUI:70B3D54DC*
ID_OUI_FROM_DATABASE=JK DEVICE CORPORATION
OUI:70B3D54DD*
ID_OUI_FROM_DATABASE=Road-iQ, LLC
ID_OUI_FROM_DATABASE=Velvac Incorporated
OUI:70B3D54DE*
ID_OUI_FROM_DATABASE=Oso Technologies, Inc.
@ -68315,6 +68399,9 @@ OUI:70B3D553E*
OUI:70B3D553F*
ID_OUI_FROM_DATABASE=Abbott Diagnostics Technologies AS
OUI:70B3D5540*
ID_OUI_FROM_DATABASE=KMtronic ltd
OUI:70B3D5541*
ID_OUI_FROM_DATABASE=Nanjing Pingguang Electronic Technology Co., Ltd
@ -68963,6 +69050,9 @@ OUI:70B3D5625*
OUI:70B3D5626*
ID_OUI_FROM_DATABASE=KRONOTECH SRL
OUI:70B3D5627*
ID_OUI_FROM_DATABASE=EarTex
OUI:70B3D5628*
ID_OUI_FROM_DATABASE=MECT SRL
@ -69077,6 +69167,9 @@ OUI:70B3D564D*
OUI:70B3D564E*
ID_OUI_FROM_DATABASE=BigStuff3, Inc.
OUI:70B3D564F*
ID_OUI_FROM_DATABASE=GUNMA ELECTRONICS CO LTD
OUI:70B3D5650*
ID_OUI_FROM_DATABASE=GIFAS-ELECTRIC GmbH
@ -70901,6 +70994,9 @@ OUI:70B3D58CF*
OUI:70B3D58D0*
ID_OUI_FROM_DATABASE=Raft Technologies
OUI:70B3D58D1*
ID_OUI_FROM_DATABASE=Field Design Inc.
OUI:70B3D58D3*
ID_OUI_FROM_DATABASE=PERFORMANCE CONTROLS, INC.
@ -71186,6 +71282,9 @@ OUI:70B3D593A*
OUI:70B3D593B*
ID_OUI_FROM_DATABASE=Changchun FAW Yanfeng Visteon Automotive Electronics.,Ltd.
OUI:70B3D593C*
ID_OUI_FROM_DATABASE=GSP Sprachtechnologie GmbH
OUI:70B3D593D*
ID_OUI_FROM_DATABASE=Elmeasure India Pvt Ltd
@ -73070,6 +73169,9 @@ OUI:70B3D5BD9*
OUI:70B3D5BDA*
ID_OUI_FROM_DATABASE=5-D Systems, Inc.
OUI:70B3D5BDC*
ID_OUI_FROM_DATABASE=EDF Lab
OUI:70B3D5BDD*
ID_OUI_FROM_DATABASE=CDR SRL
@ -73283,6 +73385,9 @@ OUI:70B3D5C26*
OUI:70B3D5C27*
ID_OUI_FROM_DATABASE=GD Mission Systems
OUI:70B3D5C28*
ID_OUI_FROM_DATABASE=Mitech Integrated Systems Inc.
OUI:70B3D5C29*
ID_OUI_FROM_DATABASE=SOFTLAND INDIA LTD
@ -73370,6 +73475,9 @@ OUI:70B3D5C45*
OUI:70B3D5C46*
ID_OUI_FROM_DATABASE=eumig industrie-TV GmbH.
OUI:70B3D5C47*
ID_OUI_FROM_DATABASE=ABB
OUI:70B3D5C48*
ID_OUI_FROM_DATABASE=Weltek Technologies Co. Ltd.
@ -73730,6 +73838,9 @@ OUI:70B3D5CC5*
OUI:70B3D5CC6*
ID_OUI_FROM_DATABASE=MB connect line GmbH Fernwartungssysteme
OUI:70B3D5CC7*
ID_OUI_FROM_DATABASE=SOtM
OUI:70B3D5CC8*
ID_OUI_FROM_DATABASE=PROFEN COMMUNICATIONS
@ -73829,6 +73940,9 @@ OUI:70B3D5CEC*
OUI:70B3D5CED*
ID_OUI_FROM_DATABASE=Advanced Products Corporation Pte Ltd
OUI:70B3D5CEE*
ID_OUI_FROM_DATABASE=ACRIOS Systems s.r.o.
OUI:70B3D5CEF*
ID_OUI_FROM_DATABASE=Ellego Powertec Oy
@ -73883,6 +73997,9 @@ OUI:70B3D5D01*
OUI:70B3D5D02*
ID_OUI_FROM_DATABASE=Arctos Showlasertechnik GmbH
OUI:70B3D5D03*
ID_OUI_FROM_DATABASE=Digitella Inc.
OUI:70B3D5D05*
ID_OUI_FROM_DATABASE=Colmek
@ -74435,6 +74552,9 @@ OUI:70B3D5DC9*
OUI:70B3D5DCA*
ID_OUI_FROM_DATABASE=DSan Corporation
OUI:70B3D5DCB*
ID_OUI_FROM_DATABASE=MIJIENETRTECH CO.,LTD
OUI:70B3D5DCC*
ID_OUI_FROM_DATABASE=Eutron SPA
@ -76809,7 +76929,7 @@ OUI:748F3C*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:748F4D*
ID_OUI_FROM_DATABASE=MEN Mikro Elektronik GmbH
ID_OUI_FROM_DATABASE=duagon Germany GmbH
OUI:74901F*
ID_OUI_FROM_DATABASE=Ragile Networks Inc.
@ -77147,6 +77267,9 @@ OUI:74E6E2*
OUI:74E7C6*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:74E9BF*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:74EA3A*
ID_OUI_FROM_DATABASE=TP-LINK TECHNOLOGIES CO.,LTD.
@ -78041,6 +78164,9 @@ OUI:78CC2B*
OUI:78CD8E*
ID_OUI_FROM_DATABASE=SMC Networks Inc
OUI:78CF2F*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:78D004*
ID_OUI_FROM_DATABASE=Neousys Technology Inc.
@ -79517,6 +79643,9 @@ OUI:804A14*
OUI:804B20*
ID_OUI_FROM_DATABASE=Ventilation Control
OUI:804B50*
ID_OUI_FROM_DATABASE=Silicon Laboratories
OUI:804E70*
ID_OUI_FROM_DATABASE=Samsung Electronics Co.,Ltd
@ -79883,6 +80012,9 @@ OUI:80B709*
OUI:80B95C*
ID_OUI_FROM_DATABASE=ELFTECH Co., Ltd.
OUI:80B97A*
ID_OUI_FROM_DATABASE=eero inc.
OUI:80BAAC*
ID_OUI_FROM_DATABASE=TeleAdapt Ltd
@ -81170,6 +81302,9 @@ OUI:8821E3*
OUI:882364*
ID_OUI_FROM_DATABASE=Watchnet DVR Inc
OUI:88238C*
ID_OUI_FROM_DATABASE=Fiberhome Telecommunication Technologies Co.,LTD
OUI:8823FE*
ID_OUI_FROM_DATABASE=TTTech Computertechnik AG
@ -81338,6 +81473,9 @@ OUI:8857EE*
OUI:885A06*
ID_OUI_FROM_DATABASE=GUANGDONG OPPO MOBILE TELECOMMUNICATIONS CORP.,LTD
OUI:885A85*
ID_OUI_FROM_DATABASE=Wistron Neweb Corporation
OUI:885A92*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@ -82688,12 +82826,51 @@ OUI:8CAAB5*
OUI:8CAB8E*
ID_OUI_FROM_DATABASE=Shanghai Feixun Communication Co.,Ltd.
OUI:8CAE490*
ID_OUI_FROM_DATABASE=Ouman Oy
OUI:8CAE491*
ID_OUI_FROM_DATABASE=H3 Platform
OUI:8CAE492*
ID_OUI_FROM_DATABASE=SEVERIN Elektrogeräte GmbH
OUI:8CAE493*
ID_OUI_FROM_DATABASE=BERTIN TECHNOLOGIES
OUI:8CAE494*
ID_OUI_FROM_DATABASE=Jiangsu Sixingda Information Technology Co., Ltd.
OUI:8CAE495*
ID_OUI_FROM_DATABASE=Gati Information Technolog(Kunshan)Co.,Ltd.
OUI:8CAE496*
ID_OUI_FROM_DATABASE=Chengdu BillDTE Technology Co., Ltd
OUI:8CAE497*
ID_OUI_FROM_DATABASE=Precitec Optronik GmbH
OUI:8CAE498*
ID_OUI_FROM_DATABASE=LLC Taipit - Measuring Equipment
OUI:8CAE499*
ID_OUI_FROM_DATABASE=TTR Corporation
OUI:8CAE49A*
ID_OUI_FROM_DATABASE=Gigawave
OUI:8CAE49B*
ID_OUI_FROM_DATABASE=Suzhou Guowang Electronics Technology Co., Ltd.
OUI:8CAE49C*
ID_OUI_FROM_DATABASE=Parametric GmbH
OUI:8CAE49D*
ID_OUI_FROM_DATABASE=Larch Networks
OUI:8CAE49E*
ID_OUI_FROM_DATABASE=Shenzhen C & D Electronics Co., Ltd.
OUI:8CAE4C*
ID_OUI_FROM_DATABASE=Plugable Technologies
@ -82919,6 +83096,9 @@ OUI:8CF112*
OUI:8CF228*
ID_OUI_FROM_DATABASE=MERCURY COMMUNICATION TECHNOLOGIES CO.,LTD.
OUI:8CF319*
ID_OUI_FROM_DATABASE=Siemens Industrial Automation Products Ltd., Chengdu
OUI:8CF5A3*
ID_OUI_FROM_DATABASE=SAMSUNG ELECTRO-MECHANICS(THAILAND)
@ -84302,6 +84482,9 @@ OUI:948DEF*
OUI:948E89*
ID_OUI_FROM_DATABASE=INDUSTRIAS UNIDAS SA DE CV
OUI:948ED3*
ID_OUI_FROM_DATABASE=Arista Networks
OUI:948FCF*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
@ -85301,6 +85484,9 @@ OUI:988B0A*
OUI:988B5D*
ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
OUI:988B69*
ID_OUI_FROM_DATABASE=Shenzhen hylitech Co.,LTD
OUI:988BAD*
ID_OUI_FROM_DATABASE=Corintech Ltd.
@ -85574,6 +85760,9 @@ OUI:98EC65*
OUI:98ED5C*
ID_OUI_FROM_DATABASE=Tesla,Inc.
OUI:98ED7E*
ID_OUI_FROM_DATABASE=eero inc.
OUI:98EECB*
ID_OUI_FROM_DATABASE=Wistron Infocomm (Zhongshan) Corporation
@ -85763,6 +85952,9 @@ OUI:9C0473*
OUI:9C04EB*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:9C0567*
ID_OUI_FROM_DATABASE=Honor Device Co., Ltd.
OUI:9C061B*
ID_OUI_FROM_DATABASE=Hangzhou H3C Technologies Co., Limited
@ -86891,6 +87083,9 @@ OUI:A03BE3*
OUI:A03C31*
ID_OUI_FROM_DATABASE=Shenzhen Belon Technology CO.,LTD
OUI:A03D6E*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:A03D6F*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@ -88019,6 +88214,27 @@ OUI:A4530E*
OUI:A45385*
ID_OUI_FROM_DATABASE=WEIFANG GOERTEK ELECTRONICS CO.,LTD
OUI:A453EE0*
ID_OUI_FROM_DATABASE=MASBER ELECTRIC SL
OUI:A453EE1*
ID_OUI_FROM_DATABASE=Stellamore
OUI:A453EE2*
ID_OUI_FROM_DATABASE=Ubisafe Smart Devices
OUI:A453EE4*
ID_OUI_FROM_DATABASE=Williamson Corporation
OUI:A453EE9*
ID_OUI_FROM_DATABASE=Dongguan HuaFuu industrial co., LTD
OUI:A453EEC*
ID_OUI_FROM_DATABASE=SOS LAB Co., Ltd.
OUI:A453EED*
ID_OUI_FROM_DATABASE=SSK CORPORATION
OUI:A45602*
ID_OUI_FROM_DATABASE=fenglian Technology Co.,Ltd.
@ -88115,6 +88331,9 @@ OUI:A46706*
OUI:A468BC*
ID_OUI_FROM_DATABASE=Oakley Inc.
OUI:A46BB6*
ID_OUI_FROM_DATABASE=Intel Corporate
OUI:A46C2A*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@ -88826,6 +89045,9 @@ OUI:A83759*
OUI:A83944*
ID_OUI_FROM_DATABASE=Actiontec Electronics, Inc
OUI:A83B5C*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:A83CCB*
ID_OUI_FROM_DATABASE=ROSSMA
@ -89138,6 +89360,9 @@ OUI:A8995C*
OUI:A89969*
ID_OUI_FROM_DATABASE=Dell Inc.
OUI:A899DC*
ID_OUI_FROM_DATABASE=i-TOP DESING TECHNOLOGY CO.,LTD
OUI:A89A93*
ID_OUI_FROM_DATABASE=Sagemcom Broadband SAS
@ -89264,6 +89489,9 @@ OUI:A8CAB9*
OUI:A8CB95*
ID_OUI_FROM_DATABASE=EAST BEST CO., LTD.
OUI:A8CC6F*
ID_OUI_FROM_DATABASE=HMD Global Oy
OUI:A8CCC5*
ID_OUI_FROM_DATABASE=Saab AB (publ)
@ -89363,6 +89591,9 @@ OUI:A8F5AC*
OUI:A8F5DD*
ID_OUI_FROM_DATABASE=ARRIS Group, Inc.
OUI:A8F766*
ID_OUI_FROM_DATABASE=ITE Tech Inc
OUI:A8F7E0*
ID_OUI_FROM_DATABASE=PLANET Technology Corporation
@ -90620,6 +90851,9 @@ OUI:B0793C*
OUI:B07994*
ID_OUI_FROM_DATABASE=Motorola Mobility LLC, a Lenovo Company
OUI:B07B25*
ID_OUI_FROM_DATABASE=Dell Inc.
OUI:B07D47*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
@ -90668,6 +90902,9 @@ OUI:B089C2*
OUI:B08BCF*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:B08BD0*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:B08C75*
ID_OUI_FROM_DATABASE=Apple, Inc.
@ -93623,6 +93860,9 @@ OUI:BCE63F*
OUI:BCE67C*
ID_OUI_FROM_DATABASE=Cambium Networks Limited
OUI:BCE712*
ID_OUI_FROM_DATABASE=Cisco Systems, Inc
OUI:BCE767*
ID_OUI_FROM_DATABASE=Quanzhou TDX Electronics Co., Ltd
@ -94481,6 +94721,9 @@ OUI:C0DF77*
OUI:C0E3A0*
ID_OUI_FROM_DATABASE=Renesas Electronics (Penang) Sdn. Bhd.
OUI:C0E3FB*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:C0E422*
ID_OUI_FROM_DATABASE=Texas Instruments
@ -94526,6 +94769,9 @@ OUI:C0F636*
OUI:C0F6C2*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:C0F6EC*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:C0F79D*
ID_OUI_FROM_DATABASE=Powercode
@ -95990,6 +96236,9 @@ OUI:C8A1BA*
OUI:C8A2CE*
ID_OUI_FROM_DATABASE=Oasis Media Systems LLC
OUI:C8A40D*
ID_OUI_FROM_DATABASE=Cooler Master Technology Inc
OUI:C8A620*
ID_OUI_FROM_DATABASE=Nebula, Inc
@ -96194,6 +96443,9 @@ OUI:C8E130*
OUI:C8E1A7*
ID_OUI_FROM_DATABASE=Vertu Corporation Limited
OUI:C8E265*
ID_OUI_FROM_DATABASE=Intel Corporate
OUI:C8E42F*
ID_OUI_FROM_DATABASE=Technical Research Design and Development
@ -96422,6 +96674,9 @@ OUI:CC1EFF*
OUI:CC1FC4*
ID_OUI_FROM_DATABASE=InVue
OUI:CC208C*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:CC20E8*
ID_OUI_FROM_DATABASE=Apple, Inc.
@ -97352,6 +97607,9 @@ OUI:D00F6D*
OUI:D01242*
ID_OUI_FROM_DATABASE=BIOS Corporation
OUI:D012CB*
ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH
OUI:D0131E*
ID_OUI_FROM_DATABASE=Sunrex Technology Corp
@ -98441,6 +98699,9 @@ OUI:D437D7*
OUI:D4389C*
ID_OUI_FROM_DATABASE=Sony Mobile Communications Inc
OUI:D439B8*
ID_OUI_FROM_DATABASE=Ciena Corporation
OUI:D43A2E*
ID_OUI_FROM_DATABASE=SHENZHEN MTC CO LTD
@ -99140,6 +99401,9 @@ OUI:D4FC13*
OUI:D8004D*
ID_OUI_FROM_DATABASE=Apple, Inc.
OUI:D80093*
ID_OUI_FROM_DATABASE=Aurender Inc.
OUI:D8052E*
ID_OUI_FROM_DATABASE=Skyviia Corporation
@ -99176,6 +99440,9 @@ OUI:D80DE3*
OUI:D80F99*
ID_OUI_FROM_DATABASE=Hon Hai Precision Ind. Co.,Ltd.
OUI:D8109F*
ID_OUI_FROM_DATABASE=HUAWEI TECHNOLOGIES CO.,LTD
OUI:D810CB*
ID_OUI_FROM_DATABASE=Andrea Informatique
@ -100934,6 +101201,9 @@ OUI:E02861*
OUI:E0286D*
ID_OUI_FROM_DATABASE=AVM Audiovisuelles Marketing und Computersysteme GmbH
OUI:E02967*
ID_OUI_FROM_DATABASE=HMD Global Oy
OUI:E02A82*
ID_OUI_FROM_DATABASE=Universal Global Scientific Industrial Co., Ltd.
@ -101765,6 +102035,9 @@ OUI:E42686*
OUI:E4268B*
ID_OUI_FROM_DATABASE=Huawei Device Co., Ltd.
OUI:E42761*
ID_OUI_FROM_DATABASE=Honor Device Co., Ltd.
OUI:E42771*
ID_OUI_FROM_DATABASE=Smartlabs
@ -103247,6 +103520,9 @@ OUI:E8F2E2*
OUI:E8F2E3*
ID_OUI_FROM_DATABASE=Starcor Beijing Co.,Limited
OUI:E8F408*
ID_OUI_FROM_DATABASE=Intel Corporate
OUI:E8F724*
ID_OUI_FROM_DATABASE=Hewlett Packard Enterprise
@ -106835,6 +107111,9 @@ OUI:FC09F6*
OUI:FC0A81*
ID_OUI_FROM_DATABASE=Extreme Networks, Inc.
OUI:FC0C45*
ID_OUI_FROM_DATABASE=Shenzhen SuperElectron Technology Co.,Ltd.
OUI:FC0F4B*
ID_OUI_FROM_DATABASE=Texas Instruments

View File

@ -1,5 +1,5 @@
--- 20-acpi-vendor.hwdb.base 2020-10-13 09:40:27.449819401 +0200
+++ 20-acpi-vendor.hwdb 2020-10-13 09:40:27.464819680 +0200
--- 20-acpi-vendor.hwdb.base 2020-10-23 13:40:57.007717408 +0200
+++ 20-acpi-vendor.hwdb 2020-10-23 13:40:57.014717445 +0200
@@ -3,6 +3,8 @@
# Data imported from:
# https://uefi.org/uefi-pnp-export

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
# SPDX-License-Identifier: LGPL-2.1+
project('systemd', 'c',
version : '246',
version : '247',
license : 'LGPLv2+',
default_options: [
'c_std=gnu99',
@ -13,7 +13,7 @@ project('systemd', 'c',
meson_version : '>= 0.46',
)
libsystemd_version = '0.29.0'
libsystemd_version = '0.30.0'
libudev_version = '1.7.0'
# We need the same data in two different formats, ugh!
@ -3338,6 +3338,7 @@ foreach tuple : tests
type = tuple.length() >= 5 ? tuple[4] : ''
defs = tuple.length() >= 6 ? tuple[5] : []
incs = tuple.length() >= 7 ? tuple[6] : includes
parallel = tuple.length() >= 8 ? tuple[7] : true
timeout = 30
name = sources[0].split('/')[-1].split('.')[0]

View File

@ -117,6 +117,8 @@ static int parse_argv(int argc, char *argv[]) {
static int run(int argc, char *argv[]) {
_cleanup_(notify_on_cleanup) const char *notify_msg = NULL;
_cleanup_(manager_freep) Manager *m = NULL;
_cleanup_free_ char *swap = NULL;
unsigned long long s = 0;
int r;
log_setup_service();
@ -131,8 +133,17 @@ static int run(int argc, char *argv[]) {
/* Do some basic requirement checks for running systemd-oomd. It's not exhaustive as some of the other
* requirements do not have a reliable means to check for in code. */
if (access("/proc/swaps", F_OK) < 0)
return log_error_errno(errno, "Swap not enabled: %m");
/* SwapTotal is always available in /proc/meminfo and defaults to 0, even on swap-disabled kernels. */
r = get_proc_field("/proc/meminfo", "SwapTotal", WHITESPACE, &swap);
if (r < 0)
return log_error_errno(r, "Failed to get SwapTotal from /proc/meminfo: %m");
r = safe_atollu(swap, &s);
if (r < 0)
return log_error_errno(r, "Failed to parse SwapTotal from /proc/meminfo: %s: %m", swap);
if (s == 0)
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Requires swap to operate");
if (!is_pressure_supported())
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Pressure Stall Information (PSI) is not supported");

View File

@ -57,7 +57,7 @@ static void test_oomd_cgroup_kill(void) {
/* If we don't have permissions to set xattrs we're likely in a userns or missing capabilities */
r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup, "user.oomd_test", "test", 4, 0);
if (IN_SET(r, -EPERM, -ENOTSUP))
if (ERRNO_IS_PRIVILEGE(r) || ERRNO_IS_NOT_SUPPORTED(r))
return (void) log_tests_skipped("Cannot set user xattrs");
/* Do this twice to also check the increment behavior on the xattrs */

View File

@ -109,31 +109,6 @@ not_found:
}
#if HAVE_BLKID
/* Detect RPMB and Boot partitions, which are not listed by blkid.
* See https://github.com/systemd/systemd/issues/5806. */
static bool device_is_mmc_special_partition(sd_device *d) {
const char *sysname;
assert(d);
if (sd_device_get_sysname(d, &sysname) < 0)
return false;
return startswith(sysname, "mmcblk") &&
(endswith(sysname, "rpmb") || endswith(sysname, "boot0") || endswith(sysname, "boot1"));
}
static bool device_is_block(sd_device *d) {
const char *ss;
assert(d);
if (sd_device_get_subsystem(d, &ss) < 0)
return false;
return streq(ss, "block");
}
static int enumerator_for_parent(sd_device *d, sd_device_enumerator **ret) {
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
int r;
@ -157,124 +132,217 @@ static int enumerator_for_parent(sd_device *d, sd_device_enumerator **ret) {
return 0;
}
static int wait_for_partitions_to_appear(
int fd,
sd_device *d,
unsigned num_partitions,
DissectImageFlags flags,
sd_device_enumerator **ret_enumerator) {
static int device_is_partition(sd_device *d, blkid_partition pp) {
blkid_loff_t bsize, bstart;
uint64_t size, start;
int partno, bpartno, r;
const char *ss, *v;
assert(d);
assert(pp);
r = sd_device_get_subsystem(d, &ss);
if (r < 0)
return r;
if (!streq(ss, "block"))
return false;
r = sd_device_get_sysattr_value(d, "partition", &v);
if (r == -ENOENT) /* Not a partition device */
return false;
if (r < 0)
return r;
r = safe_atoi(v, &partno);
if (r < 0)
return r;
errno = 0;
bpartno = blkid_partition_get_partno(pp);
if (bpartno < 0)
return errno_or_else(EIO);
if (partno != bpartno)
return false;
r = sd_device_get_sysattr_value(d, "start", &v);
if (r < 0)
return r;
r = safe_atou64(v, &start);
if (r < 0)
return r;
errno = 0;
bstart = blkid_partition_get_start(pp);
if (bstart < 0)
return errno_or_else(EIO);
if (start != (uint64_t) bstart)
return false;
r = sd_device_get_sysattr_value(d, "size", &v);
if (r < 0)
return r;
r = safe_atou64(v, &size);
if (r < 0)
return r;
errno = 0;
bsize = blkid_partition_get_size(pp);
if (bsize < 0)
return errno_or_else(EIO);
if (size != (uint64_t) bsize)
return false;
return true;
}
static int find_partition(
sd_device *parent,
blkid_partition pp,
sd_device **ret) {
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
sd_device *q;
unsigned n;
int r;
assert(fd >= 0);
assert(d);
assert(ret_enumerator);
assert(parent);
assert(pp);
assert(ret);
r = enumerator_for_parent(d, &e);
r = enumerator_for_parent(parent, &e);
if (r < 0)
return r;
/* Count the partitions enumerated by the kernel */
n = 0;
FOREACH_DEVICE(e, q) {
if (sd_device_get_devnum(q, NULL) < 0)
continue;
if (!device_is_block(q))
continue;
if (device_is_mmc_special_partition(q))
continue;
if (!FLAGS_SET(flags, DISSECT_IMAGE_NO_UDEV)) {
r = device_wait_for_initialization(q, "block", USEC_INFINITY, NULL);
r = device_is_partition(q, pp);
if (r < 0)
return r;
if (r > 0) {
*ret = sd_device_ref(q);
return 0;
}
}
n++;
return -ENXIO;
}
if (n == num_partitions + 1) {
*ret_enumerator = TAKE_PTR(e);
return 0; /* success! */
}
if (n > num_partitions + 1)
return log_debug_errno(SYNTHETIC_ERRNO(EIO),
"blkid and kernel partition lists do not match.");
/* The kernel has probed fewer partitions than blkid? Maybe the kernel prober is still running or it
* got EBUSY because udev already opened the device. Let's reprobe the device, which is a synchronous
* call that waits until probing is complete. */
for (unsigned j = 0; ; j++) {
if (j++ > 20)
return -EBUSY;
if (ioctl(fd, BLKRRPART, 0) >= 0)
break;
r = -errno;
if (r == -EINVAL) {
/* If we are running on a block device that has partition scanning off, return an
* explicit recognizable error about this, so that callers can generate a proper
* message explaining the situation. */
r = blockdev_partscan_enabled(fd);
if (r < 0)
return r;
if (r == 0)
return log_debug_errno(SYNTHETIC_ERRNO(EPROTONOSUPPORT),
"Device is a loop device and partition scanning is off!");
return -EINVAL; /* original error */
}
if (r != -EBUSY)
return r;
/* If something else has the device open, such as an udev rule, the ioctl will return
* EBUSY. Since there's no way to wait until it isn't busy anymore, let's just wait a bit,
* and try again.
*
* This is really something they should fix in the kernel! */
(void) usleep(50 * USEC_PER_MSEC);
struct wait_data {
sd_device *parent_device;
blkid_partition blkidp;
sd_device *found;
};
static inline void wait_data_done(struct wait_data *d) {
sd_device_unref(d->found);
}
return -EAGAIN; /* no success yet, try again */
}
static int loop_wait_for_partitions_to_appear(
int fd,
sd_device *d,
unsigned num_partitions,
DissectImageFlags flags,
sd_device_enumerator **ret_enumerator) {
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
static int device_monitor_handler(sd_device_monitor *monitor, sd_device *device, void *userdata) {
const char *parent1_path, *parent2_path;
struct wait_data *w = userdata;
sd_device *pp;
int r;
assert(fd >= 0);
assert(d);
assert(ret_enumerator);
assert(w);
log_debug("Waiting for device (parent + %d partitions) to appear...", num_partitions);
if (device_for_action(device, DEVICE_ACTION_REMOVE))
return 0;
if (!FLAGS_SET(flags, DISSECT_IMAGE_NO_UDEV)) {
r = device_wait_for_initialization(d, "block", USEC_INFINITY, &device);
r = sd_device_get_parent(device, &pp);
if (r < 0)
return 0; /* Doesn't have a parent? No relevant to us */
r = sd_device_get_syspath(pp, &parent1_path); /* Check parent of device of this action */
if (r < 0)
goto finish;
r = sd_device_get_syspath(w->parent_device, &parent2_path); /* Check parent of device we are looking for */
if (r < 0)
goto finish;
if (!path_equal(parent1_path, parent2_path))
return 0; /* Has a different parent than what we need, not interesting to us */
r = device_is_partition(device, w->blkidp);
if (r < 0)
goto finish;
if (r == 0) /* Not the one we need */
return 0;
/* It's the one we need! Yay! */
assert(!w->found);
w->found = sd_device_ref(device);
r = 0;
finish:
return sd_event_exit(sd_device_monitor_get_event(monitor), r);
}
static int wait_for_partition_device(
sd_device *parent,
blkid_partition pp,
usec_t deadline,
sd_device **ret) {
_cleanup_(sd_event_source_unrefp) sd_event_source *timeout_source = NULL;
_cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL;
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
int r;
assert(parent);
assert(pp);
assert(ret);
r = find_partition(parent, pp, ret);
if (r != -ENXIO)
return r;
r = sd_event_new(&event);
if (r < 0)
return r;
} else
device = sd_device_ref(d);
for (unsigned i = 0; i < N_DEVICE_NODE_LIST_ATTEMPTS; i++) {
r = wait_for_partitions_to_appear(fd, device, num_partitions, flags, ret_enumerator);
if (r != -EAGAIN)
r = sd_device_monitor_new(&monitor);
if (r < 0)
return r;
r = sd_device_monitor_filter_add_match_subsystem_devtype(monitor, "block", "partition");
if (r < 0)
return r;
r = sd_device_monitor_attach_event(monitor, event);
if (r < 0)
return r;
_cleanup_(wait_data_done) struct wait_data w = {
.parent_device = parent,
.blkidp = pp,
};
r = sd_device_monitor_start(monitor, device_monitor_handler, &w);
if (r < 0)
return r;
/* Check again, the partition might have appeared in the meantime */
r = find_partition(parent, pp, ret);
if (r != -ENXIO)
return r;
if (deadline != USEC_INFINITY) {
r = sd_event_add_time(
event, &timeout_source,
CLOCK_MONOTONIC, deadline, 0,
NULL, INT_TO_PTR(-ETIMEDOUT));
if (r < 0)
return r;
}
return log_debug_errno(SYNTHETIC_ERRNO(ENXIO),
"Kernel partitions dit not appear within %d attempts",
N_DEVICE_NODE_LIST_ATTEMPTS);
r = sd_event_loop(event);
if (r < 0)
return r;
assert(w.found);
*ret = TAKE_PTR(w.found);
return 0;
}
static void check_partition_flags(
@ -300,8 +368,90 @@ static void check_partition_flags(
}
}
static int device_wait_for_initialization_harder(
sd_device *device,
const char *subsystem,
usec_t deadline,
sd_device **ret) {
_cleanup_free_ char *uevent = NULL;
usec_t start, left, retrigger_timeout;
int r;
start = now(CLOCK_MONOTONIC);
left = usec_sub_unsigned(deadline, start);
if (DEBUG_LOGGING) {
char buf[FORMAT_TIMESPAN_MAX];
const char *sn = NULL;
(void) sd_device_get_sysname(device, &sn);
log_debug("Waiting for device '%s' to initialize for %s.", strna(sn), format_timespan(buf, sizeof(buf), left, 0));
}
if (left != USEC_INFINITY)
retrigger_timeout = CLAMP(left / 4, 1 * USEC_PER_SEC, 5 * USEC_PER_SEC); /* A fourth of the total timeout, but let's clamp to 1s…5s range */
else
retrigger_timeout = 2 * USEC_PER_SEC;
for (;;) {
usec_t local_deadline, n;
bool last_try;
n = now(CLOCK_MONOTONIC);
assert(n >= start);
/* Find next deadline, when we'll retrigger */
local_deadline = start +
DIV_ROUND_UP(n - start, retrigger_timeout) * retrigger_timeout;
if (deadline != USEC_INFINITY && deadline <= local_deadline) {
local_deadline = deadline;
last_try = true;
} else
last_try = false;
r = device_wait_for_initialization(device, subsystem, local_deadline, ret);
if (r >= 0 && DEBUG_LOGGING) {
char buf[FORMAT_TIMESPAN_MAX];
const char *sn = NULL;
(void) sd_device_get_sysname(device, &sn);
log_debug("Successfully waited for device '%s' to initialize for %s.", strna(sn), format_timespan(buf, sizeof(buf), usec_sub_unsigned(now(CLOCK_MONOTONIC), start), 0));
}
if (r != -ETIMEDOUT || last_try)
return r;
if (!uevent) {
const char *syspath;
r = sd_device_get_syspath(device, &syspath);
if (r < 0)
return r;
uevent = path_join(syspath, "uevent");
if (!uevent)
return -ENOMEM;
}
if (DEBUG_LOGGING) {
char buf[FORMAT_TIMESPAN_MAX];
log_debug("Device didn't initialize within %s, assuming lost event. Retriggering device through %s.",
format_timespan(buf, sizeof(buf), usec_sub_unsigned(now(CLOCK_MONOTONIC), start), 0),
uevent);
}
r = write_string_file(uevent, "change", WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
return r;
}
}
#endif
#define DEVICE_TIMEOUT_USEC (45 * USEC_PER_SEC)
int dissect_image(
int fd,
const VeritySettings *verity,
@ -312,7 +462,6 @@ int dissect_image(
#if HAVE_BLKID
sd_id128_t root_uuid = SD_ID128_NULL, root_verity_uuid = SD_ID128_NULL,
usr_uuid = SD_ID128_NULL, usr_verity_uuid = SD_ID128_NULL;
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
bool is_gpt, is_mbr, generic_rw, multiple_generic = false;
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
_cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
@ -321,9 +470,9 @@ int dissect_image(
sd_id128_t generic_uuid = SD_ID128_NULL;
const char *pttype = NULL;
blkid_partlist pl;
int r, generic_nr;
int r, generic_nr, n_partitions;
struct stat st;
sd_device *q;
usec_t deadline;
assert(fd >= 0);
assert(ret);
@ -370,6 +519,27 @@ int dissect_image(
if (!S_ISBLK(st.st_mode))
return -ENOTBLK;
r = sd_device_new_from_devnum(&d, 'b', st.st_rdev);
if (r < 0)
return r;
if (!FLAGS_SET(flags, DISSECT_IMAGE_NO_UDEV)) {
_cleanup_(sd_device_unrefp) sd_device *initialized = NULL;
/* If udev support is enabled, then let's wait for the device to be initialized before we doing anything. */
r = device_wait_for_initialization_harder(
d,
"block",
usec_add(now(CLOCK_MONOTONIC), DEVICE_TIMEOUT_USEC),
&initialized);
if (r < 0)
return r;
sd_device_unref(d);
d = TAKE_PTR(initialized);
}
b = blkid_new_probe();
if (!b)
return -ENOMEM;
@ -399,10 +569,6 @@ int dissect_image(
if (!m)
return -ENOMEM;
r = sd_device_new_from_devnum(&d, 'b', st.st_rdev);
if (r < 0)
return r;
if ((!(flags & DISSECT_IMAGE_GPT_ONLY) &&
(flags & DISSECT_IMAGE_REQUIRE_ROOT)) ||
(flags & DISSECT_IMAGE_NO_PARTITION_TABLE)) {
@ -412,8 +578,8 @@ int dissect_image(
(void) blkid_probe_lookup_value(b, "USAGE", &usage, NULL);
if (STRPTR_IN_SET(usage, "filesystem", "crypto")) {
const char *fstype = NULL, *options = NULL, *devname = NULL;
_cleanup_free_ char *t = NULL, *n = NULL, *o = NULL;
const char *fstype = NULL, *options = NULL;
/* OK, we have found a file system, that's our root partition then. */
(void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
@ -424,10 +590,14 @@ int dissect_image(
return -ENOMEM;
}
r = device_path_make_major_minor(st.st_mode, st.st_rdev, &n);
r = sd_device_get_devname(d, &devname);
if (r < 0)
return r;
n = strdup(devname);
if (!n)
return -ENOMEM;
m->single_file_system = true;
m->verity = verity && verity->root_hash && verity->data_path && (verity->designator < 0 || verity->designator == PARTITION_ROOT);
m->can_verity = verity && verity->data_path;
@ -451,13 +621,7 @@ int dissect_image(
m->encrypted = streq_ptr(fstype, "crypto_LUKS");
/* Even on a single partition we need to wait for udev to create the
* /dev/block/X:Y symlink to /dev/loopZ */
r = loop_wait_for_partitions_to_appear(fd, d, 0, flags, &e);
if (r < 0)
return r;
*ret = TAKE_PTR(m);
return 0;
}
}
@ -472,48 +636,51 @@ int dissect_image(
if (!is_gpt && ((flags & DISSECT_IMAGE_GPT_ONLY) || !is_mbr))
return -ENOPKG;
/* Safety check: refuse block devices that carry a partition table but for which the kernel doesn't
* do partition scanning. */
r = blockdev_partscan_enabled(fd);
if (r < 0)
return r;
if (r == 0)
return -EPROTONOSUPPORT;
errno = 0;
pl = blkid_probe_get_partitions(b);
if (!pl)
return errno_or_else(ENOMEM);
r = loop_wait_for_partitions_to_appear(fd, d, blkid_partlist_numof_partitions(pl), flags, &e);
if (r < 0)
return r;
errno = 0;
n_partitions = blkid_partlist_numof_partitions(pl);
if (n_partitions < 0)
return errno_or_else(EIO);
FOREACH_DEVICE(e, q) {
deadline = usec_add(now(CLOCK_MONOTONIC), DEVICE_TIMEOUT_USEC);
for (int i = 0; i < n_partitions; i++) {
_cleanup_(sd_device_unrefp) sd_device *q = NULL;
unsigned long long pflags;
blkid_partition pp;
const char *node;
dev_t qn;
int nr;
r = sd_device_get_devnum(q, &qn);
errno = 0;
pp = blkid_partlist_get_partition(pl, i);
if (!pp)
return errno_or_else(EIO);
r = wait_for_partition_device(d, pp, deadline, &q);
if (r < 0)
continue;
if (st.st_rdev == qn)
continue;
if (!device_is_block(q))
continue;
if (device_is_mmc_special_partition(q))
continue;
return r;
r = sd_device_get_devname(q, &node);
if (r < 0)
continue;
pp = blkid_partlist_devno_to_partition(pl, qn);
if (!pp)
continue;
return r;
pflags = blkid_partition_get_flags(pp);
errno = 0;
nr = blkid_partition_get_partno(pp);
if (nr < 0)
continue;
return errno_or_else(EIO);
if (is_gpt) {
PartitionDesignator designator = _PARTITION_DESIGNATOR_INVALID;
@ -1643,7 +1810,7 @@ static int verity_partition(
if (r == 0) {
/* devmapper might say that the device exists, but the devlink might not yet have been
* created. Check and wait for the udev event in that case. */
r = device_wait_for_devlink(node, "block", 100 * USEC_PER_MSEC, NULL);
r = device_wait_for_devlink(node, "block", usec_add(now(CLOCK_MONOTONIC), 100 * USEC_PER_MSEC), NULL);
/* Fallback to activation with a unique device if it's taking too long */
if (r == -ETIMEDOUT)
break;

View File

@ -13,17 +13,22 @@
#include <sys/ioctl.h>
#include <unistd.h>
#include "sd-device.h"
#include "alloc-util.h"
#include "blockdev-util.h"
#include "device-util.h"
#include "errno-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "loop-util.h"
#include "missing_loop.h"
#include "parse-util.h"
#include "random-util.h"
#include "stat-util.h"
#include "stdio-util.h"
#include "string-util.h"
#include "tmpfile-util.h"
static void cleanup_clear_loop_close(int *fd) {
if (*fd < 0)
@ -33,26 +38,151 @@ static void cleanup_clear_loop_close(int *fd) {
(void) safe_close(*fd);
}
static int loop_configure(int fd, const struct loop_config *c) {
static int loop_is_bound(int fd) {
struct loop_info64 info;
assert(fd >= 0);
if (ioctl(fd, LOOP_GET_STATUS64, &info) < 0) {
if (errno == ENXIO)
return false; /* not bound! */
return -errno;
}
return true; /* bound! */
}
static int device_has_block_children(sd_device *d) {
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
const char *main_sn, *main_ss;
sd_device *q;
int r;
assert(d);
/* Checks if the specified device currently has block device children (i.e. partition block
* devices). */
r = sd_device_get_sysname(d, &main_sn);
if (r < 0)
return r;
r = sd_device_get_subsystem(d, &main_ss);
if (r < 0)
return r;
if (!streq(main_ss, "block"))
return -EINVAL;
r = sd_device_enumerator_new(&e);
if (r < 0)
return r;
r = sd_device_enumerator_allow_uninitialized(e);
if (r < 0)
return r;
r = sd_device_enumerator_add_match_parent(e, d);
if (r < 0)
return r;
FOREACH_DEVICE(e, q) {
const char *ss, *sn;
r = sd_device_get_subsystem(q, &ss);
if (r < 0)
continue;
if (!streq(ss, "block"))
continue;
r = sd_device_get_sysname(q, &sn);
if (r < 0)
continue;
if (streq(sn, main_sn))
continue;
return 1; /* we have block device children */
}
return 0;
}
static int loop_configure(
int fd,
int nr,
const struct loop_config *c,
bool *try_loop_configure) {
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
_cleanup_free_ char *sysname = NULL;
_cleanup_close_ int lock_fd = -1;
int r;
assert(fd >= 0);
assert(nr >= 0);
assert(c);
assert(try_loop_configure);
if (asprintf(&sysname, "loop%i", nr) < 0)
return -ENOMEM;
r = sd_device_new_from_subsystem_sysname(&d, "block", sysname);
if (r < 0)
return r;
/* Let's lock the device before we do anything. We take the BSD lock on a second, separately opened
* fd for the device. udev after all watches for close() events (specifically IN_CLOSE_WRITE) on
* block devices to reprobe them, hence by having a separate fd we will later close() we can ensure
* we trigger udev after everything is done. If we'd lock our own fd instead and keep it open for a
* long time udev would possibly never run on it again, even though the fd is unlocked, simply
* because we never close() it. It also has the nice benefit we can use the _cleanup_close_ logic to
* automatically release the lock, after we are done. */
lock_fd = fd_reopen(fd, O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
if (lock_fd < 0)
return lock_fd;
if (flock(lock_fd, LOCK_EX) < 0)
return -errno;
/* Let's see if the device is really detached, i.e. currently has no associated partition block
* devices. On various kernels (such as 5.8) it is possible to have a loopback block device that
* superficially is detached but still has partition block devices associated for it. They only go
* away when the device is reattached. (Yes, LOOP_CLR_FD doesn't work then, because officially
* nothing is attached and LOOP_CTL_REMOVE doesn't either, since it doesn't care about partition
* block devices. */
r = device_has_block_children(d);
if (r < 0)
return r;
if (r > 0) {
r = loop_is_bound(fd);
if (r < 0)
return r;
if (r > 0)
return -EBUSY;
return -EUCLEAN; /* Bound but children? Tell caller to reattach something so that the
* partition block devices are gone too. */
}
if (*try_loop_configure) {
if (ioctl(fd, LOOP_CONFIGURE, c) < 0) {
/* Do fallback only if LOOP_CONFIGURE is not supported, propagate all other errors. Note that
* the kernel is weird: non-existing ioctls currently return EINVAL rather than ENOTTY on
* loopback block devices. They should fix that in the kernel, but in the meantime we accept
* both here. */
/* Do fallback only if LOOP_CONFIGURE is not supported, propagate all other
* errors. Note that the kernel is weird: non-existing ioctls currently return EINVAL
* rather than ENOTTY on loopback block devices. They should fix that in the kernel,
* but in the meantime we accept both here. */
if (!ERRNO_IS_NOT_SUPPORTED(errno) && errno != EINVAL)
return -errno;
*try_loop_configure = false;
} else {
bool good = true;
if (c->info.lo_sizelimit != 0) {
/* Kernel 5.8 vanilla doesn't properly propagate the size limit into the block
* device. If it's used, let's immediately check if it had the desired effect
* hence. And if not use classic LOOP_SET_STATUS64. */
/* Kernel 5.8 vanilla doesn't properly propagate the size limit into the
* block device. If it's used, let's immediately check if it had the desired
* effect hence. And if not use classic LOOP_SET_STATUS64. */
uint64_t z;
if (ioctl(fd, BLKGETSIZE64, &z) < 0) {
@ -67,9 +197,9 @@ static int loop_configure(int fd, const struct loop_config *c) {
}
if (FLAGS_SET(c->info.lo_flags, LO_FLAGS_PARTSCAN)) {
/* Kernel 5.8 vanilla doesn't properly propagate the partition scanning flag into the
* block device. Let's hence verify if things work correctly here before
* returning. */
/* Kernel 5.8 vanilla doesn't properly propagate the partition scanning flag
* into the block device. Let's hence verify if things work correctly here
* before returning. */
r = blockdev_partscan_enabled(fd);
if (r < 0)
@ -80,21 +210,51 @@ static int loop_configure(int fd, const struct loop_config *c) {
}
}
if (good)
return 0;
if (!good) {
/* LOOP_CONFIGURE doesn't work. Remember that. */
*try_loop_configure = false;
/* Otherwise, undo the attachment and use the old APIs */
(void) ioctl(fd, LOOP_CLR_FD);
/* We return EBUSY here instead of retrying immediately with LOOP_SET_FD,
* because LOOP_CLR_FD is async: if the operation cannot be executed right
* away it just sets the autoclear flag on the device. This means there's a
* good chance we cannot actually reuse the loopback device right-away. Hence
* let's assume it's busy, avoid the trouble and let the calling loop call us
* again with a new, likely unused device. */
r = -EBUSY;
goto fail;
}
return 0;
}
}
/* Since kernel commit 5db470e229e22b7eda6e23b5566e532c96fb5bc3 (kernel v5.0) the LOOP_SET_STATUS64
* ioctl can return EAGAIN in case we change the lo_offset field, if someone else is accessing the
* block device while we try to reconfigure it. This is a pretty common case, since udev might
* instantly start probing the device as soon as we attach an fd to it. Hence handle it in two ways:
* first, let's take the BSD lock that that ensures that udev will not step in between the point in
* time where we attach the fd and where we reconfigure the device. Secondly, let's wait 50ms on
* EAGAIN and retry. The former should be an efficient mechanism to avoid we have to wait 50ms
* needlessly if we are just racing against udev. The latter is protection against all other cases,
* i.e. peers that do not take the BSD lock. */
if (ioctl(fd, LOOP_SET_FD, c->fd) < 0)
return -errno;
if (ioctl(fd, LOOP_SET_STATUS64, &c->info) < 0) {
r = -errno;
for (unsigned n_attempts = 0;;) {
if (ioctl(fd, LOOP_SET_STATUS64, &c->info) >= 0)
break;
if (errno != EAGAIN || ++n_attempts >= 64) {
r = log_debug_errno(errno, "Failed to configure loopback device: %m");
goto fail;
}
/* Sleep some random time, but at least 10ms, at most 250ms. Increase the delay the more
* failed attempts we see */
(void) usleep(UINT64_C(10) * USEC_PER_MSEC +
random_u64() % (UINT64_C(240) * USEC_PER_MSEC * n_attempts/64));
}
return 0;
fail:
@ -102,6 +262,44 @@ fail:
return r;
}
static int attach_empty_file(int loop, int nr) {
_cleanup_close_ int fd = -1;
/* So here's the thing: on various kernels (5.8 at least) loop block devices might enter a state
* where they are detached but nonetheless have partitions, when used heavily. Accessing these
* partitions results in immediatey IO errors. There's no pretty way to get rid of them
* again. Neither LOOP_CLR_FD nor LOOP_CTL_REMOVE suffice (see above). What does work is to
* reassociate them with a new fd however. This is what we do here hence: we associate the devices
* with an empty file (i.e. an image that definitely has no partitons). We then immediately clear it
* again. This suffices to make the partitions go away. Ugly but appears to work. */
log_debug("Found unattached loopback block device /dev/loop%i with partitions. Attaching empty file to remove them.", nr);
fd = open_tmpfile_unlinkable(NULL, O_RDONLY);
if (fd < 0)
return fd;
if (flock(loop, LOCK_EX) < 0)
return -errno;
if (ioctl(loop, LOOP_SET_FD, fd) < 0)
return -errno;
if (ioctl(loop, LOOP_SET_STATUS64, &(struct loop_info64) {
.lo_flags = LO_FLAGS_READ_ONLY|
LO_FLAGS_AUTOCLEAR|
LO_FLAGS_PARTSCAN, /* enable partscan, so that the partitions really go away */
}) < 0)
return -errno;
if (ioctl(loop, LOOP_CLR_FD) < 0)
return -errno;
/* The caller is expected to immediately close the loopback device after this, so that the BSD lock
* is released, and udev sees the changes. */
return 0;
}
int loop_device_make(
int fd,
int open_flags,
@ -111,6 +309,7 @@ int loop_device_make(
LoopDevice **ret) {
_cleanup_free_ char *loopdev = NULL;
bool try_loop_configure = true;
struct loop_config config;
LoopDevice *d = NULL;
struct stat st;
@ -201,12 +400,17 @@ int loop_device_make(
if (!IN_SET(errno, ENOENT, ENXIO))
return -errno;
} else {
r = loop_configure(loop, &config);
r = loop_configure(loop, nr, &config, &try_loop_configure);
if (r >= 0) {
loop_with_fd = TAKE_FD(loop);
break;
}
if (r != -EBUSY)
if (r == -EUCLEAN) {
/* Make left-over partition disappear hack (see above) */
r = attach_empty_file(loop, nr);
if (r < 0 && r != -EBUSY)
return r;
} else if (r != -EBUSY)
return r;
}
@ -214,6 +418,11 @@ int loop_device_make(
return -EBUSY;
loopdev = mfree(loopdev);
/* Wait some random time, to make collision less likely. Let's pick a random time in the
* range 0ms250ms, linearly scaled by the number of failed attempts. */
(void) usleep(random_u64() % (UINT64_C(10) * USEC_PER_MSEC +
UINT64_C(240) * USEC_PER_MSEC * n_attempts/64));
}
d = new(LoopDevice, 1);

View File

@ -89,10 +89,11 @@ int mount_option_mangle(
int mode_to_inaccessible_node(const char *runtime_dir, mode_t mode, char **dest);
/* Useful for usage with _cleanup_(), unmounts, removes a directory and frees the pointer */
static inline void umount_and_rmdir_and_free(char *p) {
static inline char* umount_and_rmdir_and_free(char *p) {
PROTECT_ERRNO;
(void) umount_recursive(p, 0);
(void) rmdir(p);
free(p);
return NULL;
}
DEFINE_TRIVIAL_CLEANUP_FUNC(char*, umount_and_rmdir_and_free);

View File

@ -195,8 +195,9 @@ static int device_wait_for_initialization_internal(
sd_device *_device,
const char *devlink,
const char *subsystem,
usec_t timeout,
usec_t deadline,
sd_device **ret) {
_cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL;
_cleanup_(sd_event_source_unrefp) sd_event_source *timeout_source = NULL;
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
@ -256,10 +257,10 @@ static int device_wait_for_initialization_internal(
if (r < 0)
return log_error_errno(r, "Failed to start device monitor: %m");
if (timeout != USEC_INFINITY) {
r = sd_event_add_time_relative(
if (deadline != USEC_INFINITY) {
r = sd_event_add_time(
event, &timeout_source,
CLOCK_MONOTONIC, timeout, 0,
CLOCK_MONOTONIC, deadline, 0,
NULL, INT_TO_PTR(-ETIMEDOUT));
if (r < 0)
return log_error_errno(r, "Failed to add timeout event source: %m");
@ -287,12 +288,12 @@ static int device_wait_for_initialization_internal(
return 0;
}
int device_wait_for_initialization(sd_device *device, const char *subsystem, usec_t timeout, sd_device **ret) {
return device_wait_for_initialization_internal(device, NULL, subsystem, timeout, ret);
int device_wait_for_initialization(sd_device *device, const char *subsystem, usec_t deadline, sd_device **ret) {
return device_wait_for_initialization_internal(device, NULL, subsystem, deadline, ret);
}
int device_wait_for_devlink(const char *devlink, const char *subsystem, usec_t timeout, sd_device **ret) {
return device_wait_for_initialization_internal(NULL, devlink, subsystem, timeout, ret);
int device_wait_for_devlink(const char *devlink, const char *subsystem, usec_t deadline, sd_device **ret) {
return device_wait_for_initialization_internal(NULL, devlink, subsystem, deadline, ret);
}
int device_is_renaming(sd_device *dev) {

View File

@ -28,7 +28,7 @@ static inline int udev_parse_config(void) {
return udev_parse_config_full(NULL, NULL, NULL, NULL, NULL);
}
int device_wait_for_initialization(sd_device *device, const char *subsystem, usec_t timeout, sd_device **ret);
int device_wait_for_devlink(const char *path, const char *subsystem, usec_t timeout, sd_device **ret);
int device_wait_for_initialization(sd_device *device, const char *subsystem, usec_t deadline, sd_device **ret);
int device_wait_for_devlink(const char *path, const char *subsystem, usec_t deadline, sd_device **ret);
int device_is_renaming(sd_device *dev);
bool device_for_action(sd_device *dev, DeviceAction action);

View File

@ -433,6 +433,17 @@ tests += [
[],
[]],
[['src/test/test-loop-block.c'],
[libcore,
libshared],
[threads,
libblkid],
'',
'',
[],
includes,
false],
[['src/test/test-selinux.c'],
[],
[]],

250
src/test/test-loop-block.c Normal file
View File

@ -0,0 +1,250 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <fcntl.h>
#include <linux/loop.h>
#include <pthread.h>
#include "alloc-util.h"
#include "dissect-image.h"
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
#include "gpt.h"
#include "missing_loop.h"
#include "mkfs-util.h"
#include "mount-util.h"
#include "namespace-util.h"
#include "string-util.h"
#include "strv.h"
#include "tests.h"
#include "tmpfile-util.h"
#include "user-util.h"
#include "virt.h"
#define N_THREADS 5
#define N_ITERATIONS 3
static usec_t end = 0;
static void* thread_func(void *ptr) {
int fd = PTR_TO_FD(ptr);
int r;
for (unsigned i = 0; i < N_ITERATIONS; i++) {
_cleanup_(loop_device_unrefp) LoopDevice *loop = NULL;
_cleanup_(umount_and_rmdir_and_freep) char *mounted = NULL;
_cleanup_(dissected_image_unrefp) DissectedImage *dissected = NULL;
if (now(CLOCK_MONOTONIC) >= end) {
log_notice("Time's up, exiting thread's loop");
break;
}
log_notice("> Thread iteration #%u.", i);
assert_se(mkdtemp_malloc(NULL, &mounted) >= 0);
r = loop_device_make(fd, O_RDONLY, 0, UINT64_MAX, LO_FLAGS_PARTSCAN, &loop);
if (r < 0)
log_error_errno(r, "Failed to allocate loopback device: %m");
assert_se(r >= 0);
log_notice("Acquired loop device %s, will mount on %s", loop->node, mounted);
r = dissect_image(loop->fd, NULL, NULL, DISSECT_IMAGE_READ_ONLY, &dissected);
if (r < 0)
log_error_errno(r, "Failed dissect loopback device %s: %m", loop->node);
assert_se(r >= 0);
log_info("Dissected loop device %s", loop->node);
for (PartitionDesignator d = 0; d < _PARTITION_DESIGNATOR_MAX; d++) {
if (!dissected->partitions[d].found)
continue;
log_notice("Found node %s fstype %s designator %s",
dissected->partitions[d].node,
dissected->partitions[d].fstype,
partition_designator_to_string(d));
}
assert_se(dissected->partitions[PARTITION_ESP].found);
assert_se(dissected->partitions[PARTITION_ESP].node);
assert_se(dissected->partitions[PARTITION_XBOOTLDR].found);
assert_se(dissected->partitions[PARTITION_XBOOTLDR].node);
assert_se(dissected->partitions[PARTITION_ROOT].found);
assert_se(dissected->partitions[PARTITION_ROOT].node);
assert_se(dissected->partitions[PARTITION_HOME].found);
assert_se(dissected->partitions[PARTITION_HOME].node);
r = dissected_image_mount(dissected, mounted, UID_INVALID, DISSECT_IMAGE_READ_ONLY);
log_notice_errno(r, "Mounted %s → %s: %m", loop->node, mounted);
assert_se(r >= 0);
log_notice("Unmounting %s", mounted);
mounted = umount_and_rmdir_and_free(mounted);
log_notice("Unmounted.");
dissected = dissected_image_unref(dissected);
log_notice("Detaching loop device %s", loop->node);
loop = loop_device_unref(loop);
log_notice("Detached loop device.");
}
log_notice("Leaving thread");
return NULL;
}
static bool have_root_gpt_type(void) {
#ifdef GPT_ROOT_NATIVE
return true;
#else
return false;
#endif
}
int main(int argc, char *argv[]) {
_cleanup_free_ char *p = NULL, *cmd = NULL;
_cleanup_(pclosep) FILE *sfdisk = NULL;
_cleanup_(loop_device_unrefp) LoopDevice *loop = NULL;
_cleanup_close_ int fd = -1;
_cleanup_(dissected_image_unrefp) DissectedImage *dissected = NULL;
_cleanup_(umount_and_rmdir_and_freep) char *mounted = NULL;
pthread_t threads[N_THREADS];
const char *fs;
sd_id128_t id;
int r;
test_setup_logging(LOG_DEBUG);
log_show_tid(true);
log_show_time(true);
if (!have_root_gpt_type()) {
log_tests_skipped("No root partition GPT defined for this architecture, exiting.");
return EXIT_TEST_SKIP;
}
if (detect_container() > 0) {
log_tests_skipped("Test not supported in a container, requires udev/uevent notifications.");
return EXIT_TEST_SKIP;
}
if (strstr_ptr(ci_environment(), "autopkgtest")) {
// FIXME: we should reenable this one day
log_tests_skipped("Skipping test on Ubuntu autopkgtest CI, test too slow and installed udev too flakey.");
return EXIT_TEST_SKIP;
}
/* This is a test for the loopback block device setup code and it's use by the image dissection
* logic: since the kernel APIs are hard use and prone to races, let's test this in a heavy duty
* test: we open a bunch of threads and repeatedly allocate and deallocate loopback block devices in
* them in parallel, with an image file with a number of partitions. */
r = detach_mount_namespace();
if (ERRNO_IS_PRIVILEGE(r)) {
log_tests_skipped("Lacking privileges");
return EXIT_TEST_SKIP;
}
FOREACH_STRING(fs, "vfat", "ext4") {
r = mkfs_exists(fs);
assert_se(r >= 0);
if (!r) {
log_tests_skipped("mkfs.{vfat|ext4} not installed");
return EXIT_TEST_SKIP;
}
}
assert_se(r >= 0);
assert_se(tempfn_random_child("/var/tmp", "sfdisk", &p) >= 0);
fd = open(p, O_CREAT|O_EXCL|O_RDWR|O_CLOEXEC|O_NOFOLLOW, 0666);
assert_se(fd >= 0);
assert_se(ftruncate(fd, 256*1024*1024) >= 0);
assert_se(cmd = strjoin("sfdisk ", p));
assert_se(sfdisk = popen(cmd, "we"));
/* A reasonably complex partition table that fits on a 64K disk */
fputs("label: gpt\n"
"size=32M, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B\n"
"size=32M, type=BC13C2FF-59E6-4262-A352-B275FD6F7172\n"
"size=32M, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F\n"
"size=32M, type=", sfdisk);
#ifdef GPT_ROOT_NATIVE
fprintf(sfdisk, SD_ID128_UUID_FORMAT_STR, SD_ID128_FORMAT_VAL(GPT_ROOT_NATIVE));
#else
fprintf(sfdisk, SD_ID128_UUID_FORMAT_STR, SD_ID128_FORMAT_VAL(GPT_ROOT_X86_64));
#endif
fputs("\n"
"size=32M, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915\n", sfdisk);
assert_se(pclose(sfdisk) == 0);
sfdisk = NULL;
assert_se(loop_device_make(fd, O_RDWR, 0, UINT64_MAX, LO_FLAGS_PARTSCAN, &loop) >= 0);
assert_se(dissect_image(loop->fd, NULL, NULL, 0, &dissected) >= 0);
assert_se(dissected->partitions[PARTITION_ESP].found);
assert_se(dissected->partitions[PARTITION_ESP].node);
assert_se(dissected->partitions[PARTITION_XBOOTLDR].found);
assert_se(dissected->partitions[PARTITION_XBOOTLDR].node);
assert_se(dissected->partitions[PARTITION_ROOT].found);
assert_se(dissected->partitions[PARTITION_ROOT].node);
assert_se(dissected->partitions[PARTITION_HOME].found);
assert_se(dissected->partitions[PARTITION_HOME].node);
assert_se(sd_id128_randomize(&id) >= 0);
assert_se(make_filesystem(dissected->partitions[PARTITION_ESP].node, "vfat", "EFI", id, true) >= 0);
assert_se(sd_id128_randomize(&id) >= 0);
assert_se(make_filesystem(dissected->partitions[PARTITION_XBOOTLDR].node, "vfat", "xbootldr", id, true) >= 0);
assert_se(sd_id128_randomize(&id) >= 0);
assert_se(make_filesystem(dissected->partitions[PARTITION_ROOT].node, "ext4", "root", id, true) >= 0);
assert_se(sd_id128_randomize(&id) >= 0);
assert_se(make_filesystem(dissected->partitions[PARTITION_HOME].node, "ext4", "home", id, true) >= 0);
dissected = dissected_image_unref(dissected);
assert_se(dissect_image(loop->fd, NULL, NULL, 0, &dissected) >= 0);
assert_se(mkdtemp_malloc(NULL, &mounted) >= 0);
/* This first (writable) mount will initialize the mount point dirs, so that the subsequent read-only ones can work */
assert_se(dissected_image_mount(dissected, mounted, UID_INVALID, 0) >= 0);
assert_se(umount_recursive(mounted, 0) >= 0);
loop = loop_device_unref(loop);
log_notice("Threads are being started now");
/* Let's make sure we run for 10s on slow systems at max */
end = usec_add(now(CLOCK_MONOTONIC),
slow_tests_enabled() ? 5 * USEC_PER_SEC :
1 * USEC_PER_SEC);
for (unsigned i = 0; i < N_THREADS; i++)
assert_se(pthread_create(threads + i, NULL, thread_func, FD_TO_PTR(fd)) == 0);
log_notice("All threads started now.");
for (unsigned i = 0; i < N_THREADS; i++) {
log_notice("Joining thread #%u.", i);
void *k;
assert_se(pthread_join(threads[i], &k) == 0);
assert_se(k == NULL);
log_notice("Joined thread #%u.", i);
}
log_notice("Threads are all terminated now.");
return 0;
}

View File

@ -493,7 +493,11 @@ int info_main(int argc, char *argv[], void *userdata) {
if (arg_wait_for_initialization_timeout > 0) {
sd_device *d;
r = device_wait_for_initialization(device, NULL, arg_wait_for_initialization_timeout, &d);
r = device_wait_for_initialization(
device,
NULL,
usec_add(now(CLOCK_MONOTONIC), arg_wait_for_initialization_timeout),
&d);
if (r < 0)
return r;

1
test/TEST-56-OOMD/Makefile Symbolic link
View File

@ -0,0 +1 @@
../TEST-01-BASIC/Makefile

48
test/TEST-56-OOMD/test.sh Executable file
View File

@ -0,0 +1,48 @@
#!/usr/bin/env bash
set -e
TEST_DESCRIPTION="systemd-oomd Memory Pressure Test"
. $TEST_BASE_DIR/test-functions
check_result_nspawn() {
local ret=1
local journald_report=""
local pids=""
[[ -e $1/testok ]] && ret=0
if [[ -e $1/skipped ]]; then
echo "TEST-56-OOMD was skipped:"
cat $1/skipped
ret=0
fi
[[ -f $1/failed ]] && cp -a $1/failed $TESTDIR
save_journal $1/var/log/journal
[[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed
echo $JOURNAL_LIST
test -s $TESTDIR/failed && ret=$(($ret+1))
[ -n "$TIMED_OUT" ] && ret=$(($ret+1))
check_asan_reports "$1" || ret=$(($ret+1))
_umount_dir $initdir
return $ret
}
check_result_qemu() {
local ret=1
mount_initdir
[[ -e $initdir/testok ]] && ret=0
if [[ -e $initdir/skipped ]]; then
echo "TEST-56-OOMD was skipped:"
cat $initdir/skipped
ret=0
fi
[[ -f $initdir/failed ]] && cp -a $initdir/failed $TESTDIR
save_journal $initdir/var/log/journal
check_asan_reports "$initdir" || ret=$(($ret+1))
_umount_dir $initdir
[[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed
echo $JOURNAL_LIST
test -s $TESTDIR/failed && ret=$(($ret+1))
[ -n "$TIMED_OUT" ] && ret=$(($ret+1))
return $ret
}
do_test "$@" 56

View File

@ -65,6 +65,7 @@ BASICTOOLS=(
echo
env
false
getconf
getent
getfacl
grep

View File

@ -0,0 +1,34 @@
#!/usr/bin/env bash
set -eu -o pipefail
PAGE_SIZE=$(getconf PAGE_SIZE)
BLOAT_ITERATION_TARGET=$(( 100 << 20 )) # 100 MB
BLOAT_HOLDER=()
PID="$$"
function bloat {
local set_size=$(cat "/proc/$PID/statm" | cut -d " " -f2)
local mem_usage=$(( "$set_size" * "$PAGE_SIZE" ))
local target_mem_size=$(( "$mem_usage" + "$1" ))
BLOAT_HOLDER=()
while [[ "$mem_usage" -lt "$target_mem_size" ]]; do
echo "target $target_mem_size"
echo "mem usage $mem_usage"
BLOAT_HOLDER+=( $(printf "%0.sg" {1..1000000}) )
set_size=$(cat "/proc/$PID/statm" | cut -d " " -f2)
mem_usage=$(( "$set_size" * "$PAGE_SIZE" ))
done
}
function run {
local arr=()
while [[ true ]]; do
bloat "$BLOAT_ITERATION_TARGET"
arr+=( "$BLOAT_HOLDER" )
sleep 1
done
}
run

View File

@ -0,0 +1,7 @@
[Unit]
Description=TESTSUITE-56-OOMD
[Service]
ExecStartPre=rm -f /failed /skipped /testok
ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh
Type=oneshot

70
test/units/testsuite-56.sh Executable file
View File

@ -0,0 +1,70 @@
#!/usr/bin/env bash
set -ex
set -o pipefail
systemd-analyze log-level debug
systemd-analyze log-target console
# Loose checks to ensure the environment has the necessary features for systemd-oomd
[[ "$( awk '/SwapTotal/ { print $2 }' /proc/meminfo )" != "0" ]] || echo "no swap" >> /skipped
[[ -e /proc/pressure ]] || echo "no PSI" >> /skipped
cgroup_type=$(stat -fc %T /sys/fs/cgroup/)
if [[ "$cgroup_type" != *"cgroup2"* ]] && [[ "$cgroup_type" != *"0x63677270"* ]]; then
echo "no cgroup2" >> /skipped
fi
[[ -e /skipped ]] && exit 0 || true
cat > /etc/systemd/system/testworkload.slice <<EOF
[Slice]
CPUAccounting=true
MemoryAccounting=true
IOAccounting=true
TasksAccounting=true
ManagedOOMMemoryPressure=kill
ManagedOOMMemoryPressureLimitPercent=50%
EOF
# Create a lot of memory pressure by setting memory.high to a very small value
cat > /etc/systemd/system/testbloat.service <<EOF
[Service]
MemoryHigh=2M
Slice=testworkload.slice
ExecStart=/usr/lib/systemd/tests/testdata/units/testsuite-56-slowgrowth.sh
EOF
# This generates no memory pressure
cat > /etc/systemd/system/testchill.service <<EOF
[Service]
MemoryHigh=2M
Slice=testworkload.slice
ExecStart=sleep infinity
EOF
systemctl daemon-reload
systemctl start testbloat.service
systemctl start testchill.service
# Verify systemd-oomd is monitoring the expected units
oomctl | grep "/testworkload.slice"
oomctl | grep "50%"
# systemd-oomd watches for elevated pressure for 30 seconds before acting.
# It can take time to build up pressure so either wait 5 minutes or for the service to fail.
timeout=$(date -ud "5 minutes" +%s)
while [[ $(date -u +%s) -le $timeout ]]; do
if ! systemctl status testbloat.service; then
break
fi
sleep 15
done
# testbloat should be killed and testchill should be fine
if systemctl status testbloat.service; then exit 42; fi
if ! systemctl status testchill.service; then exit 24; fi
systemd-analyze log-level info
echo OK > /testok
exit 0