From a4d3f334c0139740bc8bf89f88f74043109dacb1 Mon Sep 17 00:00:00 2001 From: David Lehman Date: Wed, 6 Feb 2013 12:04:00 -0600 Subject: [PATCH 02/13] Account for active mounts in normal mode. (#914898) Also adds support for representing the system's nodev filesystem mounts. The include_nodev flag must be set to True prior to calling Blivet.getActiveMounts, which is called from within Blivet.reset (if flags.installer_mode is False). There can be multiple mounts of any given nodev filesystem type, which presents a problem in terms of looking up devices by name. The chosen solution is to add a unique identifier to each NoDevice instance's name. --- blivet/__init__.py | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++- blivet/devices.py | 5 +++-- blivet/devicetree.py | 2 ++ blivet/flags.py | 4 ++++ blivet/formats/fs.py | 30 +++++++++++++++++++++------- 5 files changed, 86 insertions(+), 10 deletions(-) diff --git a/blivet/__init__.py b/blivet/__init__.py index 7958eb1..6456311 100644 --- a/blivet/__init__.py +++ b/blivet/__init__.py @@ -55,6 +55,7 @@ from deviceaction import * from formats import getFormat from formats import get_device_format_class from formats import get_default_filesystem_type +from formats.fs import nodev_filesystems import devicefactory from devicelibs.dm import name_from_dm_node from devicelibs.crypto import generateBackupPassphrase @@ -406,6 +407,9 @@ class Blivet(object): if flags.installer_mode: self.roots = findExistingInstallations(self.devicetree) + if not flags.installer_mode: + self.getActiveMounts() + self.dumpState("initial") self.updateBootLoaderDiskList() @@ -1870,6 +1874,56 @@ class Blivet(object): return new + def getActiveMounts(self): + """ Reflect active mounts in the appropriate devices' formats. """ + log.info("collecting information about active mounts") + for _line in open("/proc/mounts").readlines(): + (line, pound, comment) = _line.partition("#") + try: + (devspec, mountpoint, fstype, options, rest) = line.split(None, 4) + except IndexError: + blivet_log.error("failed to parse /proc/mounts line: %s" % _line) + continue + + if fstype == "btrfs": + # get the subvol name from /proc/self/mountinfo + for line in open("/proc/self/mountinfo").readlines(): + fields = line.split() + _subvol = fields[3] + _mountpoint = fields[4] + _devspec = fields[9] + if _mountpoint == mountpoint and _devspec == devspec: + log.debug("subvol %s" % _subvol) + options += ",subvol=%s" % _subvol[1:] + + if fstype in nodev_filesystems: + if not flags.include_nodev: + continue + + log.info("found nodev %s filesystem mounted at %s" + % (fstype, mountpoint)) + # nodev filesystems require some special handling. + # For now, a lot of this is based on the idea that it's a losing + # battle to require the presence of an FS class for every type + # of nodev filesystem. Based on that idea, we just instantiate + # NoDevFS directly and then hack in the fstype as the device + # attribute. + fmt = getFormat("nodev") + fmt.device = fstype + + # NoDevice also needs some special works since they don't have + # per-instance names in the kernel. + device = NoDevice(format=fmt) + n = len([d for d in self.devices if d.format.type == fstype]) + device._name += ".%d" % n + self.devicetree._addDevice(device) + devspec = device.name + + device = self.devicetree.resolveDevice(devspec, options=options) + if device is not None: + device.format.mountpoint = mountpoint # for future mounts + device.format._mountpoint = mountpoint # active mountpoint + def mountExistingSystem(fsset, rootDevice, allowDirty=None, dirtyCB=None, @@ -2656,7 +2710,6 @@ class FSSet(object): return fstab - def getReleaseString(): relName = None relVer = None diff --git a/blivet/devices.py b/blivet/devices.py index 791084a..19885bf 100644 --- a/blivet/devices.py +++ b/blivet/devices.py @@ -3415,7 +3415,7 @@ class NoDevice(StorageDevice): format -- a DeviceFormat instance """ if format: - name = format.type + name = format.device else: name = "none" @@ -3424,7 +3424,8 @@ class NoDevice(StorageDevice): @property def path(self): """ Device node representing this device. """ - return self.name + # the name may have a '.%d' suffix to make it unique + return self.name.split(".")[0] def setup(self, orig=False): """ Open, or set up, a device. """ diff --git a/blivet/devicetree.py b/blivet/devicetree.py index 88ba130..026dda6 100644 --- a/blivet/devicetree.py +++ b/blivet/devicetree.py @@ -2142,6 +2142,8 @@ class DeviceTree(object): if edd_number == spec: device = self.getDeviceByName(edd_name) break + elif options and "nodev" in options.split(","): + device = self.getDeviceByName(devspec) else: if not devspec.startswith("/dev/"): device = self.getDeviceByName(devspec) diff --git a/blivet/flags.py b/blivet/flags.py index ed0e5dc..e892b74 100644 --- a/blivet/flags.py +++ b/blivet/flags.py @@ -54,6 +54,10 @@ class Flags(object): self.gpt = False + # whether to include nodev filesystems in the devicetree (only + # meaningful when flags.installer_mode is False) + self.include_nodev = False + self.boot_cmdline = {} self.update_from_boot_cmdline() diff --git a/blivet/formats/fs.py b/blivet/formats/fs.py index de94ff4..840adb3 100644 --- a/blivet/formats/fs.py +++ b/blivet/formats/fs.py @@ -57,14 +57,19 @@ mib = 1024 * 1024.0 fs_configs = {} -def get_kernel_filesystems(): - fs_list = [] +kernel_filesystems = [] +nodev_filesystems = [] + +def update_kernel_filesystems(): + global kernel_filesystems + global nodev_filesystems for line in open("/proc/filesystems").readlines(): - fs_list.append(line.split()[-1]) - return fs_list + fields = line.split() + kernel_filesystems.append(fields[-1]) + if fields[0] == "nodev": + nodev_filesystems.append(fields[-1]) -global kernel_filesystems -kernel_filesystems = get_kernel_filesystems() +update_kernel_filesystems() def fsConfigFromFile(config_file): """ Generate a set of attribute name/value pairs with which a @@ -485,7 +490,7 @@ class FS(DeviceFormat): # If we successfully loaded a kernel module, for this filesystem, we # also need to update the list of supported filesystems. - kernel_filesystems = get_kernel_filesystems() + update_kernel_filesystems() def testMount(self, options=None): """ Try to mount the fs and return True if successful. """ @@ -1370,6 +1375,17 @@ class NoDevFS(FS): def _setDevice(self, devspec): self._device = devspec + @property + def type(self): + if self.device != self._type: + return self.device + else: + return self._type + + @property + def mountType(self): + return self.device # this is probably set to the real/specific fstype + def _getExistingSize(self): pass -- 1.8.1