1 #include "fio.h" 2 #include "profile.h" 3 #include "debug.h" 4 #include "flist.h" 5 #include "options.h" 6 7 static FLIST_HEAD(profile_list); 8 9 struct 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 25 int 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 45 static 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 64 int 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 81 void 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 89 void 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 106 int 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 116 void 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