Add 'supertype' arg to almost all metadata methods.
[thirdparty/mdadm.git] / Examine.c
1 /*
2  * mdadm - manage Linux "md" devices aka RAID arrays.
3  *
4  * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
5  *
6  *
7  *    This program is free software; you can redistribute it and/or modify
8  *    it under the terms of the GNU General Public License as published by
9  *    the Free Software Foundation; either version 2 of the License, or
10  *    (at your option) any later version.
11  *
12  *    This program is distributed in the hope that it will be useful,
13  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *    GNU General Public License for more details.
16  *
17  *    You should have received a copy of the GNU General Public License
18  *    along with this program; if not, write to the Free Software
19  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  *    Author: Neil Brown
22  *    Email: <neilb@cse.unsw.edu.au>
23  *    Paper: Neil Brown
24  *           School of Computer Science and Engineering
25  *           The University of New South Wales
26  *           Sydney, 2052
27  *           Australia
28  */
29
30 #include        "mdadm.h"
31 #include        "dlink.h"
32
33 #if ! defined(__BIG_ENDIAN) && ! defined(__LITTLE_ENDIAN)
34 #error no endian defined
35 #endif
36 #include        "md_u.h"
37 #include        "md_p.h"
38 int Examine(mddev_dev_t devlist, int brief, int scan,
39             int SparcAdjust, struct supertype *forcest,
40             char *homehost)
41 {
42
43         /* Read the raid superblock from a device and
44          * display important content.
45          *
46          * If cannot be found, print reason: too small, bad magic
47          *
48          * Print:
49          *   version, ctime, level, size, raid+spare+
50          *   prefered minor
51          *   uuid
52          *
53          *   utime, state etc
54          *
55          * If (brief) gather devices for same array and just print a mdadm.conf line including devices=
56          * if devlist==NULL, use conf_get_devs()
57          */
58         int fd;
59         void *super = NULL;
60         int rv = 0;
61         int err = 0;
62
63         struct array {
64                 void *super;
65                 struct supertype *st;
66                 struct mdinfo info;
67                 void *devs;
68                 struct array *next;
69                 int spares;
70         } *arrays = NULL;
71
72         for (; devlist ; devlist=devlist->next) {
73                 struct supertype *st = forcest;
74
75                 fd = dev_open(devlist->devname, O_RDONLY);
76                 if (fd < 0) {
77                         if (!scan) {
78                                 fprintf(stderr,Name ": cannot open %s: %s\n",
79                                         devlist->devname, strerror(errno));
80                                 rv = 1;
81                         }
82                         err = 1;
83                 }
84                 else {
85                         if (!st)
86                                 st = guess_super(fd);
87                         if (st)
88                                 err = st->ss->load_super(st, fd, &super, (brief||scan)?NULL:devlist->devname);
89                         else {
90                                 if (!brief) {
91                                         fprintf(stderr, Name ": No md superblock detected on %s.\n", devlist->devname);
92                                         rv = 1;
93                                 }
94                                 err = 1;
95                         }
96                         close(fd);
97                 }
98                 if (err)
99                         continue;
100
101                 if (SparcAdjust)
102                         st->ss->update_super(st, NULL, super, "sparc2.2",
103                                              devlist->devname, 0, 0, NULL);
104                 /* Ok, its good enough to try, though the checksum could be wrong */
105                 if (brief) {
106                         struct array *ap;
107                         char *d;
108                         for (ap=arrays; ap; ap=ap->next) {
109                                 if (st->ss == ap->st->ss &&
110                                     st->ss->compare_super(&ap->super, super)==0)
111                                         break;
112                         }
113                         if (!ap) {
114                                 ap = malloc(sizeof(*ap));
115                                 ap->super = super;
116                                 ap->devs = dl_head();
117                                 ap->next = arrays;
118                                 ap->spares = 0;
119                                 ap->st = st;
120                                 arrays = ap;
121                                 st->ss->getinfo_super(st, &ap->info, super);
122                         } else {
123                                 st->ss->getinfo_super(st, &ap->info, super);
124                                 st->ss->free_super(st, super);
125                         }
126                         if (!(ap->info.disk.state & MD_DISK_SYNC))
127                                 ap->spares++;
128                         d = dl_strdup(devlist->devname);
129                         dl_add(ap->devs, d);
130                 } else {
131                         printf("%s:\n",devlist->devname);
132                         st->ss->examine_super(st, super, homehost);
133                         st->ss->free_super(st, super);
134                 }
135         }
136         if (brief) {
137                 struct array *ap;
138                 for (ap=arrays; ap; ap=ap->next) {
139                         char sep='=';
140                         char *d;
141                         ap->st->ss->brief_examine_super(ap->st, ap->super);
142                         if (ap->spares) printf("   spares=%d", ap->spares);
143                         if (brief > 1) {
144                                 printf("   devices");
145                                 for (d=dl_next(ap->devs); d!= ap->devs; d=dl_next(d)) {
146                                         printf("%c%s", sep, d);
147                                         sep=',';
148                                 }
149                         }
150                         ap->st->ss->free_super(ap->st, ap->super);
151                         /* FIXME free ap */
152                         if (ap->spares || brief > 1)
153                                 printf("\n");
154                 }
155         }
156         return rv;
157 }