1 #ifndef FIO_OS_LINUX_H 2 #define FIO_OS_LINUX_H 3 4 #define FIO_OS os_linux 5 6 #include <sys/ioctl.h> 7 #include <sys/uio.h> 8 #include <sys/syscall.h> 9 #include <sys/vfs.h> 10 #include <sys/mman.h> 11 #include <unistd.h> 12 #include <fcntl.h> 13 #include <errno.h> 14 #include <sched.h> 15 #include <linux/unistd.h> 16 #include <linux/raw.h> 17 #include <linux/major.h> 18 #include <byteswap.h> 19 20 #include "binject.h" 21 #include "../file.h" 22 23 #define FIO_HAVE_CPU_AFFINITY 24 #define FIO_HAVE_DISK_UTIL 25 #define FIO_HAVE_SGIO 26 #define FIO_HAVE_IOPRIO 27 #define FIO_HAVE_IOSCHED_SWITCH 28 #define FIO_HAVE_ODIRECT 29 #define FIO_HAVE_HUGETLB 30 #define FIO_HAVE_RAWBIND 31 #define FIO_HAVE_BLKTRACE 32 #define FIO_HAVE_PSHARED_MUTEX 33 #define FIO_HAVE_CL_SIZE 34 #define FIO_HAVE_CGROUPS 35 #define FIO_HAVE_FS_STAT 36 #define FIO_HAVE_TRIM 37 #define FIO_HAVE_BINJECT 38 #define FIO_HAVE_GETTID 39 #define FIO_USE_GENERIC_INIT_RANDOM_STATE 40 41 #ifdef MAP_HUGETLB 42 #define FIO_HAVE_MMAP_HUGE 43 #endif 44 45 #define OS_MAP_ANON MAP_ANONYMOUS 46 47 typedef cpu_set_t os_cpu_mask_t; 48 49 typedef struct drand48_data os_random_state_t; 50 51 #ifdef CONFIG_3ARG_AFFINITY 52 #define fio_setaffinity(pid, cpumask) \ 53 sched_setaffinity((pid), sizeof(cpumask), &(cpumask)) 54 #define fio_getaffinity(pid, ptr) \ 55 sched_getaffinity((pid), sizeof(cpu_set_t), (ptr)) 56 #elif defined(CONFIG_2ARG_AFFINITY) 57 #define fio_setaffinity(pid, cpumask) \ 58 sched_setaffinity((pid), &(cpumask)) 59 #define fio_getaffinity(pid, ptr) \ 60 sched_getaffinity((pid), (ptr)) 61 #endif 62 63 #define fio_cpu_clear(mask, cpu) (void) CPU_CLR((cpu), (mask)) 64 #define fio_cpu_set(mask, cpu) (void) CPU_SET((cpu), (mask)) 65 #define fio_cpu_isset(mask, cpu) CPU_ISSET((cpu), (mask)) 66 #define fio_cpu_count(mask) CPU_COUNT((mask)) 67 68 static inline int fio_cpuset_init(os_cpu_mask_t *mask) 69 { 70 CPU_ZERO(mask); 71 return 0; 72 } 73 74 static inline int fio_cpuset_exit(os_cpu_mask_t *mask) 75 { 76 return 0; 77 } 78 79 #define FIO_MAX_CPUS CPU_SETSIZE 80 81 enum { 82 IOPRIO_CLASS_NONE, 83 IOPRIO_CLASS_RT, 84 IOPRIO_CLASS_BE, 85 IOPRIO_CLASS_IDLE, 86 }; 87 88 enum { 89 IOPRIO_WHO_PROCESS = 1, 90 IOPRIO_WHO_PGRP, 91 IOPRIO_WHO_USER, 92 }; 93 94 #define IOPRIO_BITS 16 95 #define IOPRIO_CLASS_SHIFT 13 96 97 static inline int ioprio_set(int which, int who, int ioprio_class, int ioprio) 98 { 99 /* 100 * If no class is set, assume BE 101 */ 102 if (!ioprio_class) 103 ioprio_class = IOPRIO_CLASS_BE; 104 105 ioprio |= ioprio_class << IOPRIO_CLASS_SHIFT; 106 return syscall(__NR_ioprio_set, which, who, ioprio); 107 } 108 109 static inline int gettid(void) 110 { 111 return syscall(__NR_gettid); 112 } 113 114 #define SPLICE_DEF_SIZE (64*1024) 115 116 #ifndef BLKGETSIZE64 117 #define BLKGETSIZE64 _IOR(0x12,114,size_t) 118 #endif 119 120 #ifndef BLKFLSBUF 121 #define BLKFLSBUF _IO(0x12,97) 122 #endif 123 124 #ifndef BLKDISCARD 125 #define BLKDISCARD _IO(0x12,119) 126 #endif 127 128 static inline int blockdev_invalidate_cache(struct fio_file *f) 129 { 130 return ioctl(f->fd, BLKFLSBUF); 131 } 132 133 static inline int blockdev_size(struct fio_file *f, unsigned long long *bytes) 134 { 135 if (!ioctl(f->fd, BLKGETSIZE64, bytes)) 136 return 0; 137 138 return errno; 139 } 140 141 static inline unsigned long long os_phys_mem(void) 142 { 143 long pagesize, pages; 144 145 pagesize = sysconf(_SC_PAGESIZE); 146 pages = sysconf(_SC_PHYS_PAGES); 147 if (pages == -1 || pagesize == -1) 148 return 0; 149 150 return (unsigned long long) pages * (unsigned long long) pagesize; 151 } 152 153 static inline void os_random_seed(unsigned long seed, os_random_state_t *rs) 154 { 155 srand48_r(seed, rs); 156 } 157 158 static inline long os_random_long(os_random_state_t *rs) 159 { 160 long val; 161 162 lrand48_r(rs, &val); 163 return val; 164 } 165 166 static inline int fio_lookup_raw(dev_t dev, int *majdev, int *mindev) 167 { 168 struct raw_config_request rq; 169 int fd; 170 171 if (major(dev) != RAW_MAJOR) 172 return 1; 173 174 /* 175 * we should be able to find /dev/rawctl or /dev/raw/rawctl 176 */ 177 fd = open("/dev/rawctl", O_RDONLY); 178 if (fd < 0) { 179 fd = open("/dev/raw/rawctl", O_RDONLY); 180 if (fd < 0) 181 return 1; 182 } 183 184 rq.raw_minor = minor(dev); 185 if (ioctl(fd, RAW_GETBIND, &rq) < 0) { 186 close(fd); 187 return 1; 188 } 189 190 close(fd); 191 *majdev = rq.block_major; 192 *mindev = rq.block_minor; 193 return 0; 194 } 195 196 #ifdef O_NOATIME 197 #define FIO_O_NOATIME O_NOATIME 198 #else 199 #define FIO_O_NOATIME 0 200 #endif 201 202 #ifdef O_ATOMIC 203 #define OS_O_ATOMIC O_ATOMIC 204 #else 205 #define OS_O_ATOMIC 040000000 206 #endif 207 208 #ifdef MADV_REMOVE 209 #define FIO_MADV_FREE MADV_REMOVE 210 #endif 211 212 #if defined(__builtin_bswap16) 213 #define fio_swap16(x) __builtin_bswap16(x) 214 #else 215 #define fio_swap16(x) __bswap_16(x) 216 #endif 217 #if defined(__builtin_bswap32) 218 #define fio_swap32(x) __builtin_bswap32(x) 219 #else 220 #define fio_swap32(x) __bswap_32(x) 221 #endif 222 #if defined(__builtin_bswap64) 223 #define fio_swap64(x) __builtin_bswap64(x) 224 #else 225 #define fio_swap64(x) __bswap_64(x) 226 #endif 227 228 #define CACHE_LINE_FILE \ 229 "/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size" 230 231 static inline int arch_cache_line_size(void) 232 { 233 char size[32]; 234 int fd, ret; 235 236 fd = open(CACHE_LINE_FILE, O_RDONLY); 237 if (fd < 0) 238 return -1; 239 240 ret = read(fd, size, sizeof(size)); 241 242 close(fd); 243 244 if (ret <= 0) 245 return -1; 246 else 247 return atoi(size); 248 } 249 250 static inline unsigned long long get_fs_size(const char *path) 251 { 252 unsigned long long ret; 253 struct statfs s; 254 255 if (statfs(path, &s) < 0) 256 return -1ULL; 257 258 ret = s.f_bsize; 259 ret *= (unsigned long long) s.f_bfree; 260 return ret; 261 } 262 263 static inline int os_trim(int fd, unsigned long long start, 264 unsigned long long len) 265 { 266 uint64_t range[2]; 267 268 range[0] = start; 269 range[1] = len; 270 271 if (!ioctl(fd, BLKDISCARD, range)) 272 return 0; 273 274 return errno; 275 } 276 277 #ifdef CONFIG_SCHED_IDLE 278 static inline int fio_set_sched_idle(void) 279 { 280 struct sched_param p = { .sched_priority = 0, }; 281 return sched_setscheduler(gettid(), SCHED_IDLE, &p); 282 } 283 #endif 284 285 #endif 286