From 4107e4d8ca835b8d7d632589f12effea76b19d96 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 22 Sep 2023 14:02:03 -0700 Subject: [PATCH] QStorageInfo/Linux: avoid parsing /dev/disks/by-label for every entry Instead, create a (flat) map of the entries that we can seek on while creating the list of mountedVolumes(). On my machine, that went down from 14 times to 1. Pick-to: 6.6 Change-Id: I9d43e5b91eb142d6945cfffd17875458541f28f9 Reviewed-by: Ahmad Samir --- src/corelib/io/qstorageinfo_linux.cpp | 44 ++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/src/corelib/io/qstorageinfo_linux.cpp b/src/corelib/io/qstorageinfo_linux.cpp index d0102f28849..15bcd978fe8 100644 --- a/src/corelib/io/qstorageinfo_linux.cpp +++ b/src/corelib/io/qstorageinfo_linux.cpp @@ -91,16 +91,41 @@ static inline quint64 retrieveDeviceId(const QByteArray &device, quint64 deviceI return st.st_rdev; } -static inline QString retrieveLabel(const QByteArray &device, quint64 deviceId) +static QDirIterator devicesByLabel() { static const char pathDiskByLabel[] = "/dev/disk/by-label"; + static constexpr auto LabelFileFilter = + QDir::AllEntries | QDir::System | QDir::Hidden | QDir::NoDotAndDotDot; + return QDirIterator(QLatin1StringView(pathDiskByLabel), LabelFileFilter); +} + +static inline auto retrieveLabels() +{ + struct Entry { + QString label; + quint64 deviceId; + }; + QList result; + + QDirIterator it = devicesByLabel(); + while (it.hasNext()) { + QFileInfo fileInfo = it.nextFileInfo(); + quint64 deviceId = retrieveDeviceId(QFile::encodeName(fileInfo.filePath())); + if (!deviceId) + continue; + result.emplaceBack(Entry{ decodeFsEncString(fileInfo.fileName()), deviceId }); + } + return result; +} + +static inline QString retrieveLabel(const QByteArray &device, quint64 deviceId) +{ deviceId = retrieveDeviceId(device, deviceId); if (!deviceId) return QString(); - auto filter = QDir::AllEntries | QDir::System | QDir::Hidden | QDir::NoDotAndDotDot; - QDirIterator it(QLatin1StringView(pathDiskByLabel), filter); + QDirIterator it = devicesByLabel(); while (it.hasNext()) { QFileInfo fileInfo = it.nextFileInfo(); QString name = fileInfo.fileName(); @@ -206,6 +231,17 @@ QList QStorageInfoPrivate::mountedVolumes() if (infos.empty()) return QList{root()}; + auto labelForDevice = [labelMap = retrieveLabels()](const QByteArray &device, quint64 devid) { + devid = retrieveDeviceId(device, devid); + if (!devid) + return QString(); + for (auto &[deviceLabel, deviceId] : labelMap) { + if (devid == deviceId) + return deviceLabel; + } + return QString(); + }; + QList volumes; for (MountInfo &info : infos) { QStorageInfoPrivate d(std::move(info)); @@ -214,7 +250,7 @@ QList QStorageInfoPrivate::mountedVolumes() continue; if (info.stDev != deviceIdForPath(d.rootPath)) continue; // probably something mounted over this mountpoint - d.name = retrieveLabel(d.device, info.stDev); + d.name = labelForDevice(d.device, info.stDev); volumes.emplace_back(QStorageInfo(*new QStorageInfoPrivate(std::move(d)))); } return volumes;