Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 331971 | Differences between
and this patch

Collapse All | Expand All

(-)a/Config.in (+1 lines)
Lines 749-754 source findutils/Config.in Link Here
749
source init/Config.in
749
source init/Config.in
750
source loginutils/Config.in
750
source loginutils/Config.in
751
source e2fsprogs/Config.in
751
source e2fsprogs/Config.in
752
source mdadm/Config.in
752
source modutils/Config.in
753
source modutils/Config.in
753
source util-linux/Config.in
754
source util-linux/Config.in
754
source miscutils/Config.in
755
source miscutils/Config.in
(-)a/include/applets.src.h (+1 lines)
Lines 206-211 IF_KILLALL5(APPLET_ODDNAME(killall5, kil Link Here
206
IF_KLOGD(APPLET(klogd, _BB_DIR_SBIN, _BB_SUID_DROP))
206
IF_KLOGD(APPLET(klogd, _BB_DIR_SBIN, _BB_SUID_DROP))
207
IF_LAST(APPLET(last, _BB_DIR_USR_BIN, _BB_SUID_DROP))
207
IF_LAST(APPLET(last, _BB_DIR_USR_BIN, _BB_SUID_DROP))
208
IF_LENGTH(APPLET_NOFORK(length, length, _BB_DIR_USR_BIN, _BB_SUID_DROP, length))
208
IF_LENGTH(APPLET_NOFORK(length, length, _BB_DIR_USR_BIN, _BB_SUID_DROP, length))
209
IF_MDADM(APPLET(mdadm, _BB_DIR_SBIN, _BB_SUID_DROP))
209
IF_LESS(APPLET(less, _BB_DIR_USR_BIN, _BB_SUID_DROP))
210
IF_LESS(APPLET(less, _BB_DIR_USR_BIN, _BB_SUID_DROP))
210
IF_SETARCH(APPLET_ODDNAME(linux32, setarch, _BB_DIR_BIN, _BB_SUID_DROP, linux32))
211
IF_SETARCH(APPLET_ODDNAME(linux32, setarch, _BB_DIR_BIN, _BB_SUID_DROP, linux32))
211
IF_SETARCH(APPLET_ODDNAME(linux64, setarch, _BB_DIR_BIN, _BB_SUID_DROP, linux64))
212
IF_SETARCH(APPLET_ODDNAME(linux64, setarch, _BB_DIR_BIN, _BB_SUID_DROP, linux64))
(-)a/include/usage.src.h (+5 lines)
Lines 2404-2409 INSERT Link Here
2404
     "\n	-w	Warn about improperly formatted checksum lines" \
2404
     "\n	-w	Warn about improperly formatted checksum lines" \
2405
	)
2405
	)
2406
2406
2407
#define mdadm_trivial_usage \
2408
	""
2409
#define mdadm_full_usage \
2410
	"Assemble or Examine the mdadm arrays."
2411
2407
#define mdev_trivial_usage \
2412
#define mdev_trivial_usage \
2408
       "[-s]"
2413
       "[-s]"
2409
#define mdev_full_usage "\n\n" \
2414
#define mdev_full_usage "\n\n" \
(-)a/Makefile (+1 lines)
Lines 478-483 libs-y := \ Link Here
478
		loginutils/ \
478
		loginutils/ \
479
		mailutils/ \
479
		mailutils/ \
480
		miscutils/ \
480
		miscutils/ \
481
		mdadm/ \
481
		modutils/ \
482
		modutils/ \
482
		networking/ \
483
		networking/ \
483
		networking/libiproute/ \
484
		networking/libiproute/ \
(-)a/mdadm/bitmap.h (+287 lines)
Line 0 Link Here
1
/*
2
 * bitmap.h: Copyright (C) Peter T. Breuer (ptb@ot.uc3m.es) 2003
3
 *
4
 * additions: Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, Inc.
5
 */
6
#ifndef BITMAP_H
7
#define BITMAP_H 1
8
9
#define BITMAP_MAJOR_LO 3
10
/* version 4 insists the bitmap is in little-endian order
11
 * with version 3, it is host-endian which is non-portable
12
 */
13
#define BITMAP_MAJOR_HI 4
14
#define	BITMAP_MAJOR_HOSTENDIAN 3
15
16
#define BITMAP_MINOR 39
17
18
/*
19
 * in-memory bitmap:
20
 *
21
 * Use 16 bit block counters to track pending writes to each "chunk".
22
 * The 2 high order bits are special-purpose, the first is a flag indicating
23
 * whether a resync is needed.  The second is a flag indicating whether a
24
 * resync is active.
25
 * This means that the counter is actually 14 bits:
26
 *
27
 * +--------+--------+------------------------------------------------+
28
 * | resync | resync |               counter                          |
29
 * | needed | active |                                                |
30
 * |  (0-1) |  (0-1) |              (0-16383)                         |
31
 * +--------+--------+------------------------------------------------+
32
 *
33
 * The "resync needed" bit is set when:
34
 *    a '1' bit is read from storage at startup.
35
 *    a write request fails on some drives
36
 *    a resync is aborted on a chunk with 'resync active' set
37
 * It is cleared (and resync-active set) when a resync starts across all drives
38
 * of the chunk.
39
 *
40
 *
41
 * The "resync active" bit is set when:
42
 *    a resync is started on all drives, and resync_needed is set.
43
 *       resync_needed will be cleared (as long as resync_active wasn't already set).
44
 * It is cleared when a resync completes.
45
 *
46
 * The counter counts pending write requests, plus the on-disk bit.
47
 * When the counter is '1' and the resync bits are clear, the on-disk
48
 * bit can be cleared aswell, thus setting the counter to 0.
49
 * When we set a bit, or in the counter (to start a write), if the fields is
50
 * 0, we first set the disk bit and set the counter to 1.
51
 *
52
 * If the counter is 0, the on-disk bit is clear and the stipe is clean
53
 * Anything that dirties the stipe pushes the counter to 2 (at least)
54
 * and sets the on-disk bit (lazily).
55
 * If a periodic sweep find the counter at 2, it is decremented to 1.
56
 * If the sweep find the counter at 1, the on-disk bit is cleared and the
57
 * counter goes to zero.
58
 *
59
 * Also, we'll hijack the "map" pointer itself and use it as two 16 bit block
60
 * counters as a fallback when "page" memory cannot be allocated:
61
 *
62
 * Normal case (page memory allocated):
63
 *
64
 *     page pointer (32-bit)
65
 *
66
 *     [ ] ------+
67
 *               |
68
 *               +-------> [   ][   ]..[   ] (4096 byte page == 2048 counters)
69
 *                          c1   c2    c2048
70
 *
71
 * Hijacked case (page memory allocation failed):
72
 *
73
 *     hijacked page pointer (32-bit)
74
 *
75
 *     [		  ][		  ] (no page memory allocated)
76
 *      counter #1 (16-bit) counter #2 (16-bit)
77
 *
78
 */
79
80
#ifdef __KERNEL__
81
82
#define PAGE_BITS (PAGE_SIZE << 3)
83
#define PAGE_BIT_SHIFT (PAGE_SHIFT + 3)
84
85
typedef __u16 bitmap_counter_t;
86
#define COUNTER_BITS 16
87
#define COUNTER_BIT_SHIFT 4
88
#define COUNTER_BYTE_RATIO (COUNTER_BITS / 8)
89
#define COUNTER_BYTE_SHIFT (COUNTER_BIT_SHIFT - 3)
90
91
#define NEEDED_MASK ((bitmap_counter_t) (1 << (COUNTER_BITS - 1)))
92
#define RESYNC_MASK ((bitmap_counter_t) (1 << (COUNTER_BITS - 2)))
93
#define COUNTER_MAX ((bitmap_counter_t) RESYNC_MASK - 1)
94
#define NEEDED(x) (((bitmap_counter_t) x) & NEEDED_MASK)
95
#define RESYNC(x) (((bitmap_counter_t) x) & RESYNC_MASK)
96
#define COUNTER(x) (((bitmap_counter_t) x) & COUNTER_MAX)
97
98
/* how many counters per page? */
99
#define PAGE_COUNTER_RATIO (PAGE_BITS / COUNTER_BITS)
100
/* same, except a shift value for more efficient bitops */
101
#define PAGE_COUNTER_SHIFT (PAGE_BIT_SHIFT - COUNTER_BIT_SHIFT)
102
/* same, except a mask value for more efficient bitops */
103
#define PAGE_COUNTER_MASK  (PAGE_COUNTER_RATIO - 1)
104
105
#define BITMAP_BLOCK_SIZE 512
106
#define BITMAP_BLOCK_SHIFT 9
107
108
/* how many blocks per chunk? (this is variable) */
109
#define CHUNK_BLOCK_RATIO(bitmap) ((bitmap)->chunksize >> BITMAP_BLOCK_SHIFT)
110
#define CHUNK_BLOCK_SHIFT(bitmap) ((bitmap)->chunkshift - BITMAP_BLOCK_SHIFT)
111
#define CHUNK_BLOCK_MASK(bitmap) (CHUNK_BLOCK_RATIO(bitmap) - 1)
112
113
/* when hijacked, the counters and bits represent even larger "chunks" */
114
/* there will be 1024 chunks represented by each counter in the page pointers */
115
#define PAGEPTR_BLOCK_RATIO(bitmap) \
116
			(CHUNK_BLOCK_RATIO(bitmap) << PAGE_COUNTER_SHIFT >> 1)
117
#define PAGEPTR_BLOCK_SHIFT(bitmap) \
118
			(CHUNK_BLOCK_SHIFT(bitmap) + PAGE_COUNTER_SHIFT - 1)
119
#define PAGEPTR_BLOCK_MASK(bitmap) (PAGEPTR_BLOCK_RATIO(bitmap) - 1)
120
121
/*
122
 * on-disk bitmap:
123
 *
124
 * Use one bit per "chunk" (block set). We do the disk I/O on the bitmap
125
 * file a page at a time. There's a superblock at the start of the file.
126
 */
127
128
/* map chunks (bits) to file pages - offset by the size of the superblock */
129
#define CHUNK_BIT_OFFSET(chunk) ((chunk) + (sizeof(bitmap_super_t) << 3))
130
131
#endif
132
133
/*
134
 * bitmap structures:
135
 */
136
137
#define BITMAP_MAGIC 0x6d746962
138
139
/* use these for bitmap->flags and bitmap->sb->state bit-fields */
140
enum bitmap_state {
141
	BITMAP_ACTIVE = 0x001, /* the bitmap is in use */
142
	BITMAP_STALE  = 0x002  /* the bitmap file is out of date or had -EIO */
143
};
144
145
/* the superblock at the front of the bitmap file -- little endian */
146
typedef struct bitmap_super_s {
147
	__u32 magic;        /*  0  BITMAP_MAGIC */
148
	__u32 version;      /*  4  the bitmap major for now, could change... */
149
	__u8  uuid[16];     /*  8  128 bit uuid - must match md device uuid */
150
	__u64 events;       /* 24  event counter for the bitmap (1)*/
151
	__u64 events_cleared;/*32  event counter when last bit cleared (2) */
152
	__u64 sync_size;    /* 40  the size of the md device's sync range(3) */
153
	__u32 state;        /* 48  bitmap state information */
154
	__u32 chunksize;    /* 52  the bitmap chunk size in bytes */
155
	__u32 daemon_sleep; /* 56  seconds between disk flushes */
156
	__u32 write_behind; /* 60  number of outstanding write-behind writes */
157
158
	__u8  pad[256 - 64]; /* set to zero */
159
} bitmap_super_t;
160
161
/* notes:
162
 * (1) This event counter is updated before the eventcounter in the md superblock
163
 *    When a bitmap is loaded, it is only accepted if this event counter is equal
164
 *    to, or one greater than, the event counter in the superblock.
165
 * (2) This event counter is updated when the other one is *if*and*only*if* the 
166
 *    array is not degraded.  As bits are not cleared when the array is degraded,
167
 *    this represents the last time that any bits were cleared.
168
 *    If a device is being added that has an event count with this value or
169
 *    higher, it is accepted as conforming to the bitmap.
170
 * (3)This is the number of sectors represented by the bitmap, and is the range that
171
 *    resync happens across.  For raid1 and raid5/6 it is the size of individual
172
 *    devices.  For raid10 it is the size of the array.
173
 */
174
175
#ifdef __KERNEL__
176
177
/* the in-memory bitmap is represented by bitmap_pages */
178
struct bitmap_page {
179
	/*
180
	 * map points to the actual memory page
181
	 */
182
	char *map;
183
	/*
184
	 * in emergencies (when map cannot be alloced), hijack the map
185
	 * pointer and use it as two counters itself
186
	 */
187
	unsigned int hijacked;
188
	/*
189
	 * count of dirty bits on the page
190
	 */ 
191
	int count;
192
};
193
194
/* keep track of bitmap file pages that have pending writes on them */
195
struct page_list {
196
	struct list_head list;
197
	struct page *page;
198
};
199
200
/* the main bitmap structure - one per mddev */
201
struct bitmap {
202
	struct bitmap_page *bp;
203
	unsigned long pages; /* total number of pages in the bitmap */
204
	unsigned long missing_pages; /* number of pages not yet allocated */
205
206
	mddev_t *mddev; /* the md device that the bitmap is for */
207
208
	int counter_bits; /* how many bits per block counter */
209
210
	/* bitmap chunksize -- how much data does each bit represent? */
211
	unsigned long chunksize;
212
	unsigned long chunkshift; /* chunksize = 2^chunkshift (for bitops) */
213
	unsigned long chunks; /* total number of data chunks for the array */
214
215
	/* We hold a count on the chunk currently being synced, and drop
216
	 * it when the last block is started.  If the resync is aborted
217
	 * midway, we need to be able to drop that count, so we remember
218
	 * the counted chunk..
219
	 */
220
	unsigned long syncchunk;
221
222
	__u64	events_cleared;
223
224
	/* bitmap spinlock */
225
	spinlock_t lock;
226
227
	struct file *file; /* backing disk file */
228
	struct page *sb_page; /* cached copy of the bitmap file superblock */
229
	struct page **filemap; /* list of cache pages for the file */
230
	unsigned long *filemap_attr; /* attributes associated w/ filemap pages */
231
	unsigned long file_pages; /* number of pages in the file */
232
233
	unsigned long flags;
234
235
	/*
236
	 * the bitmap daemon - periodically wakes up and sweeps the bitmap
237
	 * file, cleaning up bits and flushing out pages to disk as necessary
238
	 */
239
	mdk_thread_t *daemon;
240
	unsigned long daemon_sleep; /* how many seconds between updates? */
241
242
	/*
243
	 * bitmap write daemon - this daemon performs writes to the bitmap file
244
	 * this thread is only needed because of a limitation in ext3 (jbd)
245
	 * that does not allow a task to have two journal transactions ongoing
246
	 * simultaneously (even if the transactions are for two different
247
	 * filesystems) -- in the case of bitmap, that would be the filesystem
248
	 * that the bitmap file resides on and the filesystem that is mounted
249
	 * on the md device -- see current->journal_info in jbd/transaction.c
250
	 */
251
	mdk_thread_t *write_daemon;
252
	mdk_thread_t *writeback_daemon;
253
	spinlock_t write_lock;
254
	struct semaphore write_ready;
255
	struct semaphore write_done;
256
	unsigned long writes_pending;
257
	wait_queue_head_t write_wait;
258
	struct list_head write_pages;
259
	struct list_head complete_pages;
260
	mempool_t *write_pool;
261
};
262
263
/* the bitmap API */
264
265
/* these are used only by md/bitmap */
266
int  bitmap_create(mddev_t *mddev);
267
void bitmap_destroy(mddev_t *mddev);
268
int  bitmap_active(struct bitmap *bitmap);
269
270
char *file_path(struct file *file, char *buf, int count);
271
void bitmap_print_sb(struct bitmap *bitmap);
272
int bitmap_update_sb(struct bitmap *bitmap);
273
274
int  bitmap_setallbits(struct bitmap *bitmap);
275
276
/* these are exported */
277
void bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors);
278
void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors,
279
		     int success);
280
int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks);
281
void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int aborted);
282
void bitmap_close_sync(struct bitmap *bitmap);
283
284
int bitmap_unplug(struct bitmap *bitmap);
285
#endif
286
287
#endif
(-)a/mdadm/config.c (+824 lines)
Line 0 Link Here
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
#include	<sys/dir.h>
33
#include	<glob.h>
34
#include	<fnmatch.h>
35
#include	<ctype.h>
36
#include	<pwd.h>
37
#include	<grp.h>
38
39
mapping_t r5layout[] = {
40
	{ "left-asymmetric", 0},
41
	{ "right-asymmetric", 1},
42
	{ "left-symmetric", 2},
43
	{ "right-symmetric", 3},
44
45
	{ "default", 2},
46
	{ "la", 0},
47
	{ "ra", 1},
48
	{ "ls", 2},
49
	{ "rs", 3},
50
	{ NULL, 0}
51
};
52
53
mapping_t pers[] = {
54
	{ "linear", -1},
55
	{ "raid0", 0},
56
	{ "0", 0},
57
	{ "stripe", 0},
58
	{ "raid1", 1},
59
	{ "1", 1},
60
	{ "mirror", 1},
61
	{ "raid4", 4},
62
	{ "4", 4},
63
	{ "raid5", 5},
64
	{ "5", 5},
65
	{ "multipath", -4},
66
	{ "mp", -4},
67
	{ "raid6", 6},
68
	{ "6", 6},
69
	{ "raid10", 10},
70
	{ "10", 10},
71
	{ "faulty", -5},
72
	{ NULL, 0}
73
};
74
/*
75
 * Read the config file
76
 *
77
 * conf_get_uuids gets a list of devicename+uuid pairs
78
 * conf_get_devs gets device names after expanding wildcards
79
 *
80
 * Each keeps the returned list and frees it when asked to make
81
 * a new list.
82
 *
83
 * The format of the config file needs to be fairly extensible.
84
 * Now, arrays only have names and uuids and devices merely are.
85
 * But later arrays might want names, and devices might want superblock
86
 * versions, and who knows what else.
87
 * I like free format, abhore backslash line continuation, adore
88
 *   indentation for structure and am ok about # comments.
89
 *
90
 * So, each line that isn't blank or a #comment must either start
91
 *  with a key word, and not be indented, or must start with a
92
 *  non-key-word and must be indented.
93
 *
94
 * Keywords are DEVICE and ARRAY
95
 * DEV{ICE} introduces some devices that might contain raid components.
96
 * e.g.
97
 *   DEV style=0 /dev/sda* /dev/hd*
98
 *   DEV style=1 /dev/sd[b-f]*
99
 * ARR{AY} describes an array giving md device and attributes like uuid=whatever
100
 * e.g.
101
 *   ARRAY /dev/md0 uuid=whatever name=something
102
 * Spaces separate words on each line.  Quoting, with "" or '' protects them,
103
 * but may not wrap over lines
104
 *
105
 */
106
107
#ifndef CONFFILE
108
#define CONFFILE "/etc/mdadm.conf"
109
#endif
110
#ifndef CONFFILE2
111
/* for Debian compatibility .... */
112
#define CONFFILE2 "/etc/mdadm/mdadm.conf"
113
#endif
114
char DefaultConfFile[] = CONFFILE;
115
char DefaultAltConfFile[] = CONFFILE2;
116
117
enum linetype { Devices, Array, Mailaddr, Mailfrom, Program, CreateDev, Homehost, LTEnd };
118
char *keywords[] = {
119
	[Devices]  = "devices",
120
	[Array]    = "array",
121
	[Mailaddr] = "mailaddr",
122
	[Mailfrom] = "mailfrom",
123
	[Program]  = "program",
124
	[CreateDev]= "create",
125
	[Homehost] = "homehost",
126
	[LTEnd]    = NULL
127
};
128
129
/*
130
 * match_keyword returns an index into the keywords array, or -1 for no match
131
 * case is ignored, and at least three characters must be given
132
 */
133
134
int match_keyword(char *word)
135
{
136
	int len = strlen(word);
137
	int n;
138
    
139
	if (len < 3) return -1;
140
	for (n=0; keywords[n]; n++) {
141
		if (strncasecmp(word, keywords[n], len)==0)
142
			return n;
143
	}
144
	return -1;
145
}
146
147
/* conf_word gets one word from the conf file.
148
 * if "allow_key", then accept words at the start of a line,
149
 * otherwise stop when such a word is found.
150
 * We assume that the file pointer is at the end of a word, so the
151
 * next character is a space, or a newline.  If not, it is the start of a line.
152
 */
153
154
char *conf_word(FILE *file, int allow_key)
155
{
156
	int wsize = 100;
157
	int len = 0;
158
	int c;
159
	int quote;
160
	int wordfound = 0;
161
	char *word = malloc(wsize);
162
163
	if (!word) abort();
164
165
	while (wordfound==0) {
166
		/* at the end of a word.. */
167
		c = getc(file);
168
		if (c == '#')
169
			while (c != EOF && c != '\n')
170
				c = getc(file);
171
		if (c == EOF) break;
172
		if (c == '\n') continue;
173
174
		if (c != ' ' && c != '\t' && ! allow_key) {
175
			ungetc(c, file);
176
			break;
177
		}
178
		/* looks like it is safe to get a word here, if there is one */
179
		quote = 0;
180
		/* first, skip any spaces */
181
		while (c == ' ' || c == '\t')
182
			c = getc(file);
183
		if (c != EOF && c != '\n' && c != '#') {
184
			/* we really have a character of a word, so start saving it */
185
			while (c != EOF && c != '\n' && (quote || (c!=' ' && c != '\t'))) {
186
				wordfound = 1;
187
				if (quote && c == quote) quote = 0;
188
				else if (quote == 0 && (c == '\'' || c == '"'))
189
					quote = c;
190
				else {
191
					if (len == wsize-1) {
192
						wsize += 100;
193
						word = realloc(word, wsize);
194
						if (!word) abort();
195
					}
196
					word[len++] = c;
197
				}
198
				c = getc(file);
199
			}
200
		}
201
		if (c != EOF) ungetc(c, file);
202
	}
203
	word[len] = 0;
204
/*    printf("word is <%s>\n", word); */
205
	if (!wordfound) {
206
		free(word);
207
		word = NULL;
208
	}
209
	return word;
210
}
211
	
212
/*
213
 * conf_line reads one logical line from the conffile.
214
 * It skips comments and continues until it finds a line that starts
215
 * with a non blank/comment.  This character is pushed back for the next call
216
 * A doubly linked list of words is returned.
217
 * the first word will be a keyword.  Other words will have had quotes removed.
218
 */
219
220
char *conf_line(FILE *file)
221
{
222
	char *w;
223
	char *list;
224
225
	w = conf_word(file, 1);
226
	if (w == NULL) return NULL;
227
228
	list = dl_strdup(w);
229
	free(w);
230
	dl_init(list);
231
232
	while ((w = conf_word(file,0))){
233
		char *w2 = dl_strdup(w);
234
		free(w);
235
		dl_add(list, w2);
236
	}
237
/*    printf("got a line\n");*/
238
	return list;
239
}
240
241
void free_line(char *line)
242
{
243
	char *w;
244
	for (w=dl_next(line); w != line; w=dl_next(line)) {
245
		dl_del(w);
246
		dl_free(w);
247
	}
248
	dl_free(line);
249
}
250
251
252
struct conf_dev {
253
    struct conf_dev *next;
254
    char *name;
255
} *cdevlist = NULL;
256
257
mddev_dev_t load_partitions(void)
258
{
259
	FILE *f = fopen("/proc/partitions", "r");
260
	char buf[1024];
261
	mddev_dev_t rv = NULL;
262
	if (f == NULL) {
263
		fprintf(stderr, Name ": cannot open /proc/partitions\n");
264
		return NULL;
265
	}
266
	while (fgets(buf, 1024, f)) {
267
		int major, minor;
268
		char *name, *mp;
269
		mddev_dev_t d;
270
271
		buf[1023] = '\0';
272
		if (buf[0] != ' ')
273
			continue;
274
		major = strtoul(buf, &mp, 10);
275
		if (mp == buf || *mp != ' ') 
276
			continue;
277
		minor = strtoul(mp, NULL, 10);
278
279
		name = map_dev(major, minor, 1);
280
		if (!name)
281
			continue;
282
		d = malloc(sizeof(*d));
283
		d->devname = strdup(name);
284
		d->next = rv;
285
		d->used = 0;
286
		rv = d;
287
	}
288
	fclose(f);
289
	return rv;
290
}
291
292
struct createinfo createinfo = {
293
	.autof = 2, /* by default, create devices with standard names */
294
	.symlinks = 1,
295
#ifdef DEBIAN
296
	.gid = 6, /* disk */
297
	.mode = 0660,
298
#else
299
	.mode = 0600,
300
#endif
301
};
302
303
int parse_auto(char *str, char *msg, int config)
304
{
305
	int autof;
306
	if (str == NULL || *str == 0)
307
		autof = 2;
308
	else if (strcasecmp(str,"no")==0)
309
		autof = 1;
310
	else if (strcasecmp(str,"yes")==0)
311
		autof = 2;
312
	else if (strcasecmp(str,"md")==0)
313
		autof = config?5:3;
314
	else {
315
		/* There might be digits, and maybe a hypen, at the end */
316
		char *e = str + strlen(str);
317
		int num = 4;
318
		int len;
319
		while (e > str && isdigit(e[-1]))
320
			e--;
321
		if (*e) {
322
			num = atoi(e);
323
			if (num <= 0) num = 1;
324
		}
325
		if (e > str && e[-1] == '-')
326
			e--;
327
		len = e - str;
328
		if ((len == 2 && strncasecmp(str,"md",2)==0)) {
329
			autof = config ? 5 : 3;
330
		} else if ((len == 3 && strncasecmp(str,"yes",3)==0)) {
331
			autof = 2;
332
		} else if ((len == 3 && strncasecmp(str,"mdp",3)==0)) {
333
			autof = config ? 6 : 4;
334
		} else if ((len == 1 && strncasecmp(str,"p",1)==0) ||
335
			   (len >= 4 && strncasecmp(str,"part",4)==0)) {
336
			autof = 6;
337
		} else {
338
			fprintf(stderr, Name ": %s arg of \"%s\" unrecognised: use no,yes,md,mdp,part\n"
339
				"        optionally followed by a number.\n",
340
				msg, str);
341
			exit(2);
342
		}
343
		autof |= num << 3;
344
	}
345
	return autof;
346
}
347
348
static void createline(char *line)
349
{
350
	char *w;
351
	char *ep;
352
353
	for (w=dl_next(line); w!=line; w=dl_next(w)) {
354
		if (strncasecmp(w, "auto=", 5) == 0)
355
			createinfo.autof = parse_auto(w+5, "auto=", 1);
356
		else if (strncasecmp(w, "owner=", 6) == 0) {
357
			if (w[6] == 0) {
358
				fprintf(stderr, Name ": missing owner name\n");
359
				continue;
360
			}
361
			createinfo.uid = strtoul(w+6, &ep, 10);
362
			if (*ep != 0) {
363
				struct passwd *pw;
364
				/* must be a name */
365
				pw = getpwnam(w+6);
366
				if (pw)
367
					createinfo.uid = pw->pw_uid;
368
				else
369
					fprintf(stderr, Name ": CREATE user %s not found\n", w+6);
370
			}
371
		} else if (strncasecmp(w, "group=", 6) == 0) {
372
			if (w[6] == 0) {
373
				fprintf(stderr, Name ": missing group name\n");
374
				continue;
375
			}
376
			createinfo.gid = strtoul(w+6, &ep, 10);
377
			if (*ep != 0) {
378
				struct group *gr;
379
				/* must be a name */
380
				gr = getgrnam(w+6);
381
				if (gr)
382
					createinfo.gid = gr->gr_gid;
383
				else
384
					fprintf(stderr, Name ": CREATE group %s not found\n", w+6);
385
			}
386
		} else if (strncasecmp(w, "mode=", 5) == 0) {
387
			if (w[5] == 0) {
388
				fprintf(stderr, Name ": missing CREATE mode\n");
389
				continue;
390
			}
391
			createinfo.mode = strtoul(w+5, &ep, 8);
392
			if (*ep != 0) {
393
				createinfo.mode = 0600;
394
				fprintf(stderr, Name ": unrecognised CREATE mode %s\n",
395
					w+5);
396
			}
397
		} else if (strncasecmp(w, "metadata=", 9) == 0) {
398
			/* style of metadata to use by default */
399
			int i;
400
			for (i=0; superlist[i] && !createinfo.supertype; i++)
401
				createinfo.supertype =
402
					superlist[i]->match_metadata_desc(w+9);
403
			if (!createinfo.supertype)
404
				fprintf(stderr, Name ": metadata format %s unknown, ignoring\n",
405
					w+9);
406
		} else if (strncasecmp(w, "symlinks=yes", 12) == 0)
407
			createinfo.symlinks = 1;
408
		else if  (strncasecmp(w, "symlinks=no", 11) == 0)
409
			createinfo.symlinks = 0;
410
		else {
411
			fprintf(stderr, Name ": unrecognised word on CREATE line: %s\n",
412
				w);
413
		}
414
	}
415
}
416
417
void devline(char *line) 
418
{
419
	char *w;
420
	struct conf_dev *cd;
421
422
	for (w=dl_next(line); w != line; w=dl_next(w)) {
423
		if (w[0] == '/' || strcasecmp(w, "partitions") == 0) {
424
			cd = malloc(sizeof(*cd));
425
			cd->name = strdup(w);
426
			cd->next = cdevlist;
427
			cdevlist = cd;
428
		} else {
429
			fprintf(stderr, Name ": unreconised word on DEVICE line: %s\n",
430
				w);
431
		}
432
	}
433
}
434
435
mddev_ident_t mddevlist = NULL;
436
mddev_ident_t *mddevlp = &mddevlist;
437
438
void arrayline(char *line)
439
{
440
	char *w;
441
442
	struct mddev_ident_s mis;
443
	mddev_ident_t mi;
444
445
	mis.uuid_set = 0;
446
	mis.super_minor = UnSet;
447
	mis.level = UnSet;
448
	mis.raid_disks = UnSet;
449
	mis.spare_disks = 0;
450
	mis.devices = NULL;
451
	mis.devname = NULL;
452
	mis.spare_group = NULL;
453
	mis.autof = 0;
454
	mis.next = NULL;
455
	mis.st = NULL;
456
	mis.bitmap_fd = -1;
457
	mis.bitmap_file = NULL;
458
	mis.name[0] = 0;
459
460
	for (w=dl_next(line); w!=line; w=dl_next(w)) {
461
		if (w[0] == '/') {
462
			if (mis.devname)
463
				fprintf(stderr, Name ": only give one device per ARRAY line: %s and %s\n",
464
					mis.devname, w);
465
			else mis.devname = w;
466
		} else if (strncasecmp(w, "uuid=", 5)==0 ) {
467
			if (mis.uuid_set)
468
				fprintf(stderr, Name ": only specify uuid once, %s ignored.\n",
469
					w);
470
			else {
471
				if (parse_uuid(w+5, mis.uuid))
472
					mis.uuid_set = 1;
473
				else
474
					fprintf(stderr, Name ": bad uuid: %s\n", w);
475
			}
476
		} else if (strncasecmp(w, "super-minor=", 12)==0 ) {
477
			if (mis.super_minor != UnSet)
478
				fprintf(stderr, Name ": only specify super-minor once, %s ignored.\n",
479
					w);
480
			else {
481
				char *endptr;
482
				mis.super_minor= strtol(w+12, &endptr, 10);
483
				if (w[12]==0 || endptr[0]!=0 || mis.super_minor < 0) {
484
					fprintf(stderr, Name ": invalid super-minor number: %s\n",
485
						w);
486
					mis.super_minor = UnSet;
487
				}
488
			}
489
		} else if (strncasecmp(w, "name=", 5)==0) {
490
			if (mis.name[0])
491
				fprintf(stderr, Name ": only specify name once, %s ignored.\n",
492
					w);
493
			else if (strlen(w+5) > 32)
494
				fprintf(stderr, Name ": name too long, ignoring %s\n", w);
495
			else
496
				strcpy(mis.name, w+5);
497
498
		} else if (strncasecmp(w, "bitmap=", 7) == 0) {
499
			if (mis.bitmap_file)
500
				fprintf(stderr, Name ": only specify bitmap file once. %s ignored\n",
501
					w);
502
			else
503
				mis.bitmap_file = strdup(w+7);
504
505
		} else if (strncasecmp(w, "devices=", 8 ) == 0 ) {
506
			if (mis.devices)
507
				fprintf(stderr, Name ": only specify devices once (use a comma separated list). %s ignored\n",
508
					w);
509
			else
510
				mis.devices = strdup(w+8);
511
		} else if (strncasecmp(w, "spare-group=", 12) == 0 ) {
512
			if (mis.spare_group)
513
				fprintf(stderr, Name ": only specify one spare group per array. %s ignored.\n",
514
					w);
515
			else
516
				mis.spare_group = strdup(w+12);
517
		} else if (strncasecmp(w, "level=", 6) == 0 ) {
518
			/* this is mainly for compatability with --brief output */
519
			mis.level = map_name(pers, w+6);
520
		} else if (strncasecmp(w, "disks=", 6) == 0 ) {
521
			/* again, for compat */
522
			mis.raid_disks = atoi(w+6);
523
		} else if (strncasecmp(w, "num-devices=", 12) == 0 ) {
524
			/* again, for compat */
525
			mis.raid_disks = atoi(w+12);
526
		} else if (strncasecmp(w, "spares=", 7) == 0 ) {
527
			/* for warning if not all spares present */
528
			mis.spare_disks = atoi(w+7);
529
		} else if (strncasecmp(w, "metadata=", 9) == 0) {
530
			/* style of metadata on the devices. */
531
			int i;
532
			
533
			for(i=0; superlist[i] && !mis.st; i++)
534
				mis.st = superlist[i]->match_metadata_desc(w+9);
535
536
			if (!mis.st)
537
				fprintf(stderr, Name ": metadata format %s unknown, ignored.\n", w+9);
538
		} else if (strncasecmp(w, "auto=", 5) == 0 ) {
539
			/* whether to create device special files as needed */
540
			mis.autof = parse_auto(w+5, "auto type", 0);
541
		} else {
542
			fprintf(stderr, Name ": unrecognised word on ARRAY line: %s\n",
543
				w);
544
		}
545
	}
546
	if (mis.devname == NULL)
547
		fprintf(stderr, Name ": ARRAY line with no device\n");
548
	else if (mis.uuid_set == 0 && mis.devices == NULL && mis.super_minor == UnSet && mis.name[0] == 0)
549
		fprintf(stderr, Name ": ARRAY line %s has no identity information.\n", mis.devname);
550
	else {
551
		mi = malloc(sizeof(*mi));
552
		*mi = mis;
553
		mi->devname = strdup(mis.devname);
554
		mi->next = NULL;
555
		*mddevlp = mi;
556
		mddevlp = &mi->next;
557
	}
558
}
559
560
static char *alert_email = NULL;
561
void mailline(char *line)
562
{
563
	char *w;
564
565
	for (w=dl_next(line); w != line ; w=dl_next(w)) {
566
		if (alert_email == NULL)
567
			alert_email = strdup(w);
568
		else
569
			fprintf(stderr, Name ": excess address on MAIL line: %s - ignored\n",
570
				w);
571
	}
572
}
573
574
static char *alert_mail_from = NULL;
575
void mailfromline(char *line)
576
{
577
	char *w;
578
579
	for (w=dl_next(line); w != line ; w=dl_next(w)) {
580
		if (alert_mail_from == NULL)
581
			alert_mail_from = strdup(w);
582
		else {
583
			char *t= NULL;
584
			asprintf(&t, "%s %s", alert_mail_from, w);
585
			free(alert_mail_from);
586
			alert_mail_from = t;
587
		}
588
	}
589
}
590
591
592
static char *alert_program = NULL;
593
void programline(char *line)
594
{
595
	char *w;
596
597
	for (w=dl_next(line); w != line ; w=dl_next(w)) {
598
		if (alert_program == NULL)
599
			alert_program = strdup(w);
600
		else
601
			fprintf(stderr, Name ": excess program on PROGRAM line: %s - ignored\n",
602
				w);
603
	}
604
}
605
606
static char *home_host = NULL;
607
void homehostline(char *line)
608
{
609
	char *w;
610
611
	for (w=dl_next(line); w != line ; w=dl_next(w)) {
612
		if (home_host == NULL)
613
			home_host = strdup(w);
614
		else
615
			fprintf(stderr, Name ": excess host name on HOMEHOST line: %s - ignored\n",
616
				w);
617
	}
618
}
619
620
621
int loaded = 0;
622
623
static char *conffile = NULL;
624
void set_conffile(char *file)
625
{
626
	conffile = file;
627
}
628
629
void load_conffile(void)
630
{
631
	FILE *f;
632
	char *line;
633
634
	if (loaded) return;
635
	if (conffile == NULL)
636
		conffile = DefaultConfFile;
637
638
	if (strcmp(conffile, "none") == 0) {
639
		loaded = 1;
640
		return;
641
	}
642
	if (strcmp(conffile, "partitions")==0) {
643
		char *list = dl_strdup("DEV");
644
		dl_init(list);
645
		dl_add(list, dl_strdup("partitions"));
646
		devline(list);
647
		free_line(list);
648
		loaded = 1;
649
		return;
650
	}
651
	f = fopen(conffile, "r");
652
	/* Debian chose to relocate mdadm.conf into /etc/mdadm/.
653
	 * To allow Debian users to compile from clean source and still
654
	 * have a working mdadm, we read /etc/mdadm/mdadm.conf
655
	 * if /etc/mdadm.conf doesn't exist
656
	 */
657
	if (f == NULL &&
658
	    conffile == DefaultConfFile) {
659
		f = fopen(DefaultAltConfFile, "r");
660
		if (f)
661
			conffile = DefaultAltConfFile;
662
	}
663
	if (f == NULL)
664
		return;
665
666
	loaded = 1;
667
	while ((line=conf_line(f))) {
668
		switch(match_keyword(line)) {
669
		case Devices:
670
			devline(line);
671
			break;
672
		case Array:
673
			arrayline(line);
674
			break;
675
		case Mailaddr:
676
			mailline(line);
677
			break;
678
		case Mailfrom:
679
			mailfromline(line);
680
			break;
681
		case Program:
682
			programline(line);
683
			break;
684
		case CreateDev:
685
			createline(line);
686
			break;
687
		case Homehost:
688
			homehostline(line);
689
			break;
690
		default:
691
			fprintf(stderr, Name ": Unknown keyword %s\n", line);
692
		}
693
		free_line(line);
694
	}
695
    
696
	fclose(f);
697
698
/*    printf("got file\n"); */
699
}
700
701
char *conf_get_mailaddr(void)
702
{
703
	load_conffile();
704
	return alert_email;
705
}
706
707
char *conf_get_mailfrom(void)
708
{
709
	load_conffile();
710
	return alert_mail_from;
711
}
712
713
char *conf_get_program(void)
714
{
715
	load_conffile();
716
	return alert_program;
717
}
718
719
char *conf_get_homehost(void)
720
{
721
	load_conffile();
722
	return home_host;
723
}
724
725
struct createinfo *conf_get_create_info(void)
726
{
727
	load_conffile();
728
	return &createinfo;
729
}
730
731
mddev_ident_t conf_get_ident(char *dev)
732
{
733
	mddev_ident_t rv;
734
	load_conffile();
735
	rv = mddevlist;
736
	while (dev && rv && strcmp(dev, rv->devname)!=0)
737
		rv = rv->next;
738
	return rv;
739
}
740
741
mddev_dev_t conf_get_devs()
742
{
743
	glob_t globbuf;
744
	struct conf_dev *cd;
745
	int flags = 0;
746
	static mddev_dev_t dlist = NULL;
747
	unsigned int i;
748
749
	while (dlist) {
750
		mddev_dev_t t = dlist;
751
		dlist = dlist->next;
752
		free(t->devname);
753
		free(t);
754
	}
755
    
756
	load_conffile();
757
758
	if (cdevlist == NULL)
759
		/* default to 'partitions */
760
		dlist = load_partitions();
761
762
	for (cd=cdevlist; cd; cd=cd->next) {
763
		if (strcasecmp(cd->name, "partitions")==0 && dlist == NULL)
764
			dlist = load_partitions();
765
		else {
766
			glob(cd->name, flags, NULL, &globbuf);
767
			flags |= GLOB_APPEND;
768
		}
769
	}
770
	if (flags & GLOB_APPEND) {
771
		for (i=0; i<globbuf.gl_pathc; i++) {
772
			mddev_dev_t t = malloc(sizeof(*t));
773
			t->devname = strdup(globbuf.gl_pathv[i]);
774
			t->next = dlist;
775
			t->used = 0;
776
			dlist = t;
777
/*	printf("one dev is %s\n", t->devname);*/
778
		}
779
		globfree(&globbuf);
780
	}
781
782
	return dlist;
783
}
784
785
int conf_test_dev(char *devname)
786
{
787
	struct conf_dev *cd;
788
	if (cdevlist == NULL)
789
		/* allow anything by default */
790
		return 1;
791
	for (cd = cdevlist ; cd ; cd = cd->next) {
792
		if (strcasecmp(cd->name, "partitions") == 0)
793
			return 1;
794
		if (fnmatch(cd->name, devname, FNM_PATHNAME) == 0)
795
			return 1;
796
	}
797
	return 0;
798
}
799
800
801
int match_oneof(char *devices, char *devname)
802
{
803
    /* check if one of the comma separated patterns in devices
804
     * matches devname
805
     */
806
807
808
    while (devices && *devices) {
809
	char patn[1024];
810
	char *p = devices;
811
	devices = strchr(devices, ',');
812
	if (!devices)
813
	    devices = p + strlen(p);
814
	if (devices-p < 1024) {
815
		strncpy(patn, p, devices-p);
816
		patn[devices-p] = 0;
817
		if (fnmatch(patn, devname, FNM_PATHNAME)==0)
818
			return 1;
819
	}
820
	if (*devices == ',')
821
		devices++;
822
    }
823
    return 0;
824
}
(-)a/mdadm/Config.in (+15 lines)
Line 0 Link Here
1
#
2
# For a description of the syntax of this configuration file,
3
# see scripts/kbuild/config-language.txt.
4
#
5
6
menu "Linux mdadm Utilities"
7
8
config MDADM
9
	bool "mdadm"
10
	default n
11
	help
12
	  assemble or examine raid array
13
14
endmenu
15
(-)a/mdadm/dlink.c (+79 lines)
Line 0 Link Here
1
2
/* doubly linked lists */
3
/* This is free software. No strings attached. No copyright claimed */
4
5
#include	<unistd.h>
6
#include	<stdlib.h>
7
#include	<string.h>
8
#ifdef __dietlibc__
9
char *strncpy(char *dest, const char *src, size_t n) __THROW;
10
#endif
11
#include	"dlink.h"
12
13
14
void *dl_head()
15
{
16
    void *h;
17
    h = dl_alloc(0);
18
    dl_next(h) = h;
19
    dl_prev(h) = h;
20
    return h;
21
}
22
23
void dl_free(void *v)
24
{
25
    struct __dl_head *vv  = v;
26
    free(vv-1);
27
}
28
29
void dl_init(void *v)
30
{
31
    dl_next(v) = v;
32
    dl_prev(v) = v;
33
}
34
35
void dl_insert(void *head, void *val)
36
{
37
    dl_next(val) = dl_next(head);
38
    dl_prev(val) = head;
39
    dl_next(dl_prev(val)) = val;
40
    dl_prev(dl_next(val)) = val;
41
}
42
43
void dl_add(void *head, void *val)
44
{
45
    dl_prev(val) = dl_prev(head);
46
    dl_next(val) = head;
47
    dl_next(dl_prev(val)) = val;
48
    dl_prev(dl_next(val)) = val;
49
}
50
51
void dl_del(void *val)
52
{
53
    if (dl_prev(val) == 0 || dl_next(val) == 0)
54
	return;
55
    dl_prev(dl_next(val)) = dl_prev(val);
56
    dl_next(dl_prev(val)) = dl_next(val);
57
    dl_prev(val) = dl_next(val) = 0;
58
}
59
60
char *dl_strndup(char *s, int l)
61
{
62
    char *n;
63
    if (s == NULL)
64
	return NULL;
65
    n = dl_newv(char, l+1);
66
    if (n == NULL)
67
	return NULL;
68
    else
69
    {
70
	strncpy(n, s, l);
71
	n[l] = 0;
72
	return n;
73
    }
74
}
75
76
char *dl_strdup(char *s)
77
{
78
    return dl_strndup(s, (int)strlen(s));
79
}
(-)a/mdadm/dlink.h (+25 lines)
Line 0 Link Here
1
2
/* doubley linked lists */
3
/* This is free software. No strings attached. No copyright claimed */
4
5
struct __dl_head
6
{
7
    void * dh_prev;
8
    void * dh_next;
9
};
10
11
#define	dl_alloc(size)	((void*)(((char*)calloc(1,(size)+sizeof(struct __dl_head)))+sizeof(struct __dl_head)))
12
#define	dl_new(t)	((t*)dl_alloc(sizeof(t)))
13
#define	dl_newv(t,n)	((t*)dl_alloc(sizeof(t)*n))
14
15
#define dl_next(p) *(&(((struct __dl_head*)(p))[-1].dh_next))
16
#define dl_prev(p) *(&(((struct __dl_head*)(p))[-1].dh_prev))
17
18
void *dl_head(void);
19
char *dl_strdup(char *);
20
char *dl_strndup(char *, int);
21
void dl_insert(void*, void*);
22
void dl_add(void*, void*);
23
void dl_del(void*);
24
void dl_free(void*);
25
void dl_init(void*);
(-)a/mdadm/Kbuild (+9 lines)
Line 0 Link Here
1
# Makefile for busybox
2
#
3
# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
4
#
5
# Licensed under the GPL v2, see the file LICENSE in this tarball.
6
7
lib-y:=
8
MDADM-y:= config.o util.o dlink.o sha1.o super0.o super1.o mdexamine.o mdassemble.o
9
lib-$(CONFIG_MDADM)	+= mdadm.o $(MDADM-y)
(-)a/mdadm/md5.h (+134 lines)
Line 0 Link Here
1
/* Declaration of functions and data types used for MD5 sum computing
2
   library functions.
3
   Copyright (C) 1995-1997,1999-2005 Free Software Foundation, Inc.
4
5
   NOTE: The canonical source of this file is maintained with the GNU C
6
   Library.  Bugs can be reported to bug-glibc@prep.ai.mit.edu.
7
8
   This program is free software; you can redistribute it and/or modify it
9
   under the terms of the GNU General Public License as published by the
10
   Free Software Foundation; either version 2, or (at your option) any
11
   later version.
12
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
18
   You should have received a copy of the GNU General Public License
19
   along with this program; if not, write to the Free Software Foundation,
20
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
21
22
#ifndef _MD5_H
23
#define _MD5_H 1
24
25
#include <stdio.h>
26
27
# include <inttypes.h>
28
#if HAVE_STDINT_H || _LIBC
29
# include <stdint.h>
30
#endif
31
32
#ifndef __GNUC_PREREQ
33
# if defined __GNUC__ && defined __GNUC_MINOR__
34
#  define __GNUC_PREREQ(maj, min) \
35
	((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
36
# else
37
#  define __GNUC_PREREQ(maj, min) 0
38
# endif
39
#endif
40
41
#ifndef __THROW
42
# if defined __cplusplus && __GNUC_PREREQ (2,8)
43
#  define __THROW	throw ()
44
# else
45
#  define __THROW
46
# endif
47
#endif
48
49
#ifndef __attribute__
50
# if ! __GNUC_PREREQ (2,8) || __STRICT_ANSI__
51
#  define __attribute__(x)
52
# endif
53
#endif
54
55
#ifndef _LIBC
56
# define __md5_buffer md5_buffer
57
# define __md5_finish_ctx md5_finish_ctx
58
# define __md5_init_ctx md5_init_ctx
59
# define __md5_process_block md5_process_block
60
# define __md5_process_bytes md5_process_bytes
61
# define __md5_read_ctx md5_read_ctx
62
# define __md5_stream md5_stream
63
#endif
64
65
typedef uint32_t md5_uint32;
66
67
/* Structure to save state of computation between the single steps.  */
68
struct md5_ctx
69
{
70
  md5_uint32 A;
71
  md5_uint32 B;
72
  md5_uint32 C;
73
  md5_uint32 D;
74
75
  md5_uint32 total[2];
76
  md5_uint32 buflen;
77
  char buffer[128] __attribute__ ((__aligned__ (__alignof__ (md5_uint32))));
78
};
79
80
/*
81
 * The following three functions are build up the low level used in
82
 * the functions `md5_stream' and `md5_buffer'.
83
 */
84
85
/* Initialize structure containing state of computation.
86
   (RFC 1321, 3.3: Step 3)  */
87
extern void __md5_init_ctx (struct md5_ctx *ctx) __THROW;
88
89
/* Starting with the result of former calls of this function (or the
90
   initialization function update the context for the next LEN bytes
91
   starting at BUFFER.
92
   It is necessary that LEN is a multiple of 64!!! */
93
extern void __md5_process_block (const void *buffer, size_t len,
94
				 struct md5_ctx *ctx) __THROW;
95
96
/* Starting with the result of former calls of this function (or the
97
   initialization function update the context for the next LEN bytes
98
   starting at BUFFER.
99
   It is NOT required that LEN is a multiple of 64.  */
100
extern void __md5_process_bytes (const void *buffer, size_t len,
101
				 struct md5_ctx *ctx) __THROW;
102
103
/* Process the remaining bytes in the buffer and put result from CTX
104
   in first 16 bytes following RESBUF.  The result is always in little
105
   endian byte order, so that a byte-wise output yields to the wanted
106
   ASCII representation of the message digest.
107
108
   IMPORTANT: On some systems it is required that RESBUF be correctly
109
   aligned for a 32 bits value.  */
110
extern void *__md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) __THROW;
111
112
113
/* Put result from CTX in first 16 bytes following RESBUF.  The result is
114
   always in little endian byte order, so that a byte-wise output yields
115
   to the wanted ASCII representation of the message digest.
116
117
   IMPORTANT: On some systems it is required that RESBUF is correctly
118
   aligned for a 32 bits value.  */
119
extern void *__md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) __THROW;
120
121
122
/* Compute MD5 message digest for bytes read from STREAM.  The
123
   resulting message digest number will be written into the 16 bytes
124
   beginning at RESBLOCK.  */
125
extern int __md5_stream (FILE *stream, void *resblock) __THROW;
126
127
/* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
128
   result is always in little endian byte order, so that a byte-wise
129
   output yields to the wanted ASCII representation of the message
130
   digest.  */
131
extern void *__md5_buffer (const char *buffer, size_t len,
132
			   void *resblock) __THROW;
133
134
#endif /* md5.h */
(-)a/mdadm/mdadm.c (+18 lines)
Line 0 Link Here
1
/*
2
 * mdadm support for busybox.
3
 * added by Alan Hourihane <alanh@fairlite.demon.co.uk>
4
 */
5
#include <string.h>
6
7
extern int mdassemble_main(int argc, char **argv);
8
extern int mdexamine_main(int argc, char **argv);
9
10
int mdadm_main(int argc, char **argv) {
11
	if (argc >= 2) {
12
		if (!strncmp(argv[1],"--assemble",10))
13
			return mdassemble_main(argc, argv);
14
		if (!strncmp(argv[1],"--examine",9))
15
			return mdexamine_main(argc, argv);
16
	}
17
	return 0;
18
}
(-)a/mdadm/mdadm.h (+540 lines)
Line 0 Link Here
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	<unistd.h>
31
#ifndef __dietlibc__
32
extern __off64_t lseek64 __P ((int __fd, __off64_t __offset, int __whence));
33
#else
34
# if defined(__NO_STAT64) || __WORDSIZE != 32
35
# define lseek64 lseek
36
# endif
37
#endif
38
39
#include	<sys/types.h>
40
#include	<sys/stat.h>
41
#include	<stdlib.h>
42
#include	<time.h>
43
#include	<sys/time.h>
44
#include	<getopt.h>
45
#include	<fcntl.h>
46
#include	<stdio.h>
47
#include	<errno.h>
48
#include	<string.h>
49
#include	<syslog.h>
50
#ifdef __dietlibc__
51
#include	<strings.h>
52
/* dietlibc has deprecated random and srandom!! */
53
#define random rand
54
#define srandom srand
55
#endif
56
57
58
#include	<linux/kdev_t.h>
59
/*#include	<linux/fs.h> */
60
#include	<sys/mount.h>
61
#include	<asm/types.h>
62
#include	<sys/ioctl.h>
63
#define	MD_MAJOR 9
64
#define MdpMinorShift 6
65
66
#ifndef BLKGETSIZE64
67
#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
68
#endif
69
70
#define DEFAULT_BITMAP_CHUNK 4096
71
#define DEFAULT_BITMAP_DELAY 5
72
#define DEFAULT_MAX_WRITE_BEHIND 256
73
74
#include	"md_u.h"
75
#include	"md_p.h"
76
#include	"bitmap.h"
77
78
#include <endian.h>
79
/* Redhat don't like to #include <asm/byteorder.h>, and
80
 * some time include <linux/byteorder/xxx_endian.h> isn't enough,
81
 * and there is no standard conversion function so... */
82
/* And dietlibc doesn't think byteswap is ok, so.. */
83
/*  #include <byteswap.h> */
84
#define bswap_16(x) (((x) & 0x00ffU) << 8 | \
85
		     ((x) & 0xff00U) >> 8)
86
#define bswap_32(x) (((x) & 0x000000ffU) << 24 | \
87
		     ((x) & 0xff000000U) >> 24 | \
88
		     ((x) & 0x0000ff00U) << 8  | \
89
		     ((x) & 0x00ff0000U) >> 8)
90
#define bswap_64(x) (((x) & 0x00000000000000ffULL) << 56 | \
91
		     ((x) & 0xff00000000000000ULL) >> 56 | \
92
		     ((x) & 0x000000000000ff00ULL) << 40 | \
93
		     ((x) & 0x00ff000000000000ULL) >> 40 | \
94
		     ((x) & 0x0000000000ff0000ULL) << 24 | \
95
		     ((x) & 0x0000ff0000000000ULL) >> 24 | \
96
		     ((x) & 0x00000000ff000000ULL) << 8 | \
97
		     ((x) & 0x000000ff00000000ULL) >> 8)
98
99
#if BYTE_ORDER == LITTLE_ENDIAN
100
#define	__cpu_to_le16(_x) (_x)
101
#define __cpu_to_le32(_x) (_x)
102
#define __cpu_to_le64(_x) (_x)
103
#define	__le16_to_cpu(_x) (_x)
104
#define __le32_to_cpu(_x) (_x)
105
#define __le64_to_cpu(_x) (_x)
106
#elif BYTE_ORDER == BIG_ENDIAN
107
#define	__cpu_to_le16(_x) bswap_16(_x)
108
#define __cpu_to_le32(_x) bswap_32(_x)
109
#define __cpu_to_le64(_x) bswap_64(_x)
110
#define	__le16_to_cpu(_x) bswap_16(_x)
111
#define __le32_to_cpu(_x) bswap_32(_x)
112
#define __le64_to_cpu(_x) bswap_64(_x)
113
#else
114
#  error "unknown endianness."
115
#endif
116
117
118
119
/* general information that might be extracted from a superblock */
120
struct mdinfo {
121
	mdu_array_info_t	array;
122
	mdu_disk_info_t		disk;
123
	__u64			events;
124
	int			uuid[4];
125
	char			name[33];
126
	unsigned long long	data_offset;
127
	unsigned long long	component_size;
128
	int			reshape_active;
129
	unsigned long long	reshape_progress;
130
	int			new_level, delta_disks, new_layout, new_chunk;
131
};
132
133
struct createinfo {
134
	int	uid;
135
	int	gid;
136
	int	autof;
137
	int	mode;
138
	int	symlinks;
139
	struct supertype *supertype;
140
};
141
142
#define Name "mdadm"
143
144
enum mode {
145
	ASSEMBLE=1,
146
	BUILD,
147
	CREATE,
148
	MANAGE,
149
	MISC,
150
	MONITOR,
151
	GROW,
152
	INCREMENTAL,
153
	AUTODETECT,
154
};
155
156
extern char short_options[];
157
extern char short_bitmap_auto_options[];
158
extern struct option long_options[];
159
extern char Version[], Usage[], Help[], OptionHelp[],
160
	Help_create[], Help_build[], Help_assemble[], Help_grow[],
161
	Help_incr[],
162
	Help_manage[], Help_misc[], Help_monitor[], Help_config[];
163
164
/* for option that don't have short equivilents, we assign arbitrary
165
 * small numbers.  '1' means an undecorated option, so we start at '2'.
166
 */
167
enum special_options {
168
	AssumeClean = 2,
169
	BitmapChunk,
170
	WriteBehind,
171
	ReAdd,
172
	NoDegraded,
173
	Sparc22,
174
	BackupFile,
175
	HomeHost,
176
	AutoHomeHost,
177
	Symlinks,
178
	AutoDetect,
179
};
180
181
/* structures read from config file */
182
/* List of mddevice names and identifiers
183
 * Identifiers can be:
184
 *    uuid=128-hex-uuid
185
 *    super-minor=decimal-minor-number-from-superblock
186
 *    devices=comma,separated,list,of,device,names,with,wildcards
187
 *
188
 * If multiple fields are present, the intersection of all matching
189
 * devices is considered
190
 */
191
#define UnSet (0xfffe)
192
typedef struct mddev_ident_s {
193
	char	*devname;
194
	
195
	int	uuid_set;
196
	int	uuid[4];
197
	char	name[33];
198
199
	unsigned int super_minor;
200
201
	char	*devices;	/* comma separated list of device
202
				 * names with wild cards
203
				 */
204
	int	level;
205
	unsigned int raid_disks;
206
	unsigned int spare_disks;
207
	struct supertype *st;
208
	int	autof;		/* 1 for normal, 2 for partitioned */
209
	char	*spare_group;
210
	char	*bitmap_file;
211
	int	bitmap_fd;
212
213
	struct mddev_ident_s *next;
214
} *mddev_ident_t;
215
216
/* List of device names - wildcards expanded */
217
typedef struct mddev_dev_s {
218
	char *devname;
219
	char disposition;	/* 'a' for add, 'r' for remove, 'f' for fail.
220
				 * Not set for names read from .config
221
				 */
222
	char writemostly;
223
	char re_add;
224
	char used;		/* set when used */
225
	struct mddev_dev_s *next;
226
} *mddev_dev_t;
227
228
typedef struct mapping {
229
	char *name;
230
	int num;
231
} mapping_t;
232
233
234
struct mdstat_ent {
235
	char		*dev;
236
	int		devnum;
237
	int		active;
238
	char		*level;
239
	char		*pattern; /* U or up, _ for down */
240
	int		percent; /* -1 if no resync */
241
	int		resync; /* 1 if resync, 0 if recovery */
242
	struct mdstat_ent *next;
243
};
244
245
extern struct mdstat_ent *mdstat_read(int hold, int start);
246
extern void free_mdstat(struct mdstat_ent *ms);
247
extern void mdstat_wait(int seconds);
248
extern int mddev_busy(int devnum);
249
250
struct map_ent {
251
	struct map_ent *next;
252
	int	devnum;
253
	int	major,minor;
254
	int	uuid[4];
255
	char	*path;
256
};
257
extern int map_update(struct map_ent **mpp, int devnum, int major, int minor,
258
		      int uuid[4], char *path);
259
extern struct map_ent *map_by_uuid(struct map_ent **map, int uuid[4]);
260
extern void map_read(struct map_ent **melp);
261
extern int map_write(struct map_ent *mel);
262
extern void map_delete(struct map_ent **mapp, int devnum);
263
extern void map_free(struct map_ent *map);
264
extern void map_add(struct map_ent **melp,
265
		    int devnum, int major, int minor, int uuid[4], char *path);
266
267
/* Data structure for holding info read from sysfs */
268
struct sysdev {
269
	char	name[20];
270
	int	role;
271
	int	major, minor;
272
	unsigned long long offset, size;
273
	int	state;
274
	int	errors;
275
	struct sysdev *next;
276
};
277
struct sysarray {
278
	char	name[20];
279
	struct sysdev *devs;
280
	int	chunk;
281
	unsigned long long component_size;
282
	int	layout;
283
	int	level;
284
	int	spares;
285
	int	cache_size;
286
	int	mismatch_cnt;
287
	int	major_version, minor_version;
288
};
289
/* various details can be requested */
290
#define	GET_LEVEL	1
291
#define	GET_LAYOUT	2
292
#define	GET_COMPONENT	4
293
#define	GET_CHUNK	8
294
#define GET_CACHE	16
295
#define	GET_MISMATCH	32
296
#define	GET_VERSION	64
297
298
#define	GET_DEVS	1024 /* gets role, major, minor */
299
#define	GET_OFFSET	2048
300
#define	GET_SIZE	4096
301
#define	GET_STATE	8192
302
#define	GET_ERROR	16384
303
304
/* If fd >= 0, get the array it is open on,
305
 * else use devnum. >=0 -> major9. <0.....
306
 */
307
extern void sysfs_free(struct sysarray *sra);
308
extern struct sysarray *sysfs_read(int fd, int devnum, unsigned long options);
309
extern int sysfs_set_str(struct sysarray *sra, struct sysdev *dev,
310
			 char *name, char *val);
311
extern int sysfs_set_num(struct sysarray *sra, struct sysdev *dev,
312
			 char *name, unsigned long long val);
313
extern int sysfs_get_ll(struct sysarray *sra, struct sysdev *dev,
314
			char *name, unsigned long long *val);
315
316
317
extern int save_stripes(int *source, unsigned long long *offsets,
318
			int raid_disks, int chunk_size, int level, int layout,
319
			int nwrites, int *dest,
320
			unsigned long long start, unsigned long long length);
321
extern int restore_stripes(int *dest, unsigned long long *offsets,
322
			   int raid_disks, int chunk_size, int level, int layout,
323
			   int source, unsigned long long read_offset,
324
			   unsigned long long start, unsigned long long length);
325
326
#ifndef Sendmail
327
#define Sendmail "/usr/lib/sendmail -t"
328
#endif
329
330
#define SYSLOG_FACILITY LOG_DAEMON
331
332
extern char *map_num(mapping_t *map, int num);
333
extern int map_name(mapping_t *map, char *name);
334
extern mapping_t r5layout[], pers[], modes[], faultylayout[];
335
336
extern char *map_dev(int major, int minor, int create);
337
338
339
extern struct superswitch {
340
	void (*examine_super)(void *sbv, char *homehost);
341
	void (*brief_examine_super)(void *sbv);
342
	void (*detail_super)(void *sbv, char *homehost);
343
	void (*export_super)(void *sbv);
344
	void (*brief_detail_super)(void *sbv);
345
	void (*uuid_from_super)(int uuid[4], void *sbv);
346
	void (*getinfo_super)(struct mdinfo *info, void *sbv);
347
	int (*match_home)(void *sbv, char *homehost);
348
	int (*update_super)(struct mdinfo *info, void *sbv, char *update,
349
			    char *devname, int verbose,
350
			    int uuid_set, char *homehost);
351
	int (*init_super)(struct supertype *st, void **sbp, mdu_array_info_t *info, unsigned long long size, char *name, char *homehost, int *uuid);
352
	void (*add_to_super)(void *sbv, mdu_disk_info_t *dinfo);
353
	int (*store_super)(struct supertype *st, int fd, void *sbv);
354
	int (*write_init_super)(struct supertype *st, void *sbv, mdu_disk_info_t *dinfo, char *devname);
355
	int (*compare_super)(void **firstp, void *secondv);
356
	int (*load_super)(struct supertype *st, int fd, void **sbp, char *devname);
357
	struct supertype * (*match_metadata_desc)(char *arg);
358
	__u64 (*avail_size)(struct supertype *st, __u64 size);
359
	int (*add_internal_bitmap)(struct supertype *st, void *sbv, int *chunkp,
360
				   int delay, int write_behind,
361
				   unsigned long long size, int may_change, int major);
362
	void (*locate_bitmap)(struct supertype *st, int fd, void *sbv);
363
	int (*write_bitmap)(struct supertype *st, int fd, void *sbv);
364
	int major;
365
	int swapuuid; /* true if uuid is bigending rather than hostendian */
366
} super0, super1, *superlist[];
367
368
struct supertype {
369
	struct superswitch *ss;
370
	int minor_version;
371
	int max_devs;
372
};
373
374
extern struct supertype *super_by_version(int vers, int minor);
375
extern struct supertype *guess_super(int fd);
376
extern int get_dev_size(int fd, char *dname, unsigned long long *sizep);
377
extern void get_one_disk(int mdfd, mdu_array_info_t *ainf,
378
			 mdu_disk_info_t *disk);
379
380
#if __GNUC__ < 3
381
struct stat64;
382
#endif
383
384
#define HAVE_NFTW  we assume
385
#define HAVE_FTW
386
387
#ifdef UCLIBC
388
# include <features.h>
389
# ifndef  __UCLIBC_HAS_FTW__
390
#  undef HAVE_FTW
391
#  undef HAVE_NFTW
392
# endif
393
#endif
394
395
#ifdef __dietlibc__
396
# undef HAVE_NFTW
397
#endif
398
399
#ifndef HAVE_NFTW
400
# define FTW_PHYS 1
401
# ifndef HAVE_FTW
402
  struct FTW {};
403
# endif
404
#endif
405
406
#ifdef HAVE_FTW
407
# include <ftw.h>
408
#endif
409
410
extern int add_dev(const char *name, const struct stat *stb, int flag, struct FTW *s);
411
412
413
extern int Manage_ro(char *devname, int fd, int readonly);
414
extern int Manage_runstop(char *devname, int fd, int runstop, int quiet);
415
extern int Manage_resize(char *devname, int fd, long long size, int raid_disks);
416
extern int Manage_reconfig(char *devname, int fd, int layout);
417
extern int Manage_subdevs(char *devname, int fd,
418
			  mddev_dev_t devlist, int verbose);
419
extern int autodetect(void);
420
extern int Grow_Add_device(char *devname, int fd, char *newdev);
421
extern int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int write_behind, int force);
422
extern int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
423
			long long size,
424
			int level, int layout, int chunksize, int raid_disks);
425
extern int Grow_restart(struct supertype *st, struct mdinfo *info,
426
			int *fdlist, int cnt, char *backup_file);
427
428
429
extern int Assemble(struct supertype *st, char *mddev, int mdfd,
430
		    mddev_ident_t ident,
431
		    mddev_dev_t devlist, char *backup_file,
432
		    int readonly, int runstop,
433
		    char *update, char *homehost,
434
		    int verbose, int force);
435
436
extern int Build(char *mddev, int mdfd, int chunk, int level, int layout,
437
		 int raiddisks,
438
		 mddev_dev_t devlist, int assume_clean,
439
		 char *bitmap_file, int bitmap_chunk, int write_behind, int delay, int verbose);
440
441
442
extern int Create(struct supertype *st, char *mddev, int mdfd,
443
		  int chunk, int level, int layout, unsigned long long size, int raiddisks, int sparedisks,
444
		  char *name, char *homehost, int *uuid,
445
		  int subdevs, mddev_dev_t devlist,
446
		  int runstop, int verbose, int force, int assume_clean,
447
		  char *bitmap_file, int bitmap_chunk, int write_behind, int delay);
448
449
extern int Detail(char *dev, int brief, int export, int test, char *homehost);
450
extern int Query(char *dev);
451
452
extern int md_get_version(int fd);
453
extern int get_linux_version(void);
454
extern int parse_uuid(char *str, int uuid[4]);
455
extern int check_ext2(int fd, char *name);
456
extern int check_reiser(int fd, char *name);
457
extern int check_raid(int fd, char *name);
458
459
extern int get_mdp_major(void);
460
extern int dev_open(char *dev, int flags);
461
extern int is_standard(char *dev, int *nump);
462
463
extern int parse_auto(char *str, char *msg, int config);
464
extern mddev_ident_t conf_get_ident(char *dev);
465
extern mddev_dev_t conf_get_devs(void);
466
extern int conf_test_dev(char *devname);
467
extern struct createinfo *conf_get_create_info(void);
468
extern void set_conffile(char *file);
469
extern char *conf_get_mailaddr(void);
470
extern char *conf_get_mailfrom(void);
471
extern char *conf_get_program(void);
472
extern char *conf_get_homehost(void);
473
extern char *conf_line(FILE *file);
474
extern char *conf_word(FILE *file, int allow_key);
475
extern void free_line(char *line);
476
extern int match_oneof(char *devices, char *devname);
477
extern void uuid_from_super(int uuid[4], mdp_super_t *super);
478
extern int same_uuid(int a[4], int b[4], int swapuuid);
479
extern void copy_uuid(void *a, int b[4], int swapuuid);
480
/* extern int compare_super(mdp_super_t *first, mdp_super_t *second);*/
481
extern unsigned long calc_csum(void *super, int bytes);
482
extern int enough(int level, int raid_disks, int layout, int clean,
483
		   char *avail, int avail_disks);
484
extern int ask(char *mesg);
485
extern unsigned long long get_component_size(int fd);
486
extern void remove_partitions(int fd);
487
488
489
extern char *human_size(long long bytes);
490
char *human_size_brief(long long bytes);
491
492
extern void put_md_name(char *name);
493
extern char *get_md_name(int dev);
494
495
extern char DefaultConfFile[];
496
497
extern int open_mddev(char *dev, int autof);
498
extern int open_mddev_devnum(char *devname, int devnum, char *name,
499
			     char *chosen_name);
500
501
502
#define	LEVEL_MULTIPATH		(-4)
503
#define	LEVEL_LINEAR		(-1)
504
#define	LEVEL_FAULTY		(-5)
505
506
507
/* faulty stuff */
508
509
#define	WriteTransient	0
510
#define	ReadTransient	1
511
#define	WritePersistent	2
512
#define	ReadPersistent	3
513
#define	WriteAll	4 /* doesn't go to device */
514
#define	ReadFixable	5
515
#define	Modes	6
516
517
#define	ClearErrors	31
518
#define	ClearFaults	30
519
520
#define AllPersist	100 /* internal use only */
521
#define	NoPersist	101
522
523
#define	ModeMask	0x1f
524
#define	ModeShift	5
525
526
527
#ifdef __TINYC__
528
#undef minor
529
#undef major
530
#undef makedev
531
#define minor(x) ((x)&0xff)
532
#define major(x) (((x)>>8)&0xff)
533
#define makedev(M,m) (((M)<<8) | (m))
534
#endif
535
536
/* for raid5 */
537
#define ALGORITHM_LEFT_ASYMMETRIC	0
538
#define ALGORITHM_RIGHT_ASYMMETRIC	1
539
#define ALGORITHM_LEFT_SYMMETRIC	2
540
#define ALGORITHM_RIGHT_SYMMETRIC	3
(-)a/mdadm/mdassemble.c (+908 lines)
Line 0 Link Here
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	<ctype.h>
32
33
static int name_matches(char *found, char *required, char *homehost)
34
{
35
	/* See if the name found matches the required name, possibly
36
	 * prefixed with 'homehost'
37
	 */
38
	char fnd[33];
39
40
	strncpy(fnd, found, 32);
41
	fnd[32] = 0;
42
	if (strcmp(found, required)==0)
43
		return 1;
44
	if (homehost) {
45
		int l = strlen(homehost);
46
		if (l < 32 && fnd[l] == ':' &&
47
		    strcmp(fnd+l+1, required)==0)
48
			return 1;
49
	}
50
	return 0;
51
}
52
53
int open_mddev(char *dev, int autof/*unused */)
54
{
55
	int mdfd = open(dev, O_RDWR, 0);
56
	if (mdfd < 0)
57
		fprintf(stderr, Name ": error opening %s: %s\n",
58
			dev, strerror(errno));
59
	else if (md_get_version(mdfd) <= 0) {
60
		fprintf(stderr, Name ": %s does not appear to be an md device\n",
61
			dev);
62
		close(mdfd);
63
		mdfd = -1;
64
	}
65
	return mdfd;
66
}
67
68
int Assemble(struct supertype *st, char *mddev, int mdfd,
69
	     mddev_ident_t ident,
70
	     mddev_dev_t devlist, char *backup_file,
71
	     int readonly, int runstop,
72
	     char *update, char *homehost,
73
	     int verbose, int force)
74
{
75
	/*
76
	 * The task of Assemble is to find a collection of
77
	 * devices that should (according to their superblocks)
78
	 * form an array, and to give this collection to the MD driver.
79
	 * In Linux-2.4 and later, this involves submitting a
80
	 * SET_ARRAY_INFO ioctl with no arg - to prepare
81
	 * the array - and then submit a number of
82
	 * ADD_NEW_DISK ioctls to add disks into
83
	 * the array.  Finally RUN_ARRAY might
84
	 * be submitted to start the array.
85
	 *
86
	 * Much of the work of Assemble is in finding and/or
87
	 * checking the disks to make sure they look right.
88
	 *
89
	 * If mddev is not set, then scan must be set and we
90
	 *  read through the config file for dev+uuid mapping
91
	 *  We recurse, setting mddev, for each device that
92
	 *    - isn't running
93
	 *    - has a valid uuid (or any uuid if !uuidset)
94
	 *
95
	 * If mddev is set, we try to determine state of md.
96
	 *   check version - must be at least 0.90.0
97
	 *   check kernel version.  must be at least 2.4.
98
	 *    If not, we can possibly fall back on START_ARRAY
99
	 *   Try to GET_ARRAY_INFO.
100
	 *     If possible, give up
101
	 *     If not, try to STOP_ARRAY just to make sure
102
	 *
103
	 * If !uuidset and scan, look in conf-file for uuid
104
	 *       If not found, give up
105
	 * If !devlist and scan and uuidset, get list of devs from conf-file
106
	 *
107
	 * For each device:
108
	 *   Check superblock - discard if bad
109
	 *   Check uuid (set if we don't have one) - discard if no match
110
	 *   Check superblock similarity if we have a superblock - discard if different
111
	 *   Record events, devicenum
112
	 * This should give us a list of devices for the array
113
	 * We should collect the most recent event number
114
	 *
115
	 * Count disks with recent enough event count
116
	 * While force && !enough disks
117
	 *    Choose newest rejected disks, update event count
118
	 *     mark clean and rewrite superblock
119
	 * If recent kernel:
120
	 *    SET_ARRAY_INFO
121
	 *    foreach device with recent events : ADD_NEW_DISK
122
	 *    if runstop == 1 || "enough" disks and runstop==0 -> RUN_ARRAY
123
	 * If old kernel:
124
	 *    Check the device numbers in superblock are right
125
	 *    update superblock if any changes
126
	 *    START_ARRAY
127
	 *
128
	 */
129
	int clean = 0;
130
	int old_linux = 0;
131
	int vers = 0; /* Keep gcc quite - it really is initialised */
132
	void *first_super = NULL, *super = NULL;
133
	struct {
134
		char *devname;
135
		unsigned int major, minor;
136
		unsigned int oldmajor, oldminor;
137
		long long events;
138
		int uptodate;
139
		int state;
140
		int raid_disk;
141
		int disk_nr;
142
	} *devices;
143
	int *best = NULL; /* indexed by raid_disk */
144
	unsigned int bestcnt = 0;
145
	int devcnt = 0;
146
	unsigned int okcnt, sparecnt;
147
	unsigned int req_cnt;
148
	unsigned int i;
149
	int most_recent = 0;
150
	int chosen_drive;
151
	int change = 0;
152
	int inargv = 0;
153
	int bitmap_done;
154
	int start_partial_ok = (runstop >= 0) && (force || devlist==NULL || mdfd < 0);
155
	unsigned int num_devs;
156
	mddev_dev_t tmpdev;
157
	struct mdinfo info;
158
	char *avail;
159
	int nextspare = 0;
160
161
	if (mdfd < 0)
162
		return 2;
163
164
	if (get_linux_version() < 2004000)
165
		old_linux = 1;
166
167
	if (mdfd >= 0) {
168
		vers = md_get_version(mdfd);
169
		if (vers <= 0) {
170
			fprintf(stderr, Name ": %s appears not to be an md device.\n", mddev);
171
			return 1;
172
		}
173
		if (vers < 9000) {
174
			fprintf(stderr, Name ": Assemble requires driver version 0.90.0 or later.\n"
175
				"    Upgrade your kernel or try --build\n");
176
			return 1;
177
		}
178
179
		if (ioctl(mdfd, GET_ARRAY_INFO, &info.array)>=0) {
180
			fprintf(stderr, Name ": device %s already active - cannot assemble it\n",
181
				mddev);
182
			return 1;
183
		}
184
		ioctl(mdfd, STOP_ARRAY, NULL); /* just incase it was started but has no content */
185
	}
186
	/*
187
	 * If any subdevs are listed, then any that don't
188
	 * match ident are discarded.  Remainder must all match and
189
	 * become the array.
190
	 * If no subdevs, then we scan all devices in the config file, but
191
	 * there must be something in the identity
192
	 */
193
194
	if (!devlist &&
195
	    ident->uuid_set == 0 &&
196
	    ident->super_minor < 0 &&
197
	    ident->devices == NULL) {
198
		fprintf(stderr, Name ": No identity information available for %s - cannot assemble.\n",
199
			mddev ? mddev : "further assembly");
200
		return 1;
201
	}
202
	if (devlist == NULL)
203
		devlist = conf_get_devs();
204
	else if (mdfd >= 0)
205
		inargv = 1;
206
207
	tmpdev = devlist; num_devs = 0;
208
	while (tmpdev) {
209
		if (tmpdev->used)
210
			tmpdev->used = 2;
211
		else
212
			num_devs++;
213
		tmpdev = tmpdev->next;
214
	}
215
	devices = malloc(num_devs * sizeof(*devices));
216
217
	if (!st && ident->st) st = ident->st;
218
219
	if (verbose>0)
220
	    fprintf(stderr, Name ": looking for devices for %s\n",
221
		    mddev ? mddev : "further assembly");
222
223
	/* first walk the list of devices to find a consistent set
224
	 * that match the criterea, if that is possible.
225
	 * We flag the one we like with 'used'.
226
	 */
227
	for (tmpdev = devlist;
228
	     tmpdev;
229
	     tmpdev = tmpdev->next) {
230
		char *devname = tmpdev->devname;
231
		int dfd;
232
		struct stat stb;
233
		struct supertype *tst = st;
234
235
		if (tmpdev->used > 1) continue;
236
237
		if (ident->devices &&
238
		    !match_oneof(ident->devices, devname)) {
239
			if ((inargv && verbose>=0) || verbose > 0)
240
				fprintf(stderr, Name ": %s is not one of %s\n", devname, ident->devices);
241
			continue;
242
		}
243
244
		if (super) {
245
			free(super);
246
			super = NULL;
247
		}
248
		
249
		dfd = dev_open(devname, O_RDONLY|O_EXCL);
250
		if (dfd < 0) {
251
			if ((inargv && verbose >= 0) || verbose > 0)
252
				fprintf(stderr, Name ": cannot open device %s: %s\n",
253
					devname, strerror(errno));
254
			tmpdev->used = 2;
255
		} else if (fstat(dfd, &stb)< 0) {
256
			/* Impossible! */
257
			fprintf(stderr, Name ": fstat failed for %s: %s\n",
258
				devname, strerror(errno));
259
			tmpdev->used = 2;
260
		} else if ((stb.st_mode & S_IFMT) != S_IFBLK) {
261
			fprintf(stderr, Name ": %s is not a block device.\n",
262
				devname);
263
			tmpdev->used = 2;
264
		} else if (!tst && (tst = guess_super(dfd)) == NULL) {
265
			if ((inargv && verbose >= 0) || verbose > 0)
266
				fprintf(stderr, Name ": no recogniseable superblock on %s\n",
267
					devname);
268
			tmpdev->used = 2;
269
		} else if (tst->ss->load_super(tst,dfd, &super, NULL)) {
270
			if ((inargv && verbose >= 0) || verbose > 0)
271
				fprintf( stderr, Name ": no RAID superblock on %s\n",
272
					 devname);
273
		} else {
274
			tst->ss->getinfo_super(&info, super);
275
		}
276
		if (dfd >= 0) close(dfd);
277
278
		if (ident->uuid_set && (!update || strcmp(update, "uuid")!= 0) &&
279
		    (!super || same_uuid(info.uuid, ident->uuid, tst->ss->swapuuid)==0)) {
280
			if ((inargv && verbose >= 0) || verbose > 0)
281
				fprintf(stderr, Name ": %s has wrong uuid.\n",
282
					devname);
283
			continue;
284
		}
285
		if (ident->name[0] && (!update || strcmp(update, "name")!= 0) &&
286
		    (!super || name_matches(info.name, ident->name, homehost)==0)) {
287
			if ((inargv && verbose >= 0) || verbose > 0)
288
				fprintf(stderr, Name ": %s has wrong name.\n",
289
					devname);
290
			continue;
291
		}
292
		if (ident->super_minor != UnSet &&
293
		    (!super || ident->super_minor != info.array.md_minor)) {
294
			if ((inargv && verbose >= 0) || verbose > 0)
295
				fprintf(stderr, Name ": %s has wrong super-minor.\n",
296
					devname);
297
			continue;
298
		}
299
		if (ident->level != UnSet &&
300
		    (!super|| ident->level != info.array.level)) {
301
			if ((inargv && verbose >= 0) || verbose > 0)
302
				fprintf(stderr, Name ": %s has wrong raid level.\n",
303
					devname);
304
			continue;
305
		}
306
		if (ident->raid_disks != UnSet &&
307
		    (!super || ident->raid_disks!= info.array.raid_disks)) {
308
			if ((inargv && verbose >= 0) || verbose > 0)
309
				fprintf(stderr, Name ": %s requires wrong number of drives.\n",
310
					devname);
311
			continue;
312
		}
313
		if (mdfd < 0) {
314
			if (tst == NULL || super == NULL)
315
				continue;
316
			if (update == NULL &&
317
			    tst->ss->match_home(super, homehost)==0) {
318
				if ((inargv && verbose >= 0) || verbose > 0)
319
					fprintf(stderr, Name ": %s is not built for host %s.\n",
320
						devname, homehost);
321
				/* Auto-assemble, and this is not a usable host */
322
				/* if update != NULL, we are updating the host
323
				 * name... */
324
				continue;
325
			}
326
		}
327
		/* If we are this far, then we are nearly commited to this device.
328
		 * If the super_block doesn't exist, or doesn't match others,
329
		 * then we probably cannot continue
330
		 * However if one of the arrays is for the homehost, and
331
		 * the other isn't that can disambiguate.
332
		 */
333
334
		if (!super) {
335
			fprintf(stderr, Name ": %s has no superblock - assembly aborted\n",
336
				devname);
337
			free(first_super);
338
			return 1;
339
		}
340
341
		if (st == NULL)
342
			st = tst;
343
		if (st->ss != tst->ss ||
344
		    st->minor_version != tst->minor_version ||
345
		    st->ss->compare_super(&first_super, super) != 0) {
346
			/* Some mismatch. If exactly one array matches this host,
347
			 * we can resolve on that one.
348
			 * Or, if we are auto assembling, we just ignore the second
349
			 * for now.
350
			 */
351
			if (mdfd < 0)
352
				continue;
353
			if (homehost) {
354
				int first = st->ss->match_home(first_super, homehost);
355
				int last = tst->ss->match_home(super, homehost);
356
				if (first+last == 1) {
357
					/* We can do something */
358
					if (first) {/* just ignore this one */
359
						if ((inargv && verbose >= 0) || verbose > 0)
360
							fprintf(stderr, Name ": %s misses out due to wrong homehost\n",
361
								devname);
362
						continue;
363
					} else { /* reject all those sofar */
364
						mddev_dev_t td;
365
						if ((inargv && verbose >= 0) || verbose > 0)
366
							fprintf(stderr, Name ": %s overrides previous devices due to good homehost\n",
367
								devname);
368
						for (td=devlist; td != tmpdev; td=td->next)
369
							if (td->used == 1)
370
								td->used = 0;
371
						tmpdev->used = 1;
372
						continue;
373
					}
374
				}
375
			}
376
			fprintf(stderr, Name ": superblock on %s doesn't match others - assembly aborted\n",
377
				devname);
378
			free(super);
379
			free(first_super);
380
			return 1;
381
		}
382
383
		tmpdev->used = 1;
384
	}
385
386
	/* Ok, no bad inconsistancy, we can try updating etc */
387
	bitmap_done = 0;
388
	for (tmpdev = devlist; tmpdev; tmpdev=tmpdev->next) if (tmpdev->used == 1) {
389
		char *devname = tmpdev->devname;
390
		struct stat stb;
391
		/* looks like a good enough match to update the super block if needed */
392
		{
393
			int dfd;
394
			dfd = dev_open(devname, O_RDWR|O_EXCL);
395
396
			remove_partitions(dfd);
397
398
			if (super) {
399
				free(super);
400
				super = NULL;
401
			}
402
403
			st->ss->load_super(st, dfd, &super, NULL);
404
			st->ss->getinfo_super(&info, super);
405
			close(dfd);
406
		}
407
408
		stat(devname, &stb);
409
410
		if (verbose > 0)
411
			fprintf(stderr, Name ": %s is identified as a member of %s, slot %d.\n",
412
				devname, mddev, info.disk.raid_disk);
413
		devices[devcnt].devname = devname;
414
		devices[devcnt].major = major(stb.st_rdev);
415
		devices[devcnt].minor = minor(stb.st_rdev);
416
		devices[devcnt].oldmajor = info.disk.major;
417
		devices[devcnt].oldminor = info.disk.minor;
418
		devices[devcnt].events = info.events;
419
		devices[devcnt].raid_disk = info.disk.raid_disk;
420
		devices[devcnt].disk_nr = info.disk.number;
421
		devices[devcnt].uptodate = 0;
422
		devices[devcnt].state = info.disk.state;
423
		if (most_recent < devcnt) {
424
			if (devices[devcnt].events
425
			    > devices[most_recent].events)
426
				most_recent = devcnt;
427
		}
428
		if (info.array.level == -4)
429
			/* with multipath, the raid_disk from the superblock is meaningless */
430
			i = devcnt;
431
		else
432
			i = devices[devcnt].raid_disk;
433
		if (i+1 == 0) {
434
			if (nextspare < info.array.raid_disks)
435
				nextspare = info.array.raid_disks;
436
			i = nextspare++;
437
		} else {
438
			if (i >= info.array.raid_disks &&
439
			    i >= nextspare)
440
				nextspare = i+1;
441
		}
442
		if (i < 10000) {
443
			if (i >= bestcnt) {
444
				unsigned int newbestcnt = i+10;
445
				int *newbest = malloc(sizeof(int)*newbestcnt);
446
				unsigned int c;
447
				for (c=0; c < newbestcnt; c++)
448
					if (c < bestcnt)
449
						newbest[c] = best[c];
450
					else
451
						newbest[c] = -1;
452
				if (best)free(best);
453
				best = newbest;
454
				bestcnt = newbestcnt;
455
			}
456
			if (best[i] >=0 &&
457
			    devices[best[i]].events == devices[devcnt].events &&
458
			    devices[best[i]].minor != devices[devcnt].minor &&
459
			    st->ss->major == 0 &&
460
			    info.array.level != -4) {
461
				/* two different devices with identical superblock.
462
				 * Could be a mis-detection caused by overlapping
463
				 * partitions.  fail-safe.
464
				 */
465
				fprintf(stderr, Name ": WARNING %s and %s appear"
466
					" to have very similar superblocks.\n"
467
					"      If they are really different, "
468
					"please --zero the superblock on one\n"
469
					"      If they are the same or overlap,"
470
					" please remove one from %s.\n",
471
					devices[best[i]].devname, devname,
472
					inargv ? "the list" :
473
					   "the\n      DEVICE list in mdadm.conf"
474
					);
475
				return 1;
476
			}
477
			if (best[i] == -1
478
			    || devices[best[i]].events < devices[devcnt].events)
479
				best[i] = devcnt;
480
		}
481
		devcnt++;
482
	}
483
484
	if (super)
485
		free(super);
486
	super = NULL;
487
488
	if (update && strcmp(update, "byteorder")==0)
489
		st->minor_version = 90;
490
491
	if (devcnt == 0) {
492
		fprintf(stderr, Name ": no devices found for %s\n",
493
			mddev);
494
		free(first_super);
495
		return 1;
496
	}
497
498
	st->ss->getinfo_super(&info, first_super);
499
	clean = info.array.state & 1;
500
501
	/* now we have some devices that might be suitable.
502
	 * I wonder how many
503
	 */
504
	avail = malloc(info.array.raid_disks);
505
	memset(avail, 0, info.array.raid_disks);
506
	okcnt = 0;
507
	sparecnt=0;
508
	for (i=0; i< bestcnt ;i++) {
509
		int j = best[i];
510
		int event_margin = 1; /* always allow a difference of '1'
511
				       * like the kernel does
512
				       */
513
		if (j < 0) continue;
514
		/* note: we ignore error flags in multipath arrays
515
		 * as they don't make sense
516
		 */
517
		if (info.array.level != -4)
518
			if (!(devices[j].state & (1<<MD_DISK_SYNC))) {
519
				if (!(devices[j].state & (1<<MD_DISK_FAULTY)))
520
					sparecnt++;
521
				continue;
522
			}
523
		if (devices[j].events+event_margin >=
524
		    devices[most_recent].events) {
525
			devices[j].uptodate = 1;
526
			if (i < info.array.raid_disks) {
527
				okcnt++;
528
				avail[i]=1;
529
			} else
530
				sparecnt++;
531
		}
532
	}
533
	while (force && !enough(info.array.level, info.array.raid_disks,
534
				info.array.layout, 1,
535
				avail, okcnt)) {
536
		/* Choose the newest best drive which is
537
		 * not up-to-date, update the superblock
538
		 * and add it.
539
		 */
540
		int fd;
541
		long long current_events;
542
		chosen_drive = -1;
543
		for (i=0; i<info.array.raid_disks && i < bestcnt; i++) {
544
			int j = best[i];
545
			if (j>=0 &&
546
			    !devices[j].uptodate &&
547
			    devices[j].events > 0 &&
548
			    (chosen_drive < 0 ||
549
			     devices[j].events > devices[chosen_drive].events))
550
				chosen_drive = j;
551
		}
552
		if (chosen_drive < 0)
553
			break;
554
		current_events = devices[chosen_drive].events;
555
	add_another:
556
		if (verbose >= 0)
557
			fprintf(stderr, Name ": forcing event count in %s(%d) from %d upto %d\n",
558
				devices[chosen_drive].devname, devices[chosen_drive].raid_disk,
559
				(int)(devices[chosen_drive].events),
560
				(int)(devices[most_recent].events));
561
		fd = dev_open(devices[chosen_drive].devname, O_RDWR|O_EXCL);
562
		if (fd < 0) {
563
			fprintf(stderr, Name ": Couldn't open %s for write - not updating\n",
564
				devices[chosen_drive].devname);
565
			devices[chosen_drive].events = 0;
566
			continue;
567
		}
568
		if (st->ss->load_super(st,fd, &super, NULL)) {
569
			close(fd);
570
			fprintf(stderr, Name ": RAID superblock disappeared from %s - not updating.\n",
571
				devices[chosen_drive].devname);
572
			devices[chosen_drive].events = 0;
573
			continue;
574
		}
575
		info.events = devices[most_recent].events;
576
		st->ss->update_super(&info, super, "force-one",
577
				     devices[chosen_drive].devname, verbose,
578
				     0, NULL);
579
580
		if (st->ss->store_super(st, fd, super)) {
581
			close(fd);
582
			fprintf(stderr, Name ": Could not re-write superblock on %s\n",
583
				devices[chosen_drive].devname);
584
			devices[chosen_drive].events = 0;
585
			free(super);
586
			continue;
587
		}
588
		close(fd);
589
		devices[chosen_drive].events = devices[most_recent].events;
590
		devices[chosen_drive].uptodate = 1;
591
		avail[chosen_drive] = 1;
592
		okcnt++;
593
		free(super);
594
595
		/* If there are any other drives of the same vintage,
596
		 * add them in as well.  We can't lose and we might gain
597
		 */
598
		for (i=0; i<info.array.raid_disks && i < bestcnt ; i++) {
599
			int j = best[i];
600
			if (j >= 0 &&
601
			    !devices[j].uptodate &&
602
			    devices[j].events > 0 &&
603
			    devices[j].events == current_events) {
604
				chosen_drive = j;
605
				goto add_another;
606
			}
607
		}
608
	}
609
610
	/* Now we want to look at the superblock which the kernel will base things on
611
	 * and compare the devices that we think are working with the devices that the
612
	 * superblock thinks are working.
613
	 * If there are differences and --force is given, then update this chosen
614
	 * superblock.
615
	 */
616
	chosen_drive = -1;
617
	super = NULL;
618
	for (i=0; chosen_drive < 0 && i<bestcnt; i++) {
619
		int j = best[i];
620
		int fd;
621
622
		if (j<0)
623
			continue;
624
		if (!devices[j].uptodate)
625
			continue;
626
		chosen_drive = j;
627
		if ((fd=dev_open(devices[j].devname, O_RDONLY|O_EXCL))< 0) {
628
			fprintf(stderr, Name ": Cannot open %s: %s\n",
629
				devices[j].devname, strerror(errno));
630
			return 1;
631
		}
632
		if (st->ss->load_super(st,fd, &super, NULL)) {
633
			close(fd);
634
			fprintf(stderr, Name ": RAID superblock has disappeared from %s\n",
635
				devices[j].devname);
636
			return 1;
637
		}
638
		close(fd);
639
	}
640
	if (super == NULL) {
641
		fprintf(stderr, Name ": No suitable drives found for %s\n", mddev);
642
		return 1;
643
	}
644
	st->ss->getinfo_super(&info, super);
645
	for (i=0; i<bestcnt; i++) {
646
		int j = best[i];
647
		unsigned int desired_state;
648
649
		if (i < info.array.raid_disks)
650
			desired_state = (1<<MD_DISK_ACTIVE) | (1<<MD_DISK_SYNC);
651
		else
652
			desired_state = 0;
653
654
		if (j<0)
655
			continue;
656
		if (!devices[j].uptodate)
657
			continue;
658
		info.disk.number = devices[j].disk_nr;
659
		info.disk.raid_disk = i;
660
		info.disk.state = desired_state;
661
662
		if (devices[j].uptodate &&
663
		    st->ss->update_super(&info, super, "assemble", NULL, verbose, 0, NULL)) {
664
			if (force) {
665
				if (verbose >= 0)
666
					fprintf(stderr, Name ": "
667
						"clearing FAULTY flag for device %d in %s for %s\n",
668
						j, mddev, devices[j].devname);
669
				change = 1;
670
			} else {
671
				if (verbose >= -1)
672
					fprintf(stderr, Name ": "
673
						"device %d in %s has wrong state in superblock, but %s seems ok\n",
674
						i, mddev, devices[j].devname);
675
			}
676
		}
677
#if 0
678
		if (!devices[j].uptodate &&
679
		    !(super.disks[i].state & (1 << MD_DISK_FAULTY))) {
680
			fprintf(stderr, Name ": devices %d of %s is not marked FAULTY in superblock, but cannot be found\n",
681
				i, mddev);
682
		}
683
#endif
684
	}
685
	if (force && !clean &&
686
	    !enough(info.array.level, info.array.raid_disks,
687
		    info.array.layout, clean,
688
		    avail, okcnt)) {
689
		change += st->ss->update_super(&info, super, "force-array",
690
					devices[chosen_drive].devname, verbose,
691
					       0, NULL);
692
		clean = 1;
693
	}
694
695
	if (change) {
696
		int fd;
697
		fd = dev_open(devices[chosen_drive].devname, O_RDWR|O_EXCL);
698
		if (fd < 0) {
699
			fprintf(stderr, Name ": Could not open %s for write - cannot Assemble array.\n",
700
				devices[chosen_drive].devname);
701
			return 1;
702
		}
703
		if (st->ss->store_super(st, fd, super)) {
704
			close(fd);
705
			fprintf(stderr, Name ": Could not re-write superblock on %s\n",
706
				devices[chosen_drive].devname);
707
			return 1;
708
		}
709
		close(fd);
710
	}
711
712
	/* count number of in-sync devices according to the superblock.
713
	 * We must have this number to start the array without -s or -R
714
	 */
715
	req_cnt = info.array.working_disks;
716
717
	/* Almost ready to actually *do* something */
718
	if (!old_linux) {
719
		int rv;
720
		if ((vers % 100) >= 1) { /* can use different versions */
721
			mdu_array_info_t inf;
722
			memset(&inf, 0, sizeof(inf));
723
			inf.major_version = st->ss->major;
724
			inf.minor_version = st->minor_version;
725
			rv = ioctl(mdfd, SET_ARRAY_INFO, &inf);
726
		} else
727
			rv = ioctl(mdfd, SET_ARRAY_INFO, NULL);
728
729
		if (rv) {
730
			fprintf(stderr, Name ": SET_ARRAY_INFO failed for %s: %s\n",
731
				mddev, strerror(errno));
732
			return 1;
733
		}
734
		if (ident->bitmap_fd >= 0) {
735
			if (ioctl(mdfd, SET_BITMAP_FILE, ident->bitmap_fd) != 0) {
736
				fprintf(stderr, Name ": SET_BITMAP_FILE failed.\n");
737
				return 1;
738
			}
739
		} else if (ident->bitmap_file) {
740
			/* From config file */
741
			int bmfd = open(ident->bitmap_file, O_RDWR);
742
			if (bmfd < 0) {
743
				fprintf(stderr, Name ": Could not open bitmap file %s\n",
744
					ident->bitmap_file);
745
				return 1;
746
			}
747
			if (ioctl(mdfd, SET_BITMAP_FILE, bmfd) != 0) {
748
				fprintf(stderr, Name ": Failed to set bitmapfile for %s\n", mddev);
749
				close(bmfd);
750
				return 1;
751
			}
752
			close(bmfd);
753
		}
754
755
		/* First, add the raid disks, but add the chosen one last */
756
		for (i=0; i<= bestcnt; i++) {
757
			int j;
758
			if (i < bestcnt) {
759
				j = best[i];
760
				if (j == chosen_drive)
761
					continue;
762
			} else
763
				j = chosen_drive;
764
765
			if (j >= 0 /* && devices[j].uptodate */) {
766
				mdu_disk_info_t disk;
767
				memset(&disk, 0, sizeof(disk));
768
				disk.major = devices[j].major;
769
				disk.minor = devices[j].minor;
770
				if (ioctl(mdfd, ADD_NEW_DISK, &disk)!=0) {
771
					fprintf(stderr, Name ": failed to add %s to %s: %s\n",
772
						devices[j].devname,
773
						mddev,
774
						strerror(errno));
775
					if (i < info.array.raid_disks || i == bestcnt)
776
						okcnt--;
777
					else
778
						sparecnt--;
779
				} else if (verbose > 0)
780
					fprintf(stderr, Name ": added %s to %s as %d\n",
781
						devices[j].devname, mddev, devices[j].raid_disk);
782
			} else if (verbose > 0 && i < info.array.raid_disks)
783
				fprintf(stderr, Name ": no uptodate device for slot %d of %s\n",
784
					i, mddev);
785
		}
786
		
787
		if (runstop == 1 ||
788
		    (runstop <= 0 &&
789
		     ( enough(info.array.level, info.array.raid_disks,
790
			      info.array.layout, clean, avail, okcnt) &&
791
		       (okcnt >= req_cnt || start_partial_ok)
792
			     ))) {
793
			if (ioctl(mdfd, RUN_ARRAY, NULL)==0) {
794
				if (verbose >= 0) {
795
					fprintf(stderr, Name ": %s has been started with %d drive%s",
796
						mddev, okcnt, okcnt==1?"":"s");
797
					if (okcnt < info.array.raid_disks)
798
						fprintf(stderr, " (out of %d)", info.array.raid_disks);
799
					if (sparecnt)
800
						fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s");
801
					fprintf(stderr, ".\n");
802
				}
803
				return 0;
804
			}
805
			fprintf(stderr, Name ": failed to RUN_ARRAY %s: %s\n",
806
				mddev, strerror(errno));
807
808
			if (!enough(info.array.level, info.array.raid_disks,
809
				    info.array.layout, 1, avail, okcnt))
810
				fprintf(stderr, Name ": Not enough devices to "
811
					"start the array.\n");
812
			else if (!enough(info.array.level,
813
					 info.array.raid_disks,
814
					 info.array.layout, clean,
815
					 avail, okcnt))
816
				fprintf(stderr, Name ": Not enough devices to "
817
					"start the array while not clean "
818
					"- consider --force.\n");
819
820
			return 1;
821
		}
822
		if (runstop == -1) {
823
			fprintf(stderr, Name ": %s assembled from %d drive%s",
824
				mddev, okcnt, okcnt==1?"":"s");
825
			if (okcnt != info.array.raid_disks)
826
				fprintf(stderr, " (out of %d)", info.array.raid_disks);
827
			fprintf(stderr, ", but not started.\n");
828
			return 0;
829
		}
830
		if (verbose >= -1) {
831
			fprintf(stderr, Name ": %s assembled from %d drive%s", mddev, okcnt, okcnt==1?"":"s");
832
			if (sparecnt)
833
				fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s");
834
			if (!enough(info.array.level, info.array.raid_disks,
835
				    info.array.layout, 1, avail, okcnt))
836
				fprintf(stderr, " - not enough to start the array.\n");
837
			else if (!enough(info.array.level,
838
					 info.array.raid_disks,
839
					 info.array.layout, clean,
840
					 avail, okcnt))
841
				fprintf(stderr, " - not enough to start the "
842
					"array while not clean - consider "
843
					"--force.\n");
844
			else {
845
				if (req_cnt == info.array.raid_disks)
846
					fprintf(stderr, " - need all %d to start it", req_cnt);
847
				else
848
					fprintf(stderr, " - need %d of %d to start", req_cnt, info.array.raid_disks);
849
				fprintf(stderr, " (use --run to insist).\n");
850
			}
851
		}
852
		return 1;
853
	} else {
854
		/* The "chosen_drive" is a good choice, and if necessary, the superblock has
855
		 * been updated to point to the current locations of devices.
856
		 * so we can just start the array
857
		 */
858
		unsigned long dev;
859
		dev = makedev(devices[chosen_drive].major,
860
			    devices[chosen_drive].minor);
861
		if (ioctl(mdfd, START_ARRAY, dev)) {
862
		    fprintf(stderr, Name ": Cannot start array: %s\n",
863
			    strerror(errno));
864
		}
865
		
866
	}
867
	return 0;
868
}
869
870
int mdfd = -1;
871
int runstop = 0;
872
int readonly = 0;
873
int verbose = 0;
874
int force = 0;
875
876
int mdassemble_main(int argc, char **argv) {
877
	mddev_ident_t array_list =  conf_get_ident(NULL);
878
	int minor;
879
	if (!array_list) {
880
		fprintf(stderr, Name ": No arrays found in config file\n");
881
		return 1;
882
	} else {
883
		for (; array_list; array_list = array_list->next) {
884
			mdu_array_info_t array;
885
			if (!strncmp("/dev/md", array_list->devname, 7)) {
886
			   	errno = 0;
887
				minor = strtoul(array_list->devname + 7, NULL, 0);
888
				if (!errno) {
889
					mknod(array_list->devname, S_IFBLK|0600, makedev(MD_MAJOR, minor));
890
				}
891
			}
892
			mdfd = open_mddev(array_list->devname, array_list->autof);
893
			if (mdfd < 0) {
894
895
				fprintf(stderr, Name ": failed to open array\n");
896
				continue;
897
			}
898
			if (ioctl(mdfd, GET_ARRAY_INFO, &array) < 0) {
899
				Assemble(array_list->st, array_list->devname, mdfd,
900
					   array_list, NULL, NULL,
901
					   readonly, runstop, NULL, NULL, verbose, force);
902
			}
903
			close(mdfd);
904
		}
905
	}
906
	return 0;
907
}
908
(-)a/mdadm/mdexamine.c (+157 lines)
Line 0 Link Here
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
39
static int Examine(mddev_dev_t devlist, int brief, int scan,
40
	    int SparcAdjust, struct supertype *forcest,
41
	    char *homehost)
42
{
43
44
	/* Read the raid superblock from a device and
45
	 * display important content.
46
	 *
47
	 * If cannot be found, print reason: too small, bad magic
48
	 *
49
	 * Print:
50
	 *   version, ctime, level, size, raid+spare+
51
	 *   prefered minor
52
	 *   uuid
53
	 *
54
	 *   utime, state etc
55
	 *
56
	 * If (brief) gather devices for same array and just print a mdadm.conf line including devices=
57
	 * if devlist==NULL, use conf_get_devs()
58
	 */
59
	int fd; 
60
	void *super = NULL;
61
	int rv = 0;
62
	int err = 0;
63
64
	struct array {
65
		void *super;
66
		struct supertype *st;
67
		struct mdinfo info;
68
		void *devs;
69
		struct array *next;
70
		int spares;
71
	} *arrays = NULL;
72
73
	for (; devlist ; devlist=devlist->next) {
74
		struct supertype *st = forcest;
75
76
		fd = dev_open(devlist->devname, O_RDONLY);
77
		if (fd < 0) {
78
			if (!scan) {
79
				fprintf(stderr,Name ": cannot open %s: %s\n",
80
					devlist->devname, strerror(errno));
81
				rv = 1;
82
			}
83
			err = 1;
84
		}
85
		else {
86
			if (!st)
87
				st = guess_super(fd);
88
			if (st)
89
				err = st->ss->load_super(st, fd, &super, (brief||scan)?NULL:devlist->devname);
90
			else {
91
				if (!brief) {
92
					fprintf(stderr, Name ": No md superblock detected on %s.\n", devlist->devname);
93
					rv = 1;
94
				}
95
				err = 1;
96
			}
97
			close(fd);
98
		}
99
		if (err)
100
			continue;
101
102
		if (SparcAdjust)
103
			st->ss->update_super(NULL, super, "sparc2.2", 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 && st->ss->compare_super(&ap->super, super)==0)
110
					break;
111
			}
112
			if (!ap) {
113
				ap = malloc(sizeof(*ap));
114
				ap->super = super;
115
				ap->devs = dl_head();
116
				ap->next = arrays;
117
				ap->spares = 0;
118
				ap->st = st;
119
				arrays = ap;
120
				st->ss->getinfo_super(&ap->info, super);
121
			} else {
122
				st->ss->getinfo_super(&ap->info, super);
123
				free(super);
124
			}
125
			if (!(ap->info.disk.state & MD_DISK_SYNC))
126
				ap->spares++;
127
			d = dl_strdup(devlist->devname);
128
			dl_add(ap->devs, d);
129
		}
130
	}
131
	if (brief) {
132
		struct array *ap;
133
		for (ap=arrays; ap; ap=ap->next) {
134
			char sep='=';
135
			char *d;
136
			ap->st->ss->brief_examine_super(ap->super);
137
			if (ap->spares) printf("   spares=%d", ap->spares);
138
			if (brief > 1) {
139
				printf("   devices");
140
				for (d=dl_next(ap->devs); d!= ap->devs; d=dl_next(d)) {
141
					printf("%c%s", sep, d);
142
					sep=',';
143
				}
144
			}
145
			free(ap->super);
146
			/* FIXME free ap */
147
			if (ap->spares || brief > 1)
148
				printf("\n");
149
		}
150
	}
151
	return rv;
152
}
153
154
int mdexamine_main(int argc, char **argv) {
155
	return Examine(conf_get_devs(), 1, 0, 0, NULL, NULL);
156
}
157
(-)a/mdadm/md_p.h (+194 lines)
Line 0 Link Here
1
/*
2
   md_p.h : physical layout of Linux RAID devices
3
          Copyright (C) 1996-98 Ingo Molnar, Gadi Oxman
4
	  
5
   This program is free software; you can redistribute it and/or modify
6
   it under the terms of the GNU General Public License as published by
7
   the Free Software Foundation; either version 2, or (at your option)
8
   any later version.
9
   
10
   You should have received a copy of the GNU General Public License
11
   (for example /usr/src/linux/COPYING); if not, write to the Free
12
   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
13
*/
14
15
#ifndef _MD_P_H
16
#define _MD_P_H
17
18
/*
19
 * RAID superblock.
20
 *
21
 * The RAID superblock maintains some statistics on each RAID configuration.
22
 * Each real device in the RAID set contains it near the end of the device.
23
 * Some of the ideas are copied from the ext2fs implementation.
24
 *
25
 * We currently use 4096 bytes as follows:
26
 *
27
 *	word offset	function
28
 *
29
 *	   0  -    31	Constant generic RAID device information.
30
 *        32  -    63   Generic state information.
31
 *	  64  -   127	Personality specific information.
32
 *	 128  -   511	12 32-words descriptors of the disks in the raid set.
33
 *	 512  -   911	Reserved.
34
 *	 912  -  1023	Disk specific descriptor.
35
 */
36
37
/*
38
 * If x is the real device size in bytes, we return an apparent size of:
39
 *
40
 *	y = (x & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES
41
 *
42
 * and place the 4kB superblock at offset y.
43
 */
44
#define MD_RESERVED_BYTES		(64 * 1024)
45
#define MD_RESERVED_SECTORS		(MD_RESERVED_BYTES / 512)
46
#define MD_RESERVED_BLOCKS		(MD_RESERVED_BYTES / BLOCK_SIZE)
47
48
#define MD_NEW_SIZE_SECTORS(x)		((x & ~(MD_RESERVED_SECTORS - 1)) - MD_RESERVED_SECTORS)
49
#define MD_NEW_SIZE_BLOCKS(x)		((x & ~(MD_RESERVED_BLOCKS - 1)) - MD_RESERVED_BLOCKS)
50
51
#define MD_SB_BYTES			4096
52
#define MD_SB_WORDS			(MD_SB_BYTES / 4)
53
#define MD_SB_BLOCKS			(MD_SB_BYTES / BLOCK_SIZE)
54
#define MD_SB_SECTORS			(MD_SB_BYTES / 512)
55
56
/*
57
 * The following are counted in 32-bit words
58
 */
59
#define	MD_SB_GENERIC_OFFSET		0
60
#define MD_SB_PERSONALITY_OFFSET	64
61
#define MD_SB_DISKS_OFFSET		128
62
#define MD_SB_DESCRIPTOR_OFFSET		992
63
64
#define MD_SB_GENERIC_CONSTANT_WORDS	32
65
#define MD_SB_GENERIC_STATE_WORDS	32
66
#define MD_SB_GENERIC_WORDS		(MD_SB_GENERIC_CONSTANT_WORDS + MD_SB_GENERIC_STATE_WORDS)
67
#define MD_SB_PERSONALITY_WORDS		64
68
#define MD_SB_DESCRIPTOR_WORDS		32
69
#define MD_SB_DISKS			27
70
#define MD_SB_DISKS_WORDS		(MD_SB_DISKS*MD_SB_DESCRIPTOR_WORDS)
71
#define MD_SB_RESERVED_WORDS		(1024 - MD_SB_GENERIC_WORDS - MD_SB_PERSONALITY_WORDS - MD_SB_DISKS_WORDS - MD_SB_DESCRIPTOR_WORDS)
72
#define MD_SB_EQUAL_WORDS		(MD_SB_GENERIC_WORDS + MD_SB_PERSONALITY_WORDS + MD_SB_DISKS_WORDS)
73
74
/*
75
 * Device "operational" state bits
76
 */
77
#define MD_DISK_FAULTY		0 /* disk is faulty / operational */
78
#define MD_DISK_ACTIVE		1 /* disk is running or spare disk */
79
#define MD_DISK_SYNC		2 /* disk is in sync with the raid set */
80
#define MD_DISK_REMOVED		3 /* disk is in sync with the raid set */
81
82
#define	MD_DISK_WRITEMOSTLY	9 /* disk is "write-mostly" is RAID1 config.
83
				   * read requests will only be sent here in 
84
				   * dire need
85
				   */
86
87
typedef struct mdp_device_descriptor_s {
88
	__u32 number;		/* 0 Device number in the entire set	      */
89
	__u32 major;		/* 1 Device major number		      */
90
	__u32 minor;		/* 2 Device minor number		      */
91
	__u32 raid_disk;	/* 3 The role of the device in the raid set   */
92
	__u32 state;		/* 4 Operational state			      */
93
	__u32 reserved[MD_SB_DESCRIPTOR_WORDS - 5];
94
} mdp_disk_t;
95
96
#define MD_SB_MAGIC		0xa92b4efc
97
98
/*
99
 * Superblock state bits
100
 */
101
#define MD_SB_CLEAN		0
102
#define MD_SB_ERRORS		1
103
104
#define	MD_SB_BITMAP_PRESENT	8 /* bitmap may be present nearby */
105
106
typedef struct mdp_superblock_s {
107
	/*
108
	 * Constant generic information
109
	 */
110
	__u32 md_magic;		/*  0 MD identifier 			      */
111
	__u32 major_version;	/*  1 major version to which the set conforms */
112
	__u32 minor_version;	/*  2 minor version ...			      */
113
	__u32 patch_version;	/*  3 patchlevel version ...		      */
114
	__u32 gvalid_words;	/*  4 Number of used words in this section    */
115
	__u32 set_uuid0;	/*  5 Raid set identifier		      */
116
	__u32 ctime;		/*  6 Creation time			      */
117
	__u32 level;		/*  7 Raid personality			      */
118
	__u32 size;		/*  8 Apparent size of each individual disk   */
119
	__u32 nr_disks;		/*  9 total disks in the raid set	      */
120
	__u32 raid_disks;	/* 10 disks in a fully functional raid set    */
121
	__u32 md_minor;		/* 11 preferred MD minor device number	      */
122
	__u32 not_persistent;	/* 12 does it have a persistent superblock    */
123
	__u32 set_uuid1;	/* 13 Raid set identifier #2		      */
124
	__u32 set_uuid2;	/* 14 Raid set identifier #3		      */
125
	__u32 set_uuid3;	/* 15 Raid set identifier #4		      */
126
	__u32 gstate_creserved[MD_SB_GENERIC_CONSTANT_WORDS - 16];
127
128
	/*
129
	 * Generic state information
130
	 */
131
	__u32 utime;		/*  0 Superblock update time		      */
132
	__u32 state;		/*  1 State bits (clean, ...)		      */
133
	__u32 active_disks;	/*  2 Number of currently active disks	      */
134
	__u32 working_disks;	/*  3 Number of working disks		      */
135
	__u32 failed_disks;	/*  4 Number of failed disks		      */
136
	__u32 spare_disks;	/*  5 Number of spare disks		      */
137
	__u32 sb_csum;		/*  6 checksum of the whole superblock        */
138
#if  __BYTE_ORDER ==  __BIG_ENDIAN
139
	__u32 events_hi;	/*  7 high-order of superblock update count   */
140
	__u32 events_lo;	/*  8 low-order of superblock update count    */
141
	__u32 cp_events_hi;	/*  9 high-order of checkpoint update count   */
142
	__u32 cp_events_lo;	/* 10 low-order of checkpoint update count    */
143
#else
144
	__u32 events_lo;	/*  7 low-order of superblock update count    */
145
	__u32 events_hi;	/*  8 high-order of superblock update count   */
146
	__u32 cp_events_lo;	/*  9 low-order of checkpoint update count    */
147
	__u32 cp_events_hi;	/* 10 high-order of checkpoint update count   */
148
#endif
149
	__u32 recovery_cp;	/* 11 recovery checkpoint sector count	      */
150
	/* There are only valid for minor_version > 90 */
151
	__u64 reshape_position;	/* 12,13 next address in array-space for reshape */
152
	__u32 new_level;	/* 14 new level we are reshaping to	      */
153
	__u32 delta_disks;	/* 15 change in number of raid_disks	      */
154
	__u32 new_layout;	/* 16 new layout			      */
155
	__u32 new_chunk;	/* 17 new chunk size (bytes)		      */
156
	__u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 18];
157
158
	/*
159
	 * Personality information
160
	 */
161
	__u32 layout;		/*  0 the array's physical layout	      */
162
	__u32 chunk_size;	/*  1 chunk size in bytes		      */
163
	__u32 root_pv;		/*  2 LV root PV */
164
	__u32 root_block;	/*  3 LV root block */
165
	__u32 pstate_reserved[MD_SB_PERSONALITY_WORDS - 4];
166
167
	/*
168
	 * Disks information
169
	 */
170
	mdp_disk_t disks[MD_SB_DISKS];
171
172
	/*
173
	 * Reserved
174
	 */
175
	__u32 reserved[MD_SB_RESERVED_WORDS];
176
177
	/*
178
	 * Active descriptor
179
	 */
180
	mdp_disk_t this_disk;
181
182
} mdp_super_t;
183
184
#ifdef __TINYC__
185
typedef unsigned long long __u64;
186
#endif
187
188
static inline __u64 md_event(mdp_super_t *sb) {
189
	__u64 ev = sb->events_hi;
190
	return (ev<<32)| sb->events_lo;
191
}
192
193
#endif 
194
(-)a/mdadm/md_u.h (+123 lines)
Line 0 Link Here
1
/*
2
   md_u.h : user <=> kernel API between Linux raidtools and RAID drivers
3
          Copyright (C) 1998 Ingo Molnar
4
	  
5
   This program is free software; you can redistribute it and/or modify
6
   it under the terms of the GNU General Public License as published by
7
   the Free Software Foundation; either version 2, or (at your option)
8
   any later version.
9
   
10
   You should have received a copy of the GNU General Public License
11
   (for example /usr/src/linux/COPYING); if not, write to the Free
12
   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
13
*/
14
15
#ifndef _MD_U_H
16
#define _MD_U_H
17
18
/* ioctls */
19
20
/* status */
21
#define RAID_VERSION		_IOR (MD_MAJOR, 0x10, mdu_version_t)
22
#define GET_ARRAY_INFO		_IOR (MD_MAJOR, 0x11, mdu_array_info_t)
23
#define GET_DISK_INFO		_IOR (MD_MAJOR, 0x12, mdu_disk_info_t)
24
#define PRINT_RAID_DEBUG	_IO (MD_MAJOR, 0x13)
25
#define RAID_AUTORUN		_IO (MD_MAJOR, 0x14)
26
#define GET_BITMAP_FILE		_IOR (MD_MAJOR, 0x15, mdu_bitmap_file_t)
27
28
/* configuration */
29
#define CLEAR_ARRAY		_IO (MD_MAJOR, 0x20)
30
#define ADD_NEW_DISK		_IOW (MD_MAJOR, 0x21, mdu_disk_info_t)
31
#define HOT_REMOVE_DISK		_IO (MD_MAJOR, 0x22)
32
#define SET_ARRAY_INFO		_IOW (MD_MAJOR, 0x23, mdu_array_info_t)
33
#define SET_DISK_INFO		_IO (MD_MAJOR, 0x24)
34
#define WRITE_RAID_INFO		_IO (MD_MAJOR, 0x25)
35
#define UNPROTECT_ARRAY		_IO (MD_MAJOR, 0x26)
36
#define PROTECT_ARRAY		_IO (MD_MAJOR, 0x27)
37
#define HOT_ADD_DISK		_IO (MD_MAJOR, 0x28)
38
#define SET_DISK_FAULTY		_IO (MD_MAJOR, 0x29)
39
#define SET_BITMAP_FILE		_IOW (MD_MAJOR, 0x2b, int)
40
41
/* usage */
42
#define RUN_ARRAY		_IOW (MD_MAJOR, 0x30, mdu_param_t)
43
#define START_ARRAY		_IO (MD_MAJOR, 0x31)
44
#define STOP_ARRAY		_IO (MD_MAJOR, 0x32)
45
#define STOP_ARRAY_RO		_IO (MD_MAJOR, 0x33)
46
#define RESTART_ARRAY_RW	_IO (MD_MAJOR, 0x34)
47
48
typedef struct mdu_version_s {
49
	int major;
50
	int minor;
51
	int patchlevel;
52
} mdu_version_t;
53
54
typedef struct mdu_array_info_s {
55
	/*
56
	 * Generic constant information
57
	 */
58
	int major_version;
59
	int minor_version;
60
	int patch_version;
61
	int ctime;
62
	int level;
63
	int size;
64
	int nr_disks;
65
	int raid_disks;
66
	int md_minor;
67
	int not_persistent;
68
69
	/*
70
	 * Generic state information
71
	 */
72
	int utime;		/*  0 Superblock update time		      */
73
	int state;		/*  1 State bits (clean, ...)		      */
74
	int active_disks;	/*  2 Number of currently active disks	      */
75
	int working_disks;	/*  3 Number of working disks		      */
76
	int failed_disks;	/*  4 Number of failed disks		      */
77
	int spare_disks;	/*  5 Number of spare disks		      */
78
79
	/*
80
	 * Personality information
81
	 */
82
	int layout;		/*  0 the array's physical layout	      */
83
	int chunk_size;	/*  1 chunk size in bytes		      */
84
85
} mdu_array_info_t;
86
87
typedef struct mdu_disk_info_s {
88
	/*
89
	 * configuration/status of one particular disk
90
	 */
91
	int number;
92
	int major;
93
	int minor;
94
	int raid_disk;
95
	int state;
96
97
} mdu_disk_info_t;
98
99
typedef struct mdu_start_info_s {
100
	/*
101
	 * configuration/status of one particular disk
102
	 */
103
	int major;
104
	int minor;
105
	int raid_disk;
106
	int state;
107
108
} mdu_start_info_t;
109
110
typedef struct mdu_bitmap_file_s
111
{
112
	char pathname[4096];
113
} mdu_bitmap_file_t;
114
115
typedef struct mdu_param_s
116
{
117
	int			personality;	/* 1,2,3,4 */
118
	int			chunk_size;	/* in bytes */
119
	int			max_fault;	/* unused for now */
120
} mdu_param_t;
121
122
#endif 
123
(-)a/mdadm/sha1.c (+423 lines)
Line 0 Link Here
1
/* sha1.c - Functions to compute SHA1 message digest of files or
2
   memory blocks according to the NIST specification FIPS-180-1.
3
4
   Copyright (C) 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
5
6
   This program is free software; you can redistribute it and/or modify it
7
   under the terms of the GNU General Public License as published by the
8
   Free Software Foundation; either version 2, or (at your option) any
9
   later version.
10
11
   This program is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
16
   You should have received a copy of the GNU General Public License
17
   along with this program; if not, write to the Free Software Foundation,
18
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
19
20
/* Written by Scott G. Miller
21
   Credits:
22
      Robert Klep <robert@ilse.nl>  -- Expansion function fix
23
*/
24
25
#ifdef HAVE_CONFIG_H
26
# include <config.h>
27
#endif
28
29
#include "sha1.h"
30
31
#include <stddef.h>
32
#include <string.h>
33
34
#if USE_UNLOCKED_IO
35
# include "unlocked-io.h"
36
#endif
37
38
/* SWAP does an endian swap on architectures that are little-endian,
39
   as SHA1 needs some data in a big-endian form.  */
40
41
#ifdef WORDS_BIGENDIAN
42
# define SWAP(n) (n)
43
#else
44
# define SWAP(n) \
45
    (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
46
#endif
47
48
#define BLOCKSIZE 4096
49
#if BLOCKSIZE % 64 != 0
50
# error "invalid BLOCKSIZE"
51
#endif
52
53
/* This array contains the bytes used to pad the buffer to the next
54
   64-byte boundary.  (RFC 1321, 3.1: Step 1)  */
55
static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ...  */ };
56
57
58
/*
59
  Takes a pointer to a 160 bit block of data (five 32 bit ints) and
60
  intializes it to the start constants of the SHA1 algorithm.  This
61
  must be called before using hash in the call to sha1_hash.
62
*/
63
void
64
sha1_init_ctx (struct sha1_ctx *ctx)
65
{
66
  ctx->A = 0x67452301;
67
  ctx->B = 0xefcdab89;
68
  ctx->C = 0x98badcfe;
69
  ctx->D = 0x10325476;
70
  ctx->E = 0xc3d2e1f0;
71
72
  ctx->total[0] = ctx->total[1] = 0;
73
  ctx->buflen = 0;
74
}
75
76
/* Put result from CTX in first 20 bytes following RESBUF.  The result
77
   must be in little endian byte order.
78
79
   IMPORTANT: On some systems it is required that RESBUF is correctly
80
   aligned for a 32 bits value.  */
81
void *
82
sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf)
83
{
84
  ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
85
  ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
86
  ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
87
  ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
88
  ((md5_uint32 *) resbuf)[4] = SWAP (ctx->E);
89
90
  return resbuf;
91
}
92
93
/* Process the remaining bytes in the internal buffer and the usual
94
   prolog according to the standard and write the result to RESBUF.
95
96
   IMPORTANT: On some systems it is required that RESBUF is correctly
97
   aligned for a 32 bits value.  */
98
void *
99
sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf)
100
{
101
  /* Take yet unprocessed bytes into account.  */
102
  md5_uint32 bytes = ctx->buflen;
103
  size_t pad;
104
105
  /* Now count remaining bytes.  */
106
  ctx->total[0] += bytes;
107
  if (ctx->total[0] < bytes)
108
    ++ctx->total[1];
109
110
  pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
111
  memcpy (&ctx->buffer[bytes], fillbuf, pad);
112
113
  /* Put the 64-bit file length in *bits* at the end of the buffer.  */
114
  *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP (ctx->total[0] << 3);
115
  *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP ((ctx->total[1] << 3) |
116
						    (ctx->total[0] >> 29));
117
118
  /* Process last bytes.  */
119
  sha1_process_block (ctx->buffer, bytes + pad + 8, ctx);
120
121
  return sha1_read_ctx (ctx, resbuf);
122
}
123
124
/* Compute SHA1 message digest for bytes read from STREAM.  The
125
   resulting message digest number will be written into the 16 bytes
126
   beginning at RESBLOCK.  */
127
int
128
sha1_stream (FILE *stream, void *resblock)
129
{
130
  struct sha1_ctx ctx;
131
  char buffer[BLOCKSIZE + 72];
132
  size_t sum;
133
134
  /* Initialize the computation context.  */
135
  sha1_init_ctx (&ctx);
136
137
  /* Iterate over full file contents.  */
138
  while (1)
139
    {
140
      /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
141
	 computation function processes the whole buffer so that with the
142
	 next round of the loop another block can be read.  */
143
      size_t n;
144
      sum = 0;
145
146
      /* Read block.  Take care for partial reads.  */
147
      while (1)
148
	{
149
	  n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
150
151
	  sum += n;
152
153
	  if (sum == BLOCKSIZE)
154
	    break;
155
156
	  if (n == 0)
157
	    {
158
	      /* Check for the error flag IFF N == 0, so that we don't
159
		 exit the loop after a partial read due to e.g., EAGAIN
160
		 or EWOULDBLOCK.  */
161
	      if (ferror (stream))
162
		return 1;
163
	      goto process_partial_block;
164
	    }
165
166
	  /* We've read at least one byte, so ignore errors.  But always
167
	     check for EOF, since feof may be true even though N > 0.
168
	     Otherwise, we could end up calling fread after EOF.  */
169
	  if (feof (stream))
170
	    goto process_partial_block;
171
	}
172
173
      /* Process buffer with BLOCKSIZE bytes.  Note that
174
			BLOCKSIZE % 64 == 0
175
       */
176
      sha1_process_block (buffer, BLOCKSIZE, &ctx);
177
    }
178
179
 process_partial_block:;
180
181
  /* Process any remaining bytes.  */
182
  if (sum > 0)
183
    sha1_process_bytes (buffer, sum, &ctx);
184
185
  /* Construct result in desired memory.  */
186
  sha1_finish_ctx (&ctx, resblock);
187
  return 0;
188
}
189
190
/* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
191
   result is always in little endian byte order, so that a byte-wise
192
   output yields to the wanted ASCII representation of the message
193
   digest.  */
194
void *
195
sha1_buffer (const char *buffer, size_t len, void *resblock)
196
{
197
  struct sha1_ctx ctx;
198
199
  /* Initialize the computation context.  */
200
  sha1_init_ctx (&ctx);
201
202
  /* Process whole buffer but last len % 64 bytes.  */
203
  sha1_process_bytes (buffer, len, &ctx);
204
205
  /* Put result in desired memory area.  */
206
  return sha1_finish_ctx (&ctx, resblock);
207
}
208
209
void
210
sha1_process_bytes (const void *buffer, size_t len, struct sha1_ctx *ctx)
211
{
212
  /* When we already have some bits in our internal buffer concatenate
213
     both inputs first.  */
214
  if (ctx->buflen != 0)
215
    {
216
      size_t left_over = ctx->buflen;
217
      size_t add = 128 - left_over > len ? len : 128 - left_over;
218
219
      memcpy (&ctx->buffer[left_over], buffer, add);
220
      ctx->buflen += add;
221
222
      if (ctx->buflen > 64)
223
	{
224
	  sha1_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
225
226
	  ctx->buflen &= 63;
227
	  /* The regions in the following copy operation cannot overlap.  */
228
	  memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
229
		  ctx->buflen);
230
	}
231
232
      buffer = (const char *) buffer + add;
233
      len -= add;
234
    }
235
236
  /* Process available complete blocks.  */
237
  if (len >= 64)
238
    {
239
#if !_STRING_ARCH_unaligned
240
# define alignof(type) offsetof (struct { char c; type x; }, x)
241
# define UNALIGNED_P(p) (((size_t) p) % alignof (md5_uint32) != 0)
242
      if (UNALIGNED_P (buffer))
243
	while (len > 64)
244
	  {
245
	    sha1_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx);
246
	    buffer = (const char *) buffer + 64;
247
	    len -= 64;
248
	  }
249
      else
250
#endif
251
	{
252
	  sha1_process_block (buffer, len & ~63, ctx);
253
	  buffer = (const char *) buffer + (len & ~63);
254
	  len &= 63;
255
	}
256
    }
257
258
  /* Move remaining bytes in internal buffer.  */
259
  if (len > 0)
260
    {
261
      size_t left_over = ctx->buflen;
262
263
      memcpy (&ctx->buffer[left_over], buffer, len);
264
      left_over += len;
265
      if (left_over >= 64)
266
	{
267
	  sha1_process_block (ctx->buffer, 64, ctx);
268
	  left_over -= 64;
269
	  memcpy (ctx->buffer, &ctx->buffer[64], left_over);
270
	}
271
      ctx->buflen = left_over;
272
    }
273
}
274
275
/* --- Code below is the primary difference between md5.c and sha1.c --- */
276
277
/* SHA1 round constants */
278
#define K1 0x5a827999L
279
#define K2 0x6ed9eba1L
280
#define K3 0x8f1bbcdcL
281
#define K4 0xca62c1d6L
282
283
/* Round functions.  Note that F2 is the same as F4.  */
284
#define F1(B,C,D) ( D ^ ( B & ( C ^ D ) ) )
285
#define F2(B,C,D) (B ^ C ^ D)
286
#define F3(B,C,D) ( ( B & C ) | ( D & ( B | C ) ) )
287
#define F4(B,C,D) (B ^ C ^ D)
288
289
/* Process LEN bytes of BUFFER, accumulating context into CTX.
290
   It is assumed that LEN % 64 == 0.
291
   Most of this code comes from GnuPG's cipher/sha1.c.  */
292
293
void
294
sha1_process_block (const void *buffer, size_t len, struct sha1_ctx *ctx)
295
{
296
  const md5_uint32 *words = buffer;
297
  size_t nwords = len / sizeof (md5_uint32);
298
  const md5_uint32 *endp = words + nwords;
299
  md5_uint32 x[16];
300
  md5_uint32 a = ctx->A;
301
  md5_uint32 b = ctx->B;
302
  md5_uint32 c = ctx->C;
303
  md5_uint32 d = ctx->D;
304
  md5_uint32 e = ctx->E;
305
306
  /* First increment the byte count.  RFC 1321 specifies the possible
307
     length of the file up to 2^64 bits.  Here we only compute the
308
     number of bytes.  Do a double word increment.  */
309
  ctx->total[0] += len;
310
  if (ctx->total[0] < len)
311
    ++ctx->total[1];
312
313
#define rol(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
314
315
#define M(I) ( tm =   x[I&0x0f] ^ x[(I-14)&0x0f] \
316
		    ^ x[(I-8)&0x0f] ^ x[(I-3)&0x0f] \
317
	       , (x[I&0x0f] = rol(tm, 1)) )
318
319
#define R(A,B,C,D,E,F,K,M)  do { E += rol( A, 5 )     \
320
				      + F( B, C, D )  \
321
				      + K	      \
322
				      + M;	      \
323
				 B = rol( B, 30 );    \
324
			       } while(0)
325
326
  while (words < endp)
327
    {
328
      md5_uint32 tm;
329
      int t;
330
      for (t = 0; t < 16; t++)
331
	{
332
	  x[t] = SWAP (*words);
333
	  words++;
334
	}
335
336
      R( a, b, c, d, e, F1, K1, x[ 0] );
337
      R( e, a, b, c, d, F1, K1, x[ 1] );
338
      R( d, e, a, b, c, F1, K1, x[ 2] );
339
      R( c, d, e, a, b, F1, K1, x[ 3] );
340
      R( b, c, d, e, a, F1, K1, x[ 4] );
341
      R( a, b, c, d, e, F1, K1, x[ 5] );
342
      R( e, a, b, c, d, F1, K1, x[ 6] );
343
      R( d, e, a, b, c, F1, K1, x[ 7] );
344
      R( c, d, e, a, b, F1, K1, x[ 8] );
345
      R( b, c, d, e, a, F1, K1, x[ 9] );
346
      R( a, b, c, d, e, F1, K1, x[10] );
347
      R( e, a, b, c, d, F1, K1, x[11] );
348
      R( d, e, a, b, c, F1, K1, x[12] );
349
      R( c, d, e, a, b, F1, K1, x[13] );
350
      R( b, c, d, e, a, F1, K1, x[14] );
351
      R( a, b, c, d, e, F1, K1, x[15] );
352
      R( e, a, b, c, d, F1, K1, M(16) );
353
      R( d, e, a, b, c, F1, K1, M(17) );
354
      R( c, d, e, a, b, F1, K1, M(18) );
355
      R( b, c, d, e, a, F1, K1, M(19) );
356
      R( a, b, c, d, e, F2, K2, M(20) );
357
      R( e, a, b, c, d, F2, K2, M(21) );
358
      R( d, e, a, b, c, F2, K2, M(22) );
359
      R( c, d, e, a, b, F2, K2, M(23) );
360
      R( b, c, d, e, a, F2, K2, M(24) );
361
      R( a, b, c, d, e, F2, K2, M(25) );
362
      R( e, a, b, c, d, F2, K2, M(26) );
363
      R( d, e, a, b, c, F2, K2, M(27) );
364
      R( c, d, e, a, b, F2, K2, M(28) );
365
      R( b, c, d, e, a, F2, K2, M(29) );
366
      R( a, b, c, d, e, F2, K2, M(30) );
367
      R( e, a, b, c, d, F2, K2, M(31) );
368
      R( d, e, a, b, c, F2, K2, M(32) );
369
      R( c, d, e, a, b, F2, K2, M(33) );
370
      R( b, c, d, e, a, F2, K2, M(34) );
371
      R( a, b, c, d, e, F2, K2, M(35) );
372
      R( e, a, b, c, d, F2, K2, M(36) );
373
      R( d, e, a, b, c, F2, K2, M(37) );
374
      R( c, d, e, a, b, F2, K2, M(38) );
375
      R( b, c, d, e, a, F2, K2, M(39) );
376
      R( a, b, c, d, e, F3, K3, M(40) );
377
      R( e, a, b, c, d, F3, K3, M(41) );
378
      R( d, e, a, b, c, F3, K3, M(42) );
379
      R( c, d, e, a, b, F3, K3, M(43) );
380
      R( b, c, d, e, a, F3, K3, M(44) );
381
      R( a, b, c, d, e, F3, K3, M(45) );
382
      R( e, a, b, c, d, F3, K3, M(46) );
383
      R( d, e, a, b, c, F3, K3, M(47) );
384
      R( c, d, e, a, b, F3, K3, M(48) );
385
      R( b, c, d, e, a, F3, K3, M(49) );
386
      R( a, b, c, d, e, F3, K3, M(50) );
387
      R( e, a, b, c, d, F3, K3, M(51) );
388
      R( d, e, a, b, c, F3, K3, M(52) );
389
      R( c, d, e, a, b, F3, K3, M(53) );
390
      R( b, c, d, e, a, F3, K3, M(54) );
391
      R( a, b, c, d, e, F3, K3, M(55) );
392
      R( e, a, b, c, d, F3, K3, M(56) );
393
      R( d, e, a, b, c, F3, K3, M(57) );
394
      R( c, d, e, a, b, F3, K3, M(58) );
395
      R( b, c, d, e, a, F3, K3, M(59) );
396
      R( a, b, c, d, e, F4, K4, M(60) );
397
      R( e, a, b, c, d, F4, K4, M(61) );
398
      R( d, e, a, b, c, F4, K4, M(62) );
399
      R( c, d, e, a, b, F4, K4, M(63) );
400
      R( b, c, d, e, a, F4, K4, M(64) );
401
      R( a, b, c, d, e, F4, K4, M(65) );
402
      R( e, a, b, c, d, F4, K4, M(66) );
403
      R( d, e, a, b, c, F4, K4, M(67) );
404
      R( c, d, e, a, b, F4, K4, M(68) );
405
      R( b, c, d, e, a, F4, K4, M(69) );
406
      R( a, b, c, d, e, F4, K4, M(70) );
407
      R( e, a, b, c, d, F4, K4, M(71) );
408
      R( d, e, a, b, c, F4, K4, M(72) );
409
      R( c, d, e, a, b, F4, K4, M(73) );
410
      R( b, c, d, e, a, F4, K4, M(74) );
411
      R( a, b, c, d, e, F4, K4, M(75) );
412
      R( e, a, b, c, d, F4, K4, M(76) );
413
      R( d, e, a, b, c, F4, K4, M(77) );
414
      R( c, d, e, a, b, F4, K4, M(78) );
415
      R( b, c, d, e, a, F4, K4, M(79) );
416
417
      a = ctx->A += a;
418
      b = ctx->B += b;
419
      c = ctx->C += c;
420
      d = ctx->D += d;
421
      e = ctx->E += e;
422
    }
423
}
(-)a/mdadm/sha1.h (+87 lines)
Line 0 Link Here
1
/* Declarations of functions and data types used for SHA1 sum
2
   library functions.
3
   Copyright (C) 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
4
5
   This program is free software; you can redistribute it and/or modify it
6
   under the terms of the GNU General Public License as published by the
7
   Free Software Foundation; either version 2, or (at your option) any
8
   later version.
9
10
   This program is distributed in the hope that it will be useful,
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
   GNU General Public License for more details.
14
15
   You should have received a copy of the GNU General Public License
16
   along with this program; if not, write to the Free Software Foundation,
17
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
18
19
#ifndef SHA1_H
20
# define SHA1_H 1
21
22
# include <stdio.h>
23
# include "md5.h"
24
25
/* Structure to save state of computation between the single steps.  */
26
struct sha1_ctx
27
{
28
  md5_uint32 A;
29
  md5_uint32 B;
30
  md5_uint32 C;
31
  md5_uint32 D;
32
  md5_uint32 E;
33
34
  md5_uint32 total[2];
35
  md5_uint32 buflen;
36
  char buffer[128] __attribute__ ((__aligned__ (__alignof__ (md5_uint32))));
37
};
38
39
40
/* Initialize structure containing state of computation. */
41
extern void sha1_init_ctx (struct sha1_ctx *ctx);
42
43
/* Starting with the result of former calls of this function (or the
44
   initialization function update the context for the next LEN bytes
45
   starting at BUFFER.
46
   It is necessary that LEN is a multiple of 64!!! */
47
extern void sha1_process_block (const void *buffer, size_t len,
48
				struct sha1_ctx *ctx);
49
50
/* Starting with the result of former calls of this function (or the
51
   initialization function update the context for the next LEN bytes
52
   starting at BUFFER.
53
   It is NOT required that LEN is a multiple of 64.  */
54
extern void sha1_process_bytes (const void *buffer, size_t len,
55
				struct sha1_ctx *ctx);
56
57
/* Process the remaining bytes in the buffer and put result from CTX
58
   in first 20 bytes following RESBUF.  The result is always in little
59
   endian byte order, so that a byte-wise output yields to the wanted
60
   ASCII representation of the message digest.
61
62
   IMPORTANT: On some systems it is required that RESBUF be correctly
63
   aligned for a 32 bits value.  */
64
extern void *sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf);
65
66
67
/* Put result from CTX in first 20 bytes following RESBUF.  The result is
68
   always in little endian byte order, so that a byte-wise output yields
69
   to the wanted ASCII representation of the message digest.
70
71
   IMPORTANT: On some systems it is required that RESBUF is correctly
72
   aligned for a 32 bits value.  */
73
extern void *sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf);
74
75
76
/* Compute SHA1 message digest for bytes read from STREAM.  The
77
   resulting message digest number will be written into the 20 bytes
78
   beginning at RESBLOCK.  */
79
extern int sha1_stream (FILE *stream, void *resblock);
80
81
/* Compute SHA1 message digest for LEN bytes beginning at BUFFER.  The
82
   result is always in little endian byte order, so that a byte-wise
83
   output yields to the wanted ASCII representation of the message
84
   digest.  */
85
extern void *sha1_buffer (const char *buffer, size_t len, void *resblock);
86
87
#endif
(-)a/mdadm/super0.c (+562 lines)
Line 0 Link Here
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
#define HAVE_STDINT_H 1
31
#include "mdadm.h"
32
/*
33
 * All handling for the 0.90.0 version superblock is in
34
 * this file.
35
 * This includes:
36
 *   - finding, loading, and writing the superblock.
37
 *   - initialising a new superblock
38
 *   - printing the superblock for --examine
39
 *   - printing part of the superblock for --detail
40
 * .. other stuff 
41
 */
42
43
44
static unsigned long calc_sb0_csum(mdp_super_t *super)
45
{
46
	unsigned long csum = super->sb_csum;
47
	unsigned long newcsum;
48
	super->sb_csum= 0 ;
49
	newcsum = calc_csum(super, MD_SB_BYTES);
50
	super->sb_csum = csum;
51
	return newcsum;
52
}
53
54
55
void super0_swap_endian(struct mdp_superblock_s *sb)
56
{
57
	/* as super0 superblocks are host-endian, it is sometimes
58
	 * useful to be able to swap the endianness 
59
	 * as (almost) everything is u32's we byte-swap every 4byte
60
	 * number.
61
	 * We then also have to swap the events_hi and events_lo
62
	 */
63
	char *sbc = (char *)sb;
64
	__u32 t32;
65
	int i;
66
67
	for (i=0; i < MD_SB_BYTES ; i+=4) {
68
		char t = sbc[i];
69
		sbc[i] = sbc[i+3];
70
		sbc[i+3] = t;
71
		t=sbc[i+1];
72
		sbc[i+1]=sbc[i+2];
73
		sbc[i+2]=t;
74
	}
75
	t32 = sb->events_hi;
76
	sb->events_hi = sb->events_lo;
77
	sb->events_lo = t32;
78
79
	t32 = sb->cp_events_hi;
80
	sb->cp_events_hi = sb->cp_events_lo;
81
	sb->cp_events_lo = t32;
82
83
}
84
85
static void brief_examine_super0(void *sbv)
86
{
87
	mdp_super_t *sb = sbv;
88
	char *c=map_num(pers, sb->level);
89
	char devname[20];
90
91
	sprintf(devname, "/dev/md%d", sb->md_minor);
92
93
	printf("ARRAY %s level=%s num-devices=%d UUID=",
94
	       devname,
95
	       c?c:"-unknown-", sb->raid_disks);
96
	if (sb->minor_version >= 90)
97
		printf("%08x:%08x:%08x:%08x", sb->set_uuid0, sb->set_uuid1,
98
		       sb->set_uuid2, sb->set_uuid3);
99
	else
100
		printf("%08x", sb->set_uuid0);
101
	printf("\n");
102
}
103
104
static int match_home0(void *sbv, char *homehost)
105
{
106
	mdp_super_t *sb = sbv;
107
	char buf[20];
108
	char *hash = sha1_buffer(homehost,
109
				 strlen(homehost),
110
				 buf);
111
112
	return (memcmp(&sb->set_uuid2, hash, 8)==0);
113
}
114
115
static void uuid_from_super0(int uuid[4], void * sbv)
116
{
117
	mdp_super_t *super = sbv;
118
	uuid[0] = super->set_uuid0;
119
	if (super->minor_version >= 90) {
120
		uuid[1] = super->set_uuid1;
121
		uuid[2] = super->set_uuid2;
122
		uuid[3] = super->set_uuid3;
123
	} else {
124
		uuid[1] = 0;
125
		uuid[2] = 0;
126
		uuid[3] = 0;
127
	}
128
}
129
130
static void getinfo_super0(struct mdinfo *info, void *sbv)
131
{
132
	mdp_super_t *sb = sbv;
133
	int working = 0;
134
	int i;
135
136
	info->array.major_version = sb->major_version;
137
	info->array.minor_version = sb->minor_version;
138
	info->array.patch_version = sb->patch_version;
139
	info->array.raid_disks = sb->raid_disks;
140
	info->array.level = sb->level;
141
	info->array.layout = sb->layout;
142
	info->array.md_minor = sb->md_minor;
143
	info->array.ctime = sb->ctime;
144
	info->array.utime = sb->utime;
145
	info->array.chunk_size = sb->chunk_size;
146
	info->array.state = sb->state;
147
	info->component_size = sb->size*2;
148
149
	info->disk.state = sb->this_disk.state;
150
	info->disk.major = sb->this_disk.major;
151
	info->disk.minor = sb->this_disk.minor;
152
	info->disk.raid_disk = sb->this_disk.raid_disk;
153
	info->disk.number = sb->this_disk.number;
154
155
	info->events = md_event(sb);
156
	info->data_offset = 0;
157
158
	uuid_from_super0(info->uuid, sbv);
159
160
	if (sb->minor_version > 90 && (sb->reshape_position+1) != 0) {
161
		info->reshape_active = 1;
162
		info->reshape_progress = sb->reshape_position;
163
		info->new_level = sb->new_level;
164
		info->delta_disks = sb->delta_disks;
165
		info->new_layout = sb->new_layout;
166
		info->new_chunk = sb->new_chunk;
167
	} else
168
		info->reshape_active = 0;
169
170
	sprintf(info->name, "%d", sb->md_minor);
171
	/* work_disks is calculated rather than read directly */
172
	for (i=0; i < MD_SB_DISKS; i++)
173
		if ((sb->disks[i].state & (1<<MD_DISK_SYNC)) &&
174
		    (sb->disks[i].raid_disk < info->array.raid_disks) &&
175
		    (sb->disks[i].state & (1<<MD_DISK_ACTIVE)) &&
176
		    !(sb->disks[i].state & (1<<MD_DISK_FAULTY)))
177
			working ++;
178
	info->array.working_disks = working;
179
}
180
181
182
static int update_super0(struct mdinfo *info, void *sbv, char *update,
183
			 char *devname, int verbose,
184
			 int uuid_set, char *homehost)
185
{
186
	/* NOTE: for 'assemble' and 'force' we need to return non-zero if any change was made.
187
	 * For others, the return value is ignored.
188
	 */
189
	int rv = 0;
190
	mdp_super_t *sb = sbv;
191
	if (strcmp(update, "sparc2.2")==0 ) {
192
		/* 2.2 sparc put the events in the wrong place
193
		 * So we copy the tail of the superblock
194
		 * up 4 bytes before continuing
195
		 */
196
		__u32 *sb32 = (__u32*)sb;
197
		memcpy(sb32+MD_SB_GENERIC_CONSTANT_WORDS+7,
198
		       sb32+MD_SB_GENERIC_CONSTANT_WORDS+7+1,
199
		       (MD_SB_WORDS - (MD_SB_GENERIC_CONSTANT_WORDS+7+1))*4);
200
		if (verbose >= 0)
201
			fprintf (stderr, Name ": adjusting superblock of %s for 2.2/sparc compatability.\n",
202
				 devname);
203
	}
204
	if (strcmp(update, "super-minor") ==0) {
205
		sb->md_minor = info->array.md_minor;
206
		if (verbose > 0)
207
			fprintf(stderr, Name ": updating superblock of %s with minor number %d\n",
208
				devname, info->array.md_minor);
209
	}
210
	if (strcmp(update, "summaries") == 0) {
211
		int i;
212
		/* set nr_disks, active_disks, working_disks,
213
		 * failed_disks, spare_disks based on disks[] 
214
		 * array in superblock.
215
		 * Also make sure extra slots aren't 'failed'
216
		 */
217
		sb->nr_disks = sb->active_disks =
218
			sb->working_disks = sb->failed_disks =
219
			sb->spare_disks = 0;
220
		for (i=0; i < MD_SB_DISKS ; i++) 
221
			if (sb->disks[i].major ||
222
			    sb->disks[i].minor) {
223
				int state = sb->disks[i].state;
224
				if (state & (1<<MD_DISK_REMOVED))
225
					continue;
226
				sb->nr_disks++;
227
				if (state & (1<<MD_DISK_ACTIVE))
228
					sb->active_disks++;
229
				if (state & (1<<MD_DISK_FAULTY))
230
					sb->failed_disks++;
231
				else
232
					sb->working_disks++;
233
				if (state == 0)
234
					sb->spare_disks++;
235
			} else if (i >= sb->raid_disks && sb->disks[i].number == 0)
236
				sb->disks[i].state = 0;
237
	}
238
	if (strcmp(update, "force-one")==0) {
239
		/* Not enough devices for a working array, so
240
		 * bring this one up-to-date.
241
		 */
242
		__u32 ehi = sb->events_hi, elo = sb->events_lo;
243
		sb->events_hi = (info->events>>32) & 0xFFFFFFFF;
244
		sb->events_lo = (info->events) & 0xFFFFFFFF;
245
		if (sb->events_hi != ehi ||
246
		    sb->events_lo != elo)
247
			rv = 1;
248
	}
249
	if (strcmp(update, "force-array")==0) {
250
		/* degraded array and 'force' requested, so
251
		 * maybe need to mark it 'clean'
252
		 */
253
		if ((sb->level == 5 || sb->level == 4 || sb->level == 6) &&
254
		    (sb->state & (1 << MD_SB_CLEAN)) == 0) {
255
			/* need to force clean */
256
			sb->state |= (1 << MD_SB_CLEAN);
257
			rv = 1;
258
		}
259
	}
260
	if (strcmp(update, "assemble")==0) {
261
		int d = info->disk.number;
262
		int wonly = sb->disks[d].state & (1<<MD_DISK_WRITEMOSTLY);
263
		if ((sb->disks[d].state & ~(1<<MD_DISK_WRITEMOSTLY))
264
		    != info->disk.state) {
265
			sb->disks[d].state = info->disk.state | wonly;
266
			rv = 1;
267
		}
268
	}
269
	if (strcmp(update, "linear-grow-new") == 0) {
270
		memset(&sb->disks[info->disk.number], 0, sizeof(sb->disks[0]));
271
		sb->disks[info->disk.number].number = info->disk.number;
272
		sb->disks[info->disk.number].major = info->disk.major;
273
		sb->disks[info->disk.number].minor = info->disk.minor;
274
		sb->disks[info->disk.number].raid_disk = info->disk.raid_disk;
275
		sb->disks[info->disk.number].state = info->disk.state;
276
		sb->this_disk = sb->disks[info->disk.number];
277
	}
278
	if (strcmp(update, "linear-grow-update") == 0) {
279
		sb->raid_disks = info->array.raid_disks;
280
		sb->nr_disks = info->array.nr_disks;
281
		sb->active_disks = info->array.active_disks;
282
		sb->working_disks = info->array.working_disks;
283
		memset(&sb->disks[info->disk.number], 0, sizeof(sb->disks[0]));
284
		sb->disks[info->disk.number].number = info->disk.number;
285
		sb->disks[info->disk.number].major = info->disk.major;
286
		sb->disks[info->disk.number].minor = info->disk.minor;
287
		sb->disks[info->disk.number].raid_disk = info->disk.raid_disk;
288
		sb->disks[info->disk.number].state = info->disk.state;
289
	}
290
	if (strcmp(update, "resync") == 0) {
291
		/* make sure resync happens */
292
		sb->state &= ~(1<<MD_SB_CLEAN);
293
		sb->recovery_cp = 0;
294
	}
295
	if (strcmp(update, "homehost") == 0 &&
296
	    homehost) {
297
		uuid_set = 0;
298
		update = "uuid";
299
		info->uuid[0] = sb->set_uuid0;
300
		info->uuid[1] = sb->set_uuid1;
301
	}
302
	if (strcmp(update, "uuid") == 0) {
303
		if (!uuid_set && homehost) {
304
			char buf[20];
305
			char *hash = sha1_buffer(homehost,
306
						 strlen(homehost),
307
						 buf);
308
			memcpy(info->uuid+2, hash, 8);
309
		}
310
		sb->set_uuid0 = info->uuid[0];
311
		sb->set_uuid1 = info->uuid[1];
312
		sb->set_uuid2 = info->uuid[2];
313
		sb->set_uuid3 = info->uuid[3];
314
		if (sb->state & (1<<MD_SB_BITMAP_PRESENT)) {
315
			struct bitmap_super_s *bm;
316
			bm = (struct bitmap_super_s*)(sb+1);
317
			uuid_from_super0((int*)bm->uuid, sbv);
318
		}
319
	}
320
	if (strcmp(update, "_reshape_progress")==0)
321
		sb->reshape_position = info->reshape_progress;
322
323
	sb->sb_csum = calc_sb0_csum(sb);
324
	return rv;
325
}
326
327
static int store_super0(struct supertype *st, int fd, void *sbv)
328
{
329
	unsigned long long dsize;
330
	unsigned long long offset;
331
	mdp_super_t *super = sbv;
332
333
	if (!get_dev_size(fd, NULL, &dsize))
334
		return 1;
335
336
	if (dsize < MD_RESERVED_SECTORS*2*512)
337
		return 2;
338
339
	offset = MD_NEW_SIZE_SECTORS(dsize>>9);
340
341
	offset *= 512;
342
343
	if (lseek64(fd, offset, 0)< 0LL)
344
		return 3;
345
346
	if (write(fd, super, sizeof(*super)) != sizeof(*super))
347
		return 4;
348
349
	if (super->state & (1<<MD_SB_BITMAP_PRESENT)) {
350
		struct bitmap_super_s * bm = (struct bitmap_super_s*)(super+1);
351
		if (__le32_to_cpu(bm->magic) == BITMAP_MAGIC)
352
			if (write(fd, bm, sizeof(*bm)) != sizeof(*bm))
353
			    return 5;
354
	}
355
356
	fsync(fd);
357
	return 0;
358
}
359
360
static int compare_super0(void **firstp, void *secondv)
361
{
362
	/*
363
	 * return:
364
	 *  0 same, or first was empty, and second was copied
365
	 *  1 second had wrong number
366
	 *  2 wrong uuid
367
	 *  3 wrong other info
368
	 */
369
	mdp_super_t *first = *firstp;
370
	mdp_super_t *second = secondv;
371
372
	int uuid1[4], uuid2[4];
373
	if (second->md_magic != MD_SB_MAGIC)
374
		return 1;
375
	if (!first) {
376
		first = malloc(MD_SB_BYTES + sizeof(struct bitmap_super_s));
377
		memcpy(first, second, MD_SB_BYTES + sizeof(struct bitmap_super_s));
378
		*firstp = first;
379
		return 0;
380
	}
381
382
	uuid_from_super0(uuid1, first);
383
	uuid_from_super0(uuid2, second);
384
	if (!same_uuid(uuid1, uuid2, 0))
385
		return 2;
386
	if (first->major_version != second->major_version ||
387
	    first->minor_version != second->minor_version ||
388
	    first->patch_version != second->patch_version ||
389
	    first->gvalid_words  != second->gvalid_words  ||
390
	    first->ctime         != second->ctime         ||
391
	    first->level         != second->level         ||
392
	    first->size          != second->size          ||
393
	    first->raid_disks    != second->raid_disks    )
394
		return 3;
395
396
	return 0;
397
}
398
399
400
static int load_super0(struct supertype *st, int fd, void **sbp, char *devname)
401
{
402
	/* try to read in the superblock
403
	 * Return:
404
	 *  0 on success
405
	 *  1 on cannot get superblock
406
	 *  2 on superblock meaningless
407
	 */
408
	unsigned long long dsize;
409
	unsigned long long offset;
410
	mdp_super_t *super;
411
	int uuid[4];
412
	struct bitmap_super_s *bsb;
413
    
414
	if (!get_dev_size(fd, devname, &dsize))
415
		return 1;
416
417
	if (dsize < MD_RESERVED_SECTORS*512 * 2) {
418
		if (devname)
419
			fprintf(stderr, Name
420
			    ": %s is too small for md: size is %llu sectors.\n",
421
				devname, dsize);
422
		return 1;
423
	}
424
425
	offset = MD_NEW_SIZE_SECTORS(dsize>>9);
426
427
	offset *= 512;
428
429
	ioctl(fd, BLKFLSBUF, 0); /* make sure we read current data */
430
431
	if (lseek64(fd, offset, 0)< 0LL) {
432
		if (devname)
433
			fprintf(stderr, Name ": Cannot seek to superblock on %s: %s\n",
434
				devname, strerror(errno));
435
		return 1;
436
	}
437
438
	super = malloc(MD_SB_BYTES + sizeof(bitmap_super_t));
439
440
	if (read(fd, super, sizeof(*super)) != MD_SB_BYTES) {
441
		if (devname)
442
			fprintf(stderr, Name ": Cannot read superblock on %s\n",
443
				devname);
444
		free(super);
445
		return 1;
446
	}
447
448
	if (st->ss && st->minor_version == 9)
449
		super0_swap_endian(super);
450
451
	if (super->md_magic != MD_SB_MAGIC) {
452
		if (devname)
453
			fprintf(stderr, Name ": No super block found on %s (Expected magic %08x, got %08x)\n",
454
				devname, MD_SB_MAGIC, super->md_magic);
455
		free(super);
456
		return 2;
457
	}
458
459
	if (super->major_version != 0) {
460
		if (devname)
461
			fprintf(stderr, Name ": Cannot interpret superblock on %s - version is %d\n",
462
				devname, super->major_version);
463
		free(super);
464
		return 2;
465
	}
466
	*sbp = super;
467
	if (st->ss == NULL) {
468
		st->ss = &super0;
469
		st->minor_version = 90;
470
		st->max_devs = MD_SB_DISKS;
471
	}
472
473
	/* Now check on the bitmap superblock */
474
	if ((super->state & (1<<MD_SB_BITMAP_PRESENT)) == 0)
475
		return 0;
476
	/* Read the bitmap superblock and make sure it looks
477
	 * valid.  If it doesn't clear the bit.  An --assemble --force
478
	 * should get that written out.
479
	 */
480
	if (read(fd, super+1, sizeof(struct bitmap_super_s))
481
	    != sizeof(struct bitmap_super_s))
482
		goto no_bitmap;
483
484
	uuid_from_super0(uuid, super);
485
	bsb = (struct bitmap_super_s *)(super+1);
486
	if (__le32_to_cpu(bsb->magic) != BITMAP_MAGIC ||
487
	    memcmp(bsb->uuid, uuid, 16) != 0)
488
		goto no_bitmap;
489
	return 0;
490
491
 no_bitmap:
492
	super->state &= ~(1<<MD_SB_BITMAP_PRESENT);
493
494
	return 0;
495
}
496
497
static struct supertype *match_metadata_desc0(char *arg)
498
{
499
	struct supertype *st = malloc(sizeof(*st));
500
	if (!st) return st;
501
502
	st->ss = &super0;
503
	st->minor_version = 90;
504
	st->max_devs = MD_SB_DISKS;
505
	if (strcmp(arg, "0") == 0 ||
506
	    strcmp(arg, "0.90") == 0 ||
507
	    strcmp(arg, "default") == 0
508
		)
509
		return st;
510
511
	st->minor_version = 9; /* flag for 'byte-swapped' */
512
	if (strcmp(arg, "0.swap")==0)
513
		return st;
514
515
	free(st);
516
	return NULL;
517
}
518
519
void locate_bitmap0(struct supertype *st, int fd, void *sbv)
520
{
521
	unsigned long long dsize;
522
	unsigned long long offset;
523
524
	if (!get_dev_size(fd, NULL, &dsize))
525
		return;
526
527
	if (dsize < MD_RESERVED_SECTORS*512 * 2)
528
		return;
529
530
	offset = MD_NEW_SIZE_SECTORS(dsize>>9);
531
532
	offset *= 512;
533
534
	offset += MD_SB_BYTES;
535
536
	lseek64(fd, offset, 0);
537
}
538
539
struct superswitch super0 = {
540
	.examine_super = NULL,
541
	.brief_examine_super = brief_examine_super0,
542
	.detail_super = NULL,
543
	.brief_detail_super = NULL,
544
	.export_super = NULL,
545
	.match_home = match_home0,
546
	.uuid_from_super = uuid_from_super0,
547
	.getinfo_super = getinfo_super0,
548
	.update_super = update_super0,
549
	.init_super = NULL,
550
	.add_to_super = NULL,
551
	.store_super = store_super0,
552
	.write_init_super = NULL,
553
	.compare_super = compare_super0,
554
	.load_super = load_super0,
555
	.match_metadata_desc = match_metadata_desc0,
556
	.avail_size = NULL,
557
	.add_internal_bitmap = NULL, 
558
	.locate_bitmap = locate_bitmap0,
559
	.write_bitmap = NULL,
560
	.major = 0,
561
	.swapuuid = 0,
562
};
(-)a/mdadm/super1.c (+731 lines)
Line 0 Link Here
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
/*
32
 * The version-1 superblock :
33
 * All numeric fields are little-endian.
34
 *
35
 * total size: 256 bytes plus 2 per device.
36
 *  1K allows 384 devices.
37
 */
38
struct mdp_superblock_1 {
39
	/* constant array information - 128 bytes */
40
	__u32	magic;		/* MD_SB_MAGIC: 0xa92b4efc - little endian */
41
	__u32	major_version;	/* 1 */
42
	__u32	feature_map;	/* 0 for now */
43
	__u32	pad0;		/* always set to 0 when writing */
44
45
	__u8	set_uuid[16];	/* user-space generated. */
46
	char	set_name[32];	/* set and interpreted by user-space */
47
48
	__u64	ctime;		/* lo 40 bits are seconds, top 24 are microseconds or 0*/
49
	__u32	level;		/* -4 (multipath), -1 (linear), 0,1,4,5 */
50
	__u32	layout;		/* only for raid5 currently */
51
	__u64	size;		/* used size of component devices, in 512byte sectors */
52
53
	__u32	chunksize;	/* in 512byte sectors */
54
	__u32	raid_disks;
55
	__u32	bitmap_offset;	/* sectors after start of superblock that bitmap starts
56
				 * NOTE: signed, so bitmap can be before superblock
57
				 * only meaningful of feature_map[0] is set.
58
				 */
59
60
	/* These are only valid with feature bit '4' */
61
	__u32	new_level;	/* new level we are reshaping to		*/
62
	__u64	reshape_position;	/* next address in array-space for reshape */
63
	__u32	delta_disks;	/* change in number of raid_disks		*/
64
	__u32	new_layout;	/* new layout					*/
65
	__u32	new_chunk;	/* new chunk size (bytes)			*/
66
	__u8	pad1[128-124];	/* set to 0 when written */
67
68
	/* constant this-device information - 64 bytes */
69
	__u64	data_offset;	/* sector start of data, often 0 */
70
	__u64	data_size;	/* sectors in this device that can be used for data */
71
	__u64	super_offset;	/* sector start of this superblock */
72
	__u64	recovery_offset;/* sectors before this offset (from data_offset) have been recovered */
73
	__u32	dev_number;	/* permanent identifier of this  device - not role in raid */
74
	__u32	cnt_corrected_read; /* number of read errors that were corrected by re-writing */
75
	__u8	device_uuid[16]; /* user-space setable, ignored by kernel */
76
        __u8    devflags;        /* per-device flags.  Only one defined...*/
77
#define WriteMostly1    1        /* mask for writemostly flag in above */
78
	__u8	pad2[64-57];	/* set to 0 when writing */
79
80
	/* array state information - 64 bytes */
81
	__u64	utime;		/* 40 bits second, 24 btes microseconds */
82
	__u64	events;		/* incremented when superblock updated */
83
	__u64	resync_offset;	/* data before this offset (from data_offset) known to be in sync */
84
	__u32	sb_csum;	/* checksum upto devs[max_dev] */
85
	__u32	max_dev;	/* size of devs[] array to consider */
86
	__u8	pad3[64-32];	/* set to 0 when writing */
87
88
	/* device state information. Indexed by dev_number.
89
	 * 2 bytes per device
90
	 * Note there are no per-device state flags. State information is rolled
91
	 * into the 'roles' value.  If a device is spare or faulty, then it doesn't
92
	 * have a meaningful role.
93
	 */
94
	__u16	dev_roles[0];	/* role in array, or 0xffff for a spare, or 0xfffe for faulty */
95
};
96
97
struct misc_dev_info {
98
	__u64 device_size;
99
};
100
101
/* feature_map bits */
102
#define MD_FEATURE_BITMAP_OFFSET	1
103
#define	MD_FEATURE_RECOVERY_OFFSET	2 /* recovery_offset is present and
104
					   * must be honoured
105
					   */
106
#define	MD_FEATURE_RESHAPE_ACTIVE	4
107
108
#define	MD_FEATURE_ALL			(1|2|4)
109
110
#ifndef offsetof
111
#define offsetof(t,f) ((size_t)&(((t*)0)->f))
112
#endif
113
static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb)
114
{
115
	unsigned int disk_csum, csum;
116
	unsigned long long newcsum;
117
	int size = sizeof(*sb) + __le32_to_cpu(sb->max_dev)*2;
118
	unsigned int *isuper = (unsigned int*)sb;
119
	int i;
120
121
/* make sure I can count... */
122
	if (offsetof(struct mdp_superblock_1,data_offset) != 128 ||
123
	    offsetof(struct mdp_superblock_1, utime) != 192 ||
124
	    sizeof(struct mdp_superblock_1) != 256) {
125
		fprintf(stderr, "WARNING - superblock isn't sized correctly\n");
126
	}
127
128
	disk_csum = sb->sb_csum;
129
	sb->sb_csum = 0;
130
	newcsum = 0;
131
	for (i=0; size>=4; size -= 4 ) {
132
		newcsum += __le32_to_cpu(*isuper);
133
		isuper++;
134
	}
135
136
	if (size == 2)
137
		newcsum += __le16_to_cpu(*(unsigned short*) isuper);
138
139
	csum = (newcsum & 0xffffffff) + (newcsum >> 32);
140
	sb->sb_csum = disk_csum;
141
	return __cpu_to_le32(csum);
142
}
143
144
static void brief_examine_super1(void *sbv)
145
{
146
	struct mdp_superblock_1 *sb = sbv;
147
	int i;
148
	unsigned long long sb_offset;
149
	char *nm;
150
	char *c=map_num(pers, __le32_to_cpu(sb->level));
151
152
	nm = strchr(sb->set_name, ':');
153
	if (nm)
154
		nm++;
155
	else if (sb->set_name[0])
156
		nm = sb->set_name;
157
	else
158
		nm = "??";
159
160
	printf("ARRAY /dev/md%s level=%s ", nm, c?c:"-unknown-");
161
	sb_offset = __le64_to_cpu(sb->super_offset);
162
	if (sb_offset <= 4)
163
		printf("metadata=1.1 ");
164
	else if (sb_offset <= 8)
165
		printf("metadata=1.2 ");
166
	else
167
		printf("metadata=1.0 ");
168
	printf("num-devices=%d UUID=", __le32_to_cpu(sb->raid_disks));
169
	for (i=0; i<16; i++) {
170
		if ((i&3)==0 && i != 0) printf(":");
171
		printf("%02x", sb->set_uuid[i]);
172
	}
173
	if (sb->set_name[0])
174
		printf(" name=%.32s", sb->set_name);
175
	printf("\n");
176
}
177
178
static int match_home1(void *sbv, char *homehost)
179
{
180
	struct mdp_superblock_1 *sb = sbv;
181
	int l = homehost ? strlen(homehost) : 0;
182
183
	return (l > 0 && l < 32 &&
184
		sb->set_name[l] == ':' &&
185
		strncmp(sb->set_name, homehost, l) == 0);
186
}
187
188
static void uuid_from_super1(int uuid[4], void * sbv)
189
{
190
	struct mdp_superblock_1 *super = sbv;
191
	char *cuuid = (char*)uuid;
192
	int i;
193
	for (i=0; i<16; i++)
194
		cuuid[i] = super->set_uuid[i];
195
}
196
197
static void getinfo_super1(struct mdinfo *info, void *sbv)
198
{
199
	struct mdp_superblock_1 *sb = sbv;
200
	int working = 0;
201
	int i;
202
	int role;
203
204
	info->array.major_version = 1;
205
	info->array.minor_version = __le32_to_cpu(sb->feature_map);
206
	info->array.patch_version = 0;
207
	info->array.raid_disks = __le32_to_cpu(sb->raid_disks);
208
	info->array.level = __le32_to_cpu(sb->level);
209
	info->array.layout = __le32_to_cpu(sb->layout);
210
	info->array.md_minor = -1;
211
	info->array.ctime = __le64_to_cpu(sb->ctime);
212
	info->array.utime = __le64_to_cpu(sb->utime);
213
	info->array.chunk_size = __le32_to_cpu(sb->chunksize)*512;
214
	info->array.state =
215
		(__le64_to_cpu(sb->resync_offset) >= __le64_to_cpu(sb->size))
216
		? 1 : 0;
217
218
	info->data_offset = __le64_to_cpu(sb->data_offset);
219
	info->component_size = __le64_to_cpu(sb->size);
220
221
	info->disk.major = 0;
222
	info->disk.minor = 0;
223
	info->disk.number = __le32_to_cpu(sb->dev_number);
224
	if (__le32_to_cpu(sb->dev_number) >= __le32_to_cpu(sb->max_dev) ||
225
	    __le32_to_cpu(sb->max_dev) > 512)
226
		role = 0xfffe;
227
	else
228
		role = __le16_to_cpu(sb->dev_roles[__le32_to_cpu(sb->dev_number)]);
229
230
	info->disk.raid_disk = -1;
231
	switch(role) {
232
	case 0xFFFF:
233
		info->disk.state = 2; /* spare: ACTIVE, not sync, not faulty */
234
		break;
235
	case 0xFFFE:
236
		info->disk.state = 1; /* faulty */
237
		break;
238
	default:
239
		info->disk.state = 6; /* active and in sync */
240
		info->disk.raid_disk = role;
241
	}
242
	info->events = __le64_to_cpu(sb->events);
243
244
	memcpy(info->uuid, sb->set_uuid, 16);
245
246
	strncpy(info->name, sb->set_name, 32);
247
	info->name[32] = 0;
248
249
	if (sb->feature_map & __le32_to_cpu(MD_FEATURE_RESHAPE_ACTIVE)) {
250
		info->reshape_active = 1;
251
		info->reshape_progress = __le64_to_cpu(sb->reshape_position);
252
		info->new_level = __le32_to_cpu(sb->new_level);
253
		info->delta_disks = __le32_to_cpu(sb->delta_disks);
254
		info->new_layout = __le32_to_cpu(sb->new_layout);
255
		info->new_chunk = __le32_to_cpu(sb->new_chunk)<<9;
256
	} else
257
		info->reshape_active = 0;
258
259
	for (i=0; i< __le32_to_cpu(sb->max_dev); i++) {
260
		role = __le16_to_cpu(sb->dev_roles[i]);
261
		if (/*role == 0xFFFF || */role < info->array.raid_disks)
262
			working++;
263
	}
264
265
	info->array.working_disks = working;
266
}
267
268
static int update_super1(struct mdinfo *info, void *sbv, char *update,
269
			 char *devname, int verbose,
270
			 int uuid_set, char *homehost)
271
{
272
	/* NOTE: for 'assemble' and 'force' we need to return non-zero if any change was made.
273
	 * For others, the return value is ignored.
274
	 */
275
	int rv = 0;
276
	struct mdp_superblock_1 *sb = sbv;
277
278
	if (strcmp(update, "force-one")==0) {
279
		/* Not enough devices for a working array,
280
		 * so bring this one up-to-date
281
		 */
282
		if (sb->events != __cpu_to_le64(info->events))
283
			rv = 1;
284
		sb->events = __cpu_to_le64(info->events);
285
	}
286
	if (strcmp(update, "force-array")==0) {
287
		/* Degraded array and 'force' requests to
288
		 * maybe need to mark it 'clean'.
289
		 */
290
		switch(__le32_to_cpu(sb->level)) {
291
		case 5: case 4: case 6:
292
			/* need to force clean */
293
			if (sb->resync_offset != ~0ULL)
294
				rv = 1;
295
			sb->resync_offset = ~0ULL;
296
		}
297
	}
298
	if (strcmp(update, "assemble")==0) {
299
		int d = info->disk.number;
300
		int want;
301
		if (info->disk.state == 6)
302
			want = __cpu_to_le32(info->disk.raid_disk);
303
		else
304
			want = 0xFFFF;
305
		if (sb->dev_roles[d] != want) {
306
			sb->dev_roles[d] = want;
307
			rv = 1;
308
		}
309
	}
310
	if (strcmp(update, "linear-grow-new") == 0) {
311
		int i;
312
		int rfd;
313
		int max = __le32_to_cpu(sb->max_dev);
314
315
		for (i=0 ; i < max ; i++)
316
			if (__le16_to_cpu(sb->dev_roles[i]) >= 0xfffe)
317
				break;
318
		sb->dev_number = __cpu_to_le32(i);
319
		info->disk.number = i;
320
		if (max >= __le32_to_cpu(sb->max_dev))
321
			sb->max_dev = __cpu_to_le32(max+1);
322
323
		if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 ||
324
		    read(rfd, sb->device_uuid, 16) != 16) {
325
			*(__u32*)(sb->device_uuid) = random();
326
			*(__u32*)(sb->device_uuid+4) = random();
327
			*(__u32*)(sb->device_uuid+8) = random();
328
			*(__u32*)(sb->device_uuid+12) = random();
329
		}
330
331
		sb->dev_roles[i] =
332
			__cpu_to_le16(info->disk.raid_disk);
333
	}
334
	if (strcmp(update, "linear-grow-update") == 0) {
335
		sb->raid_disks = __cpu_to_le32(info->array.raid_disks);
336
		sb->dev_roles[info->disk.number] =
337
			__cpu_to_le16(info->disk.raid_disk);
338
	}
339
	if (strcmp(update, "resync") == 0) {
340
		/* make sure resync happens */
341
		sb->resync_offset = 0ULL;
342
	}
343
	if (strcmp(update, "uuid") == 0) {
344
		copy_uuid(sb->set_uuid, info->uuid, super1.swapuuid);
345
346
		if (__le32_to_cpu(sb->feature_map)&MD_FEATURE_BITMAP_OFFSET) {
347
			struct bitmap_super_s *bm;
348
			bm = (struct bitmap_super_s*)(sbv+1024);
349
			memcpy(bm->uuid, sb->set_uuid, 16);
350
		}
351
	}
352
	if (strcmp(update, "homehost") == 0 &&
353
	    homehost) {
354
		char *c;
355
		update = "name";
356
		c = strchr(sb->set_name, ':');
357
		if (c)
358
			strncpy(info->name, c+1, 31 - (c-sb->set_name));
359
		else
360
			strncpy(info->name, sb->set_name, 32);
361
		info->name[32] = 0;
362
	}
363
	if (strcmp(update, "name") == 0) {
364
		if (info->name[0] == 0)
365
			sprintf(info->name, "%d", info->array.md_minor);
366
		memset(sb->set_name, 0, sizeof(sb->set_name));
367
		if (homehost &&
368
		    strchr(info->name, ':') == NULL &&
369
		    strlen(homehost)+1+strlen(info->name) < 32) {
370
			strcpy(sb->set_name, homehost);
371
			strcat(sb->set_name, ":");
372
			strcat(sb->set_name, info->name);
373
		} else
374
			strcpy(sb->set_name, info->name);
375
	}
376
	if (strcmp(update, "devicesize") == 0 &&
377
	    __le64_to_cpu(sb->super_offset) <
378
	    __le64_to_cpu(sb->data_offset)) {
379
		/* set data_size to device size less data_offset */
380
		struct misc_dev_info *misc = (struct misc_dev_info*)
381
			(sbv + 1024 + sizeof(struct bitmap_super_s));
382
		printf("Size was %llu\n", (unsigned long long)
383
		       __le64_to_cpu(sb->data_size));
384
		sb->data_size = __cpu_to_le64(
385
			misc->device_size - __le64_to_cpu(sb->data_offset));
386
		printf("Size is %llu\n", (unsigned long long)
387
		       __le64_to_cpu(sb->data_size));
388
	}
389
	if (strcmp(update, "_reshape_progress")==0)
390
		sb->reshape_position = __cpu_to_le64(info->reshape_progress);
391
392
	sb->sb_csum = calc_sb_1_csum(sb);
393
	return rv;
394
}
395
396
static void locate_bitmap1(struct supertype *st, int fd, void *sbv);
397
398
static int store_super1(struct supertype *st, int fd, void *sbv)
399
{
400
	struct mdp_superblock_1 *sb = sbv;
401
	unsigned long long sb_offset;
402
	int sbsize;
403
	unsigned long long dsize;
404
405
	if (!get_dev_size(fd, NULL, &dsize))
406
		return 1;
407
408
	dsize >>= 9;
409
410
	if (dsize < 24)
411
		return 2;
412
413
	/*
414
	 * Calculate the position of the superblock.
415
	 * It is always aligned to a 4K boundary and
416
	 * depending on minor_version, it can be:
417
	 * 0: At least 8K, but less than 12K, from end of device
418
	 * 1: At start of device
419
	 * 2: 4K from start of device.
420
	 */
421
	switch(st->minor_version) {
422
	case 0:
423
		sb_offset = dsize;
424
		sb_offset -= 8*2;
425
		sb_offset &= ~(4*2-1);
426
		break;
427
	case 1:
428
		sb_offset = 0;
429
		break;
430
	case 2:
431
		sb_offset = 4*2;
432
		break;
433
	default:
434
		return -EINVAL;
435
	}
436
437
438
439
	if (sb_offset != __le64_to_cpu(sb->super_offset) &&
440
	    0 != __le64_to_cpu(sb->super_offset)
441
		) {
442
		fprintf(stderr, Name ": internal error - sb_offset is wrong\n");
443
		abort();
444
	}
445
446
	if (lseek64(fd, sb_offset << 9, 0)< 0LL)
447
		return 3;
448
449
	sbsize = sizeof(*sb) + 2 * __le32_to_cpu(sb->max_dev);
450
451
	if (write(fd, sb, sbsize) != sbsize)
452
		return 4;
453
454
	if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) {
455
		struct bitmap_super_s *bm = (struct bitmap_super_s*)
456
			(((char*)sb)+1024);
457
		if (__le32_to_cpu(bm->magic) == BITMAP_MAGIC) {
458
			locate_bitmap1(st, fd, sbv);
459
			if (write(fd, bm, sizeof(*bm)) != sizeof(*bm))
460
			    return 5;
461
		}
462
	}
463
	fsync(fd);
464
	return 0;
465
}
466
467
static int load_super1(struct supertype *st, int fd, void **sbp, char *devname);
468
469
static int compare_super1(void **firstp, void *secondv)
470
{
471
	/*
472
	 * return:
473
	 *  0 same, or first was empty, and second was copied
474
	 *  1 second had wrong number
475
	 *  2 wrong uuid
476
	 *  3 wrong other info
477
	 */
478
	struct mdp_superblock_1 *first = *firstp;
479
	struct mdp_superblock_1 *second = secondv;
480
481
	if (second->magic != __cpu_to_le32(MD_SB_MAGIC))
482
		return 1;
483
	if (second->major_version != __cpu_to_le32(1))
484
		return 1;
485
486
	if (!first) {
487
		first = malloc(1024+sizeof(bitmap_super_t) +
488
			       sizeof(struct misc_dev_info));
489
		memcpy(first, second, 1024+sizeof(bitmap_super_t) +
490
		       sizeof(struct misc_dev_info));
491
		*firstp = first;
492
		return 0;
493
	}
494
	if (memcmp(first->set_uuid, second->set_uuid, 16)!= 0)
495
		return 2;
496
497
	if (first->ctime      != second->ctime     ||
498
	    first->level      != second->level     ||
499
	    first->layout     != second->layout    ||
500
	    first->size       != second->size      ||
501
	    first->chunksize  != second->chunksize ||
502
	    first->raid_disks != second->raid_disks)
503
		return 3;
504
	return 0;
505
}
506
507
static int load_super1(struct supertype *st, int fd, void **sbp, char *devname)
508
{
509
	unsigned long long dsize;
510
	unsigned long long sb_offset;
511
	struct mdp_superblock_1 *super;
512
	int uuid[4];
513
	struct bitmap_super_s *bsb;
514
	struct misc_dev_info *misc;
515
516
517
	if (st->ss == NULL) {
518
		int bestvers = -1;
519
		__u64 bestctime = 0;
520
		/* guess... choose latest ctime */
521
		st->ss = &super1;
522
		for (st->minor_version = 0; st->minor_version <= 2 ; st->minor_version++) {
523
			switch(load_super1(st, fd, sbp, devname)) {
524
			case 0: super = *sbp;
525
				if (bestvers == -1 ||
526
				    bestctime < __le64_to_cpu(super->ctime)) {
527
					bestvers = st->minor_version;
528
					bestctime = __le64_to_cpu(super->ctime);
529
				}
530
				free(super);
531
				*sbp = NULL;
532
				break;
533
			case 1: st->ss = NULL; return 1; /*bad device */
534
			case 2: break; /* bad, try next */
535
			}
536
		}
537
		if (bestvers != -1) {
538
			int rv;
539
			st->minor_version = bestvers;
540
			st->ss = &super1;
541
			st->max_devs = 384;
542
			rv = load_super1(st, fd, sbp, devname);
543
			if (rv) st->ss = NULL;
544
			return rv;
545
		}
546
		st->ss = NULL;
547
		return 2;
548
	}
549
	if (!get_dev_size(fd, devname, &dsize))
550
		return 1;
551
	dsize >>= 9;
552
553
	if (dsize < 24) {
554
		if (devname)
555
			fprintf(stderr, Name ": %s is too small for md: size is %llu sectors.\n",
556
				devname, dsize);
557
		return 1;
558
	}
559
560
	/*
561
	 * Calculate the position of the superblock.
562
	 * It is always aligned to a 4K boundary and
563
	 * depending on minor_version, it can be:
564
	 * 0: At least 8K, but less than 12K, from end of device
565
	 * 1: At start of device
566
	 * 2: 4K from start of device.
567
	 */
568
	switch(st->minor_version) {
569
	case 0:
570
		sb_offset = dsize;
571
		sb_offset -= 8*2;
572
		sb_offset &= ~(4*2-1);
573
		break;
574
	case 1:
575
		sb_offset = 0;
576
		break;
577
	case 2:
578
		sb_offset = 4*2;
579
		break;
580
	default:
581
		return -EINVAL;
582
	}
583
584
	ioctl(fd, BLKFLSBUF, 0); /* make sure we read current data */
585
586
587
	if (lseek64(fd, sb_offset << 9, 0)< 0LL) {
588
		if (devname)
589
			fprintf(stderr, Name ": Cannot seek to superblock on %s: %s\n",
590
				devname, strerror(errno));
591
		return 1;
592
	}
593
594
	super = malloc(1024 + sizeof(bitmap_super_t) +
595
		       sizeof(struct misc_dev_info));
596
597
	if (read(fd, super, 1024) != 1024) {
598
		if (devname)
599
			fprintf(stderr, Name ": Cannot read superblock on %s\n",
600
				devname);
601
		free(super);
602
		return 1;
603
	}
604
605
	if (__le32_to_cpu(super->magic) != MD_SB_MAGIC) {
606
		if (devname)
607
			fprintf(stderr, Name ": No super block found on %s (Expected magic %08x, got %08x)\n",
608
				devname, MD_SB_MAGIC, __le32_to_cpu(super->magic));
609
		free(super);
610
		return 2;
611
	}
612
613
	if (__le32_to_cpu(super->major_version) != 1) {
614
		if (devname)
615
			fprintf(stderr, Name ": Cannot interpret superblock on %s - version is %d\n",
616
				devname, __le32_to_cpu(super->major_version));
617
		free(super);
618
		return 2;
619
	}
620
	if (__le64_to_cpu(super->super_offset) != sb_offset) {
621
		if (devname)
622
			fprintf(stderr, Name ": No superblock found on %s (super_offset is wrong)\n",
623
				devname);
624
		free(super);
625
		return 2;
626
	}
627
	*sbp = super;
628
629
	bsb = (struct bitmap_super_s *)(((char*)super)+1024);
630
631
	misc = (struct misc_dev_info*) (bsb+1);
632
	misc->device_size = dsize;
633
634
	/* Now check on the bitmap superblock */
635
	if ((__le32_to_cpu(super->feature_map)&MD_FEATURE_BITMAP_OFFSET) == 0)
636
		return 0;
637
	/* Read the bitmap superblock and make sure it looks
638
	 * valid.  If it doesn't clear the bit.  An --assemble --force
639
	 * should get that written out.
640
	 */
641
	locate_bitmap1(st, fd, super);
642
	if (read(fd, ((char*)super)+1024, sizeof(struct bitmap_super_s))
643
	    != sizeof(struct bitmap_super_s))
644
		goto no_bitmap;
645
646
	uuid_from_super1(uuid, super);
647
	if (__le32_to_cpu(bsb->magic) != BITMAP_MAGIC ||
648
	    memcmp(bsb->uuid, uuid, 16) != 0)
649
		goto no_bitmap;
650
	return 0;
651
652
 no_bitmap:
653
	super->feature_map = __cpu_to_le32(__le32_to_cpu(super->feature_map) & ~1);
654
	return 0;
655
}
656
657
658
static struct supertype *match_metadata_desc1(char *arg)
659
{
660
	struct supertype *st = malloc(sizeof(*st));
661
	if (!st) return st;
662
663
	st->ss = &super1;
664
	st->max_devs = 384;
665
	if (strcmp(arg, "1") == 0 ||
666
	    strcmp(arg, "1.0") == 0 ||
667
	    strcmp(arg, "default/large") == 0) {
668
		st->minor_version = 0;
669
		return st;
670
	}
671
	if (strcmp(arg, "1.1") == 0) {
672
		st->minor_version = 1;
673
		return st;
674
	}
675
	if (strcmp(arg, "1.2") == 0) {
676
		st->minor_version = 2;
677
		return st;
678
	}
679
680
	free(st);
681
	return NULL;
682
}
683
684
static void locate_bitmap1(struct supertype *st, int fd, void *sbv)
685
{
686
	unsigned long long offset;
687
	struct mdp_superblock_1 *sb;
688
	int mustfree = 0;
689
690
	if (!sbv) {
691
		if (st->ss->load_super(st, fd, &sbv, NULL))
692
			return; /* no error I hope... */
693
		mustfree = 1;
694
	}
695
	sb = sbv;
696
697
	offset = __le64_to_cpu(sb->super_offset);
698
	offset += (int32_t) __le32_to_cpu(sb->bitmap_offset);
699
	if (mustfree)
700
		free(sb);
701
	lseek64(fd, offset<<9, 0);
702
}
703
704
struct superswitch super1 = {
705
	.examine_super = NULL,
706
	.brief_examine_super = brief_examine_super1,
707
	.detail_super = NULL,
708
	.brief_detail_super = NULL,
709
	.export_super = NULL,
710
	.match_home = match_home1,
711
	.uuid_from_super = uuid_from_super1,
712
	.getinfo_super = getinfo_super1,
713
	.update_super = update_super1,
714
	.init_super = NULL,
715
	.add_to_super = NULL,
716
	.store_super = store_super1,
717
	.write_init_super = NULL,
718
	.compare_super = compare_super1,
719
	.load_super = load_super1,
720
	.match_metadata_desc = match_metadata_desc1,
721
	.avail_size = NULL,
722
	.add_internal_bitmap = NULL,
723
	.locate_bitmap = locate_bitmap1,
724
	.write_bitmap = NULL,
725
	.major = 1,
726
#if __BYTE_ORDER == BIG_ENDIAN
727
	.swapuuid = 0,
728
#else
729
	.swapuuid = 1,
730
#endif
731
};
(-)a/mdadm/util.c (+652 lines)
Line 0 Link Here
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	"md_p.h"
32
#include	<sys/utsname.h>
33
#include	<ctype.h>
34
35
/*
36
 * following taken from linux/blkpg.h because they aren't
37
 * anywhere else and it isn't safe to #include linux/ * stuff.
38
 */
39
40
#define BLKPG      _IO(0x12,105)
41
42
/* The argument structure */
43
struct blkpg_ioctl_arg {
44
        int op;
45
        int flags;
46
        int datalen;
47
        void *data;
48
};
49
50
/* The subfunctions (for the op field) */
51
#define BLKPG_ADD_PARTITION	1
52
#define BLKPG_DEL_PARTITION	2
53
54
/* Sizes of name fields. Unused at present. */
55
#define BLKPG_DEVNAMELTH	64
56
#define BLKPG_VOLNAMELTH	64
57
58
/* The data structure for ADD_PARTITION and DEL_PARTITION */
59
struct blkpg_partition {
60
	long long start;		/* starting offset in bytes */
61
	long long length;		/* length in bytes */
62
	int pno;			/* partition number */
63
	char devname[BLKPG_DEVNAMELTH];	/* partition name, like sda5 or c0d1p2,
64
					   to be used in kernel messages */
65
	char volname[BLKPG_VOLNAMELTH];	/* volume label */
66
};
67
68
/*
69
 * Parse a 128 bit uuid in 4 integers
70
 * format is 32 hexx nibbles with options :.<space> separator
71
 * If not exactly 32 hex digits are found, return 0
72
 * else return 1
73
 */
74
int parse_uuid(char *str, int uuid[4])
75
{
76
    int hit = 0; /* number of Hex digIT */
77
    int i;
78
    char c;
79
    for (i=0; i<4; i++) uuid[i]=0;
80
81
    while ((c= *str++)) {
82
	int n;
83
	if (c>='0' && c<='9')
84
	    n = c-'0';
85
	else if (c>='a' && c <= 'f')
86
	    n = 10 + c - 'a';
87
	else if (c>='A' && c <= 'F')
88
	    n = 10 + c - 'A';
89
	else if (strchr(":. -", c))
90
	    continue;
91
	else return 0;
92
93
	if (hit<32) {
94
	    uuid[hit/8] <<= 4;
95
	    uuid[hit/8] += n;
96
	}
97
	hit++;
98
    }
99
    if (hit == 32)
100
	return 1;
101
    return 0;
102
    
103
}
104
105
106
/*
107
 * Get the md version number.
108
 * We use the RAID_VERSION ioctl if it is supported
109
 * If not, but we have a block device with major '9', we assume
110
 * 0.36.0
111
 *
112
 * Return version number as 24 but number - assume version parts
113
 * always < 255
114
 */
115
116
int md_get_version(int fd)
117
{
118
    struct stat stb;
119
    mdu_version_t vers;
120
121
    if (fstat(fd, &stb)<0)
122
	return -1;
123
    if ((S_IFMT&stb.st_mode) != S_IFBLK)
124
	return -1;
125
126
    if (ioctl(fd, RAID_VERSION, &vers) == 0)
127
	return  (vers.major*10000) + (vers.minor*100) + vers.patchlevel;
128
    if (errno == EACCES)
129
	    return -1;
130
    if (major(stb.st_rdev) == MD_MAJOR)
131
	return (3600);
132
    return -1;
133
}
134
135
    
136
int get_linux_version()
137
{
138
	struct utsname name;
139
	char *cp;
140
	int a,b,c;
141
	if (uname(&name) <0)
142
		return -1;
143
144
	cp = name.release;
145
	a = strtoul(cp, &cp, 10);
146
	if (*cp != '.') return -1;
147
	b = strtoul(cp+1, &cp, 10);
148
	if (*cp != '.') return -1;
149
	c = strtoul(cp+1, NULL, 10);
150
151
	return (a*1000000)+(b*1000)+c;
152
}
153
154
void remove_partitions(int fd)
155
{
156
	/* remove partitions from this block devices.
157
	 * This is used for components added to an array
158
	 */
159
#ifdef BLKPG_DEL_PARTITION
160
	struct blkpg_ioctl_arg a;
161
	struct blkpg_partition p;
162
163
	a.op = BLKPG_DEL_PARTITION;
164
	a.data = (void*)&p;
165
	a.datalen = sizeof(p);
166
	a.flags = 0;
167
	memset(a.data, 0, a.datalen);
168
	for (p.pno=0; p.pno < 16; p.pno++)
169
		ioctl(fd, BLKPG, &a);
170
#endif
171
}
172
173
int enough(int level, int raid_disks, int layout, int clean,
174
	   char *avail, int avail_disks)
175
{
176
	int copies, first;
177
	switch (level) {
178
	case 10:
179
		/* This is the tricky one - we need to check
180
		 * which actual disks are present.
181
		 */
182
		copies = (layout&255)* ((layout>>8) & 255);
183
		first=0;
184
		do {
185
			/* there must be one of the 'copies' form 'first' */
186
			int n = copies;
187
			int cnt=0;
188
			while (n--) {
189
				if (avail[first])
190
					cnt++;
191
				first = (first+1) % raid_disks;
192
			}
193
			if (cnt == 0)
194
				return 0;
195
196
		} while (first != 0);
197
		return 1;
198
199
	case -4:
200
		return avail_disks>= 1;
201
	case -1:
202
	case 0:
203
		return avail_disks == raid_disks;
204
	case 1:
205
		return avail_disks >= 1;
206
	case 4:
207
	case 5:
208
		if (clean)
209
			return avail_disks >= raid_disks-1;
210
		else
211
			return avail_disks >= raid_disks;
212
	case 6:
213
		if (clean)
214
			return avail_disks >= raid_disks-2;
215
		else
216
			return avail_disks >= raid_disks;
217
	default:
218
		return 0;
219
	}
220
}
221
222
int same_uuid(int a[4], int b[4], int swapuuid)
223
{
224
	if (swapuuid) {
225
		/* parse uuids are hostendian.
226
		 * uuid's from some superblocks are big-ending
227
		 * if there is a difference, we need to swap.. 
228
		 */
229
		unsigned char *ac = (unsigned char *)a;
230
		unsigned char *bc = (unsigned char *)b;
231
		int i;
232
		for (i=0; i<16; i+= 4) {
233
			if (ac[i+0] != bc[i+3] ||
234
			    ac[i+1] != bc[i+2] ||
235
			    ac[i+2] != bc[i+1] ||
236
			    ac[i+3] != bc[i+0])
237
				return 0;
238
		}
239
		return 1;
240
	} else {
241
		if (a[0]==b[0] &&
242
		    a[1]==b[1] &&
243
		    a[2]==b[2] &&
244
		    a[3]==b[3])
245
			return 1;
246
		return 0;
247
	}
248
}
249
void copy_uuid(void *a, int b[4], int swapuuid)
250
{
251
	if (swapuuid) {
252
		/* parse uuids are hostendian.
253
		 * uuid's from some superblocks are big-ending
254
		 * if there is a difference, we need to swap..
255
		 */
256
		unsigned char *ac = (unsigned char *)a;
257
		unsigned char *bc = (unsigned char *)b;
258
		int i;
259
		for (i=0; i<16; i+= 4) {
260
			ac[i+0] = bc[i+3];
261
			ac[i+1] = bc[i+2];
262
			ac[i+2] = bc[i+1];
263
			ac[i+3] = bc[i+0];
264
		}
265
	} else
266
		memcpy(a, b, 16);
267
}
268
269
char *map_num(mapping_t *map, int num)
270
{
271
	while (map->name) {
272
		if (map->num == num)
273
			return map->name;
274
		map++;
275
	}
276
	return NULL;
277
}
278
279
int map_name(mapping_t *map, char *name)
280
{
281
	while (map->name) {
282
		if (strcmp(map->name, name)==0)
283
			return map->num;
284
		map++;
285
	}
286
	return UnSet;
287
}
288
289
290
int is_standard(char *dev, int *nump)
291
{
292
	/* tests if dev is a "standard" md dev name.
293
	 * i.e if the last component is "/dNN" or "/mdNN",
294
	 * where NN is a string of digits 
295
	 */
296
	char *d = strrchr(dev, '/');
297
	int type=0;
298
	int num;
299
	if (!d)
300
		return 0;
301
	if (strncmp(d, "/d",2)==0)
302
		d += 2, type=1; /* /dev/md/dN{pM} */
303
	else if (strncmp(d, "/md_d", 5)==0)
304
		d += 5, type=1; /* /dev/md_dNpM */
305
	else if (strncmp(d, "/md", 3)==0)
306
		d += 3, type=-1; /* /dev/mdN */
307
	else if (d-dev > 3 && strncmp(d-2, "md/", 3)==0)
308
		d += 1, type=-1; /* /dev/md/N */
309
	else
310
		return 0;
311
	if (!*d)
312
		return 0;
313
	num = atoi(d);
314
	while (isdigit(*d))
315
		d++;
316
	if (*d)
317
		return 0;
318
	if (nump) *nump = num;
319
320
	return type;
321
}
322
323
324
/*
325
 * convert a major/minor pair for a block device into a name in /dev, if possible.
326
 * On the first call, walk /dev collecting name.
327
 * Put them in a simple linked listfor now.
328
 */
329
struct devmap {
330
    int major, minor;
331
    char *name;
332
    struct devmap *next;
333
} *devlist = NULL;
334
int devlist_ready = 0;
335
336
int add_dev(const char *name, const struct stat *stb, int flag, struct FTW *s)
337
{
338
	struct stat st;
339
	if (S_ISLNK(stb->st_mode)) {
340
		stat(name, &st);
341
		stb = &st;
342
	}
343
344
	if ((stb->st_mode&S_IFMT)== S_IFBLK) {
345
		char *n = strdup(name);
346
		struct devmap *dm = malloc(sizeof(*dm));
347
		if (strncmp(n, "/dev/./", 7)==0)
348
			strcpy(n+4, name+6);
349
		if (dm) {
350
			dm->major = major(stb->st_rdev);
351
			dm->minor = minor(stb->st_rdev);
352
			dm->name = n;
353
			dm->next = devlist;
354
			devlist = dm;
355
		}
356
	}
357
	return 0;
358
}
359
360
#ifndef HAVE_NFTW
361
#ifdef HAVE_FTW
362
int add_dev_1(const char *name, const struct stat *stb, int flag)
363
{
364
	return add_dev(name, stb, flag, NULL);
365
}
366
int nftw(const char *path, int (*han)(const char *name, const struct stat *stb, int flag, struct FTW *s), int nopenfd, int flags)
367
{
368
	return ftw(path, add_dev_1, nopenfd);
369
}
370
#else
371
int nftw(const char *path, int (*han)(const char *name, const struct stat *stb, int flag, struct FTW *s), int nopenfd, int flags)
372
{
373
	return 0;
374
}
375
#endif /* HAVE_FTW */
376
#endif /* HAVE_NFTW */
377
378
/*
379
 * Find a block device with the right major/minor number.
380
 * If we find multiple names, choose the shortest.
381
 * If we find a non-standard name, it is probably there
382
 * deliberately so prefer it over a standard name.
383
 * This applies only to names for MD devices.
384
 */
385
char *map_dev(int major, int minor, int create)
386
{
387
	struct devmap *p;
388
	char *std = NULL, *nonstd=NULL;
389
	int did_check = 0;
390
391
	if (major == 0 && minor == 0)
392
			return NULL;
393
394
 retry:
395
	if (!devlist_ready) {
396
		char *dev = "/dev";
397
		struct stat stb;
398
		while(devlist) {
399
			struct devmap *d = devlist;
400
			devlist = d->next;
401
			free(d->name);
402
			free(d);
403
		}
404
		if (lstat(dev, &stb)==0 &&
405
		    S_ISLNK(stb.st_mode))
406
			dev = "/dev/.";
407
		nftw(dev, add_dev, 10, FTW_PHYS);
408
		devlist_ready=1;
409
		did_check = 1;
410
	}
411
412
	for (p=devlist; p; p=p->next)
413
		if (p->major == major &&
414
		    p->minor == minor) {
415
			if (is_standard(p->name, NULL)) {
416
				if (std == NULL ||
417
				    strlen(p->name) < strlen(std))
418
					std = p->name;
419
			} else {
420
				if (nonstd == NULL ||
421
				    strlen(p->name) < strlen(nonstd))
422
					nonstd = p->name;
423
			}
424
		}
425
	if (!std && !nonstd && !did_check) {
426
		devlist_ready = 0;
427
		goto retry;
428
	}
429
	if (create && !std && !nonstd) {
430
		static char buf[30];
431
		snprintf(buf, sizeof(buf), "%d:%d", major, minor);
432
		nonstd = buf;
433
	}
434
435
	return nonstd ? nonstd : std;
436
}
437
438
unsigned long calc_csum(void *super, int bytes)
439
{
440
	unsigned long long newcsum = 0;
441
	int i;
442
	unsigned int csum;
443
	unsigned int *superc = (unsigned int*) super;
444
445
	for(i=0; i<bytes/4; i++)
446
		newcsum+= superc[i];
447
	csum = (newcsum& 0xffffffff) + (newcsum>>32);
448
#ifdef __alpha__
449
/* The in-kernel checksum calculation is always 16bit on 
450
 * the alpha, though it is 32 bit on i386...
451
 * I wonder what it is elsewhere... (it uses and API in
452
 * a way that it shouldn't).
453
 */
454
	csum = (csum & 0xffff) + (csum >> 16);
455
	csum = (csum & 0xffff) + (csum >> 16);
456
#endif
457
	return csum;
458
}
459
460
char *human_size(long long bytes)
461
{
462
	static char buf[30];
463
464
	/* We convert bytes to either centi-M{ega,ibi}bytes or
465
	 * centi-G{igi,ibi}bytes, with appropriate rounding,
466
	 * and then print 1/100th of those as a decimal.
467
	 * We allow upto 2048Megabytes before converting to
468
	 * gigabytes, as that shows more precision and isn't
469
	 * too large a number.
470
	 * Terrabytes are not yet handled.
471
	 */
472
473
	if (bytes < 5000*1024)
474
		buf[0]=0;
475
	else if (bytes < 2*1024LL*1024LL*1024LL) {
476
		long cMiB = (bytes / ( (1LL<<20) / 200LL ) +1) /2;
477
		long cMB  = (bytes / ( 1000000LL / 200LL ) +1) /2;
478
		snprintf(buf, sizeof(buf), " (%ld.%02ld MiB %ld.%02ld MB)",
479
			cMiB/100 , cMiB % 100,
480
			cMB/100, cMB % 100);
481
	} else {
482
		long cGiB = (bytes / ( (1LL<<30) / 200LL ) +1) /2;
483
		long cGB  = (bytes / (1000000000LL/200LL ) +1) /2;
484
		snprintf(buf, sizeof(buf), " (%ld.%02ld GiB %ld.%02ld GB)",
485
			cGiB/100 , cGiB % 100,
486
			cGB/100, cGB % 100);
487
	}
488
	return buf;
489
}
490
491
char *human_size_brief(long long bytes)
492
{
493
	static char buf[30];
494
	
495
496
	if (bytes < 5000*1024)
497
		snprintf(buf, sizeof(buf), "%ld.%02ldKiB",
498
			(long)(bytes>>10), (long)(((bytes&1023)*100+512)/1024)
499
			);
500
	else if (bytes < 2*1024LL*1024LL*1024LL)
501
		snprintf(buf, sizeof(buf), "%ld.%02ldMiB",
502
			(long)(bytes>>20),
503
			(long)((bytes&0xfffff)+0x100000/200)/(0x100000/100)
504
			);
505
	else
506
		snprintf(buf, sizeof(buf), "%ld.%02ldGiB",
507
			(long)(bytes>>30),
508
			(long)(((bytes>>10)&0xfffff)+0x100000/200)/(0x100000/100)
509
			);
510
	return buf;
511
}
512
513
int get_mdp_major(void)
514
{
515
static int mdp_major = -1;
516
	FILE *fl;
517
	char *w;
518
	int have_block = 0;
519
	int have_devices = 0;
520
	int last_num = -1;
521
522
	if (mdp_major != -1)
523
		return mdp_major;
524
	fl = fopen("/proc/devices", "r");
525
	if (!fl)
526
		return -1;
527
	while ((w = conf_word(fl, 1))) {
528
		if (have_block && strcmp(w, "devices:")==0)
529
			have_devices = 1;
530
		have_block =  (strcmp(w, "Block")==0);
531
		if (isdigit(w[0]))
532
			last_num = atoi(w);
533
		if (have_devices && strcmp(w, "mdp")==0)
534
			mdp_major = last_num;
535
		free(w);
536
	}
537
	fclose(fl);
538
	return mdp_major;
539
}
540
541
int dev_open(char *dev, int flags)
542
{
543
	/* like 'open', but if 'dev' matches %d:%d, create a temp
544
	 * block device and open that
545
	 */
546
	char *e;
547
	int fd = -1;
548
	char devname[32];
549
	int major;
550
	int minor;
551
552
	if (!dev) return -1;
553
554
	major = strtoul(dev, &e, 0);
555
	if (e > dev && *e == ':' && e[1] &&
556
	    (minor = strtoul(e+1, &e, 0)) >= 0 &&
557
	    *e == 0) {
558
		snprintf(devname, sizeof(devname), "/dev/.tmp.md.%d:%d", major, minor);
559
		if (mknod(devname, S_IFBLK|0600, makedev(major, minor))==0) {
560
			fd = open(devname, flags);
561
			unlink(devname);
562
		}
563
	} else
564
		fd = open(dev, flags);
565
	return fd;
566
}
567
568
struct superswitch *superlist[] = { &super0, &super1, NULL };
569
570
struct supertype *super_by_version(int vers, int minor)
571
{
572
	struct supertype *st = malloc(sizeof(*st));
573
	if (!st) return st;
574
	if (vers == 0) {
575
		st->ss = &super0;
576
		st->max_devs = MD_SB_DISKS;
577
	}
578
579
	if (vers == 1) {
580
		st->ss = &super1;
581
		st->max_devs = 384;
582
	}
583
	st->minor_version = minor;
584
	return st;
585
}
586
587
struct supertype *guess_super(int fd)
588
{
589
	/* try each load_super to find the best match,
590
	 * and return the best superswitch
591
	 */
592
	struct superswitch  *ss;
593
	struct supertype *st;
594
	unsigned long besttime = 0;
595
	int bestsuper = -1;
596
	
597
	void *sbp = NULL;
598
	int i;
599
600
	st = malloc(sizeof(*st));
601
	memset(st, 0, sizeof(*st));
602
	for (i=0 ; superlist[i]; i++) {
603
		int rv;
604
		ss = superlist[i];
605
		st->ss = NULL;
606
		rv = ss->load_super(st, fd, &sbp, NULL);
607
		if (rv == 0) {
608
			struct mdinfo info;
609
			ss->getinfo_super(&info, sbp);
610
			if (bestsuper == -1 ||
611
			    besttime < info.array.ctime) {
612
				bestsuper = i;
613
				besttime = info.array.ctime;
614
			}
615
			free(sbp);
616
		}
617
	}
618
	if (bestsuper != -1) {
619
		int rv;
620
		st->ss = NULL;
621
		rv = superlist[bestsuper]->load_super(st, fd, &sbp, NULL);
622
		if (rv == 0) {
623
			free(sbp);
624
			return st;
625
		}
626
	}
627
	free(st);
628
	return NULL;
629
}
630
631
/* Return size of device in bytes */
632
int get_dev_size(int fd, char *dname, unsigned long long *sizep)
633
{
634
	unsigned long long ldsize;
635
#ifdef BLKGETSIZE64
636
	if (ioctl(fd, BLKGETSIZE64, &ldsize) != 0)
637
#endif
638
	{
639
		unsigned long dsize;
640
		if (ioctl(fd, BLKGETSIZE, &dsize) == 0) {
641
			ldsize = dsize;
642
			ldsize <<= 9;
643
		} else {
644
			if (dname)
645
				fprintf(stderr, Name ": Cannot get size of %s: %s\b",
646
					dname, strerror(errno));
647
			return 0;
648
		}
649
	}
650
	*sizep = ldsize;
651
	return 1;
652
}

Return to bug 331971