Added B_TRIM_DEVICE support to BFS.

* It currently ignores the offset/size, though, and always trims everything.
* Now only SCSI support is missing.
This commit is contained in:
Axel Dörfler 2013-08-05 00:16:54 +02:00
parent a352b43896
commit 0a0ba4b5f0
3 changed files with 97 additions and 3 deletions

View File

@ -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

View File

@ -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);

View File

@ -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;