From f2c74b0be37004788215efa9465164182d737caf Mon Sep 17 00:00:00 2001 From: Markus Hilger Date: Mon, 27 Jul 2026 06:52:37 +0200 Subject: [PATCH] Fingerprint installation media off the event loop scan_iso walks an entire ISO with blocking libarchive reads, yielding only once per entry, and the header-sum branch of fingerprint reads the whole file with no yield at all. Both run in the daemon, reached from MediaImporter.init on every fingerprint and importing request. The scan costs about 8us per entry and is indifferent to media size, since libarchive seeks past file data rather than reading it: measured at 80ms for 10k entries whether the image is 0.2 GB or 8.8 GB, and at 310ms for 40k. The header-sum branch is the one that scales with size, reading a multi-gigabyte image end to end. Make the pair plain functions and hand them to a thread instead. --- confluent_server/confluent/osimage.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/confluent_server/confluent/osimage.py b/confluent_server/confluent/osimage.py index 33062708..fda01d82 100644 --- a/confluent_server/confluent/osimage.py +++ b/confluent_server/confluent/osimage.py @@ -834,7 +834,7 @@ def fingerprint_initramfs(archive): return None -async def scan_iso(archive): +def scan_iso(archive): scanudf = False filesizes = {} filecontents = {} @@ -845,7 +845,6 @@ async def scan_iso(archive): for ent in reader: if str(ent).endswith('TRANS.TBL'): continue - await asyncio.sleep(0) filesizes[str(ent)] = ent.size if str(ent) == 'README.TXT': readmecontents = b'' @@ -909,13 +908,13 @@ def parse_bfb(archive): archive.seek(currsize, os.SEEK_CUR) return None -async def fingerprint(archive): +def fingerprint(archive): archive.seek(0) header = archive.read(32768) archive.seek(32769) if archive.read(6) == b'CD001\x01': # ISO image - isoinfo = await scan_iso(archive) + isoinfo = scan_iso(archive) name = None for fun in globals(): if fun.startswith('check_'): @@ -947,7 +946,7 @@ async def import_image(filename, callback, backend=False, mfd=None, custtargpath archive = os.fdopen(int(mfd), 'rb') else: archive = open(filename, 'rb') - identity = await fingerprint(archive) + identity = await asyncio.to_thread(fingerprint, archive) if not identity: return -1 identity, imginfo, funname = identity @@ -1207,7 +1206,7 @@ class MediaImporter(object): else: medfile = open(media, 'rb') try: - identity = await fingerprint(medfile) + identity = await asyncio.to_thread(fingerprint, medfile) finally: if not self.medfile: medfile.close()