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/sysmacros.h>
     10 #include <sys/vfs.h>
     11 #include <sys/mman.h>
     12 #include <unistd.h>
     13 #include <fcntl.h>
     14 #include <errno.h>
     15 #include <sched.h>
     16 #include <linux/unistd.h>
     17 #include <linux/raw.h>
     18 #include <linux/major.h>
     19 
     20 #include "./os-linux-syscall.h"
     21 #include "binject.h"
     22 #include "../file.h"
     23 
     24 #ifndef __has_builtin         // Optional of course.
     25   #define __has_builtin(x) 0  // Compatibility with non-clang compilers.
     26 #endif
     27 
     28 #define FIO_HAVE_CPU_AFFINITY
     29 #define FIO_HAVE_DISK_UTIL
     30 #define FIO_HAVE_SGIO
     31 #define FIO_HAVE_IOPRIO
     32 #define FIO_HAVE_IOPRIO_CLASS
     33 #define FIO_HAVE_IOSCHED_SWITCH
     34 #define FIO_HAVE_ODIRECT
     35 #define FIO_HAVE_HUGETLB
     36 #define FIO_HAVE_RAWBIND
     37 #define FIO_HAVE_BLKTRACE
     38 #define FIO_HAVE_CL_SIZE
     39 #define FIO_HAVE_CGROUPS
     40 #define FIO_HAVE_FS_STAT
     41 #define FIO_HAVE_TRIM
     42 #define FIO_HAVE_BINJECT
     43 #define FIO_HAVE_GETTID
     44 #define FIO_USE_GENERIC_INIT_RANDOM_STATE
     45 #define FIO_HAVE_PWRITEV2
     46 #define FIO_HAVE_SHM_ATTACH_REMOVED
     47 
     48 #ifdef MAP_HUGETLB
     49 #define FIO_HAVE_MMAP_HUGE
     50 #endif
     51 
     52 #define OS_MAP_ANON		MAP_ANONYMOUS
     53 
     54 typedef cpu_set_t os_cpu_mask_t;
     55 
     56 typedef struct drand48_data os_random_state_t;
     57 
     58 #ifdef CONFIG_3ARG_AFFINITY
     59 #define fio_setaffinity(pid, cpumask)		\
     60 	sched_setaffinity((pid), sizeof(cpumask), &(cpumask))
     61 #define fio_getaffinity(pid, ptr)	\
     62 	sched_getaffinity((pid), sizeof(cpu_set_t), (ptr))
     63 #elif defined(CONFIG_2ARG_AFFINITY)
     64 #define fio_setaffinity(pid, cpumask)	\
     65 	sched_setaffinity((pid), &(cpumask))
     66 #define fio_getaffinity(pid, ptr)	\
     67 	sched_getaffinity((pid), (ptr))
     68 #endif
     69 
     70 #define fio_cpu_clear(mask, cpu)	(void) CPU_CLR((cpu), (mask))
     71 #define fio_cpu_set(mask, cpu)		(void) CPU_SET((cpu), (mask))
     72 #define fio_cpu_isset(mask, cpu)	CPU_ISSET((cpu), (mask))
     73 #define fio_cpu_count(mask)		CPU_COUNT((mask))
     74 
     75 static inline int fio_cpuset_init(os_cpu_mask_t *mask)
     76 {
     77 	CPU_ZERO(mask);
     78 	return 0;
     79 }
     80 
     81 static inline int fio_cpuset_exit(os_cpu_mask_t *mask)
     82 {
     83 	return 0;
     84 }
     85 
     86 #define FIO_MAX_CPUS			CPU_SETSIZE
     87 
     88 enum {
     89 	IOPRIO_CLASS_NONE,
     90 	IOPRIO_CLASS_RT,
     91 	IOPRIO_CLASS_BE,
     92 	IOPRIO_CLASS_IDLE,
     93 };
     94 
     95 enum {
     96 	IOPRIO_WHO_PROCESS = 1,
     97 	IOPRIO_WHO_PGRP,
     98 	IOPRIO_WHO_USER,
     99 };
    100 
    101 #define IOPRIO_BITS		16
    102 #define IOPRIO_CLASS_SHIFT	13
    103 
    104 #define IOPRIO_MIN_PRIO		0	/* highest priority */
    105 #define IOPRIO_MAX_PRIO		7	/* lowest priority */
    106 
    107 #define IOPRIO_MIN_PRIO_CLASS	0
    108 #define IOPRIO_MAX_PRIO_CLASS	3
    109 
    110 static inline int ioprio_set(int which, int who, int ioprio_class, int ioprio)
    111 {
    112 	/*
    113 	 * If no class is set, assume BE
    114 	 */
    115 	if (!ioprio_class)
    116 		ioprio_class = IOPRIO_CLASS_BE;
    117 
    118 	ioprio |= ioprio_class << IOPRIO_CLASS_SHIFT;
    119 	return syscall(__NR_ioprio_set, which, who, ioprio);
    120 }
    121 
    122 static inline int gettid(void)
    123 {
    124 	return syscall(__NR_gettid);
    125 }
    126 
    127 #define SPLICE_DEF_SIZE	(64*1024)
    128 
    129 #ifndef BLKGETSIZE64
    130 #define BLKGETSIZE64	_IOR(0x12,114,size_t)
    131 #endif
    132 
    133 #ifndef BLKFLSBUF
    134 #define BLKFLSBUF	_IO(0x12,97)
    135 #endif
    136 
    137 #ifndef BLKDISCARD
    138 #define BLKDISCARD	_IO(0x12,119)
    139 #endif
    140 
    141 static inline int blockdev_invalidate_cache(struct fio_file *f)
    142 {
    143 	return ioctl(f->fd, BLKFLSBUF);
    144 }
    145 
    146 static inline int blockdev_size(struct fio_file *f, unsigned long long *bytes)
    147 {
    148 	if (!ioctl(f->fd, BLKGETSIZE64, bytes))
    149 		return 0;
    150 
    151 	return errno;
    152 }
    153 
    154 static inline unsigned long long os_phys_mem(void)
    155 {
    156 	long pagesize, pages;
    157 
    158 	pagesize = sysconf(_SC_PAGESIZE);
    159 	pages = sysconf(_SC_PHYS_PAGES);
    160 	if (pages == -1 || pagesize == -1)
    161 		return 0;
    162 
    163 	return (unsigned long long) pages * (unsigned long long) pagesize;
    164 }
    165 
    166 static inline void os_random_seed(unsigned long seed, os_random_state_t *rs)
    167 {
    168 	srand48_r(seed, rs);
    169 }
    170 
    171 static inline long os_random_long(os_random_state_t *rs)
    172 {
    173 	long val;
    174 
    175 	lrand48_r(rs, &val);
    176 	return val;
    177 }
    178 
    179 static inline int fio_lookup_raw(dev_t dev, int *majdev, int *mindev)
    180 {
    181 	struct raw_config_request rq;
    182 	int fd;
    183 
    184 	if (major(dev) != RAW_MAJOR)
    185 		return 1;
    186 
    187 	/*
    188 	 * we should be able to find /dev/rawctl or /dev/raw/rawctl
    189 	 */
    190 	fd = open("/dev/rawctl", O_RDONLY);
    191 	if (fd < 0) {
    192 		fd = open("/dev/raw/rawctl", O_RDONLY);
    193 		if (fd < 0)
    194 			return 1;
    195 	}
    196 
    197 	rq.raw_minor = minor(dev);
    198 	if (ioctl(fd, RAW_GETBIND, &rq) < 0) {
    199 		close(fd);
    200 		return 1;
    201 	}
    202 
    203 	close(fd);
    204 	*majdev = rq.block_major;
    205 	*mindev = rq.block_minor;
    206 	return 0;
    207 }
    208 
    209 #ifdef O_NOATIME
    210 #define FIO_O_NOATIME	O_NOATIME
    211 #else
    212 #define FIO_O_NOATIME	0
    213 #endif
    214 
    215 #ifdef O_ATOMIC
    216 #define OS_O_ATOMIC	O_ATOMIC
    217 #else
    218 #define OS_O_ATOMIC	040000000
    219 #endif
    220 
    221 #ifdef MADV_REMOVE
    222 #define FIO_MADV_FREE	MADV_REMOVE
    223 #endif
    224 
    225 /* Check for GCC or Clang byte swap intrinsics */
    226 #if (__has_builtin(__builtin_bswap16) && __has_builtin(__builtin_bswap32) \
    227      && __has_builtin(__builtin_bswap64)) || (__GNUC__ > 4 \
    228      || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) /* fio_swapN */
    229 #define fio_swap16(x)	__builtin_bswap16(x)
    230 #define fio_swap32(x)	__builtin_bswap32(x)
    231 #define fio_swap64(x)	__builtin_bswap64(x)
    232 #else
    233 #include <byteswap.h>
    234 #define fio_swap16(x)	bswap_16(x)
    235 #define fio_swap32(x)	bswap_32(x)
    236 #define fio_swap64(x)	bswap_64(x)
    237 #endif /* fio_swapN */
    238 
    239 #define CACHE_LINE_FILE	\
    240 	"/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size"
    241 
    242 static inline int arch_cache_line_size(void)
    243 {
    244 	char size[32];
    245 	int fd, ret;
    246 
    247 	fd = open(CACHE_LINE_FILE, O_RDONLY);
    248 	if (fd < 0)
    249 		return -1;
    250 
    251 	ret = read(fd, size, sizeof(size));
    252 
    253 	close(fd);
    254 
    255 	if (ret <= 0)
    256 		return -1;
    257 	else
    258 		return atoi(size);
    259 }
    260 
    261 static inline unsigned long long get_fs_free_size(const char *path)
    262 {
    263 	unsigned long long ret;
    264 	struct statfs s;
    265 
    266 	if (statfs(path, &s) < 0)
    267 		return -1ULL;
    268 
    269 	ret = s.f_bsize;
    270 	ret *= (unsigned long long) s.f_bfree;
    271 	return ret;
    272 }
    273 
    274 static inline int os_trim(int fd, unsigned long long start,
    275 			  unsigned long long len)
    276 {
    277 	uint64_t range[2];
    278 
    279 	range[0] = start;
    280 	range[1] = len;
    281 
    282 	if (!ioctl(fd, BLKDISCARD, range))
    283 		return 0;
    284 
    285 	return errno;
    286 }
    287 
    288 #ifdef CONFIG_SCHED_IDLE
    289 static inline int fio_set_sched_idle(void)
    290 {
    291 	struct sched_param p = { .sched_priority = 0, };
    292 	return sched_setscheduler(gettid(), SCHED_IDLE, &p);
    293 }
    294 #endif
    295 
    296 #ifndef POSIX_FADV_STREAMID
    297 #define POSIX_FADV_STREAMID	8
    298 #endif
    299 
    300 #define FIO_HAVE_STREAMID
    301 
    302 #ifndef RWF_HIPRI
    303 #define RWF_HIPRI	0x00000001
    304 #endif
    305 #ifndef RWF_DSYNC
    306 #define RWF_DSYNC	0x00000002
    307 #endif
    308 #ifndef RWF_SYNC
    309 #define RWF_SYNC	0x00000004
    310 #endif
    311 
    312 #ifndef CONFIG_PWRITEV2
    313 #ifdef __NR_preadv2
    314 static inline void make_pos_h_l(unsigned long *pos_h, unsigned long *pos_l,
    315 				off_t offset)
    316 {
    317 #if BITS_PER_LONG == 64
    318 	*pos_l = offset;
    319 	*pos_h = 0;
    320 #else
    321 	*pos_l = offset & 0xffffffff;
    322 	*pos_h = ((uint64_t) offset) >> 32;
    323 #endif
    324 }
    325 static inline ssize_t preadv2(int fd, const struct iovec *iov, int iovcnt,
    326 			      off_t offset, unsigned int flags)
    327 {
    328 	unsigned long pos_l, pos_h;
    329 
    330 	make_pos_h_l(&pos_h, &pos_l, offset);
    331 	return syscall(__NR_preadv2, fd, iov, iovcnt, pos_l, pos_h, flags);
    332 }
    333 static inline ssize_t pwritev2(int fd, const struct iovec *iov, int iovcnt,
    334 			       off_t offset, unsigned int flags)
    335 {
    336 	unsigned long pos_l, pos_h;
    337 
    338 	make_pos_h_l(&pos_h, &pos_l, offset);
    339 	return syscall(__NR_pwritev2, fd, iov, iovcnt, pos_l, pos_h, flags);
    340 }
    341 #else
    342 static inline ssize_t preadv2(int fd, const struct iovec *iov, int iovcnt,
    343 			      off_t offset, unsigned int flags)
    344 {
    345 	errno = ENOSYS;
    346 	return -1;
    347 }
    348 static inline ssize_t pwritev2(int fd, const struct iovec *iov, int iovcnt,
    349 			       off_t offset, unsigned int flags)
    350 {
    351 	errno = ENOSYS;
    352 	return -1;
    353 }
    354 #endif /* __NR_preadv2 */
    355 #endif /* CONFIG_PWRITEV2 */
    356 
    357 static inline int shm_attach_to_open_removed(void)
    358 {
    359 	return 1;
    360 }
    361 
    362 #endif
    363