📄 mkraid.c
字号:
/* * mkraid.c : Utility for the Linux Multiple Devices driver * Copyright (C) 1997 Ingo Molnar, Miguel de Icaza, Gadi Oxman * Copyright (C) 1998 Erik Troan * * This utility reads a Linux MD raid1/4/5 configuration file, writes a * raid superblock on the devices in the raid set, and initializes the * set for first time use, depending on command line switches and * configuration file settings. * * This source is covered by the GNU GPL, the same as all Linux kernel * sources. */#include "common.h"#include "parser.h"#include "raid_io.h"#include "raidlib.h"#include "version.h"#include <popt.h>void printcfg (md_cfg_entry_t * cfg);void usage (void) { printf("usage: mkraid [--configfile] [--version] [--force] [--upgrade]\n"); printf(" [--dangerous-no-resync] [-acfhuv] </dev/md?>*\n");}static int makeOneRaid(mdu_version_t * ver, enum mkraidFunc func, md_cfg_entry_t * cfg, int force, int upgrade, int resync) {int i, ret, file; if (check_active(cfg)) return 1; if (analyze_sb(ver, func, cfg, force, upgrade, resync)) return 1; if (upgrade) return 0;#if 0 printcfg(cfg);#endif file = open(cfg->md_name,O_RDONLY); ret = ioctl(file, SET_ARRAY_INFO, (unsigned long)&cfg->array.param); if (ret) return 1; for (i = 0; i < cfg->array.param.nr_disks; i++) { ret = ioctl(file, ADD_NEW_DISK,(unsigned long)(cfg->array.disks+i)); if (ret) return 1; } close(file); handleOneConfig(raidrun, cfg); return 0;}int main (int argc, char *argv[]){ char *namestart=argv[0]; FILE *fp = NULL; md_cfg_entry_t *p; int exit_status=0; int version = 0, help = 0, debug = 0; char * configFile = RAID_CONFIG; int force_flag = 0; int old_force_flag = 0; int upgrade_flag = 0; int no_resync_flag = 0; int all_flag = 0; char ** args; mdu_version_t ver; poptContext optCon; int i; enum mkraidFunc func; struct poptOption optionsTable[] = { { "configfile", 'c', POPT_ARG_STRING, &configFile, 0 }, { "force", 'f', 0, &old_force_flag, 0 }, { "really-force", 'R', 0, &force_flag, 0 }, { "upgrade", 'u', 0, &upgrade_flag, 0 }, { "dangerous-no-resync", 'r', 0, &no_resync_flag, 0 }, { "help", 'h', 0, &help, 0 }, { "version", 'V', 0, &version, 0 }, { "debug", 0, 0, &debug, 0 }, { "all", 'a', 0, &all_flag, 0 }, { NULL, 0, 0, NULL, 0 } } ; optCon = poptGetContext("mkraid", argc, (const char **)argv, optionsTable, 0); if ((i = poptGetNextOpt(optCon)) < -1) { fprintf(stderr, "%s: %s\n", poptBadOption(optCon, POPT_BADOPTION_NOALIAS), poptStrerror(i)); usage(); return EXIT_FAILURE; } if (prepare_raidlib()) return EXIT_FAILURE; namestart = strrchr(argv[0], '/'); if (!namestart) namestart = argv[0]; else namestart++; if (!strcmp (namestart, "mkraid")) { func = mkraid; if (all_flag) { fprintf (stderr, "--all not possible for mkraid!\n"); return (EXIT_FAILURE); } } else if (!strcmp (namestart, "raid0run")) { func = raid0run; if (old_force_flag) { fprintf (stderr, "--force not possible for raid0run!\n"); return (EXIT_FAILURE); } if (force_flag) { fprintf (stderr, "--really-force not possible for raid0run!\n"); return (EXIT_FAILURE); } if (upgrade_flag) { fprintf (stderr, "--upgrade not possible for raid0run!\n"); return (EXIT_FAILURE); } if (no_resync_flag) { fprintf (stderr, "--dangerous-no-resync not possible for raid0run!\n"); return (EXIT_FAILURE); } } else { fprintf (stderr, "Unknown command %s\n", argv[0]); usage(); return (EXIT_FAILURE); } if (help) { usage(); return EXIT_FAILURE; } else if (version) { printf("mkraid version %d.%d.%d\n", MKRAID_MAJOR_VERSION, MKRAID_MINOR_VERSION, MKRAID_PATCHLEVEL_VERSION); return EXIT_VERSION; } fp = fopen(configFile, "r"); if (fp == NULL) { fprintf(stderr, "Couldn't open %s -- %s\n", configFile, strerror(errno)); goto abort; } srand((unsigned int) time(NULL)); if (parse_config(fp)) goto abort; args = (char **)poptGetArgs(optCon); if (!all_flag && !args) { usage(); return EXIT_FAILURE; } if (getMdVersion(&ver)) return EXIT_FAILURE; if (old_force_flag && (func == mkraid)) { fprintf(stderr, " WARNING! NOTE: if you are recovering a double-disk error or some other failure mode that made your array unrunnable but data is still intact then it's strongly recommended to use the lsraid utility and to read the lsraid HOWTO. If your RAID array holds useful and not yet backed up data then --force and the hot-add/hot-remove functionality should be used with extreme care! If your /etc/raidtab file is not in sync with the real array configuration, then --force might DESTROY ALL YOUR DATA. It's especially dangerous to use -f if the array is in degraded mode. If your /etc/raidtab file matches the real layout of on-disk data then recreating the array will not hurt your data, but be aware of the risks of doing this anyway: freshly created RAID1 and RAID5 arrays do a full resync of their mirror/parity blocks, which, if the raidtab is incorrect, the resync will wipe out data irrecoverably. Also, if your array is in degraded mode then the raidtab must match the degraded config exactly, otherwise you'll get the same kind of data destruction during resync. (see the failed-disk raidtab option.) You have been warned! [ If your array holds no data, or you have it all backed up, or if you know precisely what you are doing and you still want to proceed then use the --really-force (or -R) flag. ]"); return EXIT_FAILURE; } if (debug) { int file, ret; file = open(cfg_head->md_name, O_RDONLY); if (file == -1) { perror("could not open file"); return EXIT_FAILURE; } ret = ioctl(file, PRINT_RAID_DEBUG, 0UL); if (ret) { perror("debug ioctl failed"); return EXIT_FAILURE; } printf("dumped RAID status into the syslog.\n"); return 0; } if (all_flag) { for (p = cfg_head; p; p = p->next) { printf("considering %s...\n", p->md_name); if ((p->array.param.level != 0) && (p->array.param.level != -1)) { fprintf(stderr, "%s is not a RAID0 or LINEAR array, skipping.\n", p->md_name); continue; } if (!p->array.param.not_persistent) { fprintf(stderr, "%s is persistent, skipping.\n", p->md_name); return EXIT_FAILURE; } /* * Invert the meaning of no_resync_flag from this point on * to avoid confusion. */ if (makeOneRaid(&ver, func, p, force_flag, upgrade_flag, !no_resync_flag)) goto abort; } } else { while (*args) { for (p = cfg_head; p; p = p->next) { if (strcmp(p->md_name, *args)) continue; if (check_active(cfg)) goto abort; if (force_flag) { fprintf(stderr, "DESTROYING the contents of %s in 5 seconds, Ctrl-C if unsure!\n", *args); sleep(5); } if (func == raid0run) { if ((p->array.param.level != 0) && (p->array.param.level != -1)) { fprintf(stderr, "%s is not a RAID0 or LINEAR array!\n", p->md_name); return EXIT_FAILURE; } if (!p->array.param.not_persistent) { fprintf(stderr, "%s must be a nonpersistent RAID0 or LINEAR array!\n", p->md_name); return EXIT_FAILURE; } } if (makeOneRaid(&ver, func, p, force_flag, upgrade_flag, !no_resync_flag)) goto abort; break; } if (!p) { fprintf(stderr, "device %s is not described in config file\n", *args); exit_status++; } args++; } } fclose(fp); return 0;abort: fprintf(stderr, "mkraid: aborted.\n(In addition to the above messages, see the syslog and /proc/mdstat as well\n for potential clues.)\n"); exit_status = 1; if (fp) fclose(fp); return exit_status;}#define P(x) printf("%18s: \t %d\n",#x,cfg->array.param.x)#define DP(x) printf("%18s: \t %d\n",#x,cfg->array.disks[i].x)void printcfg (md_cfg_entry_t * cfg){ int i; P(major_version); P(minor_version); P(patch_version); P(ctime); P(level); P(size); P(nr_disks); P(raid_disks); P(md_minor); P(utime); P(state); P(active_disks); P(working_disks); P(failed_disks); P(spare_disks); P(layout); P(chunk_size); for (i = 0; i < cfg->array.param.nr_disks; i++) { printf("\n"); DP(number); DP(major); DP(minor); DP(raid_disk); DP(state); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -