QStorageInfo/Linux: fix getting information on unmounted btrfs subvols
Amends 1cd6c6c69e9813c791f8bebb6c0c9214ce765060. Btrfs can have subvolumes and each one of them is assigned a device ID when the filesystem is loaded into the kernel. But subvolumes don't all have to be a mountpoint of their own: if we insist on matching device IDs, as initRootPath() was doing, we'd fail at finding the mount point. Fixes: QTBUG-121140 Change-Id: I76ffba14ece04f24b43efffd17ab39f503000dd7 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Ahmad Samir <a.samirh78@gmail.com> (cherry picked from commit 987abb92538f8657d861611b1ced4e7eaa660adf) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
90a723b7cd
commit
f3782300d2
@ -10,6 +10,8 @@
|
|||||||
#include <private/qcore_unix_p.h>
|
#include <private/qcore_unix_p.h>
|
||||||
#include <private/qtools_p.h>
|
#include <private/qtools_p.h>
|
||||||
|
|
||||||
|
#include <q20memory.h>
|
||||||
|
|
||||||
#include <linux/mount.h>
|
#include <linux/mount.h>
|
||||||
#include <sys/statfs.h>
|
#include <sys/statfs.h>
|
||||||
|
|
||||||
@ -199,15 +201,31 @@ quint64 QStorageInfoPrivate::initRootPath()
|
|||||||
// # mount | tail -2
|
// # mount | tail -2
|
||||||
// tmpfs on /tmp/foo/bar type tmpfs (rw,relatime,inode64)
|
// tmpfs on /tmp/foo/bar type tmpfs (rw,relatime,inode64)
|
||||||
// tmpfs on /tmp/foo type tmpfs (rw,relatime,inode64)
|
// tmpfs on /tmp/foo type tmpfs (rw,relatime,inode64)
|
||||||
// But just in case there's a mount --move, we ensure the device ID does
|
//
|
||||||
// match.
|
// We try to match the device ID in case there's a mount --move.
|
||||||
|
// We can't *rely* on it because some filesystems like btrfs will assign
|
||||||
|
// device IDs to subvolumes that aren't listed in /proc/self/mountinfo.
|
||||||
|
|
||||||
const QString oldRootPath = std::exchange(rootPath, QString());
|
const QString oldRootPath = std::exchange(rootPath, QString());
|
||||||
const dev_t rootPathDevId = deviceIdForPath(oldRootPath);
|
const dev_t rootPathDevId = deviceIdForPath(oldRootPath);
|
||||||
|
MountInfo *best = nullptr;
|
||||||
for (auto it = infos.rbegin(); it != infos.rend(); ++it) {
|
for (auto it = infos.rbegin(); it != infos.rend(); ++it) {
|
||||||
if (rootPathDevId != it->stDev || !isParentOf(it->mountPoint, oldRootPath))
|
if (!isParentOf(it->mountPoint, oldRootPath))
|
||||||
continue;
|
continue;
|
||||||
auto stDev = it->stDev;
|
if (rootPathDevId == it->stDev) {
|
||||||
setFromMountInfo(std::move(*it));
|
// device ID matches; this is definitely the best option
|
||||||
|
best = q20::to_address(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!best) {
|
||||||
|
// if we can't find a device ID match, this parent path is probably
|
||||||
|
// the correct one
|
||||||
|
best = q20::to_address(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (best) {
|
||||||
|
auto stDev = best->stDev;
|
||||||
|
setFromMountInfo(std::move(*best));
|
||||||
return stDev;
|
return stDev;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user