geom_gate userland utility improvements
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

400 lines
8.8 KiB

  1. /*-
  2. * Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
  15. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
  18. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  20. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  21. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  22. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  23. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  24. * SUCH DAMAGE.
  25. *
  26. * $FreeBSD$
  27. */
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <unistd.h>
  31. #include <fcntl.h>
  32. #include <sys/param.h>
  33. #include <sys/disk.h>
  34. #include <sys/stat.h>
  35. #include <sys/endian.h>
  36. #include <sys/socket.h>
  37. #include <sys/linker.h>
  38. #include <sys/module.h>
  39. #include <netinet/in.h>
  40. #include <netinet/tcp.h>
  41. #include <arpa/inet.h>
  42. #include <signal.h>
  43. #include <err.h>
  44. #include <errno.h>
  45. #include <string.h>
  46. #include <strings.h>
  47. #include <libgen.h>
  48. #include <libutil.h>
  49. #include <netdb.h>
  50. #include <syslog.h>
  51. #include <stdarg.h>
  52. #include <stdint.h>
  53. #include <libgeom.h>
  54. #include <geom/gate/g_gate.h>
  55. #include "ggate.h"
  56. int g_gate_devfd = -1;
  57. int g_gate_verbose = 0;
  58. void
  59. g_gate_vlog(int priority, const char *message, va_list ap)
  60. {
  61. if (g_gate_verbose) {
  62. const char *prefix;
  63. switch (priority) {
  64. case LOG_ERR:
  65. prefix = "error";
  66. break;
  67. case LOG_WARNING:
  68. prefix = "warning";
  69. break;
  70. case LOG_NOTICE:
  71. prefix = "notice";
  72. break;
  73. case LOG_INFO:
  74. prefix = "info";
  75. break;
  76. case LOG_DEBUG:
  77. prefix = "debug";
  78. break;
  79. default:
  80. prefix = "unknown";
  81. }
  82. printf("%s: ", prefix);
  83. vprintf(message, ap);
  84. printf("\n");
  85. } else {
  86. if (priority != LOG_DEBUG)
  87. vsyslog(priority, message, ap);
  88. }
  89. }
  90. void
  91. g_gate_log(int priority, const char *message, ...)
  92. {
  93. va_list ap;
  94. va_start(ap, message);
  95. g_gate_vlog(priority, message, ap);
  96. va_end(ap);
  97. }
  98. void
  99. g_gate_xvlog(const char *message, va_list ap)
  100. {
  101. g_gate_vlog(LOG_ERR, message, ap);
  102. g_gate_vlog(LOG_ERR, "Exiting.", ap);
  103. exit(EXIT_FAILURE);
  104. }
  105. void
  106. g_gate_xlog(const char *message, ...)
  107. {
  108. va_list ap;
  109. va_start(ap, message);
  110. g_gate_xvlog(message, ap);
  111. /* NOTREACHED */
  112. va_end(ap);
  113. exit(EXIT_FAILURE);
  114. }
  115. off_t
  116. g_gate_mediasize(int fd)
  117. {
  118. off_t mediasize;
  119. struct stat sb;
  120. if (fstat(fd, &sb) == -1)
  121. g_gate_xlog("fstat(): %s.", strerror(errno));
  122. if (S_ISCHR(sb.st_mode)) {
  123. if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) == -1) {
  124. g_gate_xlog("Can't get media size: %s.",
  125. strerror(errno));
  126. }
  127. } else if (S_ISREG(sb.st_mode)) {
  128. mediasize = sb.st_size;
  129. } else {
  130. g_gate_xlog("Unsupported file system object.");
  131. }
  132. return (mediasize);
  133. }
  134. unsigned
  135. g_gate_sectorsize(int fd)
  136. {
  137. unsigned secsize;
  138. struct stat sb;
  139. if (fstat(fd, &sb) == -1)
  140. g_gate_xlog("fstat(): %s.", strerror(errno));
  141. if (S_ISCHR(sb.st_mode)) {
  142. if (ioctl(fd, DIOCGSECTORSIZE, &secsize) == -1) {
  143. g_gate_xlog("Can't get sector size: %s.",
  144. strerror(errno));
  145. }
  146. } else if (S_ISREG(sb.st_mode)) {
  147. secsize = 512;
  148. } else {
  149. g_gate_xlog("Unsupported file system object.");
  150. }
  151. return (secsize);
  152. }
  153. void
  154. g_gate_open_device(void)
  155. {
  156. g_gate_devfd = open("/dev/" G_GATE_CTL_NAME, O_RDWR, 0);
  157. if (g_gate_devfd == -1)
  158. err(EXIT_FAILURE, "open(/dev/%s)", G_GATE_CTL_NAME);
  159. }
  160. void
  161. g_gate_close_device(void)
  162. {
  163. close(g_gate_devfd);
  164. }
  165. void
  166. g_gate_ioctl(unsigned long req, void *data)
  167. {
  168. if (ioctl(g_gate_devfd, req, data) == -1) {
  169. g_gate_xlog("%s: ioctl(/dev/%s): %s.", getprogname(),
  170. G_GATE_CTL_NAME, strerror(errno));
  171. }
  172. }
  173. void
  174. g_gate_destroy(int unit, int force)
  175. {
  176. struct g_gate_ctl_destroy ggio;
  177. ggio.gctl_version = G_GATE_VERSION;
  178. ggio.gctl_unit = unit;
  179. ggio.gctl_force = force;
  180. g_gate_ioctl(G_GATE_CMD_DESTROY, &ggio);
  181. }
  182. void
  183. g_gate_load_module(void)
  184. {
  185. if (modfind("g_gate") == -1) {
  186. /* Not present in kernel, try loading it. */
  187. if (kldload("geom_gate") == -1 || modfind("g_gate") == -1) {
  188. if (errno != EEXIST) {
  189. errx(EXIT_FAILURE,
  190. "geom_gate module not available!");
  191. }
  192. }
  193. }
  194. }
  195. ssize_t
  196. g_gate_send(int s, const void *buf, size_t len, int flags)
  197. {
  198. ssize_t done = 0, done2;
  199. const unsigned char *p = buf;
  200. while (len > 0) {
  201. done2 = send(s, p, len, flags);
  202. if (done2 == 0)
  203. break;
  204. else if (done2 == -1) {
  205. if (errno == EAGAIN) {
  206. printf("%s: EAGAIN\n", __func__);
  207. continue;
  208. }
  209. done = -1;
  210. break;
  211. }
  212. done += done2;
  213. p += done2;
  214. len -= done2;
  215. }
  216. return (done);
  217. }
  218. ssize_t
  219. g_gate_recv(int s, void *buf, size_t len, int flags)
  220. {
  221. ssize_t done;
  222. do {
  223. done = recv(s, buf, len, flags);
  224. } while (done == -1 && errno == EAGAIN);
  225. return (done);
  226. }
  227. int nagle = 1;
  228. unsigned rcvbuf = G_GATE_RCVBUF;
  229. unsigned sndbuf = G_GATE_SNDBUF;
  230. void
  231. g_gate_socket_settings(int sfd)
  232. {
  233. struct timeval tv;
  234. int bsize, on;
  235. /* Socket settings. */
  236. on = 1;
  237. if (nagle) {
  238. if (setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, &on,
  239. sizeof(on)) == -1) {
  240. g_gate_xlog("setsockopt() error: %s.", strerror(errno));
  241. }
  242. }
  243. if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)
  244. g_gate_xlog("setsockopt(SO_REUSEADDR): %s.", strerror(errno));
  245. bsize = rcvbuf;
  246. if (setsockopt(sfd, SOL_SOCKET, SO_RCVBUF, &bsize, sizeof(bsize)) == -1)
  247. g_gate_xlog("setsockopt(SO_RCVBUF): %s.", strerror(errno));
  248. bsize = sndbuf;
  249. if (setsockopt(sfd, SOL_SOCKET, SO_SNDBUF, &bsize, sizeof(bsize)) == -1)
  250. g_gate_xlog("setsockopt(SO_SNDBUF): %s.", strerror(errno));
  251. tv.tv_sec = 8;
  252. tv.tv_usec = 0;
  253. if (setsockopt(sfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) == -1) {
  254. g_gate_log(LOG_ERR, "setsockopt(SO_SNDTIMEO) error: %s.",
  255. strerror(errno));
  256. }
  257. if (setsockopt(sfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) {
  258. g_gate_log(LOG_ERR, "setsockopt(SO_RCVTIMEO) error: %s.",
  259. strerror(errno));
  260. }
  261. }
  262. #ifdef LIBGEOM
  263. static struct gclass *
  264. find_class(struct gmesh *mesh, const char *name)
  265. {
  266. struct gclass *class;
  267. LIST_FOREACH(class, &mesh->lg_class, lg_class) {
  268. if (strcmp(class->lg_name, name) == 0)
  269. return (class);
  270. }
  271. return (NULL);
  272. }
  273. static const char *
  274. get_conf(struct ggeom *gp, const char *name)
  275. {
  276. struct gconfig *conf;
  277. LIST_FOREACH(conf, &gp->lg_config, lg_config) {
  278. if (strcmp(conf->lg_name, name) == 0)
  279. return (conf->lg_val);
  280. }
  281. return (NULL);
  282. }
  283. static void
  284. show_config(struct ggeom *gp, int verbose)
  285. {
  286. struct gprovider *pp;
  287. char buf[5];
  288. pp = LIST_FIRST(&gp->lg_provider);
  289. if (pp == NULL)
  290. return;
  291. if (!verbose) {
  292. printf("%s\n", pp->lg_name);
  293. return;
  294. }
  295. printf(" NAME: %s\n", pp->lg_name);
  296. printf(" info: %s\n", get_conf(gp, "info"));
  297. printf(" access: %s\n", get_conf(gp, "access"));
  298. printf(" timeout: %s\n", get_conf(gp, "timeout"));
  299. printf("queue_count: %s\n", get_conf(gp, "queue_count"));
  300. printf(" queue_size: %s\n", get_conf(gp, "queue_size"));
  301. printf(" references: %s\n", get_conf(gp, "ref"));
  302. humanize_number(buf, sizeof(buf), (int64_t)pp->lg_mediasize, "",
  303. HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
  304. printf(" mediasize: %jd (%s)\n", (intmax_t)pp->lg_mediasize, buf);
  305. printf(" sectorsize: %u\n", pp->lg_sectorsize);
  306. printf(" mode: %s\n", pp->lg_mode);
  307. printf("\n");
  308. }
  309. void
  310. g_gate_list(int unit, int verbose)
  311. {
  312. struct gmesh mesh;
  313. struct gclass *class;
  314. struct ggeom *gp;
  315. char name[64];
  316. int error;
  317. error = geom_gettree(&mesh);
  318. if (error != 0)
  319. exit(EXIT_FAILURE);
  320. class = find_class(&mesh, G_GATE_CLASS_NAME);
  321. if (class == NULL) {
  322. geom_deletetree(&mesh);
  323. exit(EXIT_SUCCESS);
  324. }
  325. if (unit >= 0) {
  326. snprintf(name, sizeof(name), "%s%d", G_GATE_PROVIDER_NAME,
  327. unit);
  328. }
  329. LIST_FOREACH(gp, &class->lg_geom, lg_geom) {
  330. if (unit != -1 && strcmp(gp->lg_name, name) != 0)
  331. continue;
  332. show_config(gp, verbose);
  333. }
  334. geom_deletetree(&mesh);
  335. exit(EXIT_SUCCESS);
  336. }
  337. #endif /* LIBGEOM */
  338. in_addr_t
  339. g_gate_str2ip(const char *str)
  340. {
  341. struct hostent *hp;
  342. in_addr_t ip;
  343. ip = inet_addr(str);
  344. if (ip != INADDR_NONE) {
  345. /* It is a valid IP address. */
  346. return (ip);
  347. }
  348. /* Check if it is a valid host name. */
  349. hp = gethostbyname(str);
  350. if (hp == NULL)
  351. return (INADDR_NONE);
  352. return (((struct in_addr *)(void *)hp->h_addr)->s_addr);
  353. }