sm_io.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /* $Id: sm_io.c,v 1.15 2004/02/26 22:48:08 dijkstra Exp $ */
  2. /*
  3. * Copyright (c) 2001-2004 Willem Dijkstra
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * - Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * - Redistributions in binary form must reproduce the above
  13. * copyright notice, this list of conditions and the following
  14. * disclaimer in the documentation and/or other materials provided
  15. * with the distribution.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  25. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  27. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  28. * POSSIBILITY OF SUCH DAMAGE.
  29. *
  30. */
  31. /*
  32. * Get current disk transfer statistics from kernel and return them in
  33. * symon_buf as
  34. *
  35. * total nr of transfers : total seeks : total bytes transferred
  36. *
  37. * Non re-entrant code: gets_io messes with globals r/w without a semaphore.
  38. *
  39. */
  40. #include <sys/param.h>
  41. #include <sys/sysctl.h>
  42. #include <sys/disk.h>
  43. #include <limits.h>
  44. #include <string.h>
  45. #include "error.h"
  46. #include "symon.h"
  47. #include "xmalloc.h"
  48. /* Globals for this module start with io_ */
  49. static char *io_dkstr = NULL;
  50. static struct diskstats *io_dkstats = NULL;
  51. static char **io_dknames = NULL;
  52. static int io_dks = 0;
  53. static int io_maxdks = 0;
  54. static size_t io_maxstr = 0;
  55. void
  56. gets_io()
  57. {
  58. int mib[3];
  59. char *p;
  60. int dks;
  61. size_t size;
  62. size_t strsize;
  63. /* how much memory is needed */
  64. mib[0] = CTL_HW;
  65. mib[1] = HW_DISKCOUNT;
  66. size = sizeof(dks);
  67. if (sysctl(mib, 2, &dks, &size, NULL, 0) < 0) {
  68. fatal("%s:%d: sysctl failed: can't get hw.diskcount",
  69. __FILE__, __LINE__);
  70. }
  71. mib[0] = CTL_HW;
  72. mib[1] = HW_DISKNAMES;
  73. strsize = 0;
  74. if (sysctl(mib, 2, NULL, &strsize, NULL, 0) < 0) {
  75. fatal("%s:%d: sysctl failed: can't get hw.disknames",
  76. __FILE__, __LINE__);
  77. }
  78. /* increase buffers if necessary */
  79. if (dks > io_maxdks || strsize > io_maxstr) {
  80. io_maxdks = dks;
  81. io_maxstr = strsize;
  82. if (io_maxdks > SYMON_MAX_DOBJECTS) {
  83. fatal("%s:%d: dynamic object limit (%d) exceeded for diskstat structures",
  84. __FILE__, __LINE__, SYMON_MAX_DOBJECTS);
  85. }
  86. if (io_maxstr > SYMON_MAX_OBJSIZE) {
  87. fatal("%s:%d: string size exceeded (%d)",
  88. __FILE__, __LINE__, SYMON_MAX_OBJSIZE);
  89. }
  90. io_dkstats = xrealloc(io_dkstats, io_maxdks * sizeof(struct diskstats));
  91. io_dknames = xrealloc(io_dknames, io_maxdks * sizeof(char *));
  92. io_dkstr = xrealloc(io_dkstr, io_maxstr + 1);
  93. }
  94. /* read data in anger */
  95. mib[0] = CTL_HW;
  96. mib[1] = HW_DISKNAMES;
  97. if (sysctl(mib, 2, io_dkstr, &io_maxstr, NULL, 0) < 0) {
  98. fatal("%s:%d: io can't get hw.disknames"
  99. __FILE__, __LINE__);
  100. }
  101. io_dkstr[io_maxstr] = '\0';
  102. mib[0] = CTL_HW;
  103. mib[1] = HW_DISKSTATS;
  104. size = io_maxdks * sizeof(struct diskstats);
  105. if (sysctl(mib, 2, io_dkstats, &size, NULL, 0) < 0) {
  106. fatal("%s:%d: io can't get hw.diskstats"
  107. __FILE__, __LINE__);
  108. }
  109. p = io_dkstr;
  110. io_dks = 0;
  111. io_dknames[io_dks] = p;
  112. while ((*p != '\0') && ((p - io_dkstr) < io_maxstr)) {
  113. if ((*p == ',') && (*p+1 != '\0')) {
  114. *p = '\0';
  115. io_dks++; p++;
  116. io_dknames[io_dks] = p;
  117. }
  118. p++;
  119. }
  120. }
  121. /* Prepare io module for first use */
  122. void
  123. init_io(char *s)
  124. {
  125. info("started module io(%.200s)", s);
  126. }
  127. /* Get new io statistics */
  128. int
  129. get_io(char *symon_buf, int maxlen, char *disk)
  130. {
  131. int i;
  132. /* look for disk */
  133. for (i = 0; i <= io_dks; i++) {
  134. if (strncmp(io_dknames[i], disk,
  135. (io_dkstr + io_maxstr - io_dknames[i])) == 0)
  136. #ifdef HAS_IO2
  137. return snpack(symon_buf, maxlen, disk, MT_IO2,
  138. io_dkstats[i].ds_rxfer,
  139. io_dkstats[i].ds_wxfer,
  140. io_dkstats[i].ds_seek,
  141. io_dkstats[i].ds_rbytes,
  142. io_dkstats[i].ds_wbytes);
  143. #else
  144. return snpack(symon_buf, maxlen, disk, MT_IO1,
  145. io_dkstats[i].ds_xfer,
  146. io_dkstats[i].ds_seek,
  147. io_dkstats[i].ds_bytes);
  148. #endif
  149. }
  150. return 0;
  151. }