haiku/headers/private/kernel/util/fs_trim_support.h
David Sebek bd02d81c24 Fix trim-related issues
Fixes:
* Use uint64 instead of off_t when handling offset and size
  of the trimmed range in the fs_trim_data structure
* BlockAllocator::Trim: Correct the size of a buffer
* ram_disk, mmc: Do not trim past device capacity

Improvements:
* BlockAllocator::Trim: Because the received offset and size
  are ignored by BFS (the functionality is not implemented yet),
  return B_UNSUPPORTED if the range does not cover the whole
  partition
* ram_disk, mmc: More accurate calculation of the number
  of trimmed bytes
* devfs: Add a uint64 version of translate_partition_access()

Change-Id: I24f4c08674f123ad33a5fef6e28996a4ada6ff0d
Reviewed-on: https://review.haiku-os.org/c/haiku/+/4155
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
2021-07-16 18:35:34 +00:00

72 lines
1.6 KiB
C

/*
* Copyright 2013, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT license.
*/
#ifndef _FS_TRIM_SUPPORT_H
#define _FS_TRIM_SUPPORT_H
#include <AutoDeleter.h>
#include <KernelExport.h>
#include <SupportDefs.h>
#include <kernel.h>
#include <syscall_restart.h>
static inline status_t
get_trim_data_from_user(void* buffer, size_t size, MemoryDeleter& deleter,
fs_trim_data*& _trimData)
{
if (!is_called_via_syscall() && !IS_USER_ADDRESS(buffer)) {
// Called from kernel
_trimData = (fs_trim_data*)buffer;
return B_OK;
}
// Called from userland
if (!IS_USER_ADDRESS(buffer))
return B_BAD_ADDRESS;
uint32 count;
if (user_memcpy(&count, buffer, sizeof(count)) != B_OK)
return B_BAD_ADDRESS;
size_t bytes = (count - 1) * sizeof(uint64) * 2 + sizeof(fs_trim_data);
if (bytes > size)
return B_BAD_VALUE;
void* trimBuffer = malloc(bytes);
if (trimBuffer == NULL)
return B_NO_MEMORY;
if (user_memcpy(trimBuffer, buffer, bytes) != B_OK) {
free(trimBuffer);
return B_BAD_ADDRESS;
}
// The passed in MemoryDeleter needs to take care of freeing the buffer
// later, since we had to allocate it.
deleter.SetTo(trimBuffer);
_trimData = (fs_trim_data*)trimBuffer;
return B_OK;
}
static inline status_t
copy_trim_data_to_user(void* buffer, fs_trim_data* trimData)
{
if (!is_called_via_syscall() && !IS_USER_ADDRESS(buffer))
return B_OK;
if (!IS_USER_ADDRESS(buffer))
return B_BAD_ADDRESS;
// Do not copy any ranges
return user_memcpy(buffer, trimData, offsetof(fs_trim_data, ranges));
}
#endif // _FS_TRIM_SUPPORT_H