Fix PartitionTable sector representation and used space for LVM partition

This commit is contained in:
Chantara Tith 2016-06-19 02:54:52 +07:00
parent 0f3c4b0a8c
commit 542db88336
5 changed files with 110 additions and 51 deletions

View File

@ -27,10 +27,12 @@
#include <QRegularExpression> #include <QRegularExpression>
#include <QStringList> #include <QStringList>
#include <KMountPoint> #include <KMountPoint>
#include <KDiskFreeSpaceInfo>
/** Constructs a representation of LVM device with functionning LV as Partition /** Constructs a representation of LVM device with functionning LV as Partition
@param name Volume Group name *
*/ * @param name Volume Group name
*/
LvmDevice::LvmDevice(const QString& name, const QString& iconname) LvmDevice::LvmDevice(const QString& name, const QString& iconname)
: VolumeManagerDevice(name, : VolumeManagerDevice(name,
(QStringLiteral("/dev/") + name), (QStringLiteral("/dev/") + name),
@ -56,77 +58,90 @@ void LvmDevice::initPartitions()
foreach (Partition* p, scanPartitions(*this, pTable)) { foreach (Partition* p, scanPartitions(*this, pTable)) {
pTable->append(p); pTable->append(p);
} }
setPartitionTable(pTable); setPartitionTable(pTable);
} }
/** /**
return sorted Partition(LV) Array * @returns sorted Partition(LV) Array
*/ */
QList<Partition*> LvmDevice::scanPartitions(const Device& dev, PartitionTable* pTable) const QList<Partition*> LvmDevice::scanPartitions(const Device& dev, PartitionTable* pTable) const
{ {
QList<Partition*> pList; QList<Partition*> pList;
QList<QString> lvNodeList; foreach (QString lvPath, lvPathList()) {
pList.append(scanPartition(lvPath, dev, pTable));
lvNodeList = getField(QStringLiteral("lv_path"), dev.name()).split(QStringLiteral("\n"));
foreach (QString lvNode, lvNodeList) {
pList.append(scanPartition(lvNode.trimmed(), dev, pTable));
} }
return pList; return pList;
} }
/** /**
return sorted Partition(LV) Array * @returns sorted Partition(LV) Array
*/ */
Partition* LvmDevice::scanPartition(const QString& lvPath, const Device& dev, PartitionTable* pTable) const Partition* LvmDevice::scanPartition(const QString& lvpath, const Device& dev, PartitionTable* pTable) const
{ {
/*
* NOTE:
* LVM partition have 2 different start and end sector value
* 1. representing the actual LV start from 0 -> size of LV - 1
* 2. representing abstract LV's sector inside a VG partitionTable
* start from size of last Partitions -> size of LV - 1
* Reason for this is for the LV Partition to worrks nicely with other parts of the codebase
* without too many special cases.
*/
qint64 startSector; qint64 startSector;
qint64 endSector; qint64 endSector;
qint64 lvSize;
bool mounted = isMounted(lvpath);
QString mountPoint = QString(); QString mountPoint = QString();
bool mounted = isMounted(lvPath);
KMountPoint::List mountPointList = KMountPoint::currentMountPoints(KMountPoint::NeedRealDeviceName); KMountPoint::List mountPointList = KMountPoint::currentMountPoints(KMountPoint::NeedRealDeviceName);
mountPointList.append(KMountPoint::possibleMountPoints(KMountPoint::NeedRealDeviceName)); mountPointList.append(KMountPoint::possibleMountPoints(KMountPoint::NeedRealDeviceName));
mountPoint = mountPointList.findByDevice(lvPath) ? mountPoint = mountPointList.findByDevice(lvpath) ?
mountPointList.findByDevice(lvPath)->mountPoint() : mountPointList.findByDevice(lvpath)->mountPoint() :
QString(); QString();
ExternalCommand cmd(QStringLiteral("lvm"), lvSize = getTotalLE(lvpath);
{ QStringLiteral("lvdisplay"), startSector = mappedSector(lvpath,0);
QStringLiteral("--units"), endSector = startSector + (lvSize - 1);
QStringLiteral("B"),
QStringLiteral("--maps"),
lvPath});
if (cmd.run(-1) && cmd.exitCode() == 0) { const KDiskFreeSpaceInfo freeSpaceInfo = KDiskFreeSpaceInfo::freeSpaceInfo(mountPoint);
//TODO: regex for first and last sector of the LV FileSystem* fs = FileSystemFactory::create(FileSystem::detectFileSystem(lvpath), 0, lvSize - 1);
//TODO: stringing PE into one large contingiuous array of PE ?? if (mounted && freeSpaceInfo.isValid() && mountPoint != QString()) {
QRegularExpression re(QStringLiteral("Physical extents\\h+(\\d+)\\sto\\s(\\d+)")); //TODO: fix used space report. currently incorrect
QRegularExpressionMatch match = re.match(cmd.output()); fs->setSectorsUsed(freeSpaceInfo.used() / logicalSize());
if (match.hasMatch()) {
startSector = match.captured(1).toLongLong();
endSector = match.captured(2).toLongLong();
}
} }
FileSystem* fs = FileSystemFactory::create(FileSystem::detectFileSystem(lvPath), startSector, endSector);
Partition* part = new Partition(pTable, Partition* part = new Partition(pTable,
dev, dev,
PartitionRole(PartitionRole::Lvm_Lv), PartitionRole(PartitionRole::Lvm_Lv),
fs, fs,
startSector, startSector,
endSector, endSector,
lvPath, lvpath,
PartitionTable::Flag::FlagLvm, PartitionTable::Flag::FlagLvm,
mountPoint, mountPoint,
mounted); mounted);
return part; return part;
} }
qint64 LvmDevice::mappedSector(const QString& lvpath, qint64 sector) const
{
qint64 mSector = 0;
QList<QString> lvpathList = lvPathList();
qint32 devIndex = lvpathList.indexOf(lvpath);
if (devIndex) {
for (int i = 0; i < devIndex; i++) {
//TODO: currently going over the same LV again and again is wasteful. Could use some more optimization
mSector += getTotalLE(lvpathList[i]);
}
mSector += sector;
}
return mSector;
}
QList<QString> LvmDevice::deviceNodeList() const QList<QString> LvmDevice::deviceNodeList() const
{ {
QList<QString> devPathList; QList<QString> devPathList;
@ -138,10 +153,23 @@ QList<QString> LvmDevice::deviceNodeList() const
devPathList.append(devPath.trimmed()); devPathList.append(devPath.trimmed());
} }
} }
return devPathList; return devPathList;
} }
QList<QString> LvmDevice::lvPathList() const
{
QList<QString> lvPathList;
QString cmdOutput = getField(QStringLiteral("lv_path"), name());
if (cmdOutput.size()) {
QList<QString> tempPathList = cmdOutput.split(QStringLiteral("\n"), QString::SkipEmptyParts);
foreach(QString lvPath, tempPathList) {
lvPathList.append(lvPath.trimmed());
}
}
return lvPathList;
}
qint32 LvmDevice::getPeSize(const QString& vgname) qint32 LvmDevice::getPeSize(const QString& vgname)
{ {
QString val = getField(QStringLiteral("vg_extent_size"), vgname); QString val = getField(QStringLiteral("vg_extent_size"), vgname);
@ -171,6 +199,7 @@ QString LvmDevice::getUUID(const QString& vgname)
return val.isEmpty() ? QStringLiteral("---") : val; return val.isEmpty() ? QStringLiteral("---") : val;
} }
/** Query LVM details with field name /** Query LVM details with field name
* *
* @param fieldName lvm field name * @param fieldName lvm field name
@ -196,3 +225,19 @@ QString LvmDevice::getField(const QString& fieldName, const QString& vgname)
} }
return QString(); return QString();
} }
qint32 LvmDevice::getTotalLE(const QString& lvpath)
{
ExternalCommand cmd(QStringLiteral("lvm"),
{ QStringLiteral("lvdisplay"),
lvpath});
if (cmd.run(-1) && cmd.exitCode() == 0) {
QRegularExpression re(QStringLiteral("Current LE\\h+(\\d+)"));
QRegularExpressionMatch match = re.match(cmd.output());
if (match.hasMatch()) {
return match.captured(1).toInt();
}
}
return -1;
}

View File

@ -51,16 +51,21 @@ public:
QList<Partition*> scanPartitions(const Device& dev, PartitionTable* pTable) const; QList<Partition*> scanPartitions(const Device& dev, PartitionTable* pTable) const;
Partition* scanPartition(const QString& lvPath, const Device& dev, PartitionTable* pTable) const; Partition* scanPartition(const QString& lvPath, const Device& dev, PartitionTable* pTable) const;
static qint32 getPeSize(const QString& name); static qint32 getPeSize(const QString& vgname);
static qint32 getTotalPE(const QString& name); static qint32 getTotalPE(const QString& vgname);
static qint32 getAllocatedPE(const QString& name); static qint32 getAllocatedPE(const QString& vgname);
static qint32 getFreePE(const QString& name); static qint32 getFreePE(const QString& vgname);
static QString getUUID(const QString& name); static QString getUUID(const QString& vgname);
static QString getField(const QString& fieldName, const QString& vgname = QString()); static QString getField(const QString& fieldName, const QString& vgname = QString());
static qint32 getTotalLE(const QString& lvpath);
protected: protected:
void initPartitions(); void initPartitions();
QList<QString> deviceNodeList() const override; QList<QString> deviceNodeList() const override;
qint64 mappedSector(const QString& lvpath, qint64 sector) const override;
QList<QString> lvPathList() const;
public: public:
qint32 peSize() const { qint32 peSize() const {
@ -85,6 +90,7 @@ private:
qint32 m_allocPE; qint32 m_allocPE;
qint32 m_freePE; qint32 m_freePE;
QString m_UUID; QString m_UUID;
}; };
#endif #endif

View File

@ -266,6 +266,7 @@ bool PartitionTable::getUnallocatedRange(const Device& d, PartitionNode& parent,
return end - start + 1 >= PartitionAlignment::sectorAlignment(device); return end - start + 1 >= PartitionAlignment::sectorAlignment(device);
} else if (d.type() == Device::LVM_Device) { } else if (d.type() == Device::LVM_Device) {
return false; return false;
//TODO: return range from last LE to last allocated LE
} }
return false; return false;
} }
@ -378,8 +379,12 @@ void PartitionTable::updateUnallocated(const Device& d)
qint64 PartitionTable::defaultFirstUsable(const Device& d, TableType t) qint64 PartitionTable::defaultFirstUsable(const Device& d, TableType t)
{ {
Q_UNUSED(t) Q_UNUSED(t)
const DiskDevice& diskDevice = dynamic_cast<const DiskDevice&>(d); if (d.type() == Device::LVM_Device) {
return PartitionAlignment::sectorAlignment(diskDevice); return 0;
} else {
const DiskDevice& diskDevice = dynamic_cast<const DiskDevice&>(d);
return PartitionAlignment::sectorAlignment(diskDevice);
}
} }
qint64 PartitionTable::defaultLastUsable(const Device& d, TableType t) qint64 PartitionTable::defaultLastUsable(const Device& d, TableType t)

View File

@ -1,6 +1,5 @@
/************************************************************************* /*************************************************************************
* Copyright (C) 2008 by Volker Lanz <vl@fidra.de> * * Copyright (C) 2016 by Chantara Tith <tith.chantara@gmail.com> *
* Copyright (C) 2016 by Andrius Štikonas <andrius@stikonas.eu> *
* * * *
* This program is free software; you can redistribute it and/or * * This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as * * modify it under the terms of the GNU General Public License as *
@ -43,6 +42,7 @@ QString VolumeManagerDevice::prettyDeviceNodeList() const
} }
if (rval.size()) { if (rval.size()) {
//chop off the trailing colon
rval.chop(1); rval.chop(1);
} }
return rval; return rval;

View File

@ -1,4 +1,6 @@
/************************************************************************* /*************************************************************************
* Copyright (C) 2016 by Chantara Tith <tith.chantara@gmail.com> *
* *
* This program is free software; you can redistribute it and/or * * This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as * * modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 3 of * * published by the Free Software Foundation; either version 3 of *
@ -30,14 +32,13 @@ class CoreBackend;
class SmartStatus; class SmartStatus;
class Partition; class Partition;
/** A device. /** A abstract device represeting real physical devices.
Represents a device like /dev/sda. Represents a device like /dev/sda, /dev/sdb1.
Devices are the outermost entity; they contain a PartitionTable that itself contains Partitions. Devices are the outermost entity; they contain a PartitionTable that itself contains Partitions.
@see PartitionTable, Partition @see PartitionTable, Partition
@author Volker Lanz <vl@fidra.de>
*/ */
class LIBKPMCORE_EXPORT VolumeManagerDevice : public Device class LIBKPMCORE_EXPORT VolumeManagerDevice : public Device
{ {
@ -46,13 +47,15 @@ class LIBKPMCORE_EXPORT VolumeManagerDevice : public Device
protected: protected:
VolumeManagerDevice(const QString& name, const QString& devicenode, const qint32 logicalSize, const qint64 totalLogical, const QString& iconname = QString(), Device::Type type = Device::Unknown_Device); VolumeManagerDevice(const QString& name, const QString& devicenode, const qint32 logicalSize, const qint64 totalLogical, const QString& iconname = QString(), Device::Type type = Device::Unknown_Device);
virtual QList<QString> deviceNodeList() const = 0; /** Return list of physical device or partitions that makes up volumeManagerDevice */ virtual QList<QString> deviceNodeList() const = 0; /** Return list of physical device or partitions that makes up volumeManagerDevice */
virtual qint64 mappedSector(const QString& devNode, qint64 sector) const = 0;
public: public:
//virtual void refresh() const = 0; /* VG infos can be changed, unlike disk_device */ /** string deviceNodeList together into comma-sperated list */
//virtual Qlist<Partition*> listDevices() const = 0;
virtual QString prettyDeviceNodeList() const; virtual QString prettyDeviceNodeList() const;
/** Mapper return absolute sector representing the VG */
private: private:
//QMap<QString, qint32> deviceSizeMapper;
}; };
#endif #endif