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