geom_dump.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. /*-
  2. * SPDX-License-Identifier: BSD-3-Clause
  3. *
  4. * Copyright (c) 2002 Poul-Henning Kamp
  5. * Copyright (c) 2002 Networks Associates Technology, Inc.
  6. * All rights reserved.
  7. * Copyright (c) 2013-2022 Alexander Motin <mav@FreeBSD.org>
  8. *
  9. * This software was developed for the FreeBSD Project by Poul-Henning Kamp
  10. * and NAI Labs, the Security Research Division of Network Associates, Inc.
  11. * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
  12. * DARPA CHATS research program.
  13. *
  14. * Redistribution and use in source and binary forms, with or without
  15. * modification, are permitted provided that the following conditions
  16. * are met:
  17. * 1. Redistributions of source code must retain the above copyright
  18. * notice, this list of conditions and the following disclaimer.
  19. * 2. Redistributions in binary form must reproduce the above copyright
  20. * notice, this list of conditions and the following disclaimer in the
  21. * documentation and/or other materials provided with the distribution.
  22. * 3. The names of the authors may not be used to endorse or promote
  23. * products derived from this software without specific prior written
  24. * permission.
  25. *
  26. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  27. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  30. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  31. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  32. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  33. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  34. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  35. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  36. * SUCH DAMAGE.
  37. */
  38. #include <sys/param.h>
  39. #include <sys/sbuf.h>
  40. #include <sys/systm.h>
  41. #include <sys/malloc.h>
  42. #include <machine/stdarg.h>
  43. #include <geom/geom.h>
  44. #include <geom/geom_int.h>
  45. #include <geom/geom_disk.h>
  46. static void
  47. g_confdot_consumer(struct sbuf *sb, struct g_consumer *cp)
  48. {
  49. sbuf_printf(sb, "z%p [label=\"r%dw%de%d\"];\n",
  50. cp, cp->acr, cp->acw, cp->ace);
  51. if (cp->provider)
  52. sbuf_printf(sb, "z%p -> z%p;\n", cp, cp->provider);
  53. }
  54. static void
  55. g_confdot_provider(struct sbuf *sb, struct g_provider *pp)
  56. {
  57. sbuf_printf(sb, "z%p [shape=hexagon,label=\"%s\\nr%dw%de%d\\nerr#%d\\n"
  58. "sector=%u\\nstripe=%ju\"];\n", pp, pp->name, pp->acr, pp->acw,
  59. pp->ace, pp->error, pp->sectorsize, (uintmax_t)pp->stripesize);
  60. }
  61. static void
  62. g_confdot_geom(struct sbuf *sb, struct g_geom *gp)
  63. {
  64. struct g_consumer *cp;
  65. struct g_provider *pp;
  66. sbuf_printf(sb, "z%p [shape=box,label=\"%s\\n%s\\nr#%d\"];\n",
  67. gp, gp->class->name, gp->name, gp->rank);
  68. LIST_FOREACH(cp, &gp->consumer, consumer) {
  69. g_confdot_consumer(sb, cp);
  70. sbuf_printf(sb, "z%p -> z%p;\n", gp, cp);
  71. }
  72. LIST_FOREACH(pp, &gp->provider, provider) {
  73. g_confdot_provider(sb, pp);
  74. sbuf_printf(sb, "z%p -> z%p;\n", pp, gp);
  75. }
  76. }
  77. static void
  78. g_confdot_class(struct sbuf *sb, struct g_class *mp)
  79. {
  80. struct g_geom *gp;
  81. LIST_FOREACH(gp, &mp->geom, geom)
  82. g_confdot_geom(sb, gp);
  83. }
  84. void
  85. g_confdot(void *p, int flag )
  86. {
  87. struct g_class *mp;
  88. struct sbuf *sb;
  89. KASSERT(flag != EV_CANCEL, ("g_confdot was cancelled"));
  90. sb = p;
  91. g_topology_assert();
  92. sbuf_cat(sb, "digraph geom {\n");
  93. LIST_FOREACH(mp, &g_classes, class)
  94. g_confdot_class(sb, mp);
  95. sbuf_cat(sb, "}\n");
  96. sbuf_finish(sb);
  97. }
  98. static void
  99. g_conftxt_geom(struct sbuf *sb, struct g_geom *gp, int level)
  100. {
  101. struct g_provider *pp;
  102. struct g_consumer *cp;
  103. if (gp->flags & G_GEOM_WITHER)
  104. return;
  105. LIST_FOREACH(pp, &gp->provider, provider) {
  106. sbuf_printf(sb, "%d %s %s %ju %u", level, gp->class->name,
  107. pp->name, (uintmax_t)pp->mediasize, pp->sectorsize);
  108. if (gp->dumpconf != NULL)
  109. gp->dumpconf(sb, NULL, gp, NULL, pp);
  110. sbuf_cat(sb, "\n");
  111. LIST_FOREACH(cp, &pp->consumers, consumers)
  112. g_conftxt_geom(sb, cp->geom, level + 1);
  113. }
  114. }
  115. static void
  116. g_conftxt_class(struct sbuf *sb, struct g_class *mp)
  117. {
  118. struct g_geom *gp;
  119. LIST_FOREACH(gp, &mp->geom, geom)
  120. g_conftxt_geom(sb, gp, 0);
  121. }
  122. void
  123. g_conftxt(void *p, int flag)
  124. {
  125. struct g_class *mp;
  126. struct sbuf *sb;
  127. KASSERT(flag != EV_CANCEL, ("g_conftxt was cancelled"));
  128. sb = p;
  129. g_topology_assert();
  130. LIST_FOREACH(mp, &g_classes, class) {
  131. if (!strcmp(mp->name, G_DISK_CLASS_NAME) || !strcmp(mp->name, "MD"))
  132. g_conftxt_class(sb, mp);
  133. }
  134. sbuf_finish(sb);
  135. }
  136. void
  137. g_conf_cat_escaped(struct sbuf *sb, const char *buf)
  138. {
  139. const u_char *c;
  140. for (c = buf; *c != '\0'; c++) {
  141. if (*c == '&' || *c == '<' || *c == '>' ||
  142. *c == '\'' || *c == '"' || *c > 0x7e)
  143. sbuf_printf(sb, "&#x%X;", *c);
  144. else if (*c == '\t' || *c == '\n' || *c == '\r' || *c > 0x1f)
  145. sbuf_putc(sb, *c);
  146. else
  147. sbuf_putc(sb, '?');
  148. }
  149. }
  150. void
  151. g_conf_printf_escaped(struct sbuf *sb, const char *fmt, ...)
  152. {
  153. struct sbuf *s;
  154. va_list ap;
  155. s = sbuf_new_auto();
  156. va_start(ap, fmt);
  157. sbuf_vprintf(s, fmt, ap);
  158. va_end(ap);
  159. sbuf_finish(s);
  160. g_conf_cat_escaped(sb, sbuf_data(s));
  161. sbuf_delete(s);
  162. }
  163. static void
  164. g_conf_consumer(struct sbuf *sb, struct g_consumer *cp)
  165. {
  166. sbuf_printf(sb, "\t<consumer id=\"%p\">\n", cp);
  167. sbuf_printf(sb, "\t <geom ref=\"%p\"/>\n", cp->geom);
  168. if (cp->provider != NULL)
  169. sbuf_printf(sb, "\t <provider ref=\"%p\"/>\n", cp->provider);
  170. sbuf_printf(sb, "\t <mode>r%dw%de%d</mode>\n",
  171. cp->acr, cp->acw, cp->ace);
  172. if (cp->geom->flags & G_GEOM_WITHER)
  173. ;
  174. else if (cp->geom->dumpconf != NULL) {
  175. sbuf_cat(sb, "\t <config>\n");
  176. cp->geom->dumpconf(sb, "\t ", cp->geom, cp, NULL);
  177. sbuf_cat(sb, "\t </config>\n");
  178. }
  179. sbuf_cat(sb, "\t</consumer>\n");
  180. }
  181. static void
  182. g_conf_provider(struct sbuf *sb, struct g_provider *pp)
  183. {
  184. struct g_geom_alias *gap;
  185. sbuf_printf(sb, "\t<provider id=\"%p\">\n", pp);
  186. sbuf_printf(sb, "\t <geom ref=\"%p\"/>\n", pp->geom);
  187. sbuf_printf(sb, "\t <mode>r%dw%de%d</mode>\n",
  188. pp->acr, pp->acw, pp->ace);
  189. sbuf_cat(sb, "\t <name>");
  190. g_conf_cat_escaped(sb, pp->name);
  191. sbuf_cat(sb, "</name>\n");
  192. LIST_FOREACH(gap, &pp->aliases, ga_next) {
  193. sbuf_cat(sb, "\t <alias>");
  194. g_conf_cat_escaped(sb, gap->ga_alias);
  195. sbuf_cat(sb, "</alias>\n");
  196. }
  197. sbuf_printf(sb, "\t <mediasize>%jd</mediasize>\n",
  198. (intmax_t)pp->mediasize);
  199. sbuf_printf(sb, "\t <sectorsize>%u</sectorsize>\n", pp->sectorsize);
  200. sbuf_printf(sb, "\t <stripesize>%ju</stripesize>\n", (uintmax_t)pp->stripesize);
  201. sbuf_printf(sb, "\t <stripeoffset>%ju</stripeoffset>\n", (uintmax_t)pp->stripeoffset);
  202. if (pp->flags & G_PF_WITHER)
  203. sbuf_cat(sb, "\t <wither/>\n");
  204. else if (pp->geom->flags & G_GEOM_WITHER)
  205. ;
  206. else if (pp->geom->dumpconf != NULL) {
  207. sbuf_cat(sb, "\t <config>\n");
  208. pp->geom->dumpconf(sb, "\t ", pp->geom, NULL, pp);
  209. sbuf_cat(sb, "\t </config>\n");
  210. }
  211. sbuf_cat(sb, "\t</provider>\n");
  212. }
  213. static void
  214. g_conf_geom(struct sbuf *sb, struct g_geom *gp)
  215. {
  216. struct g_consumer *cp;
  217. struct g_provider *pp;
  218. sbuf_printf(sb, " <geom id=\"%p\">\n", gp);
  219. sbuf_printf(sb, " <class ref=\"%p\"/>\n", gp->class);
  220. sbuf_cat(sb, " <name>");
  221. g_conf_cat_escaped(sb, gp->name);
  222. sbuf_cat(sb, "</name>\n");
  223. sbuf_printf(sb, " <rank>%d</rank>\n", gp->rank);
  224. if (gp->flags & G_GEOM_WITHER)
  225. sbuf_cat(sb, " <wither/>\n");
  226. else if (gp->dumpconf != NULL) {
  227. sbuf_cat(sb, " <config>\n");
  228. gp->dumpconf(sb, "\t", gp, NULL, NULL);
  229. sbuf_cat(sb, " </config>\n");
  230. }
  231. LIST_FOREACH(cp, &gp->consumer, consumer)
  232. g_conf_consumer(sb, cp);
  233. LIST_FOREACH(pp, &gp->provider, provider)
  234. g_conf_provider(sb, pp);
  235. sbuf_cat(sb, " </geom>\n");
  236. }
  237. static bool
  238. g_conf_matchgp(struct g_geom *gp, struct g_geom **gps)
  239. {
  240. if (gps == NULL)
  241. return (true);
  242. for (; *gps != NULL; gps++) {
  243. if (*gps == gp)
  244. return (true);
  245. }
  246. return (false);
  247. }
  248. static void
  249. g_conf_class(struct sbuf *sb, struct g_class *mp, struct g_geom **gps)
  250. {
  251. struct g_geom *gp;
  252. sbuf_printf(sb, " <class id=\"%p\">\n", mp);
  253. sbuf_cat(sb, " <name>");
  254. g_conf_cat_escaped(sb, mp->name);
  255. sbuf_cat(sb, "</name>\n");
  256. LIST_FOREACH(gp, &mp->geom, geom) {
  257. if (!g_conf_matchgp(gp, gps))
  258. continue;
  259. g_conf_geom(sb, gp);
  260. if (sbuf_error(sb))
  261. break;
  262. }
  263. sbuf_cat(sb, " </class>\n");
  264. }
  265. void
  266. g_conf_specific(struct sbuf *sb, struct g_geom **gps)
  267. {
  268. struct g_class *mp2;
  269. g_topology_assert();
  270. sbuf_cat(sb, "<mesh>\n");
  271. LIST_FOREACH(mp2, &g_classes, class) {
  272. g_conf_class(sb, mp2, gps);
  273. if (sbuf_error(sb))
  274. break;
  275. }
  276. sbuf_cat(sb, "</mesh>\n");
  277. sbuf_finish(sb);
  278. }
  279. void
  280. g_confxml(void *p, int flag)
  281. {
  282. KASSERT(flag != EV_CANCEL, ("g_confxml was cancelled"));
  283. g_topology_assert();
  284. g_conf_specific(p, NULL);
  285. }
  286. void
  287. (g_trace)(int level, const char *fmt, ...)
  288. {
  289. va_list ap;
  290. if (!(g_debugflags & level))
  291. return;
  292. va_start(ap, fmt);
  293. vprintf(fmt, ap);
  294. va_end(ap);
  295. printf("\n");
  296. }