1 /*
2 * Copyright 2013, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT license.
4 */
5 #ifndef _FS_TRIM_SUPPORT_H
6 #define _FS_TRIM_SUPPORT_H
7
8
9 #include <AutoDeleter.h>
10 #include <KernelExport.h>
11 #include <SupportDefs.h>
12
13 #include <kernel.h>
14 #include <syscall_restart.h>
15
16
17 static inline status_t
get_trim_data_from_user(void * buffer,size_t size,MemoryDeleter & deleter,fs_trim_data * & _trimData)18 get_trim_data_from_user(void* buffer, size_t size, MemoryDeleter& deleter,
19 fs_trim_data*& _trimData)
20 {
21 if (!is_called_via_syscall() && !IS_USER_ADDRESS(buffer)) {
22 // Called from kernel
23 _trimData = (fs_trim_data*)buffer;
24 return B_OK;
25 }
26
27 // Called from userland
28 if (!IS_USER_ADDRESS(buffer))
29 return B_BAD_ADDRESS;
30
31 uint32 count;
32 if (user_memcpy(&count, buffer, sizeof(count)) != B_OK)
33 return B_BAD_ADDRESS;
34
35 size_t bytes = (count - 1) * sizeof(uint64) * 2 + sizeof(fs_trim_data);
36 if (bytes > size)
37 return B_BAD_VALUE;
38
39 void* trimBuffer = malloc(bytes);
40 if (trimBuffer == NULL)
41 return B_NO_MEMORY;
42
43 if (user_memcpy(trimBuffer, buffer, bytes) != B_OK) {
44 free(trimBuffer);
45 return B_BAD_ADDRESS;
46 }
47
48 // The passed in MemoryDeleter needs to take care of freeing the buffer
49 // later, since we had to allocate it.
50 deleter.SetTo(trimBuffer);
51
52 _trimData = (fs_trim_data*)trimBuffer;
53 return B_OK;
54 }
55
56
57 static inline status_t
copy_trim_data_to_user(void * buffer,fs_trim_data * trimData)58 copy_trim_data_to_user(void* buffer, fs_trim_data* trimData)
59 {
60 if (!is_called_via_syscall() && !IS_USER_ADDRESS(buffer))
61 return B_OK;
62
63 if (!IS_USER_ADDRESS(buffer))
64 return B_BAD_ADDRESS;
65
66 // Do not copy any ranges
67 return user_memcpy(buffer, trimData, offsetof(fs_trim_data, ranges));
68 }
69
70
71 #endif // _FS_TRIM_SUPPORT_H
72