1/* 2 * Unix SMB/CIFS implementation. 3 * Performance Counter Daemon 4 * 5 * Copyright (C) Marcin Krzysztof Porwit 2005 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 */ 21 22#include "perf.h" 23 24void init_diskdata_desc(PERF_DATA_BLOCK *data) 25{ 26 init_perf_counter(&(data->diskInfo.diskObjDesc), 27 &(data->diskInfo.diskObjDesc), 28 get_counter_id(data), 29 "Logical Disk", 30 "The Logical Disk object consists of counters that show information about disks.", 31 0, 32 PERF_OBJECT); 33 init_perf_counter(&(data->diskInfo.freeMegs), 34 &(data->diskInfo.diskObjDesc), 35 get_counter_id(data), 36 "Megabytes Free", 37 "The amount of available disk space, in megabytes.", 38 PERF_SIZE_LARGE | PERF_TYPE_NUMBER | PERF_NUMBER_DECIMAL | PERF_DISPLAY_NO_SUFFIX, 39 PERF_COUNTER); 40 init_perf_counter(&(data->diskInfo.writesPerSec), 41 &(data->diskInfo.diskObjDesc), 42 get_counter_id(data), 43 "Writes/sec", 44 "The number of writes per second to that disk.", 45 PERF_SIZE_DWORD | PERF_TYPE_COUNTER | PERF_COUNTER_RATE | PERF_DELTA_COUNTER | PERF_DISPLAY_PER_SEC, 46 PERF_COUNTER); 47 init_perf_counter(&(data->diskInfo.readsPerSec), 48 &(data->diskInfo.diskObjDesc), 49 get_counter_id(data), 50 "Reads/sec", 51 "The number of reads of that disk per second.", 52 PERF_SIZE_DWORD | PERF_TYPE_COUNTER | PERF_COUNTER_RATE | PERF_DELTA_COUNTER | PERF_DISPLAY_PER_SEC, 53 PERF_COUNTER); 54 55 return; 56} 57void init_num_disks(PERF_DATA_BLOCK *data) 58{ 59 FILE *mtab; 60 char buf[PROC_BUF]; 61 char *start, *stop; 62 int i = 0, num; 63 64 if(!(mtab = fopen("/etc/mtab", "r"))) 65 { 66 perror("init_disk_names: fopen"); 67 exit(1); 68 } 69 70 rewind(mtab); 71 fflush(mtab); 72 73 while(fgets(buf, sizeof(buf), mtab)) 74 { 75 if(start = strstr(buf, "/dev/")) 76 { 77 if(start = strstr(start, "da")) 78 { 79 i++; 80 } 81 } 82 } 83 84 data->diskInfo.numDisks = i; 85 fclose(mtab); 86 87 return; 88} 89 90void init_disk_names(PERF_DATA_BLOCK *data) 91{ 92 FILE *mtab; 93 char buf[PROC_BUF]; 94 char *start, *stop; 95 int i = 0, num; 96 97 if(!(mtab = fopen("/etc/mtab", "r"))) 98 { 99 perror("init_disk_names: fopen"); 100 exit(1); 101 } 102 103 rewind(mtab); 104 fflush(mtab); 105 106 while(fgets(buf, sizeof(buf), mtab)) 107 { 108 if(start = strstr(buf, "/dev/")) 109 { 110 if(start = strstr(start, "da")) 111 { 112 start -=1; 113 stop = strstr(start, " "); 114 memcpy(data->diskInfo.mdata[i].name, start, stop - start); 115 start = stop +1; 116 stop = strstr(start, " "); 117 memcpy(data->diskInfo.mdata[i].mountpoint, start, stop - start); 118 i++; 119 } 120 } 121 } 122 123 fclose(mtab); 124 125 return; 126} 127 128void get_diskinfo(PERF_DATA_BLOCK *data) 129{ 130 int i; 131 DiskData *p; 132 struct statfs statfsbuf; 133 int status, num; 134 char buf[LARGE_BUF], *start; 135 FILE *diskstats; 136 long reads, writes, discard; 137 138 diskstats = fopen("/proc/diskstats", "r"); 139 rewind(diskstats); 140 fflush(diskstats); 141 status = fread(buf, sizeof(char), LARGE_BUF, diskstats); 142 fclose(diskstats); 143 144 for(i = 0; i < data->diskInfo.numDisks; i++) 145 { 146 p = &(data->diskInfo.data[i]); 147 status = statfs(data->diskInfo.mdata[i].mountpoint, &statfsbuf); 148 p->freeMegs = (statfsbuf.f_bfree*statfsbuf.f_bsize)/1048576; 149 start = strstr(buf, data->diskInfo.mdata[i].name); 150 start += strlen(data->diskInfo.mdata[i].name) + 1; 151 num = sscanf(start, "%u %u %u %u", 152 &reads, 153 &discard, 154 &writes, 155 &discard); 156 p->writesPerSec = writes; 157 p->readsPerSec = reads; 158 fprintf(stderr, "%s:\t%u\t%u\n", 159 data->diskInfo.mdata[i].mountpoint, 160 reads, writes); 161 } 162 return; 163} 164void init_disk_data(PERF_DATA_BLOCK *data) 165{ 166 init_diskdata_desc(data); 167 168 init_num_disks(data); 169 170 data->diskInfo.mdata = calloc(data->diskInfo.numDisks, sizeof(DiskMetaData)); 171 if(!data->diskInfo.mdata) 172 { 173 fatal("init_disk_data: out of memory"); 174 } 175 176 init_disk_names(data); 177 178 data->diskInfo.data = calloc(data->diskInfo.numDisks, sizeof(DiskData)); 179 if(!data->diskInfo.data) 180 { 181 fatal("init_disk_data: out of memory"); 182 } 183 184 get_diskinfo(data); 185 186 return; 187} 188 189void output_disk_desc(PERF_DATA_BLOCK *data, RuntimeSettings rt) 190{ 191 output_perf_desc(data->diskInfo.diskObjDesc, rt); 192 output_perf_desc(data->diskInfo.freeMegs, rt); 193 output_perf_desc(data->diskInfo.writesPerSec, rt); 194 output_perf_desc(data->diskInfo.readsPerSec, rt); 195 output_num_instances(data->diskInfo.diskObjDesc, data->diskInfo.numDisks, rt); 196 197 return; 198} 199 200void output_diskinfo(PERF_DATA_BLOCK *data, RuntimeSettings rt, int tdb_flags) 201{ 202 int i; 203 204 output_perf_counter(data->diskInfo.freeMegs, 205 data->diskInfo.data[0].freeMegs, 206 rt, tdb_flags); 207 output_perf_counter(data->diskInfo.writesPerSec, 208 (unsigned long long)data->diskInfo.data[0].writesPerSec, 209 rt, tdb_flags); 210 output_perf_counter(data->diskInfo.readsPerSec, 211 (unsigned long long)data->diskInfo.data[0].readsPerSec, 212 rt, tdb_flags); 213 214 for(i = 0; i < data->diskInfo.numDisks; i++) 215 { 216 output_perf_instance(data->diskInfo.diskObjDesc.index, 217 i, 218 (void *)&(data->diskInfo.data[i]), 219 sizeof(DiskData), 220 data->diskInfo.mdata[i].mountpoint, 221 rt, tdb_flags); 222 } 223 224 return; 225} 226