[PATCH 02/13] Account for active mounts in normal mode. (#914898)

David Lehman dlehman at redhat.com
Fri Mar 1 22:13:20 UTC 2013


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



More information about the anaconda-patches mailing list