PageRenderTime 45ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/gfs2-utils/group/gfs_control/main.c

#
C | 465 lines | 373 code | 84 blank | 8 comment | 55 complexity | 4d731d11e38082fe00b1e9964bee62ef MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, ISC
  1. #include "clusterautoconfig.h"
  2. #include <sys/types.h>
  3. #include <sys/un.h>
  4. #include <inttypes.h>
  5. #include <unistd.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <stdint.h>
  9. #include <stddef.h>
  10. #include <fcntl.h>
  11. #include <string.h>
  12. #include <errno.h>
  13. #include <limits.h>
  14. #include <netinet/in.h>
  15. #include "libgfscontrol.h"
  16. #define OPTION_STRING "nhV"
  17. #define OP_LIST 1
  18. #define OP_DUMP 2
  19. #define OP_PLOCKS 3
  20. #define OP_JOIN 4
  21. #define OP_LEAVE 5
  22. #define OP_JOINLEAVE 6
  23. static char *fsname;
  24. static int operation;
  25. static int opt_ind;
  26. static int ls_all_nodes;
  27. #define MAX_MG 128
  28. #define MAX_NODES 128
  29. struct gfsc_mountgroup mgs[MAX_MG];
  30. struct gfsc_node nodes[MAX_NODES];
  31. static void print_usage(const char *prog_name)
  32. {
  33. printf("Usage:\n");
  34. printf("\n");
  35. printf("%s [options] [ls|dump|plocks]\n", prog_name);
  36. printf("\n");
  37. printf("Options:\n");
  38. printf(" -n Show all node information in ls\n");
  39. printf(" -h Print this help, then exit\n");
  40. printf(" -V Print program version information, then exit\n");
  41. printf("\n");
  42. }
  43. static void decode_arguments(int argc, char **argv)
  44. {
  45. int cont = 1;
  46. int optchar;
  47. int need_fsname;
  48. while (cont) {
  49. optchar = getopt(argc, argv, OPTION_STRING);
  50. switch (optchar) {
  51. case 'n':
  52. ls_all_nodes = 1;
  53. break;
  54. case 'h':
  55. print_usage(argv[0]);
  56. exit(EXIT_SUCCESS);
  57. break;
  58. case 'V':
  59. printf("%s %s (built %s %s)\n",
  60. argv[0], VERSION, __DATE__, __TIME__);
  61. /* printf("%s\n", REDHAT_COPYRIGHT); */
  62. exit(EXIT_SUCCESS);
  63. break;
  64. case ':':
  65. case '?':
  66. fprintf(stderr, "Please use '-h' for usage.\n");
  67. exit(EXIT_FAILURE);
  68. break;
  69. case EOF:
  70. cont = 0;
  71. break;
  72. default:
  73. fprintf(stderr, "unknown option: %c\n", optchar);
  74. exit(EXIT_FAILURE);
  75. break;
  76. };
  77. }
  78. need_fsname = 1;
  79. while (optind < argc) {
  80. if (!strncmp(argv[optind], "leave", 5) &&
  81. (strlen(argv[optind]) == 5)) {
  82. operation = OP_LEAVE;
  83. opt_ind = optind + 1;
  84. break;
  85. } else if (!strncmp(argv[optind], "ls", 2) &&
  86. (strlen(argv[optind]) == 2)) {
  87. operation = OP_LIST;
  88. opt_ind = optind + 1;
  89. need_fsname = 0;
  90. break;
  91. } else if (!strncmp(argv[optind], "dump", 4) &&
  92. (strlen(argv[optind]) == 4)) {
  93. operation = OP_DUMP;
  94. opt_ind = optind + 1;
  95. need_fsname = 0;
  96. break;
  97. } else if (!strncmp(argv[optind], "plocks", 6) &&
  98. (strlen(argv[optind]) == 6)) {
  99. operation = OP_PLOCKS;
  100. opt_ind = optind + 1;
  101. break;
  102. }
  103. optind++;
  104. }
  105. if (!operation || !opt_ind) {
  106. print_usage(argv[0]);
  107. exit(EXIT_FAILURE);
  108. }
  109. if (optind < argc - 1)
  110. fsname = argv[opt_ind];
  111. else if (need_fsname) {
  112. fprintf(stderr, "fs name required\n");
  113. exit(EXIT_FAILURE);
  114. }
  115. }
  116. static int do_write(int fd, void *buf, size_t count)
  117. {
  118. int rv, off = 0;
  119. retry:
  120. rv = write(fd, (char *)buf + off, count);
  121. if (rv == -1 && errno == EINTR)
  122. goto retry;
  123. if (rv < 0)
  124. return rv;
  125. if (rv != count) {
  126. count -= rv;
  127. off += rv;
  128. goto retry;
  129. }
  130. return 0;
  131. }
  132. static void do_leave(char *table)
  133. {
  134. struct gfsc_mount_args ma;
  135. int rv;
  136. memset(&ma, 0, sizeof(ma));
  137. strncpy(ma.table, table, sizeof(ma.table));
  138. rv = gfsc_fs_leave(&ma, 0);
  139. if (rv < 0)
  140. fprintf(stderr, "gfs_controld leave error %d\n", rv);
  141. }
  142. static char *mg_flags_str(uint32_t flags)
  143. {
  144. static char str[128];
  145. int i = 0;
  146. memset(str, 0, sizeof(str));
  147. if (flags & GFSC_MF_LOCAL_RECOVERY_BUSY) {
  148. i++;
  149. strcat(str, "recover");
  150. }
  151. if (flags & GFSC_MF_FIRST_RECOVERY_NEEDED) {
  152. strcat(str, i++ ? "," : "");
  153. strcat(str, "need_first");
  154. }
  155. if (flags & GFSC_MF_KERNEL_MOUNT_ERROR) {
  156. strcat(str, i++ ? "," : "");
  157. strcat(str, "error");
  158. }
  159. if (flags & GFSC_MF_KERNEL_MOUNT_DONE) {
  160. strcat(str, i++ ? "," : "");
  161. strcat(str, "mounted");
  162. }
  163. if (flags & GFSC_MF_KERNEL_STOPPED) {
  164. strcat(str, i++ ? "," : "");
  165. strcat(str, "blocked");
  166. }
  167. if (flags & GFSC_MF_LEAVING) {
  168. strcat(str, i++ ? "," : "");
  169. strcat(str, "leave");
  170. }
  171. if (flags & GFSC_MF_JOINING) {
  172. strcat(str, i++ ? "," : "");
  173. strcat(str, "join");
  174. }
  175. /* leave this one out, it will often be set and we don't need
  176. to see it */
  177. /*
  178. if (flags & GFSC_MF_FIRST_RECOVERY_MSG)
  179. strcat(str, "first_recovery_msg ");
  180. */
  181. return str;
  182. }
  183. static char *node_mount_str(uint32_t flags)
  184. {
  185. static char str[128];
  186. int i = 0;
  187. memset(str, 0, sizeof(str));
  188. if (flags & GFSC_NF_KERNEL_MOUNT_DONE) {
  189. i++;
  190. strcat(str, "done");
  191. }
  192. if (flags & GFSC_NF_KERNEL_MOUNT_ERROR) {
  193. strcat(str, i++ ? "," : "");
  194. strcat(str, "error");
  195. }
  196. if (flags & GFSC_NF_READONLY) {
  197. strcat(str, i++ ? "," : "");
  198. strcat(str, "ro");
  199. }
  200. if (flags & GFSC_NF_SPECTATOR) {
  201. strcat(str, i++ ? "," : "");
  202. strcat(str, "spect");
  203. }
  204. if (!i)
  205. strcat(str, "none");
  206. /* ignoring CHECK_DLM */
  207. return str;
  208. }
  209. static int member_int(struct gfsc_node *n)
  210. {
  211. if (n->flags & GFSC_NF_DISALLOWED)
  212. return -1;
  213. if (n->flags & GFSC_NF_MEMBER)
  214. return 1;
  215. return 0;
  216. }
  217. static const char *condition_str(int cond)
  218. {
  219. switch (cond) {
  220. case 0:
  221. return "";
  222. case 1:
  223. return "kernel_mount_done";
  224. case 2:
  225. return "notify_nodeid";
  226. case 3:
  227. return "poll_dlm";
  228. case 4:
  229. return "pending";
  230. default:
  231. return "unknown";
  232. }
  233. }
  234. static void show_nodeids(int count, struct gfsc_node *nodes_in)
  235. {
  236. struct gfsc_node *n = nodes_in;
  237. int i;
  238. for (i = 0; i < count; i++) {
  239. printf("%d ", n->nodeid);
  240. n++;
  241. }
  242. printf("\n");
  243. }
  244. static int node_compare(const void *va, const void *vb)
  245. {
  246. const struct gfsc_node *a = va;
  247. const struct gfsc_node *b = vb;
  248. return a->nodeid - b->nodeid;
  249. }
  250. static void show_mg(struct gfsc_mountgroup *mg)
  251. {
  252. int rv, node_count;
  253. printf("name %s\n", mg->name);
  254. printf("id 0x%08x\n", mg->global_id);
  255. printf("flags 0x%08x %s\n",
  256. mg->flags, mg_flags_str(mg->flags));
  257. printf("change member %d joined %d remove %d failed %d seq %d,%d\n",
  258. mg->cg_prev.member_count, mg->cg_prev.joined_count,
  259. mg->cg_prev.remove_count, mg->cg_prev.failed_count,
  260. mg->cg_prev.combined_seq, mg->cg_prev.seq);
  261. node_count = 0;
  262. memset(&nodes, 0, sizeof(nodes));
  263. rv = gfsc_mountgroup_nodes(mg->name, GFSC_NODES_MEMBERS,
  264. MAX_NODES, &node_count, nodes);
  265. if (rv < 0) {
  266. printf("members error\n");
  267. goto next;
  268. }
  269. qsort(nodes, node_count, sizeof(struct gfsc_node), node_compare);
  270. printf("members ");
  271. show_nodeids(node_count, nodes);
  272. next:
  273. if (!mg->cg_next.seq)
  274. return;
  275. printf("new change member %d joined %d remove %d failed %d seq %d,%d\n",
  276. mg->cg_next.member_count, mg->cg_next.joined_count,
  277. mg->cg_next.remove_count, mg->cg_next.failed_count,
  278. mg->cg_next.combined_seq, mg->cg_next.seq);
  279. printf("new status wait_messages %d wait_condition %d %s\n",
  280. mg->cg_next.wait_messages, mg->cg_next.wait_condition,
  281. condition_str(mg->cg_next.wait_condition));
  282. node_count = 0;
  283. memset(&nodes, 0, sizeof(nodes));
  284. rv = gfsc_mountgroup_nodes(mg->name, GFSC_NODES_NEXT,
  285. MAX_NODES, &node_count, nodes);
  286. if (rv < 0) {
  287. printf("new members error\n");
  288. return;
  289. }
  290. qsort(nodes, node_count, sizeof(struct gfsc_node), node_compare);
  291. printf("new members ");
  292. show_nodeids(node_count, nodes);
  293. }
  294. static void show_all_nodes(int count, struct gfsc_node *nodes_in)
  295. {
  296. struct gfsc_node *n = nodes_in;
  297. int i;
  298. for (i = 0; i < count; i++) {
  299. printf("nodeid %d jid %d member %d failed %d start %d seq_add %u seq_rem %u mount %s\n",
  300. n->nodeid,
  301. n->jid,
  302. member_int(n),
  303. n->failed_reason,
  304. (n->flags & GFSC_NF_START) ? 1 : 0,
  305. n->added_seq,
  306. n->removed_seq,
  307. node_mount_str(n->flags));
  308. n++;
  309. }
  310. }
  311. static void do_list(char *name)
  312. {
  313. struct gfsc_mountgroup *mg;
  314. int node_count;
  315. int mg_count;
  316. int rv;
  317. int i;
  318. memset(mgs, 0, sizeof(mgs));
  319. if (name) {
  320. mg_count = 1;
  321. rv = gfsc_mountgroup_info(name, mgs);
  322. } else {
  323. rv = gfsc_mountgroups(MAX_MG, &mg_count, mgs);
  324. }
  325. if (rv < 0)
  326. exit(EXIT_FAILURE); /* gfs_controld probably not running */
  327. if (mg_count)
  328. printf("gfs mountgroups\n");
  329. for (i = 0; i < mg_count; i++) {
  330. mg = &mgs[i];
  331. show_mg(mg);
  332. if (!ls_all_nodes)
  333. goto next;
  334. node_count = 0;
  335. memset(&nodes, 0, sizeof(nodes));
  336. rv = gfsc_mountgroup_nodes(mg->name, GFSC_NODES_ALL,
  337. MAX_NODES, &node_count, nodes);
  338. if (rv < 0) {
  339. printf("all nodes error %d %d\n", rv, errno);
  340. goto next;
  341. }
  342. qsort(nodes, node_count, sizeof(struct gfsc_node),node_compare);
  343. printf("all nodes\n");
  344. show_all_nodes(node_count, nodes);
  345. next:
  346. printf("\n");
  347. }
  348. }
  349. static void do_plocks(char *name)
  350. {
  351. char buf[GFSC_DUMP_SIZE];
  352. memset(buf, 0, sizeof(buf));
  353. gfsc_dump_plocks(name, buf);
  354. do_write(STDOUT_FILENO, buf, strlen(buf));
  355. }
  356. static void do_dump(void)
  357. {
  358. char buf[GFSC_DUMP_SIZE];
  359. memset(buf, 0, sizeof(buf));
  360. gfsc_dump_debug(buf);
  361. do_write(STDOUT_FILENO, buf, strlen(buf));
  362. }
  363. int main(int argc, char **argv)
  364. {
  365. decode_arguments(argc, argv);
  366. switch (operation) {
  367. case OP_LEAVE:
  368. do_leave(fsname);
  369. break;
  370. case OP_LIST:
  371. do_list(fsname);
  372. break;
  373. case OP_DUMP:
  374. do_dump();
  375. break;
  376. case OP_PLOCKS:
  377. do_plocks(fsname);
  378. break;
  379. }
  380. return 0;
  381. }