status_t Inode::_ShrinkDataStream(Transaction& transaction, off_t size) { TRACE("Inode::_ShrinkDataStream()\n"); if (size < 0) return B_BAD_VALUE; uint32 blockSize = fVolume->BlockSize(); off_t oldSize = Size(); off_t lastByte = oldSize == 0 ? 0 : oldSize - 1; off_t minSize = (lastByte / blockSize + 1) * blockSize; // Minimum size that doesn't require freeing blocks if (size > minSize) { // No need to allocate more blocks TRACE("Inode::_ShrinkDataStream(): No need to allocate more blocks\n"); TRACE("Inode::_ShrinkDataStream(): Setting size to %lld\n", size); fNode.SetSize(size); return B_OK; } off_t end = size == 0 ? 0 : (size - 1) / fVolume->BlockSize() + 1; if (Flags() & EXT2_INODE_EXTENTS) { ExtentStream stream(fVolume, &fNode.extent_stream, Size()); stream.Shrink(transaction, end); ASSERT(stream.Check()); } else { DataStream stream(fVolume, &fNode.stream, oldSize); stream.Shrink(transaction, end); } fNode.SetSize(size); return _SetNumBlocks(_NumBlocks() - end * (fVolume->BlockSize() / 512)); }
status_t Inode::_EnlargeDataStream(Transaction& transaction, off_t size) { if (size < 0) return B_BAD_VALUE; TRACE("Inode::_EnlargeDataStream()\n"); uint32 blockSize = fVolume->BlockSize(); off_t oldSize = Size(); off_t maxSize = oldSize; if (maxSize % blockSize != 0) maxSize += blockSize - maxSize % blockSize; if (size <= maxSize) { // No need to allocate more blocks TRACE("Inode::_EnlargeDataStream(): No need to allocate more blocks\n"); TRACE("Inode::_EnlargeDataStream(): Setting size to %" B_PRIdOFF "\n", size); fNode.SetSize(size); return B_OK; } off_t end = size == 0 ? 0 : (size - 1) / fVolume->BlockSize() + 1; if (Flags() & EXT2_INODE_EXTENTS) { ExtentStream stream(fVolume, &fNode.extent_stream, Size()); stream.Enlarge(transaction, end); ASSERT(stream.Check()); } else { DataStream stream(fVolume, &fNode.stream, oldSize); stream.Enlarge(transaction, end); } TRACE("Inode::_EnlargeDataStream(): Setting size to %" B_PRIdOFF "\n", size); fNode.SetSize(size); TRACE("Inode::_EnlargeDataStream(): Setting allocated block count to %" B_PRIdOFF "\n", end); return _SetNumBlocks(_NumBlocks() + end * (fVolume->BlockSize() / 512)); }