/*
- * mdctl - manage Linux "md" devices aka RAID arrays.
+ * mdadm - manage Linux "md" devices aka RAID arrays.
*
- * Copyright (C) 2001 Neil Brown <neilb@cse.unsw.edu.au>
+ * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
*
*
* This program is free software; you can redistribute it and/or modify
* Australia
*/
-#include "mdctl.h"
+#include "mdadm.h"
+#include "dlink.h"
+#if ! defined(__BIG_ENDIAN) && ! defined(__LITTLE_ENDIAN)
+#error no endian defined
+#endif
#include "md_u.h"
#include "md_p.h"
-int Examine(char *dev)
+int Examine(mddev_dev_t devlist, int brief, int export, int scan,
+ int SparcAdjust, struct supertype *forcest,
+ char *homehost)
{
/* Read the raid superblock from a device and
*
* utime, state etc
*
+ * If (brief) gather devices for same array and just print a mdadm.conf line including devices=
+ * if devlist==NULL, use conf_get_devs()
*/
- int fd = open(dev, O_RDONLY, 0);
- time_t atime;
- mdp_super_t super;
- int d;
- int rv;
+ int fd;
+ int rv = 0;
+ int err = 0;
- if (fd < 0) {
- fprintf(stderr,"mdctl: cannot open %s: %s\n",
- dev, strerror(errno));
- return 1;
- }
+ struct array {
+ struct supertype *st;
+ struct mdinfo info;
+ void *devs;
+ struct array *next;
+ int spares;
+ } *arrays = NULL;
- rv = load_super(fd, &super);
- close(fd);
- switch(rv) {
- case 1:
- fprintf(stderr, "mdctl: cannot find device size for %s: %s\n",
- dev, strerror(errno));
- return 1;
- case 2:
-/* fprintf(stderr, "mdctl: %s is too small for md: size is %ld sectors\n",
- dev, size);
-*/
- fprintf(stderr, "mdctl: %s is too small for md\n",
- dev);
- return 1;
- case 3:
- fprintf(stderr, "mdctl: Cannot seek to superblock on %s: %s\n",
- dev, strerror(errno));
- return 1;
- case 4:
- fprintf(stderr, "mdctl: Cannot read superblock on %s\n",
- dev);
- return 1;
- case 5:
- fprintf(stderr, "mdctl: No super block found on %s (Expected magic %08x, got %08x)\n",
- dev, MD_SB_MAGIC, super.md_magic);
- return 1;
- case 6:
- fprintf(stderr, "mdctl: Cannot interpret superblock on %s - version is %d\n",
- dev, super.major_version);
- return 1;
- }
-
- /* Ok, its good enough to try, though the checksum could be wrong */
- printf("%s:\n",dev);
- printf(" Magic : %08x\n", super.md_magic);
- printf(" Version : %02d.%02d.%02d\n", super.major_version, super.minor_version,
- super.patch_version);
- if (super.minor_version >= 90)
- printf(" UUID : %08x:%08x:%08x:%08x\n", super.set_uuid0, super.set_uuid1,
- super.set_uuid2, super.set_uuid3);
- else
- printf(" UUID : %08x\n", super.set_uuid0);
+ for (; devlist ; devlist=devlist->next) {
+ struct supertype *st = forcest;
+
+ fd = dev_open(devlist->devname, O_RDONLY);
+ if (fd < 0) {
+ if (!scan) {
+ fprintf(stderr,Name ": cannot open %s: %s\n",
+ devlist->devname, strerror(errno));
+ rv = 1;
+ }
+ err = 1;
+ }
+ else {
+ if (!st)
+ st = guess_super(fd);
+ if (st)
+ err = st->ss->load_super(st, fd,
+ (brief||scan) ? NULL
+ :devlist->devname);
+ else {
+ if (!brief) {
+ fprintf(stderr, Name ": No md superblock detected on %s.\n", devlist->devname);
+ rv = 1;
+ }
+ err = 1;
+ }
+ close(fd);
+ }
+ if (err)
+ continue;
- atime = super.ctime;
- printf(" Creation Time : %.24s\n", ctime(&atime));
- printf(" Raid Level : %d\n", super.level);
- printf(" Size : %d\n", super.size);
- printf(" Raid Disks : %d\n", super.raid_disks);
- printf(" Total Disks : %d\n", super.nr_disks);
- printf("Preferred Minor : %d\n", super.md_minor);
- printf("\n");
- atime = super.utime;
- printf(" Update Time : %.24s\n", ctime(&atime));
- printf(" State : %s, %serrors\n",
- (super.state&(1<<MD_SB_CLEAN))?"clean":"dirty",
- (super.state&(1<<MD_SB_ERRORS))?"":"no-");
- printf(" Active Drives : %d\n", super.active_disks);
- printf(" Working Drives : %d\n", super.working_disks);
- printf(" Failed Drives : %d\n", super.failed_disks);
- printf(" Spare Drives : %d\n", super.spare_disks);
- printf(" - checksum not checked yet - \n");
- printf(" Events : %d.%d\n", super.events_hi, super.events_lo);
- printf("\n");
- printf(" Layout : %d\n", super.layout);
- printf(" Chunk Size : %dK\n", super.chunk_size/1024);
- printf("\n");
- printf(" Number Major Minor RaidDisk State\n");
- for (d= -1; d<(signed int)super.nr_disks; d++) {
- mdp_disk_t *dp;
- char nb[5];
- if (d>=0) dp = &super.disks[d];
- else dp = &super.this_disk;
- sprintf(nb, "%4d", d);
- printf("%4s %5d %5d %5d %5d ", d < 0 ? "this" : nb,
- dp->number, dp->major, dp->minor, dp->raid_disk);
- if (dp->state & (1<<MD_DISK_FAULTY)) printf(" faulty");
- if (dp->state & (1<<MD_DISK_ACTIVE)) printf(" active");
- if (dp->state & (1<<MD_DISK_SYNC)) printf(" sync");
- if (dp->state & (1<<MD_DISK_REMOVED)) printf(" removed");
- printf("\n");
+ if (SparcAdjust)
+ st->ss->update_super(st, NULL, "sparc2.2",
+ devlist->devname, 0, 0, NULL);
+ /* Ok, its good enough to try, though the checksum could be wrong */
+
+ if (brief) {
+ struct array *ap;
+ char *d;
+ for (ap=arrays; ap; ap=ap->next) {
+ if (st->ss == ap->st->ss &&
+ st->ss->compare_super(ap->st, st)==0)
+ break;
+ }
+ if (!ap) {
+ ap = malloc(sizeof(*ap));
+ ap->devs = dl_head();
+ ap->next = arrays;
+ ap->spares = 0;
+ ap->st = st;
+ arrays = ap;
+ st->ss->getinfo_super(st, &ap->info);
+ } else {
+ st->ss->getinfo_super(st, &ap->info);
+ st->ss->free_super(st);
+ }
+ if (!(ap->info.disk.state & MD_DISK_SYNC))
+ ap->spares++;
+ d = dl_strdup(devlist->devname);
+ dl_add(ap->devs, d);
+ } else if (export) {
+ st->ss->export_examine_super(st);
+ } else {
+ printf("%s:\n",devlist->devname);
+ st->ss->examine_super(st, homehost);
+ st->ss->free_super(st);
+ }
+ }
+ if (brief) {
+ struct array *ap;
+ for (ap=arrays; ap; ap=ap->next) {
+ char sep='=';
+ char *d;
+ ap->st->ss->brief_examine_super(ap->st);
+ if (ap->spares) printf(" spares=%d", ap->spares);
+ if (brief > 1) {
+ printf(" devices");
+ for (d=dl_next(ap->devs); d!= ap->devs; d=dl_next(d)) {
+ printf("%c%s", sep, d);
+ sep=',';
+ }
+ }
+ ap->st->ss->free_super(ap->st);
+ /* FIXME free ap */
+ if (ap->spares || brief > 1)
+ printf("\n");
+ }
}
- return 0;
+ return rv;
}