File indexing completed on 2024-05-05 05:48:52
0001 /* 0002 SPDX-FileCopyrightText: 2016 Chantara Tith <tith.chantara@gmail.com> 0003 SPDX-FileCopyrightText: 2016-2020 Andrius Štikonas <andrius@stikonas.eu> 0004 0005 SPDX-License-Identifier: GPL-3.0-or-later 0006 */ 0007 0008 #include "ops/resizevolumegroupoperation.h" 0009 0010 #include "core/lvmdevice.h" 0011 #include "core/partition.h" 0012 #include "fs/lvm2_pv.h" 0013 #include "jobs/resizevolumegroupjob.h" 0014 #include "jobs/movephysicalvolumejob.h" 0015 #include "util/helpers.h" 0016 0017 #include <utility> 0018 0019 #include <QString> 0020 0021 #include <KLocalizedString> 0022 0023 /** Creates a new ResizeVolumeGroupOperation. 0024 @param d the Device to create the new PartitionTable on 0025 @param partList list of LVM Physical Volumes that should be in LVM Volume Group 0026 */ 0027 ResizeVolumeGroupOperation::ResizeVolumeGroupOperation(LvmDevice& d, const QVector<const Partition*>& partList) 0028 : Operation() 0029 , m_Device(d) 0030 , m_TargetList(partList) 0031 , m_CurrentList(d.physicalVolumes()) 0032 , m_TargetSize(0) 0033 , m_CurrentSize(0) 0034 , m_GrowVolumeGroupJob(nullptr) 0035 , m_ShrinkVolumeGroupJob(nullptr) 0036 , m_MovePhysicalVolumeJob(nullptr) 0037 { 0038 for (const auto &p : targetList()) 0039 m_TargetSize += p->capacity(); 0040 for (const auto &p : currentList()) 0041 m_CurrentSize += p->capacity(); 0042 0043 QList<const Partition*> toRemoveList; 0044 for (const auto &p : currentList()) 0045 if (!targetList().contains(p)) 0046 toRemoveList.append(p); 0047 0048 QList<const Partition*> toInsertList; 0049 for (const auto &p : targetList()) 0050 if (!currentList().contains(p)) 0051 toInsertList.append(p); 0052 0053 qint64 currentFreePE = 0; 0054 for (const auto &p : currentList()) { 0055 FS::lvm2_pv *lvm2PVFs; 0056 innerFS(p, lvm2PVFs); 0057 currentFreePE += lvm2PVFs->freePE(); 0058 } 0059 qint64 removedFreePE = 0; 0060 for (const auto &p : std::as_const(toRemoveList)) { 0061 FS::lvm2_pv *lvm2PVFs; 0062 innerFS(p, lvm2PVFs); 0063 removedFreePE += lvm2PVFs->freePE(); 0064 } 0065 qint64 freePE = currentFreePE - removedFreePE; 0066 qint64 movePE = 0; 0067 for (const auto &p : std::as_const(toRemoveList)) { 0068 FS::lvm2_pv *lvm2PVFs; 0069 innerFS(p, lvm2PVFs); 0070 movePE += lvm2PVFs->allocatedPE(); 0071 } 0072 qint64 growPE = 0; 0073 for (const auto &p : std::as_const(toInsertList)) { 0074 growPE += p->capacity() / device().peSize(); 0075 } 0076 0077 if ( movePE > (freePE + growPE)) { 0078 // *ABORT* can't move 0079 } else if (partList == currentList()) { 0080 // *DO NOTHING* 0081 } else { 0082 if (!toInsertList.isEmpty()) { 0083 m_GrowVolumeGroupJob = new ResizeVolumeGroupJob(d, toInsertList, ResizeVolumeGroupJob::Type::Grow); 0084 addJob(growVolumeGroupJob()); 0085 } 0086 if (!toRemoveList.isEmpty()) { 0087 m_MovePhysicalVolumeJob = new MovePhysicalVolumeJob(d, toRemoveList); 0088 m_ShrinkVolumeGroupJob = new ResizeVolumeGroupJob(d, toRemoveList, ResizeVolumeGroupJob::Type::Shrink); 0089 addJob(movePhysicalVolumeJob()); 0090 addJob(shrinkvolumegroupjob()); 0091 } 0092 } 0093 } 0094 0095 QString ResizeVolumeGroupOperation::description() const 0096 { 0097 QString tList = QString(); 0098 for (const auto &p : targetList()) { 0099 tList += p->deviceNode() + QStringLiteral(", "); 0100 } 0101 tList.chop(2); 0102 QString curList = QString(); 0103 for (const auto &p : currentList()) { 0104 curList += p->deviceNode() + QStringLiteral(", "); 0105 } 0106 curList.chop(2); 0107 0108 return xi18nc("@info/plain", "Resize volume %1 from %2 to %3", device().name(), curList, tList); 0109 } 0110 0111 bool ResizeVolumeGroupOperation::targets(const Device& d) const 0112 { 0113 return d == device(); 0114 } 0115 0116 bool ResizeVolumeGroupOperation::targets(const Partition& p) const 0117 { 0118 for (const auto &partition : targetList()) { 0119 if (partition->partitionPath() == p.partitionPath()) { 0120 return true; 0121 } 0122 } 0123 return false; 0124 } 0125 0126 void ResizeVolumeGroupOperation::preview() 0127 { 0128 //assuming that targetSize is larger than the allocated space. 0129 device().setTotalLogical(targetSize() / device().logicalSize()); 0130 device().partitionTable()->setFirstUsableSector(PartitionTable::defaultFirstUsable(device(), PartitionTable::vmd)); 0131 device().partitionTable()->setLastUsableSector(PartitionTable::defaultLastUsable(device(), PartitionTable::vmd)); 0132 device().partitionTable()->updateUnallocated(device()); 0133 } 0134 0135 void ResizeVolumeGroupOperation::undo() 0136 { 0137 device().setTotalLogical(currentSize() / device().logicalSize()); 0138 device().partitionTable()->setFirstUsableSector(PartitionTable::defaultFirstUsable(device(), PartitionTable::vmd)); 0139 device().partitionTable()->setLastUsableSector(PartitionTable::defaultLastUsable(device(), PartitionTable::vmd)); 0140 device().partitionTable()->updateUnallocated(device()); 0141 }