Home | History | Annotate | Download | only in os
      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