os-linux.h revision d79db1222039e906dd49ae290daa59701f4e2385
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 <unistd.h> 11#include <fcntl.h> 12#include <errno.h> 13#include <sched.h> 14#include <linux/unistd.h> 15#include <linux/raw.h> 16#include <linux/major.h> 17#include <endian.h> 18 19#include "indirect.h" 20#include "binject.h" 21#include "../file.h" 22 23#define FIO_HAVE_LIBAIO 24#define FIO_HAVE_POSIXAIO 25#define FIO_HAVE_FADVISE 26#define FIO_HAVE_CPU_AFFINITY 27#define FIO_HAVE_DISK_UTIL 28#define FIO_HAVE_SGIO 29#define FIO_HAVE_IOPRIO 30#define FIO_HAVE_SPLICE 31#define FIO_HAVE_IOSCHED_SWITCH 32#define FIO_HAVE_ODIRECT 33#define FIO_HAVE_HUGETLB 34#define FIO_HAVE_RAWBIND 35#define FIO_HAVE_BLKTRACE 36#define FIO_HAVE_STRSEP 37#define FIO_HAVE_POSIXAIO_FSYNC 38#define FIO_HAVE_PSHARED_MUTEX 39#define FIO_HAVE_CL_SIZE 40#define FIO_HAVE_CGROUPS 41#define FIO_HAVE_FDATASYNC 42#define FIO_HAVE_FS_STAT 43#define FIO_HAVE_TRIM 44#define FIO_HAVE_BINJECT 45#define FIO_HAVE_CLOCK_MONOTONIC 46#define FIO_HAVE_GETTID 47#define FIO_USE_GENERIC_INIT_RANDOM_STATE 48#define FIO_HAVE_E4_ENG 49 50/* 51 * Can only enable this for newer glibcs, or the header and defines are 52 * missing 53 */ 54#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 6 55#define FIO_HAVE_FALLOCATE 56#endif 57#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 8 58#define FIO_HAVE_LINUX_FALLOCATE 59#endif 60 61#ifdef FIO_HAVE_LINUX_FALLOCATE 62#define FIO_HAVE_FALLOC_ENG 63#endif 64 65#ifdef SYNC_FILE_RANGE_WAIT_BEFORE 66#define FIO_HAVE_SYNC_FILE_RANGE 67#endif 68 69#define OS_MAP_ANON MAP_ANONYMOUS 70 71#ifndef CLOCK_MONOTONIC 72#define CLOCK_MONOTONIC 1 73#endif 74 75typedef cpu_set_t os_cpu_mask_t; 76 77typedef struct drand48_data os_random_state_t; 78 79/* 80 * we want fadvise64 really, but it's so tangled... later 81 */ 82#ifdef FIO_HAVE_FADVISE 83#define fadvise(fd, off, len, advice) \ 84 posix_fadvise((fd), (off_t)(off), (len), (advice)) 85#endif 86 87/* 88 * If you are on an ancient glibc (2.3.2), then define GLIBC_2_3_2 if you want 89 * the affinity helpers to work. 90 */ 91#ifndef GLIBC_2_3_2 92#define fio_setaffinity(pid, cpumask) \ 93 sched_setaffinity((pid), sizeof(cpumask), &(cpumask)) 94#define fio_getaffinity(pid, ptr) \ 95 sched_getaffinity((pid), sizeof(cpu_set_t), (ptr)) 96#else 97#define fio_setaffinity(pid, cpumask) \ 98 sched_setaffinity((pid), &(cpumask)) 99#define fio_getaffinity(pid, ptr) \ 100 sched_getaffinity((pid), (ptr)) 101#endif 102 103#define fio_cpu_clear(mask, cpu) (void) CPU_CLR((cpu), (mask)) 104#define fio_cpu_set(mask, cpu) (void) CPU_SET((cpu), (mask)) 105 106static inline int fio_cpuset_init(os_cpu_mask_t *mask) 107{ 108 CPU_ZERO(mask); 109 return 0; 110} 111 112static inline int fio_cpuset_exit(os_cpu_mask_t *mask) 113{ 114 return 0; 115} 116 117#define FIO_MAX_CPUS CPU_SETSIZE 118 119enum { 120 IOPRIO_CLASS_NONE, 121 IOPRIO_CLASS_RT, 122 IOPRIO_CLASS_BE, 123 IOPRIO_CLASS_IDLE, 124}; 125 126enum { 127 IOPRIO_WHO_PROCESS = 1, 128 IOPRIO_WHO_PGRP, 129 IOPRIO_WHO_USER, 130}; 131 132#define IOPRIO_BITS 16 133#define IOPRIO_CLASS_SHIFT 13 134 135static inline int ioprio_set(int which, int who, int ioprio_class, int ioprio) 136{ 137 /* 138 * If no class is set, assume BE 139 */ 140 if (!ioprio_class) 141 ioprio_class = IOPRIO_CLASS_BE; 142 143 ioprio |= ioprio_class << IOPRIO_CLASS_SHIFT; 144 return syscall(__NR_ioprio_set, which, who, ioprio); 145} 146 147static inline int gettid(void) 148{ 149 return syscall(__NR_gettid); 150} 151 152/* 153 * Just check for SPLICE_F_MOVE, if that isn't there, assume the others 154 * aren't either. 155 */ 156#ifndef SPLICE_F_MOVE 157#define SPLICE_F_MOVE (0x01) /* move pages instead of copying */ 158#define SPLICE_F_NONBLOCK (0x02) /* don't block on the pipe splicing (but */ 159 /* we may still block on the fd we splice */ 160 /* from/to, of course */ 161#define SPLICE_F_MORE (0x04) /* expect more data */ 162#define SPLICE_F_GIFT (0x08) /* pages passed in are a gift */ 163 164static inline int splice(int fdin, loff_t *off_in, int fdout, loff_t *off_out, 165 size_t len, unsigned int flags) 166{ 167 return syscall(__NR_sys_splice, fdin, off_in, fdout, off_out, len, flags); 168} 169 170static inline int tee(int fdin, int fdout, size_t len, unsigned int flags) 171{ 172 return syscall(__NR_sys_tee, fdin, fdout, len, flags); 173} 174 175static inline int vmsplice(int fd, const struct iovec *iov, 176 unsigned long nr_segs, unsigned int flags) 177{ 178 return syscall(__NR_sys_vmsplice, fd, iov, nr_segs, flags); 179} 180#endif 181 182#define SPLICE_DEF_SIZE (64*1024) 183 184#ifdef FIO_HAVE_SYSLET 185 186struct syslet_uatom; 187struct async_head_user; 188 189/* 190 * syslet stuff 191 */ 192static inline struct syslet_uatom * 193async_exec(struct syslet_uatom *atom, struct async_head_user *ahu) 194{ 195 return (struct syslet_uatom *) syscall(__NR_async_exec, atom, ahu); 196} 197 198static inline long 199async_wait(unsigned long min_wait_events, unsigned long user_ring_idx, 200 struct async_head_user *ahu) 201{ 202 return syscall(__NR_async_wait, min_wait_events, 203 user_ring_idx, ahu); 204} 205 206static inline long async_thread(void *event, struct async_head_user *ahu) 207{ 208 return syscall(__NR_async_thread, event, ahu); 209} 210 211static inline long umem_add(unsigned long *uptr, unsigned long inc) 212{ 213 return syscall(__NR_umem_add, uptr, inc); 214} 215#endif /* FIO_HAVE_SYSLET */ 216 217#ifndef BLKGETSIZE64 218#define BLKGETSIZE64 _IOR(0x12,114,size_t) 219#endif 220 221#ifndef BLKFLSBUF 222#define BLKFLSBUF _IO(0x12,97) 223#endif 224 225#ifndef BLKDISCARD 226#define BLKDISCARD _IO(0x12,119) 227#endif 228 229static inline int blockdev_invalidate_cache(struct fio_file *f) 230{ 231 return ioctl(f->fd, BLKFLSBUF); 232} 233 234static inline int blockdev_size(struct fio_file *f, unsigned long long *bytes) 235{ 236 if (!ioctl(f->fd, BLKGETSIZE64, bytes)) 237 return 0; 238 239 return errno; 240} 241 242static inline unsigned long long os_phys_mem(void) 243{ 244 long pagesize, pages; 245 246 pagesize = sysconf(_SC_PAGESIZE); 247 pages = sysconf(_SC_PHYS_PAGES); 248 if (pages == -1 || pagesize == -1) 249 return 0; 250 251 return (unsigned long long) pages * (unsigned long long) pagesize; 252} 253 254static inline void os_random_seed(unsigned long seed, os_random_state_t *rs) 255{ 256 srand48_r(seed, rs); 257} 258 259static inline long os_random_long(os_random_state_t *rs) 260{ 261 long val; 262 263 lrand48_r(rs, &val); 264 return val; 265} 266 267static inline int fio_lookup_raw(dev_t dev, int *majdev, int *mindev) 268{ 269 struct raw_config_request rq; 270 int fd; 271 272 if (major(dev) != RAW_MAJOR) 273 return 1; 274 275 /* 276 * we should be able to find /dev/rawctl or /dev/raw/rawctl 277 */ 278 fd = open("/dev/rawctl", O_RDONLY); 279 if (fd < 0) { 280 fd = open("/dev/raw/rawctl", O_RDONLY); 281 if (fd < 0) 282 return 1; 283 } 284 285 rq.raw_minor = minor(dev); 286 if (ioctl(fd, RAW_GETBIND, &rq) < 0) { 287 close(fd); 288 return 1; 289 } 290 291 close(fd); 292 *majdev = rq.block_major; 293 *mindev = rq.block_minor; 294 return 0; 295} 296 297#ifdef O_NOATIME 298#define FIO_O_NOATIME O_NOATIME 299#else 300#define FIO_O_NOATIME 0 301#endif 302 303#ifdef MADV_REMOVE 304#define FIO_MADV_FREE MADV_REMOVE 305#endif 306 307#if __BYTE_ORDER == __LITTLE_ENDIAN 308#define FIO_LITTLE_ENDIAN 309#elif __BYTE_ORDER == __BIG_ENDIAN 310#define FIO_BIG_ENDIAN 311#else 312#error "Unknown endianness" 313#endif 314 315#define fio_swap16(x) __bswap_16(x) 316#define fio_swap32(x) __bswap_32(x) 317#define fio_swap64(x) __bswap_64(x) 318 319#define CACHE_LINE_FILE \ 320 "/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size" 321 322static inline int arch_cache_line_size(void) 323{ 324 char size[32]; 325 int fd, ret; 326 327 fd = open(CACHE_LINE_FILE, O_RDONLY); 328 if (fd < 0) 329 return -1; 330 331 ret = read(fd, size, sizeof(size)); 332 333 close(fd); 334 335 if (ret <= 0) 336 return -1; 337 else 338 return atoi(size); 339} 340 341static inline unsigned long long get_fs_size(const char *path) 342{ 343 unsigned long long ret; 344 struct statfs s; 345 346 if (statfs(path, &s) < 0) 347 return -1ULL; 348 349 ret = s.f_bsize; 350 ret *= (unsigned long long) s.f_bfree; 351 return ret; 352} 353 354static inline int os_trim(int fd, unsigned long long start, 355 unsigned long long len) 356{ 357 uint64_t range[2]; 358 359 range[0] = start; 360 range[1] = len; 361 362 if (!ioctl(fd, BLKDISCARD, range)) 363 return 0; 364 365 return errno; 366} 367 368#endif 369