1#include "fio.h"
2#include "profile.h"
3#include "debug.h"
4#include "flist.h"
5#include "options.h"
6
7static FLIST_HEAD(profile_list);
8
9struct profile_ops *find_profile(const char *profile)
10{
11	struct profile_ops *ops = NULL;
12	struct flist_head *n;
13
14	flist_for_each(n, &profile_list) {
15		ops = flist_entry(n, struct profile_ops, list);
16		if (!strcmp(profile, ops->name))
17			break;
18
19		ops = NULL;
20	}
21
22	return ops;
23}
24
25int load_profile(const char *profile)
26{
27	struct profile_ops *ops;
28
29	dprint(FD_PROFILE, "loading profile '%s'\n", profile);
30
31	ops = find_profile(profile);
32	if (ops) {
33		if (ops->prep_cmd()) {
34			log_err("fio: profile %s prep failed\n", profile);
35			return 1;
36		}
37		add_job_opts(ops->cmdline, FIO_CLIENT_TYPE_CLI);
38		return 0;
39	}
40
41	log_err("fio: profile '%s' not found\n", profile);
42	return 1;
43}
44
45static int add_profile_options(struct profile_ops *ops)
46{
47	struct fio_option *o;
48
49	if (!ops->options)
50		return 0;
51
52	o = ops->options;
53	while (o->name) {
54		o->prof_name = ops->name;
55		o->prof_opts = ops->opt_data;
56		if (add_option(o))
57			return 1;
58		o++;
59	}
60
61	return 0;
62}
63
64int register_profile(struct profile_ops *ops)
65{
66	int ret;
67
68	dprint(FD_PROFILE, "register profile '%s'\n", ops->name);
69
70	ret = add_profile_options(ops);
71	if (!ret) {
72		flist_add_tail(&ops->list, &profile_list);
73		add_opt_posval("profile", ops->name, ops->desc);
74		return 0;
75	}
76
77	invalidate_profile_options(ops->name);
78	return ret;
79}
80
81void unregister_profile(struct profile_ops *ops)
82{
83	dprint(FD_PROFILE, "unregister profile '%s'\n", ops->name);
84	flist_del(&ops->list);
85	invalidate_profile_options(ops->name);
86	del_opt_posval("profile", ops->name);
87}
88
89void profile_add_hooks(struct thread_data *td)
90{
91	struct profile_ops *ops;
92
93	if (!exec_profile)
94		return;
95
96	ops = find_profile(exec_profile);
97	if (!ops)
98		return;
99
100	if (ops->io_ops) {
101		td->prof_io_ops = *ops->io_ops;
102		td->flags |= TD_F_PROFILE_OPS;
103	}
104}
105
106int profile_td_init(struct thread_data *td)
107{
108	struct prof_io_ops *ops = &td->prof_io_ops;
109
110	if (ops->td_init)
111		return ops->td_init(td);
112
113	return 0;
114}
115
116void profile_td_exit(struct thread_data *td)
117{
118	struct prof_io_ops *ops = &td->prof_io_ops;
119
120	if (ops->td_exit)
121		ops->td_exit(td);
122}
123