#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>
#include <libgen.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "fio.h"
#include "verify.h"
#include "parse.h"
#include "lib/fls.h"
#include "options.h"
#include "crc/crc32c.h"
/*
* Check if mmap/mmaphuge has a :/foo/bar/file at the end. If so, return that.
*/
static char *get_opt_postfix(const char *str)
{
char *p = strstr(str, ":");
if (!p)
return NULL;
p++;
strip_blank_front(&p);
strip_blank_end(p);
return strdup(p);
}
static int converthexchartoint(char a)
{
int base;
switch (a) {
case '0'...'9':
base = '0';
break;
case 'A'...'F':
base = 'A' - 10;
break;
case 'a'...'f':
base = 'a' - 10;
break;
default:
base = 0;
}
return a - base;
}
static int bs_cmp(const void *p1, const void *p2)
{
const struct bssplit *bsp1 = p1;
const struct bssplit *bsp2 = p2;
return bsp1->perc < bsp2->perc;
}
static int bssplit_ddir(struct thread_options *o, int ddir, char *str)
{
struct bssplit *bssplit;
unsigned int i, perc, perc_missing;
unsigned int max_bs, min_bs;
long long val;
char *fname;
o->bssplit_nr[ddir] = 4;
bssplit = malloc(4 * sizeof(struct bssplit));
i = 0;
max_bs = 0;
min_bs = -1;
while ((fname = strsep(&str, ":")) != NULL) {
char *perc_str;
if (!strlen(fname))
break;
/*
* grow struct buffer, if needed
*/
if (i == o->bssplit_nr[ddir]) {
o->bssplit_nr[ddir] <<= 1;
bssplit = realloc(bssplit, o->bssplit_nr[ddir]
* sizeof(struct bssplit));
}
perc_str = strstr(fname, "/");
if (perc_str) {
*perc_str = '\0';
perc_str++;
perc = atoi(perc_str);
if (perc > 100)
perc = 100;
else if (!perc)
perc = -1;
} else
perc = -1;
if (str_to_decimal(fname, &val, 1, o)) {
log_err("fio: bssplit conversion failed\n");
free(o->bssplit);
return 1;
}
if (val > max_bs)
max_bs = val;
if (val < min_bs)
min_bs = val;
bssplit[i].bs = val;
bssplit[i].perc = perc;
i++;
}
o->bssplit_nr[ddir] = i;
/*
* Now check if the percentages add up, and how much is missing
*/
perc = perc_missing = 0;
for (i = 0; i < o->bssplit_nr[ddir]; i++) {
struct bssplit *bsp = &bssplit[i];
if (bsp->perc == (unsigned char) -1)
perc_missing++;
else
perc += bsp->perc;
}
if (perc > 100) {
log_err("fio: bssplit percentages add to more than 100%%\n");
free(bssplit);
return 1;
}
/*
* If values didn't have a percentage set, divide the remains between
* them.
*/
if (perc_missing) {
for (i = 0; i < o->bssplit_nr[ddir]; i++) {
struct bssplit *bsp = &bssplit[i];
if (bsp->perc == (unsigned char) -1)
bsp->perc = (100 - perc) / perc_missing;
}
}
o->min_bs[ddir] = min_bs;
o->max_bs[ddir] = max_bs;
/*
* now sort based on percentages, for ease of lookup
*/
qsort(bssplit, o->bssplit_nr[ddir], sizeof(struct bssplit), bs_cmp);
o->bssplit[ddir] = bssplit;
return 0;
}
static int str_bssplit_cb(void *data, const char *input)
{
struct thread_data *td = data;
char *str, *p, *odir, *ddir;
int ret = 0;
p = str = strdup(input);
strip_blank_front(&str);
strip_blank_end(str);
odir = strchr(str, ',');
if (odir) {
ddir = strchr(odir + 1, ',');
if (ddir) {
ret = bssplit_ddir(&td->o, DDIR_TRIM, ddir + 1);
if (!ret)
*ddir = '\0';
} else {
char *op;
op = strdup(odir + 1);
ret = bssplit_ddir(&td->o, DDIR_TRIM, op);
free(op);
}
if (!ret)
ret = bssplit_ddir(&td->o, DDIR_WRITE, odir + 1);
if (!ret) {
*odir = '\0';
ret = bssplit_ddir(&td->o, DDIR_READ, str);
}
} else {
char *op;
op = strdup(str);
ret = bssplit_ddir(&td->o, DDIR_WRITE, op);
free(op);
if (!ret) {
op = strdup(str);
ret = bssplit_ddir(&td->o, DDIR_TRIM, op);
free(op);
}
ret = bssplit_ddir(&td->o, DDIR_READ, str);
}
free(p);
return ret;
}
static int str2error(char *str)
{
const char *err[] = { "EPERM", "ENOENT", "ESRCH", "EINTR", "EIO",
"ENXIO", "E2BIG", "ENOEXEC", "EBADF",
"ECHILD", "EAGAIN", "ENOMEM", "EACCES",
"EFAULT", "ENOTBLK", "EBUSY", "EEXIST",
"EXDEV", "ENODEV", "ENOTDIR", "EISDIR",
"EINVAL", "ENFILE", "EMFILE", "ENOTTY",
"ETXTBSY","EFBIG", "ENOSPC", "ESPIPE",
"EROFS","EMLINK", "EPIPE", "EDOM", "ERANGE" };
int i = 0, num = sizeof(err) / sizeof(void *);
while (i < num) {
if (!strcmp(err[i], str))
return i + 1;
i++;
}
return 0;
}
static int ignore_error_type(struct thread_data *td, int etype, char *str)
{
unsigned int i;
int *error;
char *fname;
if (etype >= ERROR_TYPE_CNT) {
log_err("Illegal error type\n");
return 1;
}
td->o.ignore_error_nr[etype] = 4;
error = malloc(4 * sizeof(struct bssplit));
i = 0;
while ((fname = strsep(&str, ":")) != NULL) {
if (!strlen(fname))
break;
/*
* grow struct buffer, if needed
*/
if (i == td->o.ignore_error_nr[etype]) {
td->o.ignore_error_nr[etype] <<= 1;
error = realloc(error, td->o.ignore_error_nr[etype]
* sizeof(int));
}
if (fname[0] == 'E') {
error[i] = str2error(fname);
} else {
error[i] = atoi(fname);
if (error[i] < 0)
error[i] = error[i];
}
if (!error[i]) {
log_err("Unknown error %s, please use number value \n",
fname);
free(error);
return 1;
}
i++;
}
if (i) {
td->o.continue_on_error |= 1 << etype;
td->o.ignore_error_nr[etype] = i;
td->o.ignore_error[etype] = error;
}
return 0;
}
static int str_ignore_error_cb(void *data, const char *input)
{
struct thread_data *td = data;
char *str, *p, *n;
int type = 0, ret = 1;
p = str = strdup(input);
strip_blank_front(&str);
strip_blank_end(str);
while (p) {
n = strchr(p, ',');
if (n)
*n++ = '\0';
ret = ignore_error_type(td, type, p);
if (ret)
break;
p = n;
type++;
}
free(str);
return ret;
}
static int str_rw_cb(void *data, const char *str)
{
struct thread_data *td = data;
struct thread_options *o = &td->o;
char *nr = get_opt_postfix(str);
o->ddir_seq_nr = 1;
o->ddir_seq_add = 0;
if (!nr)
return 0;
if (td_random(td))
o->ddir_seq_nr = atoi(nr);
else {
long long val;
if (str_to_decimal(nr, &val, 1, o)) {
log_err("fio: rw postfix parsing failed\n");
free(nr);
return 1;
}
o->ddir_seq_add = val;
}
free(nr);
return 0;
}
static int str_mem_cb(void *data, const char *mem)
{
struct thread_data *td = data;
if (td->o.mem_type == MEM_MMAPHUGE || td->o.mem_type == MEM_MMAP)
td->o.mmapfile = get_opt_postfix(mem);
return 0;
}
static int fio_clock_source_cb(void *data, const char *str)
{
struct thread_data *td = data;
fio_clock_source = td->o.clocksource;
fio_clock_source_set = 1;
fio_clock_init();
return 0;
}
static int str_rwmix_read_cb(void *data, unsigned long long *val)
{
struct thread_data *td = data;
td->o.rwmix[DDIR_READ] = *val;
td->o.rwmix[DDIR_WRITE] = 100 - *val;
return 0;
}
static int str_rwmix_write_cb(void *data, unsigned long long *val)
{
struct thread_data *td = data;
td->o.rwmix[DDIR_WRITE] = *val;
td->o.rwmix[DDIR_READ] = 100 - *val;
return 0;
}
static int str_exitall_cb(void)
{
exitall_on_terminate = 1;
return 0;
}
#ifdef FIO_HAVE_CPU_AFFINITY
static int str_cpumask_cb(void *data, unsigned long long *val)
{
struct thread_data *td = data;
unsigned int i;
long max_cpu;
int ret;
ret = fio_cpuset_init(&td->o.cpumask);
if (ret < 0) {
log_err("fio: cpuset_init failed\n");
td_verror(td, ret, "fio_cpuset_init");
return 1;
}
max_cpu = cpus_online();
for (i = 0; i < sizeof(int) * 8; i++) {
if ((1 << i) & *val) {
if (i > max_cpu) {
log_err("fio: CPU %d too large (max=%ld)\n", i,
max_cpu);
return 1;
}
dprint(FD_PARSE, "set cpu allowed %d\n", i);
fio_cpu_set(&td->o.cpumask, i);
}
}
td->o.cpumask_set = 1;
return 0;
}
static int set_cpus_allowed(struct thread_data *td, os_cpu_mask_t *mask,
const char *input)
{
char *cpu, *str, *p;
long max_cpu;
test_sharing
- 粉丝: 47
- 资源: 1
最新资源
- C# Winform简单的俄罗斯方块小游戏源码2.zip
- 混合动力汽车动态规划算法理论油耗计算与视频教学,使用matlab编写快速计算程序,整个工程结构模块化,可以快速改为串联,并联,混联等 控制量可以快速扩展为档位,转矩,转速等 状态量一般为SOC,目
- 全国职业院校技能大赛网络建设与运维规程
- agv 1223.fbx
- 考虑泄流效应的光伏无功优化matlab 以IEEE33节点为例,分析泄流效应下,最佳网络无功补偿方案,程序运行稳定
- jetbra插件工具,方便开发者快速开发
- 云计算2401班课程设计资料.zip
- 企业宣传PPT模板, 企业宣传PPT模板
- 微环谐振腔的光学频率梳matlab仿真 微腔光频梳仿真 包括求解LLE方程(Lugiato-Lefever equation)实现微环中的光频梳,同时考虑了色散,克尔非线性,外部泵浦等因素,具有可延展
- 生菜生长记录数据集.zip
- 基于Springboot+Vue健身房管理系统-毕业源码案例设计(高分项目).zip
- 中国风格, 节日 主题, PPT模板
- lcd取模工具,很难找的有用的LCD显示开发工具
- 基于Springboot+Vue健身房管理系统-毕业源码案例设计(源码+数据库).zip
- 基于Springboot+Vue江理工文档管理系统的设计与实现-毕业源码案例设计(源码+论文).zip
- 基于Springboot+Vue教师工作量管理系统-毕业源码案例设计(高分毕业设计).zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈