]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_scrub_all: walk the lsblk device/fs hierarchy correctly
authorDarrick J. Wong <darrick.wong@oracle.com>
Thu, 28 Mar 2019 23:05:01 +0000 (18:05 -0500)
committerEric Sandeen <sandeen@redhat.com>
Thu, 28 Mar 2019 23:05:01 +0000 (18:05 -0500)
Back when I was designing xfs_scrub_all, I naïvely assumed that the
emitted output would always list physical storage before the virtual
devices stacked atop it.  However, this is not actually true when one
omits the "NAME" column, which is crucial to forcing the output (json or
otherwise) to capture the block device hierarchy.  If the assumption is
violated, the program crashes with a python exception.

To fix this, force the hierarchal json output and restructure the
discovery routines to walk the json object that we receive, from the top
(physical devices) downwards to wherever there are live xfs filesystems.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
scrub/xfs_scrub_all.in

index c4e9899d42c62590d771105a343b259ac40c1cee..5b76b49adab84d9828682677288ae61fd58c0858 100644 (file)
@@ -28,9 +28,21 @@ def DEVNULL():
 
 def find_mounts():
        '''Map mountpoints to physical disks.'''
+       def find_xfs_mounts(bdev, fs, lastdisk):
+               '''Attach lastdisk to each fs found under bdev.'''
+               if bdev['fstype'] == 'xfs' and bdev['mountpoint'] is not None:
+                       mnt = bdev['mountpoint']
+                       if mnt in fs:
+                               fs[mnt].add(lastdisk)
+                       else:
+                               fs[mnt] = set([lastdisk])
+               if 'children' not in bdev:
+                       return
+               for child in bdev['children']:
+                       find_xfs_mounts(child, fs, lastdisk)
 
        fs = {}
-       cmd=['lsblk', '-o', 'KNAME,TYPE,FSTYPE,MOUNTPOINT', '-J']
+       cmd=['lsblk', '-o', 'NAME,KNAME,TYPE,FSTYPE,MOUNTPOINT', '-J']
        result = subprocess.Popen(cmd, stdout=subprocess.PIPE)
        result.wait()
        if result.returncode != 0:
@@ -38,18 +50,12 @@ def find_mounts():
        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
        for bdev in bdevdata['blockdevices']:
-               if bdev['type'] in ('disk', 'loop'):
-                       lastdisk = bdev['kname']
-               if bdev['fstype'] == 'xfs':
-                       mnt = bdev['mountpoint']
-                       if mnt is None:
-                               continue
-                       if mnt in fs:
-                               fs[mnt].add(lastdisk)
-                       else:
-                               fs[mnt] = set([lastdisk])
+               lastdisk = bdev['kname']
+               find_xfs_mounts(bdev, fs, lastdisk)
+
        return fs
 
 def kill_systemd(unit, proc):