📄 lsraid.c
字号:
/* * lsraid.c - A tool for displaying md device information. * * Copyright (C) 2002 Oracle Corporation, Joel Becker * <joel.becker@oracle.com> * All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have recieved a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 021110-1307, USA. */#include "common.h"#include "parser.h"#include "raid_io.h"#include "raidlib.h"#include "version.h"#include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/ioctl.h>#include <sys/time.h>#include <time.h>#include <dirent.h>#include <fcntl.h>#include <unistd.h>#include <errno.h>#include <linux/types.h>#include <linux/major.h>#include <linux/fs.h>#include <linux/raid/md_u.h>#include <linux/raid/md_p.h>/* Local copies of things I use - Clean up later */#include "list.h"/* * Defines */#define LSRAID_VERSION "0.7.0"/* Imagine the fun when we get to different major,minor sizes :-) */#define MAJORBITS 8#define MINORBITS 8#define MAJORS (1 << MAJORBITS)#define MINORS (1 << MINORBITS)/* Debugging for device scanning */#define SCAN_DEBUG 0/* * Typedefs */typedef struct _LSRContext LSRContext;typedef struct _LSRNamEnt LSRNamEnt;typedef struct _LSRDir LSRDir;typedef struct _LSRArray LSRArray;typedef struct _LSRDisk LSRDisk;/* * Enums */typedef enum{ LSR_ARRAY = 'A', LSR_DISK = 'D', LSR_RAIDTAB = 'R'} LSRAction;typedef enum{ LSR_ARRAY_GOOD = 1 << 0, LSR_ARRAY_SPARE = 1 << 1, LSR_ARRAY_FAILED = 1 << 2, LSR_DISK_LONG = 1 << 3, LSR_DEV_SCAN = 1 << 4} LSRFlags;/* * Structures */struct _LSRContext{ LSRAction action; LSRFlags flags; struct list_head o_arrays; /* Array names from parse_options */ struct list_head o_disks; /* Disk names from parse_options */ struct list_head arrays; /* Anchor for list of arrays (a_list) */ struct list_head disks; /* Anchor for list of disks (d_list) */ char ***devtable; /* Table of known device names (major, minor) -> name */};struct _LSRNamEnt{ struct list_head list; char *name; union { LSRArray *array; LSRDisk *disk; } u;};struct _LSRDir{ struct list_head list; char name[PATH_MAX + 1]; DIR *dir;};struct _LSRArray{ struct list_head a_list; /* Hook into list of arrays */ struct list_head disks; /* Anchor for array disks (d_array) */ char *name; /* Device name */ unsigned int uuid0; /* Array uuid */ unsigned int uuid1; unsigned int uuid2; unsigned int uuid3; int minor; /* Array minor (in MD major) */ mdu_array_info_t info; /* Online info */};struct _LSRDisk{ struct list_head d_list; /* Hook into list of disks */ struct list_head d_array; /* Hook into array disks */ LSRArray *array; /* Pointer to owning array */ char *name; /* Device name */ int major; /* Device major */ int minor; /* Device minor */ mdu_disk_info_t info; /* Online info */ mdp_super_t sb; /* On-disk superblock */};/* * Prototypes */static void print_usage(int rc);static void print_usage_long();static void print_version();static void parse_options(LSRContext *ctxt, int argc, char *argv[]);static LSRContext *alloc_context();static LSRNamEnt *alloc_nament();static LSRArray *alloc_array();static LSRDisk *alloc_disk();static int read_md_super(LSRContext *ctxt, LSRDisk *disk);static int query_array(LSRContext *ctxt, LSRArray *array);static int fill_array(LSRContext *ctxt, LSRArray *array);static int fill_disk(LSRContext *ctxt, LSRDisk *disk);static LSRArray *find_add_array(LSRContext *ctxt, char *name, int minor);static LSRDisk *find_add_disk(LSRContext *ctxt, char *name, int major, int minor);static int find_device(LSRContext *ctxt, char **name, int major, int minor);static void maybe_add_device(LSRContext *ctxt, int major, int minor);static int load_partitions(LSRContext *ctxt);static LSRDir *alloc_dir();static LSRDir *pop_dir(struct list_head *dtree);static LSRDir *push_dir(struct list_head *dtree, char *name);static int scan_slash_dev(LSRContext *ctxt);static int scan_arrays(LSRContext *ctxt);static int scan_disks(LSRContext *ctxt);static void clean_context(LSRContext *ctxt);static void disk_state_offline(LSRDisk *disk, char *state);static void disk_state_online(LSRDisk *disk, char *state);static const char *disk_state(LSRDisk *disk);static void dump_disk_long(LSRDisk *disk);static void dump_disk_short(LSRDisk *disk);static void dump_disks(LSRContext *ctxt);static void dump_array_diskinfo(LSRContext *ctxt, char **diskinfo, int numdisks, int raid_disks);static void dump_array_online(LSRContext *ctxt, LSRArray *array);static void dump_array_offline(LSRContext *ctxt, LSRArray *array);static void dump_array(LSRContext *ctxt, LSRArray *array);static void dump_arrays(LSRContext *ctxt);static void dump_raidtab_array_online(LSRArray *array);static void dump_raidtab_array_offline(LSRArray *array);static void dump_raidtab_array(LSRArray *array);static void dump_raidtab(LSRContext *ctxt);#if 0 /* Currently unused */static int sb_equal(LSRDisk *disk1, LSRDisk *disk2);#endif /* Currently unused *//* * Functions */static void print_version(){ fprintf(stdout, "lsraid version " LSRAID_VERSION "\n"); exit(0);} /* print_version() */static void print_usage_long(){ /* FIXME */ print_usage(0);} /* print_usage_long() */static void print_usage(int rc){ FILE *output = rc ? stderr : stdout; fprintf(output, "Usage: lsraid -A [-g|-f|-s] {-a <device> | -d <device>} ...\n" " lsraid -A [-g|-f|-s] -p\n" " lsraid -D [-l] {-a <device> | -d <device>} ...\n" " lsraid -D [-l] -p\n" " lsraid -R {-a <device> | -d <device>} ...\n" " lsraid -R -p\n" " lsraid -h\n" " lsriad -V\n"); exit(rc);} /* print_usage() */static LSRContext *alloc_context(){ LSRContext *ctxt; ctxt = (LSRContext *)malloc(sizeof(LSRContext)); if (ctxt) { memset(ctxt, 0, sizeof(LSRContext)); INIT_LIST_HEAD(&ctxt->o_disks); INIT_LIST_HEAD(&ctxt->o_arrays); INIT_LIST_HEAD(&ctxt->disks); INIT_LIST_HEAD(&ctxt->arrays); ctxt->devtable = (char ***)malloc(MAJORS * sizeof(char **)); if (!ctxt->devtable) { free(ctxt); return(NULL); } memset(ctxt->devtable, 0, MAJORS * sizeof(char **)); } return(ctxt);} /* alloc_context() */static LSRNamEnt *alloc_nament(){ LSRNamEnt *ent; ent = (LSRNamEnt *)malloc(sizeof(LSRNamEnt)); if (ent) { memset(ent, 0, sizeof(LSRNamEnt)); INIT_LIST_HEAD(&ent->list); } return(ent);} /* alloc_nament() */static LSRArray *alloc_array(){ LSRArray *array; array = (LSRArray *)malloc(sizeof(LSRArray)); if (array) { memset(array, 0, sizeof(LSRArray)); INIT_LIST_HEAD(&array->a_list); INIT_LIST_HEAD(&array->disks); array->minor = -1; } return(array);} /* alloc_array() */static LSRDisk *alloc_disk(){ LSRDisk *disk; disk = (LSRDisk *)malloc(sizeof(LSRDisk)); if (disk) { memset(disk, 0, sizeof(LSRDisk)); INIT_LIST_HEAD(&disk->d_list); INIT_LIST_HEAD(&disk->d_array); } return(disk);} /* alloc_disk() */static void parse_options(LSRContext *ctxt, int argc, char *argv[]){ int i; LSRNamEnt *ent; /* Pre-clear */ ctxt->action = 0; ctxt->flags = 0; for (i = 1; i < argc; i++) { if (argv[i][0] != '-') break; switch (argv[i][1]) { case '-': if (argv[i][2] == '\0') { i++; break; } else if (strcmp(argv[i], "--help") == 0) print_usage_long(); else if (strcmp(argv[i], "--version") == 0) print_version(); else { fprintf(stderr, "lsraid: Invalid option: %s\n", argv[i]); } break; case 'h': case '?': case 'H': print_usage(0); break; case 'V': print_version(); break; case 'A': case 'D': case 'R': if (ctxt->action) { fprintf(stderr, "lsraid: Options %c and %c cannot be combined\n", argv[i][1], ctxt->action); print_usage(EINVAL); } ctxt->action = argv[i][1]; break; case 'g': ctxt->flags |= LSR_ARRAY_GOOD; break; case 's': ctxt->flags |= LSR_ARRAY_SPARE; break; case 'f': ctxt->flags |= LSR_ARRAY_FAILED; break; case 'p': ctxt->flags |= LSR_DEV_SCAN; break; case 'a': i++; if (i >= argc) { fprintf(stderr, "lsraid: Option \'-a\' requires an argument\n"); print_usage(EINVAL); } ent = alloc_nament(); if (!ent) { fprintf(stderr, "lsraid: Unable to allocate memory for information on array \"%s\": %s\n", argv[i], strerror(errno)); return; } ent->name = argv[i]; list_add_tail(&ent->list, &ctxt->o_arrays); break; case 'd': i++; if (i >= argc) { fprintf(stderr, "lsraid: Option \'-d\' requires an argument\n"); print_usage(EINVAL); } ent = alloc_nament(); if (!ent) { fprintf(stderr, "lsraid: Unable to allocate memory for information on device \"%s\": %s\n", argv[i], strerror(errno)); return; } ent->name = argv[i]; list_add_tail(&ent->list, &ctxt->o_disks); break; case 'l': ctxt->flags |= LSR_DISK_LONG; break; default: fprintf(stderr, "lsraid: Invalid option: %s\n", argv[i]); print_usage(EINVAL); break; } } if ((ctxt->flags & LSR_DISK_LONG) && (ctxt->action != LSR_DISK)) { fprintf(stderr, "lsraid: '-l' option requires '-D' option\n"); print_usage(EINVAL); } if ((ctxt->flags & (LSR_ARRAY_GOOD | LSR_ARRAY_FAILED | LSR_ARRAY_SPARE)) && (ctxt->action != LSR_ARRAY)) { fprintf(stderr, "lsraid: '-g', '-f', and '-s' options require '-A' option\n"); print_usage(EINVAL); } if (list_empty(&ctxt->o_arrays) && list_empty(&ctxt->o_disks)) { if (!(ctxt->flags & LSR_DEV_SCAN)) { fprintf(stderr, "lsraid: You must specify a device to query\n"); print_usage(EINVAL); } } else if (ctxt->flags & LSR_DEV_SCAN) { fprintf(stderr, "lsraid: The '-p' option cannot be combined with the '-a' option\n" " or the '-d' option\n"); print_usage(EINVAL); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -