#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 <netinet/in.h>
#include "fio.h"
#include "verify.h"
#include "parse.h"
#include "lib/fls.h"
#include "lib/pattern.h"
#include "options.h"
#include "optgroup.h"
char client_sockaddr_str[INET6_ADDRSTRLEN] = { 0 };
#define cb_data_to_td(data) container_of(data, struct thread_data, o)
static struct pattern_fmt_desc fmt_desc[] = {
{
.fmt = "%o",
.len = FIELD_SIZE(struct io_u *, offset),
.paste = paste_blockoff
}
};
/*
* 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 bs_cmp(const void *p1, const void *p2)
{
const struct bssplit *bsp1 = p1;
const struct bssplit *bsp2 = p2;
return (int) bsp1->perc - (int) bsp2->perc;
}
struct split {
unsigned int nr;
unsigned int val1[ZONESPLIT_MAX];
unsigned long long val2[ZONESPLIT_MAX];
};
static int split_parse_ddir(struct thread_options *o, struct split *split,
enum fio_ddir ddir, char *str, bool absolute,
unsigned int max_splits)
{
unsigned long long perc;
unsigned int i;
long long val;
char *fname;
split->nr = 0;
i = 0;
while ((fname = strsep(&str, ":")) != NULL) {
char *perc_str;
if (!strlen(fname))
break;
perc_str = strstr(fname, "/");
if (perc_str) {
*perc_str = '\0';
perc_str++;
if (absolute) {
if (str_to_decimal(perc_str, &val, 1, o, 0, 0)) {
log_err("fio: split conversion failed\n");
return 1;
}
perc = val;
} else {
perc = atoi(perc_str);
if (perc > 100)
perc = 100;
else if (!perc)
perc = -1U;
}
} else {
if (absolute)
perc = 0;
else
perc = -1U;
}
if (str_to_decimal(fname, &val, 1, o, 0, 0)) {
log_err("fio: split conversion failed\n");
return 1;
}
split->val1[i] = val;
split->val2[i] = perc;
i++;
if (i == max_splits) {
log_err("fio: hit max of %d split entries\n", i);
break;
}
}
split->nr = i;
return 0;
}
static int bssplit_ddir(struct thread_options *o, enum fio_ddir ddir, char *str,
bool data)
{
unsigned int i, perc, perc_missing;
unsigned int max_bs, min_bs;
struct split split;
memset(&split, 0, sizeof(split));
if (split_parse_ddir(o, &split, ddir, str, data, BSSPLIT_MAX))
return 1;
if (!split.nr)
return 0;
max_bs = 0;
min_bs = -1;
o->bssplit[ddir] = malloc(split.nr * sizeof(struct bssplit));
o->bssplit_nr[ddir] = split.nr;
for (i = 0; i < split.nr; i++) {
if (split.val1[i] > max_bs)
max_bs = split.val1[i];
if (split.val1[i] < min_bs)
min_bs = split.val1[i];
o->bssplit[ddir][i].bs = split.val1[i];
o->bssplit[ddir][i].perc =split.val2[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 = &o->bssplit[ddir][i];
if (bsp->perc == -1U)
perc_missing++;
else
perc += bsp->perc;
}
if (perc > 100 && perc_missing > 1) {
log_err("fio: bssplit percentages add to more than 100%%\n");
free(o->bssplit[ddir]);
o->bssplit[ddir] = NULL;
return 1;
}
/*
* If values didn't have a percentage set, divide the remains between
* them.
*/
if (perc_missing) {
if (perc_missing == 1 && o->bssplit_nr[ddir] == 1)
perc = 100;
for (i = 0; i < o->bssplit_nr[ddir]; i++) {
struct bssplit *bsp = &o->bssplit[ddir][i];
if (bsp->perc == -1U)
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(o->bssplit[ddir], o->bssplit_nr[ddir], sizeof(struct bssplit), bs_cmp);
return 0;
}
typedef int (split_parse_fn)(struct thread_options *, enum fio_ddir, char *, bool);
static int str_split_parse(struct thread_data *td, char *str,
split_parse_fn *fn, bool data)
{
char *odir, *ddir;
int ret = 0;
odir = strchr(str, ',');
if (odir) {
ddir = strchr(odir + 1, ',');
if (ddir) {
ret = fn(&td->o, DDIR_TRIM, ddir + 1, data);
if (!ret)
*ddir = '\0';
} else {
char *op;
op = strdup(odir + 1);
ret = fn(&td->o, DDIR_TRIM, op, data);
free(op);
}
if (!ret)
ret = fn(&td->o, DDIR_WRITE, odir + 1, data);
if (!ret) {
*odir = '\0';
ret = fn(&td->o, DDIR_READ, str, data);
}
} else {
char *op;
op = strdup(str);
ret = fn(&td->o, DDIR_WRITE, op, data);
free(op);
if (!ret) {
op = strdup(str);
ret = fn(&td->o, DDIR_TRIM, op, data);
free(op);
}
if (!ret)
ret = fn(&td->o, DDIR_READ, str, data);
}
return ret;
}
static int str_bssplit_cb(void *data, const char *input)
{
struct thread_data *td = cb_data_to_td(data);
char *str, *p;
int ret = 0;
p = str = strdup(input);
strip_blank_front(&str);
strip_blank_end(str);
ret = str_split_parse(td, str, bssplit_ddir, false);
if (parse_dryrun()) {
int i;
for (i = 0; i < DDIR_RWDIR_CNT; i++) {
free(td->o.bssplit[i]);
td->o.bssplit[i] = NULL;
td->o.bssplit_nr[i] = 0;
}
}
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(char *);
while (i < num) {
if (!strcmp(err[i], str))
return i + 1;
i++;
}
return 0;
}
static int ignore_error_type(struct thread_data *td, enum error_type_bit 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 = calloc(4, sizeof(int));
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);
td->o.ignore_error_nr[etype] = 0;
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;
} else {
td->o.ignore_error_nr[etype] = 0;
free(error);
}
return 0;
}
static int str_ignore_error_cb(void *data, const char *input)
{
struct thread_data *td = cb_data_to_td(data);
char *str, *p, *n;
int ret = 1;
enum error_type_bit type = 0;
if (parse_dryrun())
return 0;
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 = cb_data_to_td(data);
struct thread_options *o = &td->o;
char *nr;
if (parse_dryrun())
return 0;
o->ddir_seq_nr = 1;
o->ddir_seq_add = 0;
nr = get_opt_postfix(str);
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, 0, 0)) {
log_err("fio: rw postfix parsing failed\n");
free(nr);
return 1;
}
o->ddir_seq_add = val;
}
free(nr);
return 0;
}
Rudy,Zhao
- 粉丝: 104
- 资源: 1
最新资源
- NSArgumentNullException如何解决.md
- VueError解决办法.md
- buvid、did参数生成算法
- tiny-cuda-cnn.zip
- 关于月度总结的PPT模板
- 手表品牌与型号数据集,手表型号数据
- 基于Java实现(IDEA)的贪吃蛇游戏-源码+jar文件+项目报告
- 数字按键3.2考试代码
- 颜色拾取器 for Windows
- 台球检测40-YOLO(v5至v11)、COCO、CreateML、Paligemma、TFRecord、VOC数据集合集.rar
- # 基于MATLAB的导航科学计算库
- Qt源码ModbusTCP 主机客户端通信程序 基于QT5 QWidget, 实现ModbusTCP 主机客户端通信,支持以下功能: 1、支持断线重连 2、通过INI文件配置自定义服务器I
- tesseract ocr 训练相关的环境部署包,包括jdk-8u331-windows-x64.exe、jTessBoxEditorFX-2.6.0.zip 等
- 好用的Linux终端管理工具,支持自定义多行脚本命令,密码保存、断链续接,SFTP等功能
- 大学毕业设计写作与答辩指南:选题、研究方法及PPT制作
- 小偏差线性化模型,航空发动机线性化,非线性系统线性化,求解线性系统具体参数,最小二乘拟合 MATLAB Simulink 航空发动机,非线性,线性,非线性系统,线性系统,最小二乘,拟合,小偏差,系统辨
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈