1 |
199 |
simons |
/*
|
2 |
|
|
md.h : Multiple Devices driver for Linux
|
3 |
|
|
Copyright (C) 1994-96 Marc ZYNGIER
|
4 |
|
|
<zyngier@ufr-info-p7.ibp.fr> or
|
5 |
|
|
<maz@gloups.fdn.fr>
|
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, or (at your option)
|
10 |
|
|
any later version.
|
11 |
|
|
|
12 |
|
|
You should have received a copy of the GNU General Public License
|
13 |
|
|
(for example /usr/src/linux/COPYING); if not, write to the Free
|
14 |
|
|
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
15 |
|
|
*/
|
16 |
|
|
|
17 |
|
|
#ifndef _MD_H
|
18 |
|
|
#define _MD_H
|
19 |
|
|
|
20 |
|
|
#include <asm/segment.h>
|
21 |
|
|
#include <linux/major.h>
|
22 |
|
|
#include <linux/ioctl.h>
|
23 |
|
|
#include <linux/types.h>
|
24 |
|
|
|
25 |
|
|
/*
|
26 |
|
|
* Different major versions are not compatible.
|
27 |
|
|
* Different minor versions are only downward compatible.
|
28 |
|
|
* Different patchlevel versions are downward and upward compatible.
|
29 |
|
|
*/
|
30 |
|
|
#define MD_MAJOR_VERSION 0
|
31 |
|
|
#define MD_MINOR_VERSION 36
|
32 |
|
|
#define MD_PATCHLEVEL_VERSION 3
|
33 |
|
|
|
34 |
|
|
/* ioctls */
|
35 |
|
|
#define REGISTER_DEV _IO (MD_MAJOR, 1)
|
36 |
|
|
#define START_MD _IO (MD_MAJOR, 2)
|
37 |
|
|
#define STOP_MD _IO (MD_MAJOR, 3)
|
38 |
|
|
|
39 |
|
|
/*
|
40 |
|
|
personalities :
|
41 |
|
|
Byte 0 : Chunk size factor
|
42 |
|
|
Byte 1 : Fault tolerance count for each physical device
|
43 |
|
|
( 0 means no fault tolerance,
|
44 |
|
|
0xFF means always tolerate faults), not used by now.
|
45 |
|
|
Byte 2 : Personality
|
46 |
|
|
Byte 3 : Reserved.
|
47 |
|
|
*/
|
48 |
|
|
|
49 |
|
|
#define FAULT_SHIFT 8
|
50 |
|
|
#define PERSONALITY_SHIFT 16
|
51 |
|
|
|
52 |
|
|
#define FACTOR_MASK 0x000000FFUL
|
53 |
|
|
#define FAULT_MASK 0x0000FF00UL
|
54 |
|
|
#define PERSONALITY_MASK 0x00FF0000UL
|
55 |
|
|
|
56 |
|
|
#define MD_RESERVED 0 /* Not used by now */
|
57 |
|
|
#define LINEAR (1UL << PERSONALITY_SHIFT)
|
58 |
|
|
#define STRIPED (2UL << PERSONALITY_SHIFT)
|
59 |
|
|
#define RAID0 STRIPED
|
60 |
|
|
#define RAID1 (3UL << PERSONALITY_SHIFT)
|
61 |
|
|
#define RAID5 (4UL << PERSONALITY_SHIFT)
|
62 |
|
|
#define MAX_PERSONALITY 5
|
63 |
|
|
|
64 |
|
|
/*
|
65 |
|
|
* MD superblock.
|
66 |
|
|
*
|
67 |
|
|
* The MD superblock maintains some statistics on each MD configuration.
|
68 |
|
|
* Each real device in the MD set contains it near the end of the device.
|
69 |
|
|
* Some of the ideas are copied from the ext2fs implementation.
|
70 |
|
|
*
|
71 |
|
|
* We currently use 4096 bytes as follows:
|
72 |
|
|
*
|
73 |
|
|
* word offset function
|
74 |
|
|
*
|
75 |
|
|
* 0 - 31 Constant generic MD device information.
|
76 |
|
|
* 32 - 63 Generic state information.
|
77 |
|
|
* 64 - 127 Personality specific information.
|
78 |
|
|
* 128 - 511 12 32-words descriptors of the disks in the raid set.
|
79 |
|
|
* 512 - 911 Reserved.
|
80 |
|
|
* 912 - 1023 Disk specific descriptor.
|
81 |
|
|
*/
|
82 |
|
|
|
83 |
|
|
/*
|
84 |
|
|
* If x is the real device size in bytes, we return an apparent size of:
|
85 |
|
|
*
|
86 |
|
|
* y = (x & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES
|
87 |
|
|
*
|
88 |
|
|
* and place the 4kB superblock at offset y.
|
89 |
|
|
*/
|
90 |
|
|
#define MD_RESERVED_BYTES (64 * 1024)
|
91 |
|
|
#define MD_RESERVED_SECTORS (MD_RESERVED_BYTES / 512)
|
92 |
|
|
#define MD_RESERVED_BLOCKS (MD_RESERVED_BYTES / BLOCK_SIZE)
|
93 |
|
|
|
94 |
|
|
#define MD_NEW_SIZE_SECTORS(x) ((x & ~(MD_RESERVED_SECTORS - 1)) - MD_RESERVED_SECTORS)
|
95 |
|
|
#define MD_NEW_SIZE_BLOCKS(x) ((x & ~(MD_RESERVED_BLOCKS - 1)) - MD_RESERVED_BLOCKS)
|
96 |
|
|
|
97 |
|
|
#define MD_SB_BYTES 4096
|
98 |
|
|
#define MD_SB_WORDS (MD_SB_BYTES / 4)
|
99 |
|
|
#define MD_SB_BLOCKS (MD_SB_BYTES / BLOCK_SIZE)
|
100 |
|
|
#define MD_SB_SECTORS (MD_SB_BYTES / 512)
|
101 |
|
|
|
102 |
|
|
/*
|
103 |
|
|
* The following are counted in 32-bit words
|
104 |
|
|
*/
|
105 |
|
|
#define MD_SB_GENERIC_OFFSET 0
|
106 |
|
|
#define MD_SB_PERSONALITY_OFFSET 64
|
107 |
|
|
#define MD_SB_DISKS_OFFSET 128
|
108 |
|
|
#define MD_SB_DESCRIPTOR_OFFSET 992
|
109 |
|
|
|
110 |
|
|
#define MD_SB_GENERIC_CONSTANT_WORDS 32
|
111 |
|
|
#define MD_SB_GENERIC_STATE_WORDS 32
|
112 |
|
|
#define MD_SB_GENERIC_WORDS (MD_SB_GENERIC_CONSTANT_WORDS + MD_SB_GENERIC_STATE_WORDS)
|
113 |
|
|
#define MD_SB_PERSONALITY_WORDS 64
|
114 |
|
|
#define MD_SB_DISKS_WORDS 384
|
115 |
|
|
#define MD_SB_DESCRIPTOR_WORDS 32
|
116 |
|
|
#define MD_SB_RESERVED_WORDS (1024 - MD_SB_GENERIC_WORDS - MD_SB_PERSONALITY_WORDS - MD_SB_DISKS_WORDS - MD_SB_DESCRIPTOR_WORDS)
|
117 |
|
|
#define MD_SB_EQUAL_WORDS (MD_SB_GENERIC_WORDS + MD_SB_PERSONALITY_WORDS + MD_SB_DISKS_WORDS)
|
118 |
|
|
#define MD_SB_DISKS (MD_SB_DISKS_WORDS / MD_SB_DESCRIPTOR_WORDS)
|
119 |
|
|
|
120 |
|
|
/*
|
121 |
|
|
* Device "operational" state bits
|
122 |
|
|
*/
|
123 |
|
|
#define MD_FAULTY_DEVICE 0 /* Device is faulty / operational */
|
124 |
|
|
#define MD_ACTIVE_DEVICE 1 /* Device is a part or the raid set / spare disk */
|
125 |
|
|
#define MD_SYNC_DEVICE 2 /* Device is in sync with the raid set */
|
126 |
|
|
|
127 |
|
|
typedef struct md_device_descriptor_s {
|
128 |
|
|
__u32 number; /* 0 Device number in the entire set */
|
129 |
|
|
__u32 major; /* 1 Device major number */
|
130 |
|
|
__u32 minor; /* 2 Device minor number */
|
131 |
|
|
__u32 raid_disk; /* 3 The role of the device in the raid set */
|
132 |
|
|
__u32 state; /* 4 Operational state */
|
133 |
|
|
__u32 reserved[MD_SB_DESCRIPTOR_WORDS - 5];
|
134 |
|
|
} md_descriptor_t;
|
135 |
|
|
|
136 |
|
|
#define MD_SB_MAGIC 0xa92b4efc
|
137 |
|
|
|
138 |
|
|
/*
|
139 |
|
|
* Superblock state bits
|
140 |
|
|
*/
|
141 |
|
|
#define MD_SB_CLEAN 0
|
142 |
|
|
#define MD_SB_ERRORS 1
|
143 |
|
|
|
144 |
|
|
typedef struct md_superblock_s {
|
145 |
|
|
|
146 |
|
|
/*
|
147 |
|
|
* Constant generic information
|
148 |
|
|
*/
|
149 |
|
|
__u32 md_magic; /* 0 MD identifier */
|
150 |
|
|
__u32 major_version; /* 1 major version to which the set conforms */
|
151 |
|
|
__u32 minor_version; /* 2 minor version to which the set conforms */
|
152 |
|
|
__u32 patch_version; /* 3 patchlevel version to which the set conforms */
|
153 |
|
|
__u32 gvalid_words; /* 4 Number of non-reserved words in this section */
|
154 |
|
|
__u32 set_magic; /* 5 Raid set identifier */
|
155 |
|
|
__u32 ctime; /* 6 Creation time */
|
156 |
|
|
__u32 level; /* 7 Raid personality (mirroring, raid5, ...) */
|
157 |
|
|
__u32 size; /* 8 Apparent size of each individual disk, in kB */
|
158 |
|
|
__u32 nr_disks; /* 9 Number of total disks in the raid set */
|
159 |
|
|
__u32 raid_disks; /* 10 Number of disks in a fully functional raid set */
|
160 |
|
|
__u32 gstate_creserved[MD_SB_GENERIC_CONSTANT_WORDS - 11];
|
161 |
|
|
|
162 |
|
|
/*
|
163 |
|
|
* Generic state information
|
164 |
|
|
*/
|
165 |
|
|
__u32 utime; /* 0 Superblock update time */
|
166 |
|
|
__u32 state; /* 1 State bits (clean, ...) */
|
167 |
|
|
__u32 active_disks; /* 2 Number of currently active disks (some non-faulty disks might not be in sync) */
|
168 |
|
|
__u32 working_disks; /* 3 Number of working disks */
|
169 |
|
|
__u32 failed_disks; /* 4 Number of failed disks */
|
170 |
|
|
__u32 spare_disks; /* 5 Number of spare disks */
|
171 |
|
|
__u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 6];
|
172 |
|
|
|
173 |
|
|
/*
|
174 |
|
|
* Personality information
|
175 |
|
|
*/
|
176 |
|
|
__u32 parity_algorithm;
|
177 |
|
|
__u32 chunk_size;
|
178 |
|
|
__u32 pstate_reserved[MD_SB_PERSONALITY_WORDS - 2];
|
179 |
|
|
|
180 |
|
|
/*
|
181 |
|
|
* Disks information
|
182 |
|
|
*/
|
183 |
|
|
md_descriptor_t disks[MD_SB_DISKS];
|
184 |
|
|
|
185 |
|
|
/*
|
186 |
|
|
* Reserved
|
187 |
|
|
*/
|
188 |
|
|
__u32 reserved[MD_SB_RESERVED_WORDS];
|
189 |
|
|
|
190 |
|
|
/*
|
191 |
|
|
* Active descriptor
|
192 |
|
|
*/
|
193 |
|
|
md_descriptor_t descriptor;
|
194 |
|
|
} md_superblock_t;
|
195 |
|
|
|
196 |
|
|
#ifdef __KERNEL__
|
197 |
|
|
|
198 |
|
|
#include <linux/mm.h>
|
199 |
|
|
#include <linux/fs.h>
|
200 |
|
|
#include <linux/blkdev.h>
|
201 |
|
|
|
202 |
|
|
#define MAX_REAL 8 /* Max number of physical dev per md dev */
|
203 |
|
|
#define MAX_MD_DEV 4 /* Max number of md dev */
|
204 |
|
|
#define MAX_MD_THREADS 2 /* Max number of kernel threads */
|
205 |
|
|
|
206 |
|
|
#define FACTOR(a) ((a)->repartition & FACTOR_MASK)
|
207 |
|
|
#define MAX_FAULT(a) (((a)->repartition & FAULT_MASK)>>8)
|
208 |
|
|
#define PERSONALITY(a) ((a)->repartition & PERSONALITY_MASK)
|
209 |
|
|
|
210 |
|
|
#define FACTOR_SHIFT(a) (PAGE_SHIFT + (a) - 10)
|
211 |
|
|
|
212 |
|
|
struct real_dev
|
213 |
|
|
{
|
214 |
|
|
kdev_t dev; /* Device number */
|
215 |
|
|
int size; /* Device size (in blocks) */
|
216 |
|
|
int offset; /* Real device offset (in blocks) in md dev
|
217 |
|
|
(only used in linear mode) */
|
218 |
|
|
struct inode *inode; /* Lock inode */
|
219 |
|
|
md_superblock_t *sb;
|
220 |
|
|
u32 sb_offset;
|
221 |
|
|
};
|
222 |
|
|
|
223 |
|
|
struct md_dev;
|
224 |
|
|
|
225 |
|
|
struct md_personality
|
226 |
|
|
{
|
227 |
|
|
char *name;
|
228 |
|
|
int (*map)(struct md_dev *md_dev, kdev_t *rdev,
|
229 |
|
|
unsigned long *rsector, unsigned long size);
|
230 |
|
|
int (*make_request)(struct md_dev *md_dev, int rw, struct buffer_head * bh);
|
231 |
|
|
void (*end_request)(struct buffer_head * bh, int uptodate);
|
232 |
|
|
int (*run)(int minor, struct md_dev *md_dev);
|
233 |
|
|
int (*stop)(int minor, struct md_dev *md_dev);
|
234 |
|
|
int (*status)(char *page, int minor, struct md_dev *md_dev);
|
235 |
|
|
int (*ioctl)(struct inode *inode, struct file *file,
|
236 |
|
|
unsigned int cmd, unsigned long arg);
|
237 |
|
|
int max_invalid_dev;
|
238 |
|
|
int (*error_handler)(struct md_dev *md_dev, kdev_t dev);
|
239 |
|
|
};
|
240 |
|
|
|
241 |
|
|
struct md_dev
|
242 |
|
|
{
|
243 |
|
|
struct real_dev devices[MAX_REAL];
|
244 |
|
|
struct md_personality *pers;
|
245 |
|
|
md_superblock_t *sb;
|
246 |
|
|
int sb_dirty;
|
247 |
|
|
int repartition;
|
248 |
|
|
int busy;
|
249 |
|
|
int nb_dev;
|
250 |
|
|
void *private;
|
251 |
|
|
};
|
252 |
|
|
|
253 |
|
|
struct md_thread {
|
254 |
|
|
void (*run) (void *data);
|
255 |
|
|
void *data;
|
256 |
|
|
struct wait_queue *wqueue;
|
257 |
|
|
__u32 flags;
|
258 |
|
|
};
|
259 |
|
|
|
260 |
|
|
#define THREAD_WAKEUP 0
|
261 |
|
|
|
262 |
|
|
extern struct md_dev md_dev[MAX_MD_DEV];
|
263 |
|
|
extern int md_size[MAX_MD_DEV];
|
264 |
|
|
|
265 |
|
|
extern char *partition_name (kdev_t dev);
|
266 |
|
|
|
267 |
|
|
extern int register_md_personality (int p_num, struct md_personality *p);
|
268 |
|
|
extern int unregister_md_personality (int p_num);
|
269 |
|
|
extern struct md_thread *md_register_thread (void (*run) (void *data), void *data);
|
270 |
|
|
extern void md_unregister_thread (struct md_thread *thread);
|
271 |
|
|
extern void md_wakeup_thread(struct md_thread *thread);
|
272 |
|
|
extern int md_update_sb (int minor);
|
273 |
|
|
|
274 |
|
|
#endif __KERNEL__
|
275 |
|
|
#endif _MD_H
|