2013-08-15 03:34:59 +04:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
|
|
|
|
|
2021-01-17 17:22:52 +03:00
|
|
|
#include <AutoDeleter.h>
|
2013-11-03 03:18:57 +04:00
|
|
|
#include <KernelExport.h>
|
2021-01-17 17:22:52 +03:00
|
|
|
#include <SupportDefs.h>
|
2013-08-15 03:34:59 +04:00
|
|
|
|
|
|
|
#include <kernel.h>
|
2013-11-03 03:18:57 +04:00
|
|
|
#include <syscall_restart.h>
|
2013-08-15 03:34:59 +04:00
|
|
|
|
|
|
|
|
|
|
|
static inline status_t
|
2013-11-03 03:18:57 +04:00
|
|
|
get_trim_data_from_user(void* buffer, size_t size, MemoryDeleter& deleter,
|
|
|
|
fs_trim_data*& _trimData)
|
2013-08-15 03:34:59 +04:00
|
|
|
{
|
2013-11-03 03:18:57 +04:00
|
|
|
if (!is_called_via_syscall() && !IS_USER_ADDRESS(buffer)) {
|
|
|
|
// Called from kernel
|
|
|
|
_trimData = (fs_trim_data*)buffer;
|
|
|
|
return B_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Called from userland
|
2013-08-15 03:34:59 +04:00
|
|
|
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;
|
|
|
|
|
2013-11-03 03:18:57 +04:00
|
|
|
if (user_memcpy(trimBuffer, buffer, bytes) != B_OK) {
|
|
|
|
free(trimBuffer);
|
2013-08-15 03:34:59 +04:00
|
|
|
return B_BAD_ADDRESS;
|
2013-11-03 03:18:57 +04:00
|
|
|
}
|
2013-08-15 03:34:59 +04:00
|
|
|
|
2014-01-22 21:00:31 +04:00
|
|
|
// The passed in MemoryDeleter needs to take care of freeing the buffer
|
|
|
|
// later, since we had to allocate it.
|
|
|
|
deleter.SetTo(trimBuffer);
|
|
|
|
|
2013-08-15 03:34:59 +04:00
|
|
|
_trimData = (fs_trim_data*)trimBuffer;
|
|
|
|
return B_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline status_t
|
|
|
|
copy_trim_data_to_user(void* buffer, fs_trim_data* trimData)
|
|
|
|
{
|
2013-11-03 03:18:57 +04:00
|
|
|
if (!is_called_via_syscall() && !IS_USER_ADDRESS(buffer))
|
|
|
|
return B_OK;
|
|
|
|
|
|
|
|
if (!IS_USER_ADDRESS(buffer))
|
|
|
|
return B_BAD_ADDRESS;
|
|
|
|
|
2013-08-15 03:34:59 +04:00
|
|
|
// Do not copy any ranges
|
2021-07-01 00:49:04 +03:00
|
|
|
return user_memcpy(buffer, trimData, offsetof(fs_trim_data, ranges));
|
2013-08-15 03:34:59 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif // _FS_TRIM_SUPPORT_H
|