This seems okay to me. We should be able to handle this better in the device tree, but this approach will do for now. Dave On Wed, 2010-12-22 at 11:22 +0100, Ales Kozumplik wrote: > This change necessitates from two previous commits: > 1) 6e6d3df9a78730996e6ac7d463e3b50dbc164b4c, resulting in > DeviceTree.populate() being called twice now, for the second time at the > end of autopart. > > 2) 5c83bbf01800ca86d1c8e4cd95d14480165b344c, which causes already > coalesced mpath devices (disks and partitions) never to be torn down > during anaconda run. > > Given that, we don't want to let identifyMultipath give > DeviceTree.populate() existing mpath devices (dm-0, dm-1, > etc.). populate() would try to add those before the slave mpath members > (sda, sdb) and although the addUdevDevice() logic will eventually > recursively request sda and sdb while working on dm-0, the udev info we > get for sda in sdb at that point is obtained thorugh a call to > udev_get_block_device() which will not give us a correctly filled in > ID_FS_TYPE (unlike the enriched info dictionaries that idenitfyMultipath() > gives us). > > Alternative solution would be to embed a layer between DeviceTree and > udev.py. This layer would remember the additional database values that are > not returned by udev itself but rather discovered by us, such as the > "multipath_member" value of ID_FS_TYPE. > > For the partitions part, the patch only does what identifyMultipath()'s > documentation promises: "3) removes the individual members of an mpath's > partitions". This step is optional and to make the function better > defined: note that e.g. sda3 will be scanned later in populate() anyway as > it will naturally still appear in udev_get_block_devices(). > > Resolves: rhbz#636570 > --- > storage/devicelibs/mpath.py | 70 +++++++++++++++++++++++++++--------------- > storage/devicetree.py | 13 ++++---- > storage/udev.py | 8 +++++ > 3 files changed, 59 insertions(+), 32 deletions(-) > > diff --git a/storage/devicelibs/mpath.py b/storage/devicelibs/mpath.py > index 0d0efde..113c544 100644 > --- a/storage/devicelibs/mpath.py > +++ b/storage/devicelibs/mpath.py > @@ -7,6 +7,31 @@ import logging > > log = logging.getLogger("storage") > > +def _filter_out_mpath_devices(devices): > + retval = [] > + for d in devices: > + if udev_device_is_multipath(d): > + log.debug("filtering out coalesced mpath device: %s" % d['name']) > + else: > + retval.append(d) > + return retval > + > +def _filter_out_mpath_partitions(devices, multipaths): > + """ > + Use serial numbers of the multipath members to filter devices from the > + devices list. The returned list will only partitions that are NOT partitions > + of the multipath members. > + """ > + serials = set(udev_device_get_serial(d) > + for mpath_members in multipaths for d in mpath_members) > + retval = [] > + for d in devices: > + if udev_device_get_serial(d) in serials: > + log.debug("filtering out mpath partition: %s" % d['name']) > + else: > + retval.append(d) > + return retval > + > def parseMultipathOutput(output): > """ > Parse output from "multipath -d" or "multipath -ll" and form a topology. > @@ -84,14 +109,22 @@ def parseMultipathOutput(output): > return mpaths > > def identifyMultipaths(devices): > - # this function does a couple of things > - # 1) identifies multipath disks > - # 2) sets their ID_FS_TYPE to multipath_member > - # 3) removes the individual members of an mpath's partitions > - # sample input with multipath pair [sdb,sdc] > - # [sr0, sda, sda1, sdb, sdb1, sdb2, sdc, sdc1, sdd, sdd1, sdd2] > - # sample output: > - # [sda, sdd], [[sdb, sdc]], [sr0, sda1, sdd1, sdd2]] > + """ > + This function does a couple of things: > + 1) identifies multipath disks, > + 2) sets their ID_FS_TYPE to multipath_member, > + 3) removes the individual members of an mpath's partitions as well as any > + coalesced multipath devices: > + > + sample input: > + [sr0, sda, sda1, sdb, sdb1, sdb2, sdc, sdc1, sdd, sdd1, sdd2, dm-0] > + where: > + [sdb, sdc] is a multipath pair > + dm-0 is a mutliapth device already coalesced from [sdb, sdc] > + > + sample output: > + [sda, sdd], [[sdb, sdc]], [sr0, sda1, sdd1, sdd2]] > + """ > log.info("devices to scan for multipath: %s" % [d['name'] for d in devices]) > > with open("/etc/multipath.conf") as conf: > @@ -165,23 +198,10 @@ def identifyMultipaths(devices): > > multipaths.append([devmap[d] for d in disks]) > > - non_disk_serials = {} > - for name,device in non_disk_devices.items(): > - serial = udev_device_get_serial(device) > - non_disk_serials.setdefault(serial, []) > - non_disk_serials[serial].append(device) > - > - for mpath in multipaths: > - for serial in [d.get('ID_SERIAL_SHORT') for d in mpath]: > - if non_disk_serials.has_key(serial): > - log.info("filtering out non disk devices [%s]" % [d['name'] for d in non_disk_serials[serial]]) > - for name in [d['name'] for d in non_disk_serials[serial]]: > - if non_disk_devices.has_key(name): > - del non_disk_devices[name] > - > - partition_devices = [] > - for device in non_disk_devices.values(): > - partition_devices.append(device) > + # singlepaths and partitions should not contain multipath devices: > + singlepath_disks = _filter_out_mpath_devices(singlepath_disks) > + partition_devices = _filter_out_mpath_partitions( > + non_disk_devices.values(), multipaths) > > # this is the list of devices we want to keep from the original > # device list, but we want to maintain its original order. > diff --git a/storage/devicetree.py b/storage/devicetree.py > index 45fc455..f45e656 100644 > --- a/storage/devicetree.py > +++ b/storage/devicetree.py > @@ -2026,19 +2026,18 @@ class DeviceTree(object): > % (livetarget,)) > self.protectedDevNames.append(livetarget) > > - # First iteration - let's just look for disks. > - old_devices = {} > - > - devices = udev_get_block_devices() > - for dev in devices: > - old_devices[dev['name']] = dev > - > cfg = self.__multipathConfigWriter.write() > open("/etc/multipath.conf", "w+").write(cfg) > del cfg > > + devices = udev_get_block_devices() > (singles, mpaths, partitions) = devicelibs.mpath.identifyMultipaths(devices) > devices = singles + reduce(list.__add__, mpaths, []) + partitions > + # remember all the devices idenitfyMultipaths() gave us at this point > + old_devices = {} > + for dev in devices: > + old_devices[dev['name']] = dev > + > log.info("devices to scan: %s" % [d['name'] for d in devices]) > for dev in devices: > self.addUdevDevice(dev) > diff --git a/storage/udev.py b/storage/udev.py > index 59b7519..7ba5a9c 100644 > --- a/storage/udev.py > +++ b/storage/udev.py > @@ -472,6 +472,14 @@ def udev_device_is_dmraid_partition(info, devicetree): > > return False > > +def udev_device_is_multipath(info): > + """ Return True if the device is a multipath device or a partition of one.""" > + if not udev_device_is_dm(info): > + return False > + if udev_device_get_name(info).startswith("mpath"): > + return True > + return False > + > def udev_device_is_multipath_partition(info, devicetree): > """ Return True if the device is a partition of a multipath device. """ > if not udev_device_is_dm(info): _______________________________________________ Anaconda-devel-list mailing list Anaconda-devel-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/anaconda-devel-list