1e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/* 2e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * I/O monitor based on block queue trace data 3e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * 4e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Copyright IBM Corp. 2008 5e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * 6e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Author(s): Martin Peschke <mp3@de.ibm.com> 7e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * 8e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * This program is free software; you can redistribute it and/or modify 9e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * it under the terms of the GNU General Public License as published by 10e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * the Free Software Foundation; either version 2 of the License, or 11e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * (at your option) any later version. 12e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * 13e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * This program is distributed in the hope that it will be useful, 14e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * but WITHOUT ANY WARRANTY; without even the implied warranty of 15e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * GNU General Public License for more details. 17e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * 18e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * You should have received a copy of the GNU General Public License 19e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * along with this program; if not, write to the Free Software 20e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */ 22e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 23e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <sys/types.h> 24e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <sys/stat.h> 25e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <fcntl.h> 26e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <unistd.h> 27e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <stdio.h> 28e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <stdlib.h> 29e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <string.h> 30e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <signal.h> 31e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <getopt.h> 32e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <errno.h> 33e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <locale.h> 34e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <libgen.h> 35e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <sys/msg.h> 36e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <pthread.h> 37e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <time.h> 38e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 39e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include "blktrace.h" 40e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include "rbtree.h" 41e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include "jhash.h" 42e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include "blkiomon.h" 43e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 44e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstruct trace { 45e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct blk_io_trace bit; 46e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct rb_node node; 47e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct trace *next; 48e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat long sequence; 49e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}; 50e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 51e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstruct rb_search { 52e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct rb_node **node_ptr; 53e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct rb_node *parent; 54e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}; 55e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 56e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstruct dstat_msg { 57e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat long mtype; 58e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct blkiomon_stat stat; 59e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}; 60e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 61e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstruct dstat { 62e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct dstat_msg msg; 63e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct rb_node node; 64e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct dstat *next; 65e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}; 66e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 67e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstruct output { 68e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat char *fn; 69e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat FILE *fp; 70e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat char *buf; 71e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat int pipe; 72e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}; 73e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 74e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic char blkiomon_version[] = "0.3"; 75e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 76e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic FILE *ifp; 77e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int interval = -1; 78e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 79e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic struct trace *vacant_traces_list = NULL; 80e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int vacant_traces = 0; 81e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 82e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#define TRACE_HASH_SIZE 128 83e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstruct trace *thash[TRACE_HASH_SIZE] = {}; 84e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 85e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic struct dstat *vacant_dstats_list = NULL; 86e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic struct rb_root dstat_tree[2] = { RB_ROOT, RB_ROOT }; 87e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic struct dstat *dstat_list[2] = {}; 88e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int dstat_curr = 0; 89e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 90e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic struct output drvdata, human, binary, debug; 91e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 92e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic char *msg_q_name = NULL; 93e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int msg_q_id = -1, msg_q = -1; 94e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic long msg_id = -1; 95e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 96e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic pthread_t interval_thread; 97e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic pthread_mutex_t dstat_mutex = PTHREAD_MUTEX_INITIALIZER; 98e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 99e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatint data_is_native = -1; 100e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 101e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int up = 1; 102e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 103e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/* debugging */ 104e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic long leftover = 0, driverdata = 0, match = 0, mismatch = 0, sequence = 0; 105e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 106e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void dump_bit(struct trace *t, const char *descr) 107e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 108e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct blk_io_trace *bit = &t->bit; 109e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 110e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!debug.fn) 111e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return; 112e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 113e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "--- %s ---\n", descr); 114e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "magic %16d\n", bit->magic); 115e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "sequence %16d\n", bit->sequence); 116e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "time %16ld\n", (unsigned long)bit->time); 117e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "sector %16ld\n", (unsigned long)bit->sector); 118e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "bytes %16d\n", bit->bytes); 119e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "action %16x\n", bit->action); 120e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "pid %16d\n", bit->pid); 121e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "device %16d\n", bit->device); 122e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "cpu %16d\n", bit->cpu); 123e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "error %16d\n", bit->error); 124e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "pdu_len %16d\n", bit->pdu_len); 125e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 126e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "order %16ld\n", t->sequence); 127e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 128e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 129e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void dump_bits(struct trace *t1, struct trace *t2, const char *descr) 130e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 131e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct blk_io_trace *bit1 = &t1->bit; 132e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct blk_io_trace *bit2 = &t2->bit; 133e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 134e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!debug.fn) 135e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return; 136e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 137e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "--- %s ---\n", descr); 138e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "magic %16d %16d\n", bit1->magic, bit2->magic); 139e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "sequence %16d %16d\n", 140e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat bit1->sequence, bit2->sequence); 141e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "time %16ld %16ld\n", 142e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat (unsigned long)bit1->time, (unsigned long)bit2->time); 143e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "sector %16ld %16ld\n", 144e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat (unsigned long)bit1->sector, (unsigned long)bit2->sector); 145e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "bytes %16d %16d\n", bit1->bytes, bit2->bytes); 146e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "action %16x %16x\n", bit1->action, bit2->action); 147e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "pid %16d %16d\n", bit1->pid, bit2->pid); 148e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "device %16d %16d\n", bit1->device, bit2->device); 149e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "cpu %16d %16d\n", bit1->cpu, bit2->cpu); 150e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "error %16d %16d\n", bit1->error, bit2->error); 151e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "pdu_len %16d %16d\n", bit1->pdu_len, bit2->pdu_len); 152e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 153e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "order %16ld %16ld\n", t1->sequence, t2->sequence); 154e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 155e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 156e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic struct dstat *blkiomon_alloc_dstat(void) 157e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 158e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct dstat *dstat; 159e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 160e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (vacant_dstats_list) { 161e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dstat = vacant_dstats_list; 162e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat vacant_dstats_list = dstat->next; 163e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } else 164e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dstat = malloc(sizeof(*dstat)); 165e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!dstat) { 166e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, 167e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "blkiomon: could not allocate device statistic"); 168e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return NULL; 169e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 170e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 171e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat blkiomon_stat_init(&dstat->msg.stat); 172e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return dstat; 173e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 174e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 175e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic struct dstat *blkiomon_find_dstat(struct rb_search *search, __u32 device) 176e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 177e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct rb_node **p = &(dstat_tree[dstat_curr].rb_node); 178e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct rb_node *parent = NULL; 179e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct dstat *dstat; 180e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 181e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat while (*p) { 182e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat parent = *p; 183e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 184e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dstat = rb_entry(parent, struct dstat, node); 185e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 186e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (dstat->msg.stat.device < device) 187e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat p = &(*p)->rb_left; 188e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat else if (dstat->msg.stat.device > device) 189e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat p = &(*p)->rb_right; 190e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat else 191e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return dstat; 192e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 193e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat search->node_ptr = p; 194e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat search->parent = parent; 195e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return NULL; 196e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 197e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 198e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic struct dstat *blkiomon_get_dstat(__u32 device) 199e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 200e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct dstat *dstat; 201e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct rb_search search; 202e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 203e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat pthread_mutex_lock(&dstat_mutex); 204e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 205e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dstat = blkiomon_find_dstat(&search, device); 206e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (dstat) 207e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat goto out; 208e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 209e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dstat = blkiomon_alloc_dstat(); 210e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!dstat) 211e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat goto out; 212e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 213e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dstat->msg.stat.device = device; 214e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 215e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat rb_link_node(&dstat->node, search.parent, search.node_ptr); 216e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat rb_insert_color(&dstat->node, &dstat_tree[dstat_curr]); 217e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 218e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dstat->next = dstat_list[dstat_curr]; 219e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dstat_list[dstat_curr] = dstat; 220e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 221e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatout: 222e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat pthread_mutex_unlock(&dstat_mutex); 223e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return dstat; 224e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 225e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 226e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int blkiomon_output_msg_q(struct dstat *dstat) 227e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 228e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!msg_q_name) 229e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 0; 230e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 231e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dstat->msg.mtype = msg_id; 232e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return msgsnd(msg_q, &dstat->msg, sizeof(struct blkiomon_stat), 0); 233e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 234e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 235e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int blkiomon_output_binary(struct dstat *dstat) 236e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 237e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct blkiomon_stat *p = &dstat->msg.stat; 238e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 239e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!binary.fn) 240e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 0; 241e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 242e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (fwrite(p, sizeof(*p), 1, binary.fp) != 1) 243e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat goto failed; 244e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (binary.pipe && fflush(binary.fp)) 245e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat goto failed; 246e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 0; 247e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 248e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatfailed: 249e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, "blkiomon: could not write to %s\n", binary.fn); 250e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fclose(binary.fp); 251e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat binary.fn = NULL; 252e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 1; 253e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 254e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 255e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic struct dstat *blkiomon_output(struct dstat *head, struct timespec *ts) 256e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 257e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct dstat *dstat, *tail = NULL; 258e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 259e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat for (dstat = head; dstat; dstat = dstat->next) { 260e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dstat->msg.stat.time = ts->tv_sec; 261e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat blkiomon_stat_print(human.fp, &dstat->msg.stat); 262e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat blkiomon_stat_to_be(&dstat->msg.stat); 263e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat blkiomon_output_binary(dstat); 264e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat blkiomon_output_msg_q(dstat); 265e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat tail = dstat; 266e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 267e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return tail; 268e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 269e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 270e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void *blkiomon_interval(void *data) 271e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 272e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct timespec wake, r; 273e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct dstat *head, *tail; 274e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat int finished; 275e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 276e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat clock_gettime(CLOCK_REALTIME, &wake); 277e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 278e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat while (1) { 279e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat wake.tv_sec += interval; 280e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &wake, &r)) { 281e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, "blkiomon: interrupted sleep"); 282e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat continue; 283e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 284e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 285e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /* grab tree and make data gatherer build up another tree */ 286e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat pthread_mutex_lock(&dstat_mutex); 287e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat finished = dstat_curr; 288e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dstat_curr = dstat_curr ? 0 : 1; 289e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat pthread_mutex_unlock(&dstat_mutex); 290e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 291e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat head = dstat_list[finished]; 292e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!head) 293e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat continue; 294e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dstat_list[finished] = NULL; 295e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dstat_tree[finished] = RB_ROOT; 296e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat tail = blkiomon_output(head, &wake); 297e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 298e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat pthread_mutex_lock(&dstat_mutex); 299e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat tail->next = vacant_dstats_list; 300e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat vacant_dstats_list = head; 301e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat pthread_mutex_unlock(&dstat_mutex); 302e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 303e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return data; 304e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 305e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 306e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#define BLK_DATADIR(a) (((a) >> BLK_TC_SHIFT) & (BLK_TC_READ | BLK_TC_WRITE)) 307e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 308e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int blkiomon_account(struct blk_io_trace *bit_d, 309e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct blk_io_trace *bit_c) 310e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 311e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct dstat *dstat; 312e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct blkiomon_stat *p; 313e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat __u64 d2c = (bit_c->time - bit_d->time) / 1000; /* ns -> us */ 314e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat __u32 size = bit_d->bytes; 315e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat __u64 thrput = size * 1000 / d2c; 316e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 317e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dstat = blkiomon_get_dstat(bit_d->device); 318e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!dstat) 319e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 1; 320e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat p = &dstat->msg.stat; 321e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 322e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (BLK_DATADIR(bit_c->action) & BLK_TC_READ) { 323e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat minmax_account(&p->thrput_r, thrput); 324e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat minmax_account(&p->size_r, size); 325e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat minmax_account(&p->d2c_r, d2c); 326e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } else if (BLK_DATADIR(bit_c->action) & BLK_TC_WRITE) { 327e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat minmax_account(&p->thrput_w, thrput); 328e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat minmax_account(&p->size_w, size); 329e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat minmax_account(&p->d2c_w, d2c); 330e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } else 331e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat p->bidir++; 332e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 333e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat histlog2_account(p->size_hist, size, &size_hist); 334e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat histlog2_account(p->d2c_hist, d2c, &d2c_hist); 335e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 0; 336e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 337e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 338e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic struct trace *blkiomon_alloc_trace(void) 339e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 340e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct trace *t = vacant_traces_list; 341e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (t) { 342e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat vacant_traces_list = t->next; 343e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat vacant_traces--; 344e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } else 345e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat t = malloc(sizeof(*t)); 346e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat memset(t, 0, sizeof(*t)); 347e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return t; 348e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 349e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 350e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void blkiomon_free_trace(struct trace *t) 351e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 352e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (vacant_traces < 256) { 353e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat t->next = vacant_traces_list; 354e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat vacant_traces_list = t; 355e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat vacant_traces++; 356e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } else 357e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat free(t); 358e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 359e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 360e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int action(int a) 361e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 362e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat int bits = BLK_TC_WRITE | BLK_TC_READ | BLK_TC_FS | BLK_TC_PC; 363e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return a & (BLK_TC_ACT(bits)); 364e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 365e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 366e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void blkiomon_store_trace(struct trace *t) 367e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 368e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat int i = t->bit.sector % TRACE_HASH_SIZE; 369e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 370e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat t->next = thash[i]; 371e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat thash[i] = t; 372e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 373e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 374e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic struct trace *blkiomon_fetch_trace(struct blk_io_trace *bit) 375e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 376e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat int i = bit->sector % TRACE_HASH_SIZE; 377e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct trace *t, *prev = NULL; 378e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 379e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat for (t = thash[i]; t; t = t->next) { 380e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (t->bit.device == bit->device && 381e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat t->bit.sector == bit->sector && 382e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat action(t->bit.action) == action(bit->action)) { 383e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (prev) 384e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat prev->next = t->next; 385e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat else 386e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat thash[i] = t->next; 387e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return t; 388e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 389e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat prev = t; 390e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 391e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return NULL; 392e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 393e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 394e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic struct trace *blkiomon_do_trace(struct trace *t) 395e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 396e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct trace *t_stored, *t_old, *t_young; 397e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 398e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /* store trace if there is no match yet */ 399e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat t_stored = blkiomon_fetch_trace(&t->bit); 400e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!t_stored) { 401e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat blkiomon_store_trace(t); 402e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return blkiomon_alloc_trace(); 403e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 404e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 405e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /* figure out older trace and younger trace */ 406e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (t_stored->bit.time < t->bit.time) { 407e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat t_old = t_stored; 408e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat t_young = t; 409e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } else { 410e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat t_old = t; 411e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat t_young = t_stored; 412e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 413e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 414e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /* we need an older D trace and a younger C trace */ 415e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (t_old->bit.action & BLK_TC_ACT(BLK_TC_ISSUE) && 416e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat t_young->bit.action & BLK_TC_ACT(BLK_TC_COMPLETE)) { 417e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /* matching D and C traces - update statistics */ 418e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat match++; 419e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat blkiomon_account(&t_old->bit, &t_young->bit); 420e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat blkiomon_free_trace(t_stored); 421e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return t; 422e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 423e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 424e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /* no matching D and C traces - keep more recent trace */ 425e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dump_bits(t_old, t_young, "mismatch"); 426e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat mismatch++; 427e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat blkiomon_store_trace(t_young); 428e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return t_old; 429e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 430e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 431e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int blkiomon_dump_drvdata(struct blk_io_trace *bit, void *pdu_buf) 432e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 433e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!drvdata.fn) 434e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 0; 435e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 436e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (fwrite(bit, sizeof(*bit), 1, drvdata.fp) != 1) 437e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat goto failed; 438e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (fwrite(pdu_buf, bit->pdu_len, 1, drvdata.fp) != 1) 439e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat goto failed; 440e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (drvdata.pipe && fflush(drvdata.fp)) 441e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat goto failed; 442e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 0; 443e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 444e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatfailed: 445e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, "blkiomon: could not write to %s\n", drvdata.fn); 446e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fclose(drvdata.fp); 447e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat drvdata.fn = NULL; 448e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 1; 449e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 450e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 451e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int blkiomon_do_fifo(void) 452e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 453e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct trace *t; 454e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct blk_io_trace *bit; 455e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat void *pdu_buf = NULL; 456e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 457e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat t = blkiomon_alloc_trace(); 458e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!t) 459e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 1; 460e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat bit = &t->bit; 461e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 462e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat while (up) { 463e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (fread(bit, sizeof(*bit), 1, ifp) != 1) { 464e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!feof(ifp)) 465e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, 466e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "blkiomon: could not read trace"); 467e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat break; 468e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 469e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (ferror(ifp)) { 470e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat clearerr(ifp); 471e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, "blkiomon: error while reading trace"); 472e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat break; 473e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 474e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 475e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (data_is_native == -1 && check_data_endianness(bit->magic)) { 476e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, "blkiomon: endianess problem\n"); 477e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat break; 478e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 479e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 480e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /* endianess */ 481e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat trace_to_cpu(bit); 482e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (verify_trace(bit)) { 483e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, "blkiomon: bad trace\n"); 484e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat break; 485e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 486e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 487e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /* read additional trace payload */ 488e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (bit->pdu_len) { 489e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat pdu_buf = realloc(pdu_buf, bit->pdu_len); 490e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (fread(pdu_buf, bit->pdu_len, 1, ifp) != 1) { 491e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat clearerr(ifp); 492e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, "blkiomon: could not read payload\n"); 493e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat break; 494e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 495e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 496e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 497e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat t->sequence = sequence++; 498e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 499e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /* forward low-level device driver trace to other tool */ 500e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (bit->action & BLK_TC_ACT(BLK_TC_DRV_DATA)) { 501e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat driverdata++; 502e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (blkiomon_dump_drvdata(bit, pdu_buf)) { 503e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, "blkiomon: could not send trace\n"); 504e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat break; 505e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 506e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat continue; 507e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 508e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 509e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!(bit->action & BLK_TC_ACT(BLK_TC_ISSUE | BLK_TC_COMPLETE))) 510e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat continue; 511e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 512e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /* try to find matching trace and update statistics */ 513e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat t = blkiomon_do_trace(t); 514e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!t) { 515e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, "blkiomon: could not alloc trace\n"); 516e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat break; 517e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 518e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat bit = &t->bit; 519e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat /* t and bit will be recycled for next incoming trace */ 520e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 521e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat blkiomon_free_trace(t); 522e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat free(pdu_buf); 523e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 0; 524e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 525e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 526e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int blkiomon_open_output(struct output *out) 527e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 528e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat int mode, vbuf_size; 529e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 530e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!out->fn) 531e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 0; 532e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 533e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!strcmp(out->fn, "-")) { 534e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat out->fp = fdopen(STDOUT_FILENO, "w"); 535e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat mode = _IOLBF; 536e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat vbuf_size = 4096; 537e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat out->pipe = 1; 538e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } else { 539e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat out->fp = fopen(out->fn, "w"); 540e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat mode = _IOFBF; 541e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat vbuf_size = 128 * 1024; 542e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat out->pipe = 0; 543e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 544e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!out->fp) 545e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat goto failed; 546e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat out->buf = malloc(128 * 1024); 547e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (setvbuf(out->fp, out->buf, mode, vbuf_size)) 548e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat goto failed; 549e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 0; 550e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 551e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatfailed: 552e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, "blkiomon: could not write to %s\n", out->fn); 553e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat out->fn = NULL; 554e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat free(out->buf); 555e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 1; 556e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 557e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 558e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic int blkiomon_open_msg_q(void) 559e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 560e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat key_t key; 561e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 562e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!msg_q_name) 563e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 0; 564e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!msg_q_id || msg_id <= 0) 565e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 1; 566e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat key = ftok(msg_q_name, msg_q_id); 567e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (key == -1) 568e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 1; 569e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat while (up) { 570e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat msg_q = msgget(key, S_IRWXU); 571e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (msg_q >= 0) 572e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat break; 573e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 574e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return (msg_q >= 0 ? 0 : -1); 575e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 576e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 577e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void blkiomon_debug(void) 578e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 579e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat int i; 580e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct trace *t; 581e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 582e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!debug.fn) 583e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return; 584e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 585e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat for (i = 0; i < TRACE_HASH_SIZE; i++) 586e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat for (t = thash[i]; t; t = t->next) { 587e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dump_bit(t, "leftover"); 588e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat leftover++; 589e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 590e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 591e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(debug.fp, "%ld leftover, %ld match, %ld mismatch, " 592e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "%ld driverdata, %ld overall\n", 593e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat leftover, match, mismatch, driverdata, sequence); 594e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 595e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 596e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#define S_OPTS "b:d:D:h:I:Q:q:m:V" 597e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 598e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic char usage_str[] = "\n\nblkiomon " \ 599e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "-I <interval> | --interval=<interval>\n" \ 600e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "[ -h <file> | --human-readable=<file> ]\n" \ 601e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "[ -b <file> | --binary=<file> ]\n" \ 602e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "[ -D <file> | --debug=<file> ]\n" \ 603e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "[ -Q <path name> | --msg-queue=<path name>]\n" \ 604e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "[ -q <msg queue id> | --msg-queue-id=<msg queue id>]\n" \ 605e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "[ -m <msg id> | --msg-id=<msg id>]\n" \ 606e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "[ -V | --version ]\n\n" \ 607e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "\t-I Sample interval.\n" \ 608e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "\t-h Human-readable output file.\n" \ 609e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "\t-b Binary output file.\n" \ 610e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "\t-d Output file for data emitted by low level device driver.\n" \ 611e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "\t-D Output file for debugging data.\n" \ 612e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "\t-Qqm Output to message queue using given ID for messages.\n" \ 613e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat "\t-V Print program version.\n\n"; 614e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 615e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic struct option l_opts[] = { 616e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat { 617e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .name = "human-readable", 618e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .has_arg = required_argument, 619e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .flag = NULL, 620e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .val = 'h' 621e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat }, 622e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat { 623e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .name = "binary", 624e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .has_arg = required_argument, 625e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .flag = NULL, 626e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .val = 'b' 627e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat }, 628e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat { 629e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .name = "dump-lldd", 630e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .has_arg = required_argument, 631e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .flag = NULL, 632e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .val = 'd' 633e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat }, 634e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat { 635e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .name = "debug", 636e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .has_arg = required_argument, 637e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .flag = NULL, 638e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .val = 'D' 639e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat }, 640e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat { 641e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .name = "interval", 642e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .has_arg = required_argument, 643e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .flag = NULL, 644e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .val = 'I' 645e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat }, 646e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat { 647e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .name = "msg-queue", 648e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .has_arg = required_argument, 649e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .flag = NULL, 650e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .val = 'Q' 651e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat }, 652e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat { 653e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .name = "msg-queue-id", 654e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .has_arg = required_argument, 655e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .flag = NULL, 656e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .val = 'q' 657e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat }, 658e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat { 659e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .name = "msg-id", 660e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .has_arg = required_argument, 661e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .flag = NULL, 662e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .val = 'm' 663e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat }, 664e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat { 665e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .name = "version", 666e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .has_arg = no_argument, 667e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .flag = NULL, 668e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .val = 'V' 669e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat }, 670e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat { 671e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat .name = NULL, 672e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 673e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat}; 674e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 675e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void blkiomon_signal(int signal) 676e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 677e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, "blkiomon: terminated by signal\n"); 678e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat up = signal & 0; 679e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 680e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 681e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatint main(int argc, char *argv[]) 682e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 683e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat int c; 684e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 685e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat signal(SIGALRM, blkiomon_signal); 686e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat signal(SIGINT, blkiomon_signal); 687e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat signal(SIGTERM, blkiomon_signal); 688e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat signal(SIGQUIT, blkiomon_signal); 689e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 690e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat while ((c = getopt_long(argc, argv, S_OPTS, l_opts, NULL)) != -1) { 691e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat switch (c) { 692e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat case 'h': 693e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat human.fn = optarg; 694e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat break; 695e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat case 'b': 696e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat binary.fn = optarg; 697e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat break; 698e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat case 'd': 699e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat drvdata.fn = optarg; 700e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat break; 701e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat case 'D': 702e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat debug.fn = optarg; 703e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat break; 704e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat case 'I': 705e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat interval = atoi(optarg); 706e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat break; 707e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat case 'Q': 708e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat msg_q_name = optarg; 709e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat break; 710e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat case 'q': 711e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat msg_q_id = atoi(optarg); 712e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat break; 713e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat case 'm': 714e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat msg_id = atoi(optarg); 715e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat break; 716e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat case 'V': 717e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat printf("%s version %s\n", argv[0], blkiomon_version); 718e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 0; 719e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat default: 720e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, "Usage: %s", usage_str); 721e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 1; 722e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 723e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 724e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 725e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (interval <= 0) { 726e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, "Usage: %s", usage_str); 727e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 1; 728e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 729e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 730e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat ifp = fdopen(STDIN_FILENO, "r"); 731e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (!ifp) { 732e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat perror("blkiomon: could not open stdin for reading"); 733e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 1; 734e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 735e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 736e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (blkiomon_open_output(&human)) 737e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 1; 738e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (blkiomon_open_output(&binary)) 739e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 1; 740e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (blkiomon_open_output(&drvdata)) 741e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 1; 742e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (blkiomon_open_output(&debug)) 743e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 1; 744e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (blkiomon_open_msg_q()) 745e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 1; 746e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 747e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (pthread_create(&interval_thread, NULL, blkiomon_interval, NULL)) { 748e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fprintf(stderr, "blkiomon: could not create thread"); 749e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 1; 750e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 751e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 752e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat blkiomon_do_fifo(); 753e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 754e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat blkiomon_debug(); 755e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return 0; 756e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 757