]> git-server-git.apps.pok.os.sepia.ceph.com Git - xfsprogs-dev.git/commitdiff
xfs_scrub_all: fix deadlock if lsblk produces a lot of output
authorDarrick J. Wong <djwong@kernel.org>
Thu, 30 Apr 2026 15:54:06 +0000 (08:54 -0700)
committerAndrey Albershteyn <aalbersh@kernel.org>
Wed, 6 May 2026 09:24:04 +0000 (11:24 +0200)
Patrick Fischer reported a deadlock in find_mounts() that is the result
of lsblk producing so much output that it fills the pipe buffer.  When
this happens, lsblk blocks on write()ing the pipe, at which point
waiting for lsblk to exit will also block forever.

Now that we can be reasonably assured that everyone has Python 3.5
(because RHEL6 is long dead), we can replace this whole mess with a call
to subprocess.run that captures the output.  The json library can
convert a byte array directly to a python dict, which means we don't
need to concatenate iterated lines or any of that stuff anymore.

Reported-by: patrick.fischer@siedl.net
Link: https://lore.kernel.org/linux-xfs/323580211.1220195.1777554001363.JavaMail.zimbra@siedl.net/
Cc: <linux-xfs@vger.kernel.org> # v4.15.0
Fixes: f1dca11cad1308 ("xfs_scrub: create a script to scrub all xfs filesystems")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Andrey Albershteyn <aalbersh@kernel.org>
scrub/xfs_scrub_all.py.in

index 9f861639a43ce480f80cb7c701309b9559d0bc45..dbb6c36e467d3f0343f7ad88ba9d0cab7ab15e95 100644 (file)
@@ -53,15 +53,16 @@ def find_mounts():
 
        fs = {}
        cmd=['lsblk', '-o', 'NAME,KNAME,TYPE,FSTYPE,MOUNTPOINT', '-J']
-       result = subprocess.Popen(cmd, stdout=subprocess.PIPE)
-       result.wait()
-       if result.returncode != 0:
+       try:
+               proc = subprocess.run(cmd, capture_output = True, text = True, check = True)
+       except Exception as e:
+               print(e)
+               return fs
+       if proc.returncode != 0:
                return fs
-       sarray = [x.decode(sys.stdout.encoding) for x in result.stdout.readlines()]
-       output = ' '.join(sarray)
-       bdevdata = json.loads(output)
 
        # The lsblk output had better be in disks-then-partitions order
+       bdevdata = json.loads(proc.stdout)
        for bdev in bdevdata['blockdevices']:
                lastdisk = bdev['kname']
                find_xfs_mounts(bdev, fs, lastdisk)