/************************************************************************* * Copyright (C) 2016 by Chantara Tith * * * * 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 * * the License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* *************************************************************************/ #include "ops/resizevolumegroupoperation.h" #include "core/lvmdevice.h" #include "fs/lvm2_pv.h" #include "core/partition.h" #include "jobs/resizevolumegroupjob.h" #include "jobs/movephysicalvolumejob.h" #include #include /** Creates a new ResizeVolumeGroupOperation. @param d the Device to create the new PartitionTable on @param t the type for the new PartitionTable */ ResizeVolumeGroupOperation::ResizeVolumeGroupOperation(LvmDevice& dev, const QStringList partlist) : Operation(), m_Device(dev), m_TargetList(partlist), m_CurrentList(LvmDevice::getPVs(dev.name())), m_GrowVolumeGroupJob(nullptr), m_ShrinkVolumeGroupJob(nullptr), m_MovePhysicalVolumeJob(nullptr) { const QStringList clist = currentList(); m_TargetSize = FS::lvm2_pv::getPVSize(targetList()); m_CurrentSize = FS::lvm2_pv::getPVSize(currentList()); QStringList toRemoveList = clist; for (QString path : partlist) { if (toRemoveList.contains(path)) { toRemoveList.removeAll(path); } } QStringList toInsertList = partlist; for (QString path : clist) { if (toInsertList.contains(path)) { toInsertList.removeAll(path); } } qint64 freePE = FS::lvm2_pv::getFreePE(clist) - FS::lvm2_pv::getFreePE(toRemoveList); qint64 movePE = FS::lvm2_pv::getAllocatedPE(toRemoveList); qint64 growPE = FS::lvm2_pv::getPVSize(toInsertList) / LvmDevice::getPeSize(dev.name()); if ( movePE > (freePE + growPE)) { // *ABORT* can't move } else if (partlist == clist) { // *DO NOTHING* } else { if (!toInsertList.isEmpty()) { m_GrowVolumeGroupJob = new ResizeVolumeGroupJob(dev, toInsertList, ResizeVolumeGroupJob::Grow); addJob(growVolumeGroupJob()); } if (!toRemoveList.isEmpty()) { m_MovePhysicalVolumeJob = new MovePhysicalVolumeJob(dev, toRemoveList); m_ShrinkVolumeGroupJob = new ResizeVolumeGroupJob(dev, toRemoveList, ResizeVolumeGroupJob::Shrink); addJob(movePhysicalVolumeJob()); addJob(shrinkvolumegroupjob()); } } } QString ResizeVolumeGroupOperation::description() const { QString tlist = QString(); for (QString path : targetList()) { tlist += path + QStringLiteral(","); } tlist.chop(1); QString clist = QString(); for (QString path : currentList()) { clist += path + QStringLiteral(","); } clist.chop(1); return xi18nc("@info/plain", "Resize volume %1 from %2 to %3", device().name(), clist, tlist); } bool ResizeVolumeGroupOperation::targets(const Device& d) const { return d == device(); } bool ResizeVolumeGroupOperation::targets(const Partition& part) const { for (QString partPath : targetList()) { if (partPath == part.partitionPath()) { return true; } } return false; } void ResizeVolumeGroupOperation::preview() { //asumming that targetSize is larger than the allocated space. device().setTotalLogical(targetSize() / device().logicalSize()); device().partitionTable()->setFirstUsableSector(PartitionTable::defaultFirstUsable(device(), PartitionTable::vmd)); device().partitionTable()->setLastUsableSector(PartitionTable::defaultLastUsable(device(), PartitionTable::vmd)); device().partitionTable()->updateUnallocated(device()); } void ResizeVolumeGroupOperation::undo() { device().setTotalLogical(currentSize() / device().logicalSize()); device().partitionTable()->setFirstUsableSector(PartitionTable::defaultFirstUsable(device(), PartitionTable::vmd)); device().partitionTable()->setLastUsableSector(PartitionTable::defaultLastUsable(device(), PartitionTable::vmd)); device().partitionTable()->updateUnallocated(device()); }