Nir Soffer has uploaded a new change for review.
Change subject: mount: Improve loop devices resolving
......................................................................
mount: Improve loop devices resolving
_resolveLoopDevice() used O(n^2) search for resolving loop device
backing file. For every block device in /proc/mounts, it read and parsed
all lines of /etc/mtab, even all platforms where /etc/mtab contains not
additional info.
This patch changes the search so /etc/mtab is read and parsed once only
on platforms where it is different from /proc/mounts. On these
platforms, we can get the loop device backing file from /etc/mtab. On
platforms where /etc/mtab is a symlink to /proc/self/mounts, we get the
backing file from /sys/block/loop*/loop/backing_file.
The new code assumes that loop devices are named /dev/loop*, which
simplifes the code for resolving the backing file.
Change-Id: I40c0bd772327248e6fe08189dada043ea1c6c080
Relates-to:
https://bugzilla.redhat.com/1099856
Signed-off-by: Nir Soffer <nsoffer(a)redhat.com>
---
M vdsm/storage/mount.py
1 file changed, 35 insertions(+), 53 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/90/28090/1
diff --git a/vdsm/storage/mount.py b/vdsm/storage/mount.py
index 1671bf8..cc633bf 100644
--- a/vdsm/storage/mount.py
+++ b/vdsm/storage/mount.py
@@ -22,7 +22,6 @@
from os.path import normpath
import re
import os
-import stat
from vdsm import constants
import misc
@@ -32,6 +31,11 @@
VFS_NFS = "nfs"
VFS_NFS4 = "nfs4"
VFS_EXT3 = "ext3"
+
+# Mounts sources
+
+PROC_MOUNTS = '/proc/mounts'
+ETC_MTAB = '/etc/mtab'
MountRecord = namedtuple("MountRecord", "fs_spec fs_file fs_vfstype
"
"fs_mntops fs_freq fs_passno")
@@ -61,12 +65,6 @@
fs_freq, fs_passno)
-def _iterateMtab():
- with open("/etc/mtab", "r") as f:
- for line in f:
- yield _parseFstabLine(line)
-
-
def _parseFstabPath(path):
return _RE_ESCAPE.sub(lambda s: chr(int(s.group()[1:], 8)), path)
@@ -75,58 +73,42 @@
pass
-def _resolveLoopDevice(path):
- """
- Loop devices appear as the loop device under /proc/mount instead of the
- backing file. As the mount command does the resolution so must we.
- """
- if not path.startswith("/"):
- return path
-
- try:
- st = os.stat(path)
- except:
- return path
-
- if not stat.S_ISBLK(st.st_mode):
- return path
-
- minor = os.minor(st.st_rdev)
- major = os.major(st.st_rdev)
- loopdir = "/sys/dev/block/%d:%d/loop" % (major, minor)
- if os.path.exists(loopdir):
- with open(loopdir + "/backing_file", "r") as f:
- # Remove trailing newline
- return f.read()[:-1]
-
- # Old kernels might not have the sysfs entry, this is a bit slower and does
- # not work on hosts that do support the above method.
- for rec in _iterateMtab():
- loopOpt = "loop=%s" % path
- for opt in rec.fs_mntops:
- if opt != loopOpt:
- continue
-
- return rec.fs_spec
-
- return path
+def _readLoopDeviceBackingFile(device):
+ device_name = device[len('/dev/'):]
+ path = '/sys/block/%s/loop/backing_file' % device_name
+ with open(path) as f:
+ return f.readline().rstrip()
-def _iterKnownMounts():
- with open("/proc/mounts", "r") as f:
+def _readMountRecords(path):
+ records = {}
+ with open(path) as f:
for line in f:
- yield _parseFstabLine(line)
+ rec = _parseFstabLine(line)
+ records[rec.fs_file] = rec
+ return records
def _iterMountRecords():
- for rec in _iterKnownMounts():
- realSpec = _resolveLoopDevice(rec.fs_spec)
- if rec.fs_spec == realSpec:
- yield rec
- continue
-
- yield MountRecord(realSpec, rec.fs_file, rec.fs_vfstype,
- rec.fs_mntops, rec.fs_freq, rec.fs_passno)
+ mounts = _readMountRecords(PROC_MOUNTS)
+ if not os.path.samefile(ETC_MTAB, PROC_MOUNTS):
+ mtab = _readMountRecords(ETC_MTAB)
+ else:
+ mtab = None
+ for mountpoint, rec in mounts.iteritems():
+ if rec.fs_spec.startswith('/dev/loop'):
+ if mtab:
+ fs_spec = mtab[mountpoint].fs_spec
+ else:
+ try:
+ fs_spec = _readLoopDeviceBackingFile(rec.fs_spec)
+ except IOError as e:
+ if e.errno != errno.ENOENT:
+ raise
+ fs_spec = rec.fs_spec
+ yield MountRecord(fs_spec, rec.fs_file, rec.fs_vfstype,
+ rec.fs_mntops, rec.fs_freq, rec.fs_passno)
+ yield rec
def iterMounts():
--
To view, visit
http://gerrit.ovirt.org/28090
To unsubscribe, visit
http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I40c0bd772327248e6fe08189dada043ea1c6c080
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Nir Soffer <nsoffer(a)redhat.com>