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