From 0a0ba4b5f09da93410943578b6c5aa1f3aa60cb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Mon, 5 Aug 2013 00:16:54 +0200 Subject: [PATCH] Added B_TRIM_DEVICE support to BFS. * It currently ignores the offset/size, though, and always trims everything. * Now only SCSI support is missing. --- .../file_systems/bfs/BlockAllocator.cpp | 78 ++++++++++++++++++- .../kernel/file_systems/bfs/BlockAllocator.h | 6 +- .../file_systems/bfs/kernel_interface.cpp | 16 +++- 3 files changed, 97 insertions(+), 3 deletions(-) diff --git a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp index a6aceca9ce..432df6c963 100644 --- a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp +++ b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2012, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2001-2013, Axel Dörfler, axeld@pinc-software.de. * This file may be used under the terms of the MIT License. */ @@ -1190,6 +1190,62 @@ BlockAllocator::_CheckGroup(int32 groupIndex) const #endif // DEBUG_ALLOCATION_GROUPS +status_t +BlockAllocator::Trim(off_t offset, off_t size, off_t& trimmedSize) +{ + RecursiveLocker locker(fLock); + + // TODO: take given offset and size into account! + int32 lastGroup = fNumGroups - 1; + uint32 firstBlock = 0; + uint32 firstBit = 0; + off_t currentBlock = 0; + uint32 blockShift = fVolume->BlockShift(); + + off_t firstFree = -1; + size_t freeLength = 0; + trimmedSize = 0; + + AllocationBlock cached(fVolume); + for (int32 groupIndex = 0; groupIndex <= lastGroup; groupIndex++) { + AllocationGroup& group = fGroups[groupIndex]; + + for (uint32 block = firstBlock; block < group.NumBlocks(); block++) { + cached.SetTo(group, block); + + for (uint32 i = firstBit; i < cached.NumBlockBits(); i++) { + if (cached.IsUsed(i)) { + // Block is in use + if (freeLength > 0) { + status_t status = _TrimNext(firstFree << blockShift, + freeLength << blockShift, trimmedSize); + if (status != B_OK) + return status; + + freeLength = 0; + } + } else if (freeLength++ == 0) { + // Block is free, start new free range + firstFree = currentBlock; + } + + currentBlock++; + } + } + + firstBlock = 0; + firstBit = 0; + } + + if (freeLength > 0) { + return _TrimNext(firstFree << blockShift, freeLength << blockShift, + trimmedSize); + } + + return B_OK; +} + + // #pragma mark - Bitmap validity checking // TODO: implement new FS checking API @@ -2124,6 +2180,26 @@ BlockAllocator::_AddInodeToIndex(Inode* inode) } +status_t +BlockAllocator::_TrimNext(off_t offset, off_t size, off_t& trimmedSize) +{ + PRINT(("_TrimNext(offset %lld, size %lld)\n", offset, size)); + + fs_trim_data trimData; + trimData.offset = offset; + trimData.size = size; + trimData.trimmed_size = 0; + + if (ioctl(fVolume->Device(), B_TRIM_DEVICE, &trimData, + sizeof(fs_trim_data)) != 0) { + return errno; + } + + trimmedSize += trimData.trimmed_size; + return B_OK; +} + + // #pragma mark - debugger commands diff --git a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.h b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.h index ba490ba010..88b9d525d1 100644 --- a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.h +++ b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.h @@ -1,5 +1,5 @@ /* - * Copyright 2001-2012, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2001-2013, Axel Dörfler, axeld@pinc-software.de. * This file may be used under the terms of the MIT License. */ #ifndef BLOCK_ALLOCATOR_H @@ -46,6 +46,8 @@ public: int32 group, uint16 start, uint16 numBlocks, uint16 minimum, block_run& run); + status_t Trim(off_t offset, off_t size, off_t& trimmedSize); + status_t StartChecking(const check_control* control); status_t StopChecking(check_control* control); status_t CheckNextNode(check_control* control); @@ -81,6 +83,8 @@ private: void _FreeIndices(); status_t _AddInodeToIndex(Inode* inode); status_t _WriteBackCheckBitmap(); + status_t _TrimNext(off_t offset, off_t size, + off_t& trimmedSize); static status_t _Initialize(BlockAllocator* self); diff --git a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp index 6504c9915c..11400033ca 100644 --- a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2010, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2001-2013, Axel Dörfler, axeld@pinc-software.de. * This file may be used under the terms of the MIT License. */ @@ -623,6 +623,20 @@ bfs_ioctl(fs_volume* _volume, fs_vnode* _node, void* _cookie, uint32 cmd, Volume* volume = (Volume*)_volume->private_volume; switch (cmd) { + case B_TRIM_DEVICE: + { + fs_trim_data trimData; + if (user_memcpy(&trimData, buffer, sizeof(fs_trim_data)) != B_OK) + return B_BAD_ADDRESS; + + status_t status = volume->Allocator().Trim(trimData.offset, + trimData.size, trimData.trimmed_size); + if (status != B_OK) + return status; + + return user_memcpy(buffer, &trimData, sizeof(fs_trim_data)); + } + case BFS_IOCTL_VERSION: { uint32 version = 0x10000;