19e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg#include "fio.h" 29e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg#include "mutex.h" 39e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg#include "smalloc.h" 49e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg#include "flist.h" 59e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg 69e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenbergstruct fio_flow { 79e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg unsigned int refs; 89e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg struct flist_head list; 99e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg unsigned int id; 109e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg long long int flow_counter; 119e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg}; 129e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg 139e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenbergstatic struct flist_head *flow_list; 149e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenbergstatic struct fio_mutex *flow_lock; 159e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg 169e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenbergint flow_threshold_exceeded(struct thread_data *td) 179e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg{ 189e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg struct fio_flow *flow = td->flow; 199e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg int sign; 209e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg 219e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg if (!flow) 229e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg return 0; 239e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg 249e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg sign = td->o.flow > 0 ? 1 : -1; 259e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg if (sign * flow->flow_counter > td->o.flow_watermark) { 26cb44aa1f72811770d50e1ba5da3d96f2beb51025Jens Axboe if (td->o.flow_sleep) { 27cb44aa1f72811770d50e1ba5da3d96f2beb51025Jens Axboe io_u_quiesce(td); 289e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg usleep(td->o.flow_sleep); 29cb44aa1f72811770d50e1ba5da3d96f2beb51025Jens Axboe } 30cb44aa1f72811770d50e1ba5da3d96f2beb51025Jens Axboe 319e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg return 1; 329e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg } 339e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg 349e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg /* No synchronization needed because it doesn't 359e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg * matter if the flow count is slightly inaccurate */ 369e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg flow->flow_counter += td->o.flow; 379e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg return 0; 389e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg} 399e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg 409e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenbergstatic struct fio_flow *flow_get(unsigned int id) 419e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg{ 428e8b225d177c8e824785a87a1116309049a27a7cDaniel Ehrenberg struct fio_flow *flow = NULL; 439e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg struct flist_head *n; 449e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg 45fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe if (!flow_lock) 46fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe return NULL; 47fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe 489e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg fio_mutex_down(flow_lock); 499e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg 509e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg flist_for_each(n, flow_list) { 519e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg flow = flist_entry(n, struct fio_flow, list); 529e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg if (flow->id == id) 539e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg break; 549e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg 559e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg flow = NULL; 569e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg } 579e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg 589e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg if (!flow) { 599e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg flow = smalloc(sizeof(*flow)); 60fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe if (!flow) { 61fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe log_err("fio: smalloc pool exhausted\n"); 62fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe return NULL; 63fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe } 649e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg flow->refs = 0; 659e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg INIT_FLIST_HEAD(&flow->list); 669e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg flow->id = id; 679e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg flow->flow_counter = 0; 689e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg 699e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg flist_add_tail(&flow->list, flow_list); 709e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg } 719e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg 729e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg flow->refs++; 739e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg fio_mutex_up(flow_lock); 749e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg return flow; 759e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg} 769e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg 779e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenbergstatic void flow_put(struct fio_flow *flow) 789e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg{ 79fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe if (!flow_lock) 80fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe return; 81fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe 829e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg fio_mutex_down(flow_lock); 839e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg 849e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg if (!--flow->refs) { 859e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg flist_del(&flow->list); 869e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg sfree(flow); 879e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg } 889e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg 899e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg fio_mutex_up(flow_lock); 909e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg} 919e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg 929e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenbergvoid flow_init_job(struct thread_data *td) 939e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg{ 949e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg if (td->o.flow) 959e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg td->flow = flow_get(td->o.flow_id); 969e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg} 979e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg 989e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenbergvoid flow_exit_job(struct thread_data *td) 999e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg{ 1009e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg if (td->flow) { 1019e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg flow_put(td->flow); 1029e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg td->flow = NULL; 1039e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg } 1049e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg} 1059e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg 1069e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenbergvoid flow_init(void) 1079e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg{ 1089e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg flow_list = smalloc(sizeof(*flow_list)); 109fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe if (!flow_list) { 110fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe log_err("fio: smalloc pool exhausted\n"); 111fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe return; 112fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe } 113fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe 114fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe flow_lock = fio_mutex_init(FIO_MUTEX_UNLOCKED); 115fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe if (!flow_lock) { 116fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe log_err("fio: failed to allocate flow lock\n"); 117fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe sfree(flow_list); 118fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe return; 119fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe } 120fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe 1219e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg INIT_FLIST_HEAD(flow_list); 1229e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg} 1239e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg 1249e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenbergvoid flow_exit(void) 1259e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg{ 126fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe if (flow_lock) 127fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe fio_mutex_remove(flow_lock); 128fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe if (flow_list) 129fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe sfree(flow_list); 1309e684a4976b7934f5ce011ea281dfef3352e5738Dan Ehrenberg} 131