From c82ed8b2795cbf6d82dfe3857fec7c16688137a4 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 22 Sep 2023 13:36:12 -0700 Subject: [PATCH] QStorageInfo/Linux: avoid parsing /proc/self/mountinfo N+1 times Mine has 41 lines, of which 22 are returned by parseMountInfo with filtering. That meant the file was parsed once to get the listing, then 22 times more to create a QStorageInfo for each entry. Now QStorageInfo::mountedVolumes() opens the file and parses it only once. Pick-to: 6.6 Change-Id: I9d43e5b91eb142d6945cfffd178752ef6c2122f2 Reviewed-by: Edward Welbourne Reviewed-by: Ahmad Samir --- src/corelib/io/qstorageinfo.cpp | 5 ++++ src/corelib/io/qstorageinfo.h | 1 + src/corelib/io/qstorageinfo_linux.cpp | 8 +++--- src/corelib/io/qstorageinfo_linux_p.h | 11 +------- src/corelib/io/qstorageinfo_p.h | 37 +++++++++++++++++++-------- 5 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/corelib/io/qstorageinfo.cpp b/src/corelib/io/qstorageinfo.cpp index 2a12c2cd85..4f206bc907 100644 --- a/src/corelib/io/qstorageinfo.cpp +++ b/src/corelib/io/qstorageinfo.cpp @@ -37,6 +37,11 @@ QT_IMPL_METATYPE_EXTERN(QStorageInfo) \snippet code/src_corelib_io_qstorageinfo.cpp 2 */ +QStorageInfo::QStorageInfo(QStorageInfoPrivate &dd) + : d(&dd) +{ +} + /*! Constructs an empty QStorageInfo object. diff --git a/src/corelib/io/qstorageinfo.h b/src/corelib/io/qstorageinfo.h index d25eee1840..45869519bc 100644 --- a/src/corelib/io/qstorageinfo.h +++ b/src/corelib/io/qstorageinfo.h @@ -56,6 +56,7 @@ public: static QStorageInfo root(); private: + explicit QStorageInfo(QStorageInfoPrivate &dd); friend class QStorageInfoPrivate; friend inline bool operator==(const QStorageInfo &first, const QStorageInfo &second) { diff --git a/src/corelib/io/qstorageinfo_linux.cpp b/src/corelib/io/qstorageinfo_linux.cpp index 0bf6b9e238..8b53629e25 100644 --- a/src/corelib/io/qstorageinfo_linux.cpp +++ b/src/corelib/io/qstorageinfo_linux.cpp @@ -164,12 +164,12 @@ QList QStorageInfoPrivate::mountedVolumes() QList volumes; for (MountInfo &info : infos) { - QStorageInfo storage(info.mountPoint); - storage.d->device = info.device; - storage.d->fileSystemType = info.fsType; - storage.d->subvolume = info.fsRoot; + QStorageInfoPrivate d(std::move(info)); + d.retrieveVolumeInfo(); + QStorageInfo storage(*new QStorageInfoPrivate(std::move(d))); if (storage.bytesTotal() == 0 && storage != root()) continue; + storage.d->name = retrieveLabel(storage.d->device); volumes.push_back(storage); } return volumes; diff --git a/src/corelib/io/qstorageinfo_linux_p.h b/src/corelib/io/qstorageinfo_linux_p.h index 1033d78f73..1a59ee910f 100644 --- a/src/corelib/io/qstorageinfo_linux_p.h +++ b/src/corelib/io/qstorageinfo_linux_p.h @@ -29,6 +29,7 @@ QT_BEGIN_NAMESPACE using namespace Qt::StringLiterals; +using MountInfo = QStorageInfoPrivate::MountInfo; static const char MountInfoPath[] = "/proc/self/mountinfo"; @@ -152,16 +153,6 @@ static void tokenizeLine(std::array &fields, QByteAr } } -namespace { -struct MountInfo { - QString mountPoint; - QByteArray fsType; - QByteArray device; - QByteArray fsRoot; - dev_t stDev = 0; -}; -} - // parseMountInfo() is called from: // - QStorageInfoPrivate::initRootPath(), where a list of all mounted volumes is needed // - QStorageInfoPrivate::mountedVolumes(), where some filesystem types are ignored diff --git a/src/corelib/io/qstorageinfo_p.h b/src/corelib/io/qstorageinfo_p.h index ae4ff02f0b..92bcdaac3d 100644 --- a/src/corelib/io/qstorageinfo_p.h +++ b/src/corelib/io/qstorageinfo_p.h @@ -28,10 +28,7 @@ inline Q_LOGGING_CATEGORY(lcStorageInfo, "qt.core.qstorageinfo", QtWarningMsg) class QStorageInfoPrivate : public QSharedData { public: - inline QStorageInfoPrivate() : QSharedData(), - bytesTotal(-1), bytesFree(-1), bytesAvailable(-1), blockSize(-1), - readOnly(false), ready(false), valid(false) - {} + QStorageInfoPrivate() = default; void initRootPath(); void doStat(); @@ -59,6 +56,24 @@ protected: void retrieveLabel(); #elif defined(Q_OS_UNIX) void retrieveVolumeInfo(); + +# ifdef Q_OS_LINUX +public: + struct MountInfo { + QString mountPoint; + QByteArray fsType; + QByteArray device; + QByteArray fsRoot; + dev_t stDev = 0; + }; + QStorageInfoPrivate(MountInfo &&info) + : rootPath(std::move(info.mountPoint)), + device(std::move(info.device)), + subvolume(std::move(info.fsRoot)), + fileSystemType(std::move(info.fsType)) + { + } +# endif #endif public: @@ -68,14 +83,14 @@ public: QByteArray fileSystemType; QString name; - qint64 bytesTotal; - qint64 bytesFree; - qint64 bytesAvailable; - ulong blockSize; + qint64 bytesTotal = -1; + qint64 bytesFree = -1; + qint64 bytesAvailable = -1; + ulong blockSize = ulong(-1); - bool readOnly; - bool ready; - bool valid; + bool readOnly = false; + bool ready = false; + bool valid = false; }; // Common helper functions