LVM support #6
|
@ -27,10 +27,12 @@
|
|||
#include <QRegularExpression>
|
||||
#include <QStringList>
|
||||
#include <KMountPoint>
|
||||
#include <KDiskFreeSpaceInfo>
|
||||
|
||||
/** 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)
|
||||
: VolumeManagerDevice(name,
|
||||
(QStringLiteral("/dev/") + name),
|
||||
|
@ -56,77 +58,90 @@ void LvmDevice::initPartitions()
|
|||
foreach (Partition* p, scanPartitions(*this, pTable)) {
|
||||
pTable->append(p);
|
||||
}
|
||||
|
||||
setPartitionTable(pTable);
|
||||
}
|
||||
|
||||
/**
|
||||
return sorted Partition(LV) Array
|
||||
*/
|
||||
* @returns sorted Partition(LV) Array
|
||||
*/
|
||||
QList<Partition*> LvmDevice::scanPartitions(const Device& dev, PartitionTable* pTable) const
|
||||
{
|
||||
QList<Partition*> pList;
|
||||
QList<QString> lvNodeList;
|
||||
|
||||
lvNodeList = getField(QStringLiteral("lv_path"), dev.name()).split(QStringLiteral("\n"));
|
||||
|
||||
foreach (QString lvNode, lvNodeList) {
|
||||
pList.append(scanPartition(lvNode.trimmed(), dev, pTable));
|
||||
foreach (QString lvPath, lvPathList()) {
|
||||
pList.append(scanPartition(lvPath, dev, pTable));
|
||||
}
|
||||
|
||||
return pList;
|
||||
}
|
||||
|
||||
/**
|
||||
return sorted Partition(LV) Array
|
||||
*/
|
||||
Partition* LvmDevice::scanPartition(const QString& lvPath, const Device& dev, PartitionTable* pTable) const
|
||||
* @returns sorted Partition(LV) Array
|
||||
*/
|
||||
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 endSector;
|
||||
qint64 lvSize;
|
||||
|
||||
bool mounted = isMounted(lvpath);
|
||||
QString mountPoint = QString();
|
||||
bool mounted = isMounted(lvPath);
|
||||
|
||||
KMountPoint::List mountPointList = KMountPoint::currentMountPoints(KMountPoint::NeedRealDeviceName);
|
||||
mountPointList.append(KMountPoint::possibleMountPoints(KMountPoint::NeedRealDeviceName));
|
||||
mountPoint = mountPointList.findByDevice(lvPath) ?
|
||||
mountPointList.findByDevice(lvPath)->mountPoint() :
|
||||
mountPoint = mountPointList.findByDevice(lvpath) ?
|
||||
mountPointList.findByDevice(lvpath)->mountPoint() :
|
||||
QString();
|
||||
|
||||
ExternalCommand cmd(QStringLiteral("lvm"),
|
||||
{ QStringLiteral("lvdisplay"),
|
||||
QStringLiteral("--units"),
|
||||
QStringLiteral("B"),
|
||||
QStringLiteral("--maps"),
|
||||
lvPath});
|
||||
lvSize = getTotalLE(lvpath);
|
||||
startSector = mappedSector(lvpath,0);
|
||||
endSector = startSector + (lvSize - 1);
|
||||
|
||||
if (cmd.run(-1) && cmd.exitCode() == 0) {
|
||||
const KDiskFreeSpaceInfo freeSpaceInfo = KDiskFreeSpaceInfo::freeSpaceInfo(mountPoint);
|
||||
|
||||
//TODO: regex for first and last sector of the LV
|
||||
//TODO: stringing PE into one large contingiuous array of PE ??
|
||||
QRegularExpression re(QStringLiteral("Physical extents\\h+(\\d+)\\sto\\s(\\d+)"));
|
||||
QRegularExpressionMatch match = re.match(cmd.output());
|
||||
if (match.hasMatch()) {
|
||||
startSector = match.captured(1).toLongLong();
|
||||
endSector = match.captured(2).toLongLong();
|
||||
}
|
||||
FileSystem* fs = FileSystemFactory::create(FileSystem::detectFileSystem(lvpath), 0, lvSize - 1);
|
||||
if (mounted && freeSpaceInfo.isValid() && mountPoint != QString()) {
|
||||
//TODO: fix used space report. currently incorrect
|
||||
fs->setSectorsUsed(freeSpaceInfo.used() / logicalSize());
|
||||
}
|
||||
|
||||
FileSystem* fs = FileSystemFactory::create(FileSystem::detectFileSystem(lvPath), startSector, endSector);
|
||||
|
||||
Partition* part = new Partition(pTable,
|
||||
dev,
|
||||
PartitionRole(PartitionRole::Lvm_Lv),
|
||||
fs,
|
||||
startSector,
|
||||
endSector,
|
||||
lvPath,
|
||||
lvpath,
|
||||
PartitionTable::Flag::FlagLvm,
|
||||
mountPoint,
|
||||
mounted);
|
||||
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> devPathList;
|
||||
|
@ -138,10 +153,23 @@ QList<QString> LvmDevice::deviceNodeList() const
|
|||
devPathList.append(devPath.trimmed());
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
QString val = getField(QStringLiteral("vg_extent_size"), vgname);
|
||||
|
@ -171,6 +199,7 @@ QString LvmDevice::getUUID(const QString& vgname)
|
|||
return val.isEmpty() ? QStringLiteral("---") : val;
|
||||
|
||||
}
|
||||
|
||||
/** Query LVM details with field name
|
||||
*
|
||||
* @param fieldName lvm field name
|
||||
|
@ -196,3 +225,19 @@ QString LvmDevice::getField(const QString& fieldName, const QString& vgname)
|
|||
}
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -51,16 +51,21 @@ public:
|
|||
QList<Partition*> scanPartitions(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 getTotalPE(const QString& name);
|
||||
static qint32 getAllocatedPE(const QString& name);
|
||||
static qint32 getFreePE(const QString& name);
|
||||
static QString getUUID(const QString& name);
|
||||
static qint32 getPeSize(const QString& vgname);
|
||||
static qint32 getTotalPE(const QString& vgname);
|
||||
static qint32 getAllocatedPE(const QString& vgname);
|
||||
static qint32 getFreePE(const QString& vgname);
|
||||
static QString getUUID(const QString& vgname);
|
||||
static QString getField(const QString& fieldName, const QString& vgname = QString());
|
||||
|
||||
static qint32 getTotalLE(const QString& lvpath);
|
||||
|
||||
protected:
|
||||
void initPartitions();
|
||||
QList<QString> deviceNodeList() const override;
|
||||
qint64 mappedSector(const QString& lvpath, qint64 sector) const override;
|
||||
|
||||
QList<QString> lvPathList() const;
|
||||
|
||||
public:
|
||||
qint32 peSize() const {
|
||||
|
@ -85,6 +90,7 @@ private:
|
|||
qint32 m_allocPE;
|
||||
qint32 m_freePE;
|
||||
QString m_UUID;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -266,6 +266,7 @@ bool PartitionTable::getUnallocatedRange(const Device& d, PartitionNode& parent,
|
|||
return end - start + 1 >= PartitionAlignment::sectorAlignment(device);
|
||||
} else if (d.type() == Device::LVM_Device) {
|
||||
return false;
|
||||
//TODO: return range from last LE to last allocated LE
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -378,8 +379,12 @@ void PartitionTable::updateUnallocated(const Device& d)
|
|||
qint64 PartitionTable::defaultFirstUsable(const Device& d, TableType t)
|
||||
{
|
||||
Q_UNUSED(t)
|
||||
const DiskDevice& diskDevice = dynamic_cast<const DiskDevice&>(d);
|
||||
return PartitionAlignment::sectorAlignment(diskDevice);
|
||||
if (d.type() == Device::LVM_Device) {
|
||||
return 0;
|
||||
} else {
|
||||
const DiskDevice& diskDevice = dynamic_cast<const DiskDevice&>(d);
|
||||
return PartitionAlignment::sectorAlignment(diskDevice);
|
||||
}
|
||||
}
|
||||
|
||||
qint64 PartitionTable::defaultLastUsable(const Device& d, TableType t)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/*************************************************************************
|
||||
* Copyright (C) 2008 by Volker Lanz <vl@fidra.de> *
|
||||
* Copyright (C) 2016 by Andrius Štikonas <andrius@stikonas.eu> *
|
||||
* Copyright (C) 2016 by Chantara Tith <tith.chantara@gmail.com> *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
|
@ -43,6 +42,7 @@ QString VolumeManagerDevice::prettyDeviceNodeList() const
|
|||
}
|
||||
|
||||
if (rval.size()) {
|
||||
//chop off the trailing colon
|
||||
rval.chop(1);
|
||||
}
|
||||
return rval;
|
||||
|
|
|
@ -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 *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
* published by the Free Software Foundation; either version 3 of *
|
||||
|
@ -30,14 +32,13 @@ class CoreBackend;
|
|||
class SmartStatus;
|
||||
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.
|
||||
|
||||
@see PartitionTable, Partition
|
||||
@author Volker Lanz <vl@fidra.de>
|
||||
*/
|
||||
class LIBKPMCORE_EXPORT VolumeManagerDevice : public Device
|
||||
{
|
||||
|
@ -46,13 +47,15 @@ class LIBKPMCORE_EXPORT VolumeManagerDevice : public Device
|
|||
protected:
|
||||
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 qint64 mappedSector(const QString& devNode, qint64 sector) const = 0;
|
||||
|
||||
public:
|
||||
//virtual void refresh() const = 0; /* VG infos can be changed, unlike disk_device */
|
||||
//virtual Qlist<Partition*> listDevices() const = 0;
|
||||
/** string deviceNodeList together into comma-sperated list */
|
||||
virtual QString prettyDeviceNodeList() const;
|
||||
/** Mapper return absolute sector representing the VG */
|
||||
|
||||
private:
|
||||
//QMap<QString, qint32> deviceSizeMapper;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue