| @@ -1,2209 +1,2226 @@ | | | @@ -1,2209 +1,2226 @@ |
1 | /* $NetBSD: rf_netbsdkintf.c,v 1.265 2009/06/10 14:17:13 pooka Exp $ */ | | 1 | /* $NetBSD: rf_netbsdkintf.c,v 1.266 2009/07/23 21:58:06 dyoung Exp $ */ |
2 | /*- | | 2 | /*- |
3 | * Copyright (c) 1996, 1997, 1998, 2008 The NetBSD Foundation, Inc. | | 3 | * Copyright (c) 1996, 1997, 1998, 2008 The NetBSD Foundation, Inc. |
4 | * All rights reserved. | | 4 | * All rights reserved. |
5 | * | | 5 | * |
6 | * This code is derived from software contributed to The NetBSD Foundation | | 6 | * This code is derived from software contributed to The NetBSD Foundation |
7 | * by Greg Oster; Jason R. Thorpe. | | 7 | * by Greg Oster; Jason R. Thorpe. |
8 | * | | 8 | * |
9 | * Redistribution and use in source and binary forms, with or without | | 9 | * Redistribution and use in source and binary forms, with or without |
10 | * modification, are permitted provided that the following conditions | | 10 | * modification, are permitted provided that the following conditions |
11 | * are met: | | 11 | * are met: |
12 | * 1. Redistributions of source code must retain the above copyright | | 12 | * 1. Redistributions of source code must retain the above copyright |
13 | * notice, this list of conditions and the following disclaimer. | | 13 | * notice, this list of conditions and the following disclaimer. |
14 | * 2. Redistributions in binary form must reproduce the above copyright | | 14 | * 2. Redistributions in binary form must reproduce the above copyright |
15 | * notice, this list of conditions and the following disclaimer in the | | 15 | * notice, this list of conditions and the following disclaimer in the |
16 | * documentation and/or other materials provided with the distribution. | | 16 | * documentation and/or other materials provided with the distribution. |
17 | * | | 17 | * |
18 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 18 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
19 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 19 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
20 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 20 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
21 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 21 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
22 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 22 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
28 | * POSSIBILITY OF SUCH DAMAGE. | | 28 | * POSSIBILITY OF SUCH DAMAGE. |
29 | */ | | 29 | */ |
30 | | | 30 | |
31 | /* | | 31 | /* |
32 | * Copyright (c) 1990, 1993 | | 32 | * Copyright (c) 1990, 1993 |
33 | * The Regents of the University of California. All rights reserved. | | 33 | * The Regents of the University of California. All rights reserved. |
34 | * | | 34 | * |
35 | * This code is derived from software contributed to Berkeley by | | 35 | * This code is derived from software contributed to Berkeley by |
36 | * the Systems Programming Group of the University of Utah Computer | | 36 | * the Systems Programming Group of the University of Utah Computer |
37 | * Science Department. | | 37 | * Science Department. |
38 | * | | 38 | * |
39 | * Redistribution and use in source and binary forms, with or without | | 39 | * Redistribution and use in source and binary forms, with or without |
40 | * modification, are permitted provided that the following conditions | | 40 | * modification, are permitted provided that the following conditions |
41 | * are met: | | 41 | * are met: |
42 | * 1. Redistributions of source code must retain the above copyright | | 42 | * 1. Redistributions of source code must retain the above copyright |
43 | * notice, this list of conditions and the following disclaimer. | | 43 | * notice, this list of conditions and the following disclaimer. |
44 | * 2. Redistributions in binary form must reproduce the above copyright | | 44 | * 2. Redistributions in binary form must reproduce the above copyright |
45 | * notice, this list of conditions and the following disclaimer in the | | 45 | * notice, this list of conditions and the following disclaimer in the |
46 | * documentation and/or other materials provided with the distribution. | | 46 | * documentation and/or other materials provided with the distribution. |
47 | * 3. Neither the name of the University nor the names of its contributors | | 47 | * 3. Neither the name of the University nor the names of its contributors |
48 | * may be used to endorse or promote products derived from this software | | 48 | * may be used to endorse or promote products derived from this software |
49 | * without specific prior written permission. | | 49 | * without specific prior written permission. |
50 | * | | 50 | * |
51 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 51 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
52 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 52 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
53 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 53 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
54 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 54 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
55 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 55 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
56 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 56 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
57 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 57 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
58 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 58 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
59 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 59 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
60 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 60 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
61 | * SUCH DAMAGE. | | 61 | * SUCH DAMAGE. |
62 | * | | 62 | * |
63 | * from: Utah $Hdr: cd.c 1.6 90/11/28$ | | 63 | * from: Utah $Hdr: cd.c 1.6 90/11/28$ |
64 | * | | 64 | * |
65 | * @(#)cd.c 8.2 (Berkeley) 11/16/93 | | 65 | * @(#)cd.c 8.2 (Berkeley) 11/16/93 |
66 | */ | | 66 | */ |
67 | | | 67 | |
68 | /* | | 68 | /* |
69 | * Copyright (c) 1988 University of Utah. | | 69 | * Copyright (c) 1988 University of Utah. |
70 | * | | 70 | * |
71 | * This code is derived from software contributed to Berkeley by | | 71 | * This code is derived from software contributed to Berkeley by |
72 | * the Systems Programming Group of the University of Utah Computer | | 72 | * the Systems Programming Group of the University of Utah Computer |
73 | * Science Department. | | 73 | * Science Department. |
74 | * | | 74 | * |
75 | * Redistribution and use in source and binary forms, with or without | | 75 | * Redistribution and use in source and binary forms, with or without |
76 | * modification, are permitted provided that the following conditions | | 76 | * modification, are permitted provided that the following conditions |
77 | * are met: | | 77 | * are met: |
78 | * 1. Redistributions of source code must retain the above copyright | | 78 | * 1. Redistributions of source code must retain the above copyright |
79 | * notice, this list of conditions and the following disclaimer. | | 79 | * notice, this list of conditions and the following disclaimer. |
80 | * 2. Redistributions in binary form must reproduce the above copyright | | 80 | * 2. Redistributions in binary form must reproduce the above copyright |
81 | * notice, this list of conditions and the following disclaimer in the | | 81 | * notice, this list of conditions and the following disclaimer in the |
82 | * documentation and/or other materials provided with the distribution. | | 82 | * documentation and/or other materials provided with the distribution. |
83 | * 3. All advertising materials mentioning features or use of this software | | 83 | * 3. All advertising materials mentioning features or use of this software |
84 | * must display the following acknowledgement: | | 84 | * must display the following acknowledgement: |
85 | * This product includes software developed by the University of | | 85 | * This product includes software developed by the University of |
86 | * California, Berkeley and its contributors. | | 86 | * California, Berkeley and its contributors. |
87 | * 4. Neither the name of the University nor the names of its contributors | | 87 | * 4. Neither the name of the University nor the names of its contributors |
88 | * may be used to endorse or promote products derived from this software | | 88 | * may be used to endorse or promote products derived from this software |
89 | * without specific prior written permission. | | 89 | * without specific prior written permission. |
90 | * | | 90 | * |
91 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 91 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
92 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 92 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
93 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 93 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
94 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 94 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
95 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 95 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
96 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 96 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
97 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 97 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
98 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 98 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
99 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 99 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
100 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 100 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
101 | * SUCH DAMAGE. | | 101 | * SUCH DAMAGE. |
102 | * | | 102 | * |
103 | * from: Utah $Hdr: cd.c 1.6 90/11/28$ | | 103 | * from: Utah $Hdr: cd.c 1.6 90/11/28$ |
104 | * | | 104 | * |
105 | * @(#)cd.c 8.2 (Berkeley) 11/16/93 | | 105 | * @(#)cd.c 8.2 (Berkeley) 11/16/93 |
106 | */ | | 106 | */ |
107 | | | 107 | |
108 | /* | | 108 | /* |
109 | * Copyright (c) 1995 Carnegie-Mellon University. | | 109 | * Copyright (c) 1995 Carnegie-Mellon University. |
110 | * All rights reserved. | | 110 | * All rights reserved. |
111 | * | | 111 | * |
112 | * Authors: Mark Holland, Jim Zelenka | | 112 | * Authors: Mark Holland, Jim Zelenka |
113 | * | | 113 | * |
114 | * Permission to use, copy, modify and distribute this software and | | 114 | * Permission to use, copy, modify and distribute this software and |
115 | * its documentation is hereby granted, provided that both the copyright | | 115 | * its documentation is hereby granted, provided that both the copyright |
116 | * notice and this permission notice appear in all copies of the | | 116 | * notice and this permission notice appear in all copies of the |
117 | * software, derivative works or modified versions, and any portions | | 117 | * software, derivative works or modified versions, and any portions |
118 | * thereof, and that both notices appear in supporting documentation. | | 118 | * thereof, and that both notices appear in supporting documentation. |
119 | * | | 119 | * |
120 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" | | 120 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" |
121 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND | | 121 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND |
122 | * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. | | 122 | * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. |
123 | * | | 123 | * |
124 | * Carnegie Mellon requests users of this software to return to | | 124 | * Carnegie Mellon requests users of this software to return to |
125 | * | | 125 | * |
126 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU | | 126 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU |
127 | * School of Computer Science | | 127 | * School of Computer Science |
128 | * Carnegie Mellon University | | 128 | * Carnegie Mellon University |
129 | * Pittsburgh PA 15213-3890 | | 129 | * Pittsburgh PA 15213-3890 |
130 | * | | 130 | * |
131 | * any improvements or extensions that they make and grant Carnegie the | | 131 | * any improvements or extensions that they make and grant Carnegie the |
132 | * rights to redistribute these changes. | | 132 | * rights to redistribute these changes. |
133 | */ | | 133 | */ |
134 | | | 134 | |
135 | /*********************************************************** | | 135 | /*********************************************************** |
136 | * | | 136 | * |
137 | * rf_kintf.c -- the kernel interface routines for RAIDframe | | 137 | * rf_kintf.c -- the kernel interface routines for RAIDframe |
138 | * | | 138 | * |
139 | ***********************************************************/ | | 139 | ***********************************************************/ |
140 | | | 140 | |
141 | #include <sys/cdefs.h> | | 141 | #include <sys/cdefs.h> |
142 | __KERNEL_RCSID(0, "$NetBSD: rf_netbsdkintf.c,v 1.265 2009/06/10 14:17:13 pooka Exp $"); | | 142 | __KERNEL_RCSID(0, "$NetBSD: rf_netbsdkintf.c,v 1.266 2009/07/23 21:58:06 dyoung Exp $"); |
143 | | | 143 | |
144 | #ifdef _KERNEL_OPT | | 144 | #ifdef _KERNEL_OPT |
145 | #include "opt_compat_netbsd.h" | | 145 | #include "opt_compat_netbsd.h" |
146 | #include "opt_raid_autoconfig.h" | | 146 | #include "opt_raid_autoconfig.h" |
147 | #include "raid.h" | | 147 | #include "raid.h" |
148 | #endif | | 148 | #endif |
149 | | | 149 | |
150 | #include <sys/param.h> | | 150 | #include <sys/param.h> |
151 | #include <sys/errno.h> | | 151 | #include <sys/errno.h> |
152 | #include <sys/pool.h> | | 152 | #include <sys/pool.h> |
153 | #include <sys/proc.h> | | 153 | #include <sys/proc.h> |
154 | #include <sys/queue.h> | | 154 | #include <sys/queue.h> |
155 | #include <sys/disk.h> | | 155 | #include <sys/disk.h> |
156 | #include <sys/device.h> | | 156 | #include <sys/device.h> |
157 | #include <sys/stat.h> | | 157 | #include <sys/stat.h> |
158 | #include <sys/ioctl.h> | | 158 | #include <sys/ioctl.h> |
159 | #include <sys/fcntl.h> | | 159 | #include <sys/fcntl.h> |
160 | #include <sys/systm.h> | | 160 | #include <sys/systm.h> |
161 | #include <sys/vnode.h> | | 161 | #include <sys/vnode.h> |
162 | #include <sys/disklabel.h> | | 162 | #include <sys/disklabel.h> |
163 | #include <sys/conf.h> | | 163 | #include <sys/conf.h> |
164 | #include <sys/buf.h> | | 164 | #include <sys/buf.h> |
165 | #include <sys/bufq.h> | | 165 | #include <sys/bufq.h> |
166 | #include <sys/user.h> | | 166 | #include <sys/user.h> |
167 | #include <sys/reboot.h> | | 167 | #include <sys/reboot.h> |
168 | #include <sys/kauth.h> | | 168 | #include <sys/kauth.h> |
169 | | | 169 | |
170 | #include <prop/proplib.h> | | 170 | #include <prop/proplib.h> |
171 | | | 171 | |
172 | #include <dev/raidframe/raidframevar.h> | | 172 | #include <dev/raidframe/raidframevar.h> |
173 | #include <dev/raidframe/raidframeio.h> | | 173 | #include <dev/raidframe/raidframeio.h> |
174 | | | 174 | |
175 | #include "rf_raid.h" | | 175 | #include "rf_raid.h" |
176 | #include "rf_copyback.h" | | 176 | #include "rf_copyback.h" |
177 | #include "rf_dag.h" | | 177 | #include "rf_dag.h" |
178 | #include "rf_dagflags.h" | | 178 | #include "rf_dagflags.h" |
179 | #include "rf_desc.h" | | 179 | #include "rf_desc.h" |
180 | #include "rf_diskqueue.h" | | 180 | #include "rf_diskqueue.h" |
181 | #include "rf_etimer.h" | | 181 | #include "rf_etimer.h" |
182 | #include "rf_general.h" | | 182 | #include "rf_general.h" |
183 | #include "rf_kintf.h" | | 183 | #include "rf_kintf.h" |
184 | #include "rf_options.h" | | 184 | #include "rf_options.h" |
185 | #include "rf_driver.h" | | 185 | #include "rf_driver.h" |
186 | #include "rf_parityscan.h" | | 186 | #include "rf_parityscan.h" |
187 | #include "rf_threadstuff.h" | | 187 | #include "rf_threadstuff.h" |
188 | | | 188 | |
189 | #ifdef COMPAT_50 | | 189 | #ifdef COMPAT_50 |
190 | #include "rf_compat50.h" | | 190 | #include "rf_compat50.h" |
191 | #endif | | 191 | #endif |
192 | | | 192 | |
193 | #ifdef DEBUG | | 193 | #ifdef DEBUG |
194 | int rf_kdebug_level = 0; | | 194 | int rf_kdebug_level = 0; |
195 | #define db1_printf(a) if (rf_kdebug_level > 0) printf a | | 195 | #define db1_printf(a) if (rf_kdebug_level > 0) printf a |
196 | #else /* DEBUG */ | | 196 | #else /* DEBUG */ |
197 | #define db1_printf(a) { } | | 197 | #define db1_printf(a) { } |
198 | #endif /* DEBUG */ | | 198 | #endif /* DEBUG */ |
199 | | | 199 | |
200 | static RF_Raid_t **raidPtrs; /* global raid device descriptors */ | | 200 | static RF_Raid_t **raidPtrs; /* global raid device descriptors */ |
201 | | | 201 | |
202 | #if (RF_INCLUDE_PARITY_DECLUSTERING_DS > 0) | | 202 | #if (RF_INCLUDE_PARITY_DECLUSTERING_DS > 0) |
203 | RF_DECLARE_STATIC_MUTEX(rf_sparet_wait_mutex) | | 203 | RF_DECLARE_STATIC_MUTEX(rf_sparet_wait_mutex) |
204 | | | 204 | |
205 | static RF_SparetWait_t *rf_sparet_wait_queue; /* requests to install a | | 205 | static RF_SparetWait_t *rf_sparet_wait_queue; /* requests to install a |
206 | * spare table */ | | 206 | * spare table */ |
207 | static RF_SparetWait_t *rf_sparet_resp_queue; /* responses from | | 207 | static RF_SparetWait_t *rf_sparet_resp_queue; /* responses from |
208 | * installation process */ | | 208 | * installation process */ |
209 | #endif | | 209 | #endif |
210 | | | 210 | |
211 | MALLOC_DEFINE(M_RAIDFRAME, "RAIDframe", "RAIDframe structures"); | | 211 | MALLOC_DEFINE(M_RAIDFRAME, "RAIDframe", "RAIDframe structures"); |
212 | | | 212 | |
213 | /* prototypes */ | | 213 | /* prototypes */ |
214 | static void KernelWakeupFunc(struct buf *); | | 214 | static void KernelWakeupFunc(struct buf *); |
215 | static void InitBP(struct buf *, struct vnode *, unsigned, | | 215 | static void InitBP(struct buf *, struct vnode *, unsigned, |
216 | dev_t, RF_SectorNum_t, RF_SectorCount_t, void *, void (*) (struct buf *), | | 216 | dev_t, RF_SectorNum_t, RF_SectorCount_t, void *, void (*) (struct buf *), |
217 | void *, int, struct proc *); | | 217 | void *, int, struct proc *); |
218 | static void raidinit(RF_Raid_t *); | | 218 | static void raidinit(RF_Raid_t *); |
219 | | | 219 | |
220 | void raidattach(int); | | 220 | void raidattach(int); |
221 | static int raid_match(device_t, cfdata_t, void *); | | 221 | static int raid_match(device_t, cfdata_t, void *); |
222 | static void raid_attach(device_t, device_t, void *); | | 222 | static void raid_attach(device_t, device_t, void *); |
223 | static int raid_detach(device_t, int); | | 223 | static int raid_detach(device_t, int); |
224 | | | 224 | |
225 | dev_type_open(raidopen); | | 225 | dev_type_open(raidopen); |
226 | dev_type_close(raidclose); | | 226 | dev_type_close(raidclose); |
227 | dev_type_read(raidread); | | 227 | dev_type_read(raidread); |
228 | dev_type_write(raidwrite); | | 228 | dev_type_write(raidwrite); |
229 | dev_type_ioctl(raidioctl); | | 229 | dev_type_ioctl(raidioctl); |
230 | dev_type_strategy(raidstrategy); | | 230 | dev_type_strategy(raidstrategy); |
231 | dev_type_dump(raiddump); | | 231 | dev_type_dump(raiddump); |
232 | dev_type_size(raidsize); | | 232 | dev_type_size(raidsize); |
233 | | | 233 | |
234 | const struct bdevsw raid_bdevsw = { | | 234 | const struct bdevsw raid_bdevsw = { |
235 | raidopen, raidclose, raidstrategy, raidioctl, | | 235 | raidopen, raidclose, raidstrategy, raidioctl, |
236 | raiddump, raidsize, D_DISK | | 236 | raiddump, raidsize, D_DISK |
237 | }; | | 237 | }; |
238 | | | 238 | |
239 | const struct cdevsw raid_cdevsw = { | | 239 | const struct cdevsw raid_cdevsw = { |
240 | raidopen, raidclose, raidread, raidwrite, raidioctl, | | 240 | raidopen, raidclose, raidread, raidwrite, raidioctl, |
241 | nostop, notty, nopoll, nommap, nokqfilter, D_DISK | | 241 | nostop, notty, nopoll, nommap, nokqfilter, D_DISK |
242 | }; | | 242 | }; |
243 | | | 243 | |
244 | static struct dkdriver rf_dkdriver = { raidstrategy, minphys }; | | 244 | static struct dkdriver rf_dkdriver = { raidstrategy, minphys }; |
245 | | | 245 | |
246 | /* XXX Not sure if the following should be replacing the raidPtrs above, | | 246 | /* XXX Not sure if the following should be replacing the raidPtrs above, |
247 | or if it should be used in conjunction with that... | | 247 | or if it should be used in conjunction with that... |
248 | */ | | 248 | */ |
249 | | | 249 | |
250 | struct raid_softc { | | 250 | struct raid_softc { |
251 | device_t sc_dev; | | 251 | device_t sc_dev; |
252 | int sc_flags; /* flags */ | | 252 | int sc_flags; /* flags */ |
253 | int sc_cflags; /* configuration flags */ | | 253 | int sc_cflags; /* configuration flags */ |
254 | uint64_t sc_size; /* size of the raid device */ | | 254 | uint64_t sc_size; /* size of the raid device */ |
255 | char sc_xname[20]; /* XXX external name */ | | 255 | char sc_xname[20]; /* XXX external name */ |
256 | struct disk sc_dkdev; /* generic disk device info */ | | 256 | struct disk sc_dkdev; /* generic disk device info */ |
257 | struct bufq_state *buf_queue; /* used for the device queue */ | | 257 | struct bufq_state *buf_queue; /* used for the device queue */ |
258 | }; | | 258 | }; |
259 | /* sc_flags */ | | 259 | /* sc_flags */ |
260 | #define RAIDF_INITED 0x01 /* unit has been initialized */ | | 260 | #define RAIDF_INITED 0x01 /* unit has been initialized */ |
261 | #define RAIDF_WLABEL 0x02 /* label area is writable */ | | 261 | #define RAIDF_WLABEL 0x02 /* label area is writable */ |
262 | #define RAIDF_LABELLING 0x04 /* unit is currently being labelled */ | | 262 | #define RAIDF_LABELLING 0x04 /* unit is currently being labelled */ |
| | | 263 | #define RAIDF_SHUTDOWN 0x08 /* unit is being shutdown */ |
263 | #define RAIDF_WANTED 0x40 /* someone is waiting to obtain a lock */ | | 264 | #define RAIDF_WANTED 0x40 /* someone is waiting to obtain a lock */ |
264 | #define RAIDF_LOCKED 0x80 /* unit is locked */ | | 265 | #define RAIDF_LOCKED 0x80 /* unit is locked */ |
265 | | | 266 | |
266 | #define raidunit(x) DISKUNIT(x) | | 267 | #define raidunit(x) DISKUNIT(x) |
267 | int numraid = 0; | | 268 | int numraid = 0; |
268 | | | 269 | |
269 | extern struct cfdriver raid_cd; | | 270 | extern struct cfdriver raid_cd; |
270 | CFATTACH_DECL_NEW(raid, sizeof(struct raid_softc), | | 271 | CFATTACH_DECL3_NEW(raid, sizeof(struct raid_softc), |
271 | raid_match, raid_attach, raid_detach, NULL); | | 272 | raid_match, raid_attach, raid_detach, NULL, NULL, NULL, |
| | | 273 | DVF_DETACH_SHUTDOWN); |
272 | | | 274 | |
273 | /* | | 275 | /* |
274 | * Allow RAIDOUTSTANDING number of simultaneous IO's to this RAID device. | | 276 | * Allow RAIDOUTSTANDING number of simultaneous IO's to this RAID device. |
275 | * Be aware that large numbers can allow the driver to consume a lot of | | 277 | * Be aware that large numbers can allow the driver to consume a lot of |
276 | * kernel memory, especially on writes, and in degraded mode reads. | | 278 | * kernel memory, especially on writes, and in degraded mode reads. |
277 | * | | 279 | * |
278 | * For example: with a stripe width of 64 blocks (32k) and 5 disks, | | 280 | * For example: with a stripe width of 64 blocks (32k) and 5 disks, |
279 | * a single 64K write will typically require 64K for the old data, | | 281 | * a single 64K write will typically require 64K for the old data, |
280 | * 64K for the old parity, and 64K for the new parity, for a total | | 282 | * 64K for the old parity, and 64K for the new parity, for a total |
281 | * of 192K (if the parity buffer is not re-used immediately). | | 283 | * of 192K (if the parity buffer is not re-used immediately). |
282 | * Even it if is used immediately, that's still 128K, which when multiplied | | 284 | * Even it if is used immediately, that's still 128K, which when multiplied |
283 | * by say 10 requests, is 1280K, *on top* of the 640K of incoming data. | | 285 | * by say 10 requests, is 1280K, *on top* of the 640K of incoming data. |
284 | * | | 286 | * |
285 | * Now in degraded mode, for example, a 64K read on the above setup may | | 287 | * Now in degraded mode, for example, a 64K read on the above setup may |
286 | * require data reconstruction, which will require *all* of the 4 remaining | | 288 | * require data reconstruction, which will require *all* of the 4 remaining |
287 | * disks to participate -- 4 * 32K/disk == 128K again. | | 289 | * disks to participate -- 4 * 32K/disk == 128K again. |
288 | */ | | 290 | */ |
289 | | | 291 | |
290 | #ifndef RAIDOUTSTANDING | | 292 | #ifndef RAIDOUTSTANDING |
291 | #define RAIDOUTSTANDING 6 | | 293 | #define RAIDOUTSTANDING 6 |
292 | #endif | | 294 | #endif |
293 | | | 295 | |
294 | #define RAIDLABELDEV(dev) \ | | 296 | #define RAIDLABELDEV(dev) \ |
295 | (MAKEDISKDEV(major((dev)), raidunit((dev)), RAW_PART)) | | 297 | (MAKEDISKDEV(major((dev)), raidunit((dev)), RAW_PART)) |
296 | | | 298 | |
297 | /* declared here, and made public, for the benefit of KVM stuff.. */ | | 299 | /* declared here, and made public, for the benefit of KVM stuff.. */ |
298 | struct raid_softc *raid_softc; | | 300 | struct raid_softc *raid_softc; |
299 | | | 301 | |
300 | static void raidgetdefaultlabel(RF_Raid_t *, struct raid_softc *, | | 302 | static void raidgetdefaultlabel(RF_Raid_t *, struct raid_softc *, |
301 | struct disklabel *); | | 303 | struct disklabel *); |
302 | static void raidgetdisklabel(dev_t); | | 304 | static void raidgetdisklabel(dev_t); |
303 | static void raidmakedisklabel(struct raid_softc *); | | 305 | static void raidmakedisklabel(struct raid_softc *); |
304 | | | 306 | |
305 | static int raidlock(struct raid_softc *); | | 307 | static int raidlock(struct raid_softc *); |
306 | static void raidunlock(struct raid_softc *); | | 308 | static void raidunlock(struct raid_softc *); |
307 | | | 309 | |
| | | 310 | static int raid_detach_unlocked(struct raid_softc *); |
| | | 311 | |
308 | static void rf_markalldirty(RF_Raid_t *); | | 312 | static void rf_markalldirty(RF_Raid_t *); |
309 | static void rf_set_properties(struct raid_softc *, RF_Raid_t *); | | 313 | static void rf_set_properties(struct raid_softc *, RF_Raid_t *); |
310 | | | 314 | |
311 | void rf_ReconThread(struct rf_recon_req *); | | 315 | void rf_ReconThread(struct rf_recon_req *); |
312 | void rf_RewriteParityThread(RF_Raid_t *raidPtr); | | 316 | void rf_RewriteParityThread(RF_Raid_t *raidPtr); |
313 | void rf_CopybackThread(RF_Raid_t *raidPtr); | | 317 | void rf_CopybackThread(RF_Raid_t *raidPtr); |
314 | void rf_ReconstructInPlaceThread(struct rf_recon_req *); | | 318 | void rf_ReconstructInPlaceThread(struct rf_recon_req *); |
315 | int rf_autoconfig(device_t); | | 319 | int rf_autoconfig(device_t); |
316 | void rf_buildroothack(RF_ConfigSet_t *); | | 320 | void rf_buildroothack(RF_ConfigSet_t *); |
317 | | | 321 | |
318 | RF_AutoConfig_t *rf_find_raid_components(void); | | 322 | RF_AutoConfig_t *rf_find_raid_components(void); |
319 | RF_ConfigSet_t *rf_create_auto_sets(RF_AutoConfig_t *); | | 323 | RF_ConfigSet_t *rf_create_auto_sets(RF_AutoConfig_t *); |
320 | static int rf_does_it_fit(RF_ConfigSet_t *,RF_AutoConfig_t *); | | 324 | static int rf_does_it_fit(RF_ConfigSet_t *,RF_AutoConfig_t *); |
321 | static int rf_reasonable_label(RF_ComponentLabel_t *); | | 325 | static int rf_reasonable_label(RF_ComponentLabel_t *); |
322 | void rf_create_configuration(RF_AutoConfig_t *,RF_Config_t *, RF_Raid_t *); | | 326 | void rf_create_configuration(RF_AutoConfig_t *,RF_Config_t *, RF_Raid_t *); |
323 | int rf_set_autoconfig(RF_Raid_t *, int); | | 327 | int rf_set_autoconfig(RF_Raid_t *, int); |
324 | int rf_set_rootpartition(RF_Raid_t *, int); | | 328 | int rf_set_rootpartition(RF_Raid_t *, int); |
325 | void rf_release_all_vps(RF_ConfigSet_t *); | | 329 | void rf_release_all_vps(RF_ConfigSet_t *); |
326 | void rf_cleanup_config_set(RF_ConfigSet_t *); | | 330 | void rf_cleanup_config_set(RF_ConfigSet_t *); |
327 | int rf_have_enough_components(RF_ConfigSet_t *); | | 331 | int rf_have_enough_components(RF_ConfigSet_t *); |
328 | int rf_auto_config_set(RF_ConfigSet_t *, int *); | | 332 | int rf_auto_config_set(RF_ConfigSet_t *, int *); |
329 | static int rf_sync_component_caches(RF_Raid_t *raidPtr); | | 333 | static int rf_sync_component_caches(RF_Raid_t *raidPtr); |
330 | | | 334 | |
331 | static int raidautoconfig = 0; /* Debugging, mostly. Set to 0 to not | | 335 | static int raidautoconfig = 0; /* Debugging, mostly. Set to 0 to not |
332 | allow autoconfig to take place. | | 336 | allow autoconfig to take place. |
333 | Note that this is overridden by having | | 337 | Note that this is overridden by having |
334 | RAID_AUTOCONFIG as an option in the | | 338 | RAID_AUTOCONFIG as an option in the |
335 | kernel config file. */ | | 339 | kernel config file. */ |
336 | | | 340 | |
337 | struct RF_Pools_s rf_pools; | | 341 | struct RF_Pools_s rf_pools; |
338 | | | 342 | |
339 | void | | 343 | void |
340 | raidattach(int num) | | 344 | raidattach(int num) |
341 | { | | 345 | { |
342 | int raidID; | | 346 | int raidID; |
343 | int i, rc; | | 347 | int i, rc; |
344 | | | 348 | |
345 | aprint_debug("raidattach: Asked for %d units\n", num); | | 349 | aprint_debug("raidattach: Asked for %d units\n", num); |
346 | | | 350 | |
347 | if (num <= 0) { | | 351 | if (num <= 0) { |
348 | #ifdef DIAGNOSTIC | | 352 | #ifdef DIAGNOSTIC |
349 | panic("raidattach: count <= 0"); | | 353 | panic("raidattach: count <= 0"); |
350 | #endif | | 354 | #endif |
351 | return; | | 355 | return; |
352 | } | | 356 | } |
353 | /* This is where all the initialization stuff gets done. */ | | 357 | /* This is where all the initialization stuff gets done. */ |
354 | | | 358 | |
355 | numraid = num; | | 359 | numraid = num; |
356 | | | 360 | |
357 | /* Make some space for requested number of units... */ | | 361 | /* Make some space for requested number of units... */ |
358 | | | 362 | |
359 | RF_Malloc(raidPtrs, num * sizeof(RF_Raid_t *), (RF_Raid_t **)); | | 363 | RF_Malloc(raidPtrs, num * sizeof(RF_Raid_t *), (RF_Raid_t **)); |
360 | if (raidPtrs == NULL) { | | 364 | if (raidPtrs == NULL) { |
361 | panic("raidPtrs is NULL!!"); | | 365 | panic("raidPtrs is NULL!!"); |
362 | } | | 366 | } |
363 | | | 367 | |
364 | #if (RF_INCLUDE_PARITY_DECLUSTERING_DS > 0) | | 368 | #if (RF_INCLUDE_PARITY_DECLUSTERING_DS > 0) |
365 | rf_mutex_init(&rf_sparet_wait_mutex); | | 369 | rf_mutex_init(&rf_sparet_wait_mutex); |
366 | | | 370 | |
367 | rf_sparet_wait_queue = rf_sparet_resp_queue = NULL; | | 371 | rf_sparet_wait_queue = rf_sparet_resp_queue = NULL; |
368 | #endif | | 372 | #endif |
369 | | | 373 | |
370 | for (i = 0; i < num; i++) | | 374 | for (i = 0; i < num; i++) |
371 | raidPtrs[i] = NULL; | | 375 | raidPtrs[i] = NULL; |
372 | rc = rf_BootRaidframe(); | | 376 | rc = rf_BootRaidframe(); |
373 | if (rc == 0) | | 377 | if (rc == 0) |
374 | aprint_normal("Kernelized RAIDframe activated\n"); | | 378 | aprint_normal("Kernelized RAIDframe activated\n"); |
375 | else | | 379 | else |
376 | panic("Serious error booting RAID!!"); | | 380 | panic("Serious error booting RAID!!"); |
377 | | | 381 | |
378 | /* put together some datastructures like the CCD device does.. This | | 382 | /* put together some datastructures like the CCD device does.. This |
379 | * lets us lock the device and what-not when it gets opened. */ | | 383 | * lets us lock the device and what-not when it gets opened. */ |
380 | | | 384 | |
381 | raid_softc = (struct raid_softc *) | | 385 | raid_softc = (struct raid_softc *) |
382 | malloc(num * sizeof(struct raid_softc), | | 386 | malloc(num * sizeof(struct raid_softc), |
383 | M_RAIDFRAME, M_NOWAIT); | | 387 | M_RAIDFRAME, M_NOWAIT); |
384 | if (raid_softc == NULL) { | | 388 | if (raid_softc == NULL) { |
385 | aprint_error("WARNING: no memory for RAIDframe driver\n"); | | 389 | aprint_error("WARNING: no memory for RAIDframe driver\n"); |
386 | return; | | 390 | return; |
387 | } | | 391 | } |
388 | | | 392 | |
389 | memset(raid_softc, 0, num * sizeof(struct raid_softc)); | | 393 | memset(raid_softc, 0, num * sizeof(struct raid_softc)); |
390 | | | 394 | |
391 | for (raidID = 0; raidID < num; raidID++) { | | 395 | for (raidID = 0; raidID < num; raidID++) { |
392 | bufq_alloc(&raid_softc[raidID].buf_queue, "fcfs", 0); | | 396 | bufq_alloc(&raid_softc[raidID].buf_queue, "fcfs", 0); |
393 | | | 397 | |
394 | RF_Malloc(raidPtrs[raidID], sizeof(RF_Raid_t), | | 398 | RF_Malloc(raidPtrs[raidID], sizeof(RF_Raid_t), |
395 | (RF_Raid_t *)); | | 399 | (RF_Raid_t *)); |
396 | if (raidPtrs[raidID] == NULL) { | | 400 | if (raidPtrs[raidID] == NULL) { |
397 | aprint_error("WARNING: raidPtrs[%d] is NULL\n", raidID); | | 401 | aprint_error("WARNING: raidPtrs[%d] is NULL\n", raidID); |
398 | numraid = raidID; | | 402 | numraid = raidID; |
399 | return; | | 403 | return; |
400 | } | | 404 | } |
401 | } | | 405 | } |
402 | | | 406 | |
403 | if (config_cfattach_attach(raid_cd.cd_name, &raid_ca)) { | | 407 | if (config_cfattach_attach(raid_cd.cd_name, &raid_ca)) { |
404 | aprint_error("raidattach: config_cfattach_attach failed?\n"); | | 408 | aprint_error("raidattach: config_cfattach_attach failed?\n"); |
405 | } | | 409 | } |
406 | | | 410 | |
407 | #ifdef RAID_AUTOCONFIG | | 411 | #ifdef RAID_AUTOCONFIG |
408 | raidautoconfig = 1; | | 412 | raidautoconfig = 1; |
409 | #endif | | 413 | #endif |
410 | | | 414 | |
411 | /* | | 415 | /* |
412 | * Register a finalizer which will be used to auto-config RAID | | 416 | * Register a finalizer which will be used to auto-config RAID |
413 | * sets once all real hardware devices have been found. | | 417 | * sets once all real hardware devices have been found. |
414 | */ | | 418 | */ |
415 | if (config_finalize_register(NULL, rf_autoconfig) != 0) | | 419 | if (config_finalize_register(NULL, rf_autoconfig) != 0) |
416 | aprint_error("WARNING: unable to register RAIDframe finalizer\n"); | | 420 | aprint_error("WARNING: unable to register RAIDframe finalizer\n"); |
417 | } | | 421 | } |
418 | | | 422 | |
419 | int | | 423 | int |
420 | rf_autoconfig(device_t self) | | 424 | rf_autoconfig(device_t self) |
421 | { | | 425 | { |
422 | RF_AutoConfig_t *ac_list; | | 426 | RF_AutoConfig_t *ac_list; |
423 | RF_ConfigSet_t *config_sets; | | 427 | RF_ConfigSet_t *config_sets; |
424 | | | 428 | |
425 | if (raidautoconfig == 0) | | 429 | if (raidautoconfig == 0) |
426 | return (0); | | 430 | return (0); |
427 | | | 431 | |
428 | /* XXX This code can only be run once. */ | | 432 | /* XXX This code can only be run once. */ |
429 | raidautoconfig = 0; | | 433 | raidautoconfig = 0; |
430 | | | 434 | |
431 | /* 1. locate all RAID components on the system */ | | 435 | /* 1. locate all RAID components on the system */ |
432 | aprint_debug("Searching for RAID components...\n"); | | 436 | aprint_debug("Searching for RAID components...\n"); |
433 | ac_list = rf_find_raid_components(); | | 437 | ac_list = rf_find_raid_components(); |
434 | | | 438 | |
435 | /* 2. Sort them into their respective sets. */ | | 439 | /* 2. Sort them into their respective sets. */ |
436 | config_sets = rf_create_auto_sets(ac_list); | | 440 | config_sets = rf_create_auto_sets(ac_list); |
437 | | | 441 | |
438 | /* | | 442 | /* |
439 | * 3. Evaluate each set andconfigure the valid ones. | | 443 | * 3. Evaluate each set andconfigure the valid ones. |
440 | * This gets done in rf_buildroothack(). | | 444 | * This gets done in rf_buildroothack(). |
441 | */ | | 445 | */ |
442 | rf_buildroothack(config_sets); | | 446 | rf_buildroothack(config_sets); |
443 | | | 447 | |
444 | return 1; | | 448 | return 1; |
445 | } | | 449 | } |
446 | | | 450 | |
447 | void | | 451 | void |
448 | rf_buildroothack(RF_ConfigSet_t *config_sets) | | 452 | rf_buildroothack(RF_ConfigSet_t *config_sets) |
449 | { | | 453 | { |
450 | RF_ConfigSet_t *cset; | | 454 | RF_ConfigSet_t *cset; |
451 | RF_ConfigSet_t *next_cset; | | 455 | RF_ConfigSet_t *next_cset; |
452 | int retcode; | | 456 | int retcode; |
453 | int raidID; | | 457 | int raidID; |
454 | int rootID; | | 458 | int rootID; |
455 | int col; | | 459 | int col; |
456 | int num_root; | | 460 | int num_root; |
457 | char *devname; | | 461 | char *devname; |
458 | | | 462 | |
459 | rootID = 0; | | 463 | rootID = 0; |
460 | num_root = 0; | | 464 | num_root = 0; |
461 | cset = config_sets; | | 465 | cset = config_sets; |
462 | while(cset != NULL ) { | | 466 | while(cset != NULL ) { |
463 | next_cset = cset->next; | | 467 | next_cset = cset->next; |
464 | if (rf_have_enough_components(cset) && | | 468 | if (rf_have_enough_components(cset) && |
465 | cset->ac->clabel->autoconfigure==1) { | | 469 | cset->ac->clabel->autoconfigure==1) { |
466 | retcode = rf_auto_config_set(cset,&raidID); | | 470 | retcode = rf_auto_config_set(cset,&raidID); |
467 | if (!retcode) { | | 471 | if (!retcode) { |
468 | aprint_debug("raid%d: configured ok\n", raidID); | | 472 | aprint_debug("raid%d: configured ok\n", raidID); |
469 | if (cset->rootable) { | | 473 | if (cset->rootable) { |
470 | rootID = raidID; | | 474 | rootID = raidID; |
471 | num_root++; | | 475 | num_root++; |
472 | } | | 476 | } |
473 | } else { | | 477 | } else { |
474 | /* The autoconfig didn't work :( */ | | 478 | /* The autoconfig didn't work :( */ |
475 | aprint_debug("Autoconfig failed with code %d for raid%d\n", retcode, raidID); | | 479 | aprint_debug("Autoconfig failed with code %d for raid%d\n", retcode, raidID); |
476 | rf_release_all_vps(cset); | | 480 | rf_release_all_vps(cset); |
477 | } | | 481 | } |
478 | } else { | | 482 | } else { |
479 | /* we're not autoconfiguring this set... | | 483 | /* we're not autoconfiguring this set... |
480 | release the associated resources */ | | 484 | release the associated resources */ |
481 | rf_release_all_vps(cset); | | 485 | rf_release_all_vps(cset); |
482 | } | | 486 | } |
483 | /* cleanup */ | | 487 | /* cleanup */ |
484 | rf_cleanup_config_set(cset); | | 488 | rf_cleanup_config_set(cset); |
485 | cset = next_cset; | | 489 | cset = next_cset; |
486 | } | | 490 | } |
487 | | | 491 | |
488 | /* if the user has specified what the root device should be | | 492 | /* if the user has specified what the root device should be |
489 | then we don't touch booted_device or boothowto... */ | | 493 | then we don't touch booted_device or boothowto... */ |
490 | | | 494 | |
491 | if (rootspec != NULL) | | 495 | if (rootspec != NULL) |
492 | return; | | 496 | return; |
493 | | | 497 | |
494 | /* we found something bootable... */ | | 498 | /* we found something bootable... */ |
495 | | | 499 | |
496 | if (num_root == 1) { | | 500 | if (num_root == 1) { |
497 | booted_device = raid_softc[rootID].sc_dev; | | 501 | booted_device = raid_softc[rootID].sc_dev; |
498 | } else if (num_root > 1) { | | 502 | } else if (num_root > 1) { |
499 | | | 503 | |
500 | /* | | 504 | /* |
501 | * Maybe the MD code can help. If it cannot, then | | 505 | * Maybe the MD code can help. If it cannot, then |
502 | * setroot() will discover that we have no | | 506 | * setroot() will discover that we have no |
503 | * booted_device and will ask the user if nothing was | | 507 | * booted_device and will ask the user if nothing was |
504 | * hardwired in the kernel config file | | 508 | * hardwired in the kernel config file |
505 | */ | | 509 | */ |
506 | | | 510 | |
507 | if (booted_device == NULL) | | 511 | if (booted_device == NULL) |
508 | cpu_rootconf(); | | 512 | cpu_rootconf(); |
509 | if (booted_device == NULL) | | 513 | if (booted_device == NULL) |
510 | return; | | 514 | return; |
511 | | | 515 | |
512 | num_root = 0; | | 516 | num_root = 0; |
513 | for (raidID = 0; raidID < numraid; raidID++) { | | 517 | for (raidID = 0; raidID < numraid; raidID++) { |
514 | if (raidPtrs[raidID]->valid == 0) | | 518 | if (raidPtrs[raidID]->valid == 0) |
515 | continue; | | 519 | continue; |
516 | | | 520 | |
517 | if (raidPtrs[raidID]->root_partition == 0) | | 521 | if (raidPtrs[raidID]->root_partition == 0) |
518 | continue; | | 522 | continue; |
519 | | | 523 | |
520 | for (col = 0; col < raidPtrs[raidID]->numCol; col++) { | | 524 | for (col = 0; col < raidPtrs[raidID]->numCol; col++) { |
521 | devname = raidPtrs[raidID]->Disks[col].devname; | | 525 | devname = raidPtrs[raidID]->Disks[col].devname; |
522 | devname += sizeof("/dev/") - 1; | | 526 | devname += sizeof("/dev/") - 1; |
523 | if (strncmp(devname, device_xname(booted_device), | | 527 | if (strncmp(devname, device_xname(booted_device), |
524 | strlen(device_xname(booted_device))) != 0) | | 528 | strlen(device_xname(booted_device))) != 0) |
525 | continue; | | 529 | continue; |
526 | aprint_debug("raid%d includes boot device %s\n", | | 530 | aprint_debug("raid%d includes boot device %s\n", |
527 | raidID, devname); | | 531 | raidID, devname); |
528 | num_root++; | | 532 | num_root++; |
529 | rootID = raidID; | | 533 | rootID = raidID; |
530 | } | | 534 | } |
531 | } | | 535 | } |
532 | | | 536 | |
533 | if (num_root == 1) { | | 537 | if (num_root == 1) { |
534 | booted_device = raid_softc[rootID].sc_dev; | | 538 | booted_device = raid_softc[rootID].sc_dev; |
535 | } else { | | 539 | } else { |
536 | /* we can't guess.. require the user to answer... */ | | 540 | /* we can't guess.. require the user to answer... */ |
537 | boothowto |= RB_ASKNAME; | | 541 | boothowto |= RB_ASKNAME; |
538 | } | | 542 | } |
539 | } | | 543 | } |
540 | } | | 544 | } |
541 | | | 545 | |
542 | | | 546 | |
543 | int | | 547 | int |
544 | raidsize(dev_t dev) | | 548 | raidsize(dev_t dev) |
545 | { | | 549 | { |
546 | struct raid_softc *rs; | | 550 | struct raid_softc *rs; |
547 | struct disklabel *lp; | | 551 | struct disklabel *lp; |
548 | int part, unit, omask, size; | | 552 | int part, unit, omask, size; |
549 | | | 553 | |
550 | unit = raidunit(dev); | | 554 | unit = raidunit(dev); |
551 | if (unit >= numraid) | | 555 | if (unit >= numraid) |
552 | return (-1); | | 556 | return (-1); |
553 | rs = &raid_softc[unit]; | | 557 | rs = &raid_softc[unit]; |
554 | | | 558 | |
555 | if ((rs->sc_flags & RAIDF_INITED) == 0) | | 559 | if ((rs->sc_flags & RAIDF_INITED) == 0) |
556 | return (-1); | | 560 | return (-1); |
557 | | | 561 | |
558 | part = DISKPART(dev); | | 562 | part = DISKPART(dev); |
559 | omask = rs->sc_dkdev.dk_openmask & (1 << part); | | 563 | omask = rs->sc_dkdev.dk_openmask & (1 << part); |
560 | lp = rs->sc_dkdev.dk_label; | | 564 | lp = rs->sc_dkdev.dk_label; |
561 | | | 565 | |
562 | if (omask == 0 && raidopen(dev, 0, S_IFBLK, curlwp)) | | 566 | if (omask == 0 && raidopen(dev, 0, S_IFBLK, curlwp)) |
563 | return (-1); | | 567 | return (-1); |
564 | | | 568 | |
565 | if (lp->d_partitions[part].p_fstype != FS_SWAP) | | 569 | if (lp->d_partitions[part].p_fstype != FS_SWAP) |
566 | size = -1; | | 570 | size = -1; |
567 | else | | 571 | else |
568 | size = lp->d_partitions[part].p_size * | | 572 | size = lp->d_partitions[part].p_size * |
569 | (lp->d_secsize / DEV_BSIZE); | | 573 | (lp->d_secsize / DEV_BSIZE); |
570 | | | 574 | |
571 | if (omask == 0 && raidclose(dev, 0, S_IFBLK, curlwp)) | | 575 | if (omask == 0 && raidclose(dev, 0, S_IFBLK, curlwp)) |
572 | return (-1); | | 576 | return (-1); |
573 | | | 577 | |
574 | return (size); | | 578 | return (size); |
575 | | | 579 | |
576 | } | | 580 | } |
577 | | | 581 | |
578 | int | | 582 | int |
579 | raiddump(dev_t dev, daddr_t blkno, void *va, size_t size) | | 583 | raiddump(dev_t dev, daddr_t blkno, void *va, size_t size) |
580 | { | | 584 | { |
581 | int unit = raidunit(dev); | | 585 | int unit = raidunit(dev); |
582 | struct raid_softc *rs; | | 586 | struct raid_softc *rs; |
583 | const struct bdevsw *bdev; | | 587 | const struct bdevsw *bdev; |
584 | struct disklabel *lp; | | 588 | struct disklabel *lp; |
585 | RF_Raid_t *raidPtr; | | 589 | RF_Raid_t *raidPtr; |
586 | daddr_t offset; | | 590 | daddr_t offset; |
587 | int part, c, sparecol, j, scol, dumpto; | | 591 | int part, c, sparecol, j, scol, dumpto; |
588 | int error = 0; | | 592 | int error = 0; |
589 | | | 593 | |
590 | if (unit >= numraid) | | 594 | if (unit >= numraid) |
591 | return (ENXIO); | | 595 | return (ENXIO); |
592 | | | 596 | |
593 | rs = &raid_softc[unit]; | | 597 | rs = &raid_softc[unit]; |
594 | raidPtr = raidPtrs[unit]; | | 598 | raidPtr = raidPtrs[unit]; |
595 | | | 599 | |
596 | if ((rs->sc_flags & RAIDF_INITED) == 0) | | 600 | if ((rs->sc_flags & RAIDF_INITED) == 0) |
597 | return ENXIO; | | 601 | return ENXIO; |
598 | | | 602 | |
599 | /* we only support dumping to RAID 1 sets */ | | 603 | /* we only support dumping to RAID 1 sets */ |
600 | if (raidPtr->Layout.numDataCol != 1 || | | 604 | if (raidPtr->Layout.numDataCol != 1 || |
601 | raidPtr->Layout.numParityCol != 1) | | 605 | raidPtr->Layout.numParityCol != 1) |
602 | return EINVAL; | | 606 | return EINVAL; |
603 | | | 607 | |
604 | | | 608 | |
605 | if ((error = raidlock(rs)) != 0) | | 609 | if ((error = raidlock(rs)) != 0) |
606 | return error; | | 610 | return error; |
607 | | | 611 | |
608 | if (size % DEV_BSIZE != 0) { | | 612 | if (size % DEV_BSIZE != 0) { |
609 | error = EINVAL; | | 613 | error = EINVAL; |
610 | goto out; | | 614 | goto out; |
611 | } | | 615 | } |
612 | | | 616 | |
613 | if (blkno + size / DEV_BSIZE > rs->sc_size) { | | 617 | if (blkno + size / DEV_BSIZE > rs->sc_size) { |
614 | printf("%s: blkno (%" PRIu64 ") + size / DEV_BSIZE (%zu) > " | | 618 | printf("%s: blkno (%" PRIu64 ") + size / DEV_BSIZE (%zu) > " |
615 | "sc->sc_size (%" PRIu64 ")\n", __func__, blkno, | | 619 | "sc->sc_size (%" PRIu64 ")\n", __func__, blkno, |
616 | size / DEV_BSIZE, rs->sc_size); | | 620 | size / DEV_BSIZE, rs->sc_size); |
617 | error = EINVAL; | | 621 | error = EINVAL; |
618 | goto out; | | 622 | goto out; |
619 | } | | 623 | } |
620 | | | 624 | |
621 | part = DISKPART(dev); | | 625 | part = DISKPART(dev); |
622 | lp = rs->sc_dkdev.dk_label; | | 626 | lp = rs->sc_dkdev.dk_label; |
623 | offset = lp->d_partitions[part].p_offset + RF_PROTECTED_SECTORS; | | 627 | offset = lp->d_partitions[part].p_offset + RF_PROTECTED_SECTORS; |
624 | | | 628 | |
625 | /* figure out what device is alive.. */ | | 629 | /* figure out what device is alive.. */ |
626 | | | 630 | |
627 | /* | | 631 | /* |
628 | Look for a component to dump to. The preference for the | | 632 | Look for a component to dump to. The preference for the |
629 | component to dump to is as follows: | | 633 | component to dump to is as follows: |
630 | 1) the master | | 634 | 1) the master |
631 | 2) a used_spare of the master | | 635 | 2) a used_spare of the master |
632 | 3) the slave | | 636 | 3) the slave |
633 | 4) a used_spare of the slave | | 637 | 4) a used_spare of the slave |
634 | */ | | 638 | */ |
635 | | | 639 | |
636 | dumpto = -1; | | 640 | dumpto = -1; |
637 | for (c = 0; c < raidPtr->numCol; c++) { | | 641 | for (c = 0; c < raidPtr->numCol; c++) { |
638 | if (raidPtr->Disks[c].status == rf_ds_optimal) { | | 642 | if (raidPtr->Disks[c].status == rf_ds_optimal) { |
639 | /* this might be the one */ | | 643 | /* this might be the one */ |
640 | dumpto = c; | | 644 | dumpto = c; |
641 | break; | | 645 | break; |
642 | } | | 646 | } |
643 | } | | 647 | } |
644 | | | 648 | |
645 | /* | | 649 | /* |
646 | At this point we have possibly selected a live master or a | | 650 | At this point we have possibly selected a live master or a |
647 | live slave. We now check to see if there is a spared | | 651 | live slave. We now check to see if there is a spared |
648 | master (or a spared slave), if we didn't find a live master | | 652 | master (or a spared slave), if we didn't find a live master |
649 | or a live slave. | | 653 | or a live slave. |
650 | */ | | 654 | */ |
651 | | | 655 | |
652 | for (c = 0; c < raidPtr->numSpare; c++) { | | 656 | for (c = 0; c < raidPtr->numSpare; c++) { |
653 | sparecol = raidPtr->numCol + c; | | 657 | sparecol = raidPtr->numCol + c; |
654 | if (raidPtr->Disks[sparecol].status == rf_ds_used_spare) { | | 658 | if (raidPtr->Disks[sparecol].status == rf_ds_used_spare) { |
655 | /* How about this one? */ | | 659 | /* How about this one? */ |
656 | scol = -1; | | 660 | scol = -1; |
657 | for(j=0;j<raidPtr->numCol;j++) { | | 661 | for(j=0;j<raidPtr->numCol;j++) { |
658 | if (raidPtr->Disks[j].spareCol == sparecol) { | | 662 | if (raidPtr->Disks[j].spareCol == sparecol) { |
659 | scol = j; | | 663 | scol = j; |
660 | break; | | 664 | break; |
661 | } | | 665 | } |
662 | } | | 666 | } |
663 | if (scol == 0) { | | 667 | if (scol == 0) { |
664 | /* | | 668 | /* |
665 | We must have found a spared master! | | 669 | We must have found a spared master! |
666 | We'll take that over anything else | | 670 | We'll take that over anything else |
667 | found so far. (We couldn't have | | 671 | found so far. (We couldn't have |
668 | found a real master before, since | | 672 | found a real master before, since |
669 | this is a used spare, and it's | | 673 | this is a used spare, and it's |
670 | saying that it's replacing the | | 674 | saying that it's replacing the |
671 | master.) On reboot (with | | 675 | master.) On reboot (with |
672 | autoconfiguration turned on) | | 676 | autoconfiguration turned on) |
673 | sparecol will become the 1st | | 677 | sparecol will become the 1st |
674 | component (component0) of this set. | | 678 | component (component0) of this set. |
675 | */ | | 679 | */ |
676 | dumpto = sparecol; | | 680 | dumpto = sparecol; |
677 | break; | | 681 | break; |
678 | } else if (scol != -1) { | | 682 | } else if (scol != -1) { |
679 | /* | | 683 | /* |
680 | Must be a spared slave. We'll dump | | 684 | Must be a spared slave. We'll dump |
681 | to that if we havn't found anything | | 685 | to that if we havn't found anything |
682 | else so far. | | 686 | else so far. |
683 | */ | | 687 | */ |
684 | if (dumpto == -1) | | 688 | if (dumpto == -1) |
685 | dumpto = sparecol; | | 689 | dumpto = sparecol; |
686 | } | | 690 | } |
687 | } | | 691 | } |
688 | } | | 692 | } |
689 | | | 693 | |
690 | if (dumpto == -1) { | | 694 | if (dumpto == -1) { |
691 | /* we couldn't find any live components to dump to!?!? | | 695 | /* we couldn't find any live components to dump to!?!? |
692 | */ | | 696 | */ |
693 | error = EINVAL; | | 697 | error = EINVAL; |
694 | goto out; | | 698 | goto out; |
695 | } | | 699 | } |
696 | | | 700 | |
697 | bdev = bdevsw_lookup(raidPtr->Disks[dumpto].dev); | | 701 | bdev = bdevsw_lookup(raidPtr->Disks[dumpto].dev); |
698 | | | 702 | |
699 | /* | | 703 | /* |
700 | Note that blkno is relative to this particular partition. | | 704 | Note that blkno is relative to this particular partition. |
701 | By adding the offset of this partition in the RAID | | 705 | By adding the offset of this partition in the RAID |
702 | set, and also adding RF_PROTECTED_SECTORS, we get a | | 706 | set, and also adding RF_PROTECTED_SECTORS, we get a |
703 | value that is relative to the partition used for the | | 707 | value that is relative to the partition used for the |
704 | underlying component. | | 708 | underlying component. |
705 | */ | | 709 | */ |
706 | | | 710 | |
707 | error = (*bdev->d_dump)(raidPtr->Disks[dumpto].dev, | | 711 | error = (*bdev->d_dump)(raidPtr->Disks[dumpto].dev, |
708 | blkno + offset, va, size); | | 712 | blkno + offset, va, size); |
709 | | | 713 | |
710 | out: | | 714 | out: |
711 | raidunlock(rs); | | 715 | raidunlock(rs); |
712 | | | 716 | |
713 | return error; | | 717 | return error; |
714 | } | | 718 | } |
715 | /* ARGSUSED */ | | 719 | /* ARGSUSED */ |
716 | int | | 720 | int |
717 | raidopen(dev_t dev, int flags, int fmt, | | 721 | raidopen(dev_t dev, int flags, int fmt, |
718 | struct lwp *l) | | 722 | struct lwp *l) |
719 | { | | 723 | { |
720 | int unit = raidunit(dev); | | 724 | int unit = raidunit(dev); |
721 | struct raid_softc *rs; | | 725 | struct raid_softc *rs; |
722 | struct disklabel *lp; | | 726 | struct disklabel *lp; |
723 | int part, pmask; | | 727 | int part, pmask; |
724 | int error = 0; | | 728 | int error = 0; |
725 | | | 729 | |
726 | if (unit >= numraid) | | 730 | if (unit >= numraid) |
727 | return (ENXIO); | | 731 | return (ENXIO); |
728 | rs = &raid_softc[unit]; | | 732 | rs = &raid_softc[unit]; |
729 | | | 733 | |
730 | if ((error = raidlock(rs)) != 0) | | 734 | if ((error = raidlock(rs)) != 0) |
731 | return (error); | | 735 | return (error); |
| | | 736 | |
| | | 737 | if ((rs->sc_flags & RAIDF_SHUTDOWN) != 0) { |
| | | 738 | error = EBUSY; |
| | | 739 | goto bad; |
| | | 740 | } |
| | | 741 | |
732 | lp = rs->sc_dkdev.dk_label; | | 742 | lp = rs->sc_dkdev.dk_label; |
733 | | | 743 | |
734 | part = DISKPART(dev); | | 744 | part = DISKPART(dev); |
735 | | | 745 | |
736 | /* | | 746 | /* |
737 | * If there are wedges, and this is not RAW_PART, then we | | 747 | * If there are wedges, and this is not RAW_PART, then we |
738 | * need to fail. | | 748 | * need to fail. |
739 | */ | | 749 | */ |
740 | if (rs->sc_dkdev.dk_nwedges != 0 && part != RAW_PART) { | | 750 | if (rs->sc_dkdev.dk_nwedges != 0 && part != RAW_PART) { |
741 | error = EBUSY; | | 751 | error = EBUSY; |
742 | goto bad; | | 752 | goto bad; |
743 | } | | 753 | } |
744 | pmask = (1 << part); | | 754 | pmask = (1 << part); |
745 | | | 755 | |
746 | if ((rs->sc_flags & RAIDF_INITED) && | | 756 | if ((rs->sc_flags & RAIDF_INITED) && |
747 | (rs->sc_dkdev.dk_openmask == 0)) | | 757 | (rs->sc_dkdev.dk_openmask == 0)) |
748 | raidgetdisklabel(dev); | | 758 | raidgetdisklabel(dev); |
749 | | | 759 | |
750 | /* make sure that this partition exists */ | | 760 | /* make sure that this partition exists */ |
751 | | | 761 | |
752 | if (part != RAW_PART) { | | 762 | if (part != RAW_PART) { |
753 | if (((rs->sc_flags & RAIDF_INITED) == 0) || | | 763 | if (((rs->sc_flags & RAIDF_INITED) == 0) || |
754 | ((part >= lp->d_npartitions) || | | 764 | ((part >= lp->d_npartitions) || |
755 | (lp->d_partitions[part].p_fstype == FS_UNUSED))) { | | 765 | (lp->d_partitions[part].p_fstype == FS_UNUSED))) { |
756 | error = ENXIO; | | 766 | error = ENXIO; |
757 | goto bad; | | 767 | goto bad; |
758 | } | | 768 | } |
759 | } | | 769 | } |
760 | /* Prevent this unit from being unconfigured while open. */ | | 770 | /* Prevent this unit from being unconfigured while open. */ |
761 | switch (fmt) { | | 771 | switch (fmt) { |
762 | case S_IFCHR: | | 772 | case S_IFCHR: |
763 | rs->sc_dkdev.dk_copenmask |= pmask; | | 773 | rs->sc_dkdev.dk_copenmask |= pmask; |
764 | break; | | 774 | break; |
765 | | | 775 | |
766 | case S_IFBLK: | | 776 | case S_IFBLK: |
767 | rs->sc_dkdev.dk_bopenmask |= pmask; | | 777 | rs->sc_dkdev.dk_bopenmask |= pmask; |
768 | break; | | 778 | break; |
769 | } | | 779 | } |
770 | | | 780 | |
771 | if ((rs->sc_dkdev.dk_openmask == 0) && | | 781 | if ((rs->sc_dkdev.dk_openmask == 0) && |
772 | ((rs->sc_flags & RAIDF_INITED) != 0)) { | | 782 | ((rs->sc_flags & RAIDF_INITED) != 0)) { |
773 | /* First one... mark things as dirty... Note that we *MUST* | | 783 | /* First one... mark things as dirty... Note that we *MUST* |
774 | have done a configure before this. I DO NOT WANT TO BE | | 784 | have done a configure before this. I DO NOT WANT TO BE |
775 | SCRIBBLING TO RANDOM COMPONENTS UNTIL IT'S BEEN DETERMINED | | 785 | SCRIBBLING TO RANDOM COMPONENTS UNTIL IT'S BEEN DETERMINED |
776 | THAT THEY BELONG TOGETHER!!!!! */ | | 786 | THAT THEY BELONG TOGETHER!!!!! */ |
777 | /* XXX should check to see if we're only open for reading | | 787 | /* XXX should check to see if we're only open for reading |
778 | here... If so, we needn't do this, but then need some | | 788 | here... If so, we needn't do this, but then need some |
779 | other way of keeping track of what's happened.. */ | | 789 | other way of keeping track of what's happened.. */ |
780 | | | 790 | |
781 | rf_markalldirty( raidPtrs[unit] ); | | 791 | rf_markalldirty( raidPtrs[unit] ); |
782 | } | | 792 | } |
783 | | | 793 | |
784 | | | 794 | |
785 | rs->sc_dkdev.dk_openmask = | | 795 | rs->sc_dkdev.dk_openmask = |
786 | rs->sc_dkdev.dk_copenmask | rs->sc_dkdev.dk_bopenmask; | | 796 | rs->sc_dkdev.dk_copenmask | rs->sc_dkdev.dk_bopenmask; |
787 | | | 797 | |
788 | bad: | | 798 | bad: |
789 | raidunlock(rs); | | 799 | raidunlock(rs); |
790 | | | 800 | |
791 | return (error); | | 801 | return (error); |
792 | | | 802 | |
793 | | | 803 | |
794 | } | | 804 | } |
795 | /* ARGSUSED */ | | 805 | /* ARGSUSED */ |
796 | int | | 806 | int |
797 | raidclose(dev_t dev, int flags, int fmt, struct lwp *l) | | 807 | raidclose(dev_t dev, int flags, int fmt, struct lwp *l) |
798 | { | | 808 | { |
799 | int unit = raidunit(dev); | | 809 | int unit = raidunit(dev); |
800 | cfdata_t cf; | | | |
801 | struct raid_softc *rs; | | 810 | struct raid_softc *rs; |
802 | int error = 0; | | 811 | int error = 0; |
803 | int part; | | 812 | int part; |
804 | | | 813 | |
805 | if (unit >= numraid) | | 814 | if (unit >= numraid) |
806 | return (ENXIO); | | 815 | return (ENXIO); |
807 | rs = &raid_softc[unit]; | | 816 | rs = &raid_softc[unit]; |
808 | | | 817 | |
809 | if ((error = raidlock(rs)) != 0) | | 818 | if ((error = raidlock(rs)) != 0) |
810 | return (error); | | 819 | return (error); |
811 | | | 820 | |
812 | part = DISKPART(dev); | | 821 | part = DISKPART(dev); |
813 | | | 822 | |
814 | /* ...that much closer to allowing unconfiguration... */ | | 823 | /* ...that much closer to allowing unconfiguration... */ |
815 | switch (fmt) { | | 824 | switch (fmt) { |
816 | case S_IFCHR: | | 825 | case S_IFCHR: |
817 | rs->sc_dkdev.dk_copenmask &= ~(1 << part); | | 826 | rs->sc_dkdev.dk_copenmask &= ~(1 << part); |
818 | break; | | 827 | break; |
819 | | | 828 | |
820 | case S_IFBLK: | | 829 | case S_IFBLK: |
821 | rs->sc_dkdev.dk_bopenmask &= ~(1 << part); | | 830 | rs->sc_dkdev.dk_bopenmask &= ~(1 << part); |
822 | break; | | 831 | break; |
823 | } | | 832 | } |
824 | rs->sc_dkdev.dk_openmask = | | 833 | rs->sc_dkdev.dk_openmask = |
825 | rs->sc_dkdev.dk_copenmask | rs->sc_dkdev.dk_bopenmask; | | 834 | rs->sc_dkdev.dk_copenmask | rs->sc_dkdev.dk_bopenmask; |
826 | | | 835 | |
827 | if ((rs->sc_dkdev.dk_openmask == 0) && | | 836 | if ((rs->sc_dkdev.dk_openmask == 0) && |
828 | ((rs->sc_flags & RAIDF_INITED) != 0)) { | | 837 | ((rs->sc_flags & RAIDF_INITED) != 0)) { |
829 | /* Last one... device is not unconfigured yet. | | 838 | /* Last one... device is not unconfigured yet. |
830 | Device shutdown has taken care of setting the | | 839 | Device shutdown has taken care of setting the |
831 | clean bits if RAIDF_INITED is not set | | 840 | clean bits if RAIDF_INITED is not set |
832 | mark things as clean... */ | | 841 | mark things as clean... */ |
833 | | | 842 | |
834 | rf_update_component_labels(raidPtrs[unit], | | 843 | rf_update_component_labels(raidPtrs[unit], |
835 | RF_FINAL_COMPONENT_UPDATE); | | 844 | RF_FINAL_COMPONENT_UPDATE); |
836 | if (doing_shutdown) { | | | |
837 | /* last one, and we're going down, so | | | |
838 | lights out for this RAID set too. */ | | | |
839 | error = rf_Shutdown(raidPtrs[unit]); | | | |
840 | | | | |
841 | /* It's no longer initialized... */ | | | |
842 | rs->sc_flags &= ~RAIDF_INITED; | | | |
843 | | | 845 | |
844 | /* detach the device */ | | 846 | /* If the kernel is shutting down, it will detach |
845 | | | 847 | * this RAID set soon enough. |
846 | cf = device_cfdata(rs->sc_dev); | | 848 | */ |
847 | error = config_detach(rs->sc_dev, DETACH_QUIET); | | | |
848 | free(cf, M_RAIDFRAME); | | | |
849 | | | | |
850 | /* Detach the disk. */ | | | |
851 | disk_detach(&rs->sc_dkdev); | | | |
852 | disk_destroy(&rs->sc_dkdev); | | | |
853 | } | | | |
854 | } | | 849 | } |
855 | | | 850 | |
856 | raidunlock(rs); | | 851 | raidunlock(rs); |
857 | return (0); | | 852 | return (0); |
858 | | | 853 | |
859 | } | | 854 | } |
860 | | | 855 | |
861 | void | | 856 | void |
862 | raidstrategy(struct buf *bp) | | 857 | raidstrategy(struct buf *bp) |
863 | { | | 858 | { |
864 | int s; | | 859 | int s; |
865 | | | 860 | |
866 | unsigned int raidID = raidunit(bp->b_dev); | | 861 | unsigned int raidID = raidunit(bp->b_dev); |
867 | RF_Raid_t *raidPtr; | | 862 | RF_Raid_t *raidPtr; |
868 | struct raid_softc *rs = &raid_softc[raidID]; | | 863 | struct raid_softc *rs = &raid_softc[raidID]; |
869 | int wlabel; | | 864 | int wlabel; |
870 | | | 865 | |
871 | if ((rs->sc_flags & RAIDF_INITED) ==0) { | | 866 | if ((rs->sc_flags & RAIDF_INITED) ==0) { |
872 | bp->b_error = ENXIO; | | 867 | bp->b_error = ENXIO; |
873 | goto done; | | 868 | goto done; |
874 | } | | 869 | } |
875 | if (raidID >= numraid || !raidPtrs[raidID]) { | | 870 | if (raidID >= numraid || !raidPtrs[raidID]) { |
876 | bp->b_error = ENODEV; | | 871 | bp->b_error = ENODEV; |
877 | goto done; | | 872 | goto done; |
878 | } | | 873 | } |
879 | raidPtr = raidPtrs[raidID]; | | 874 | raidPtr = raidPtrs[raidID]; |
880 | if (!raidPtr->valid) { | | 875 | if (!raidPtr->valid) { |
881 | bp->b_error = ENODEV; | | 876 | bp->b_error = ENODEV; |
882 | goto done; | | 877 | goto done; |
883 | } | | 878 | } |
884 | if (bp->b_bcount == 0) { | | 879 | if (bp->b_bcount == 0) { |
885 | db1_printf(("b_bcount is zero..\n")); | | 880 | db1_printf(("b_bcount is zero..\n")); |
886 | goto done; | | 881 | goto done; |
887 | } | | 882 | } |
888 | | | 883 | |
889 | /* | | 884 | /* |
890 | * Do bounds checking and adjust transfer. If there's an | | 885 | * Do bounds checking and adjust transfer. If there's an |
891 | * error, the bounds check will flag that for us. | | 886 | * error, the bounds check will flag that for us. |
892 | */ | | 887 | */ |
893 | | | 888 | |
894 | wlabel = rs->sc_flags & (RAIDF_WLABEL | RAIDF_LABELLING); | | 889 | wlabel = rs->sc_flags & (RAIDF_WLABEL | RAIDF_LABELLING); |
895 | if (DISKPART(bp->b_dev) == RAW_PART) { | | 890 | if (DISKPART(bp->b_dev) == RAW_PART) { |
896 | uint64_t size; /* device size in DEV_BSIZE unit */ | | 891 | uint64_t size; /* device size in DEV_BSIZE unit */ |
897 | | | 892 | |
898 | if (raidPtr->logBytesPerSector > DEV_BSHIFT) { | | 893 | if (raidPtr->logBytesPerSector > DEV_BSHIFT) { |
899 | size = raidPtr->totalSectors << | | 894 | size = raidPtr->totalSectors << |
900 | (raidPtr->logBytesPerSector - DEV_BSHIFT); | | 895 | (raidPtr->logBytesPerSector - DEV_BSHIFT); |
901 | } else { | | 896 | } else { |
902 | size = raidPtr->totalSectors >> | | 897 | size = raidPtr->totalSectors >> |
903 | (DEV_BSHIFT - raidPtr->logBytesPerSector); | | 898 | (DEV_BSHIFT - raidPtr->logBytesPerSector); |
904 | } | | 899 | } |
905 | if (bounds_check_with_mediasize(bp, DEV_BSIZE, size) <= 0) { | | 900 | if (bounds_check_with_mediasize(bp, DEV_BSIZE, size) <= 0) { |
906 | goto done; | | 901 | goto done; |
907 | } | | 902 | } |
908 | } else { | | 903 | } else { |
909 | if (bounds_check_with_label(&rs->sc_dkdev, bp, wlabel) <= 0) { | | 904 | if (bounds_check_with_label(&rs->sc_dkdev, bp, wlabel) <= 0) { |
910 | db1_printf(("Bounds check failed!!:%d %d\n", | | 905 | db1_printf(("Bounds check failed!!:%d %d\n", |
911 | (int) bp->b_blkno, (int) wlabel)); | | 906 | (int) bp->b_blkno, (int) wlabel)); |
912 | goto done; | | 907 | goto done; |
913 | } | | 908 | } |
914 | } | | 909 | } |
915 | s = splbio(); | | 910 | s = splbio(); |
916 | | | 911 | |
917 | bp->b_resid = 0; | | 912 | bp->b_resid = 0; |
918 | | | 913 | |
919 | /* stuff it onto our queue */ | | 914 | /* stuff it onto our queue */ |
920 | bufq_put(rs->buf_queue, bp); | | 915 | bufq_put(rs->buf_queue, bp); |
921 | | | 916 | |
922 | /* scheduled the IO to happen at the next convenient time */ | | 917 | /* scheduled the IO to happen at the next convenient time */ |
923 | wakeup(&(raidPtrs[raidID]->iodone)); | | 918 | wakeup(&(raidPtrs[raidID]->iodone)); |
924 | | | 919 | |
925 | splx(s); | | 920 | splx(s); |
926 | return; | | 921 | return; |
927 | | | 922 | |
928 | done: | | 923 | done: |
929 | bp->b_resid = bp->b_bcount; | | 924 | bp->b_resid = bp->b_bcount; |
930 | biodone(bp); | | 925 | biodone(bp); |
931 | } | | 926 | } |
932 | /* ARGSUSED */ | | 927 | /* ARGSUSED */ |
933 | int | | 928 | int |
934 | raidread(dev_t dev, struct uio *uio, int flags) | | 929 | raidread(dev_t dev, struct uio *uio, int flags) |
935 | { | | 930 | { |
936 | int unit = raidunit(dev); | | 931 | int unit = raidunit(dev); |
937 | struct raid_softc *rs; | | 932 | struct raid_softc *rs; |
938 | | | 933 | |
939 | if (unit >= numraid) | | 934 | if (unit >= numraid) |
940 | return (ENXIO); | | 935 | return (ENXIO); |
941 | rs = &raid_softc[unit]; | | 936 | rs = &raid_softc[unit]; |
942 | | | 937 | |
943 | if ((rs->sc_flags & RAIDF_INITED) == 0) | | 938 | if ((rs->sc_flags & RAIDF_INITED) == 0) |
944 | return (ENXIO); | | 939 | return (ENXIO); |
945 | | | 940 | |
946 | return (physio(raidstrategy, NULL, dev, B_READ, minphys, uio)); | | 941 | return (physio(raidstrategy, NULL, dev, B_READ, minphys, uio)); |
947 | | | 942 | |
948 | } | | 943 | } |
949 | /* ARGSUSED */ | | 944 | /* ARGSUSED */ |
950 | int | | 945 | int |
951 | raidwrite(dev_t dev, struct uio *uio, int flags) | | 946 | raidwrite(dev_t dev, struct uio *uio, int flags) |
952 | { | | 947 | { |
953 | int unit = raidunit(dev); | | 948 | int unit = raidunit(dev); |
954 | struct raid_softc *rs; | | 949 | struct raid_softc *rs; |
955 | | | 950 | |
956 | if (unit >= numraid) | | 951 | if (unit >= numraid) |
957 | return (ENXIO); | | 952 | return (ENXIO); |
958 | rs = &raid_softc[unit]; | | 953 | rs = &raid_softc[unit]; |
959 | | | 954 | |
960 | if ((rs->sc_flags & RAIDF_INITED) == 0) | | 955 | if ((rs->sc_flags & RAIDF_INITED) == 0) |
961 | return (ENXIO); | | 956 | return (ENXIO); |
962 | | | 957 | |
963 | return (physio(raidstrategy, NULL, dev, B_WRITE, minphys, uio)); | | 958 | return (physio(raidstrategy, NULL, dev, B_WRITE, minphys, uio)); |
964 | | | 959 | |
965 | } | | 960 | } |
966 | | | 961 | |
| | | 962 | static int |
| | | 963 | raid_detach_unlocked(struct raid_softc *rs) |
| | | 964 | { |
| | | 965 | int error; |
| | | 966 | RF_Raid_t *raidPtr; |
| | | 967 | |
| | | 968 | raidPtr = raidPtrs[device_unit(rs->sc_dev)]; |
| | | 969 | |
| | | 970 | /* |
| | | 971 | * If somebody has a partition mounted, we shouldn't |
| | | 972 | * shutdown. |
| | | 973 | */ |
| | | 974 | if (rs->sc_dkdev.dk_openmask != 0) |
| | | 975 | return EBUSY; |
| | | 976 | |
| | | 977 | if ((rs->sc_flags & RAIDF_INITED) == 0) |
| | | 978 | ; /* not initialized: nothing to do */ |
| | | 979 | else if ((error = rf_Shutdown(raidPtr)) != 0) |
| | | 980 | return error; |
| | | 981 | else |
| | | 982 | rs->sc_flags &= ~(RAIDF_INITED|RAIDF_SHUTDOWN); |
| | | 983 | |
| | | 984 | /* Detach the disk. */ |
| | | 985 | disk_detach(&rs->sc_dkdev); |
| | | 986 | disk_destroy(&rs->sc_dkdev); |
| | | 987 | |
| | | 988 | return 0; |
| | | 989 | } |
| | | 990 | |
967 | int | | 991 | int |
968 | raidioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) | | 992 | raidioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) |
969 | { | | 993 | { |
970 | int unit = raidunit(dev); | | 994 | int unit = raidunit(dev); |
971 | int error = 0; | | 995 | int error = 0; |
972 | int part, pmask; | | 996 | int part, pmask; |
973 | cfdata_t cf; | | 997 | cfdata_t cf; |
974 | struct raid_softc *rs; | | 998 | struct raid_softc *rs; |
975 | RF_Config_t *k_cfg, *u_cfg; | | 999 | RF_Config_t *k_cfg, *u_cfg; |
976 | RF_Raid_t *raidPtr; | | 1000 | RF_Raid_t *raidPtr; |
977 | RF_RaidDisk_t *diskPtr; | | 1001 | RF_RaidDisk_t *diskPtr; |
978 | RF_AccTotals_t *totals; | | 1002 | RF_AccTotals_t *totals; |
979 | RF_DeviceConfig_t *d_cfg, **ucfgp; | | 1003 | RF_DeviceConfig_t *d_cfg, **ucfgp; |
980 | u_char *specific_buf; | | 1004 | u_char *specific_buf; |
981 | int retcode = 0; | | 1005 | int retcode = 0; |
982 | int column; | | 1006 | int column; |
983 | int raidid; | | 1007 | int raidid; |
984 | struct rf_recon_req *rrcopy, *rr; | | 1008 | struct rf_recon_req *rrcopy, *rr; |
985 | RF_ComponentLabel_t *clabel; | | 1009 | RF_ComponentLabel_t *clabel; |
986 | RF_ComponentLabel_t *ci_label; | | 1010 | RF_ComponentLabel_t *ci_label; |
987 | RF_ComponentLabel_t **clabel_ptr; | | 1011 | RF_ComponentLabel_t **clabel_ptr; |
988 | RF_SingleComponent_t *sparePtr,*componentPtr; | | 1012 | RF_SingleComponent_t *sparePtr,*componentPtr; |
989 | RF_SingleComponent_t component; | | 1013 | RF_SingleComponent_t component; |
990 | RF_ProgressInfo_t progressInfo, **progressInfoPtr; | | 1014 | RF_ProgressInfo_t progressInfo, **progressInfoPtr; |
991 | int i, j, d; | | 1015 | int i, j, d; |
992 | #ifdef __HAVE_OLD_DISKLABEL | | 1016 | #ifdef __HAVE_OLD_DISKLABEL |
993 | struct disklabel newlabel; | | 1017 | struct disklabel newlabel; |
994 | #endif | | 1018 | #endif |
995 | struct dkwedge_info *dkw; | | 1019 | struct dkwedge_info *dkw; |
996 | | | 1020 | |
997 | if (unit >= numraid) | | 1021 | if (unit >= numraid) |
998 | return (ENXIO); | | 1022 | return (ENXIO); |
999 | rs = &raid_softc[unit]; | | 1023 | rs = &raid_softc[unit]; |
1000 | raidPtr = raidPtrs[unit]; | | 1024 | raidPtr = raidPtrs[unit]; |
1001 | | | 1025 | |
1002 | db1_printf(("raidioctl: %d %d %d %d\n", (int) dev, | | 1026 | db1_printf(("raidioctl: %d %d %d %d\n", (int) dev, |
1003 | (int) DISKPART(dev), (int) unit, (int) cmd)); | | 1027 | (int) DISKPART(dev), (int) unit, (int) cmd)); |
1004 | | | 1028 | |
1005 | /* Must be open for writes for these commands... */ | | 1029 | /* Must be open for writes for these commands... */ |
1006 | switch (cmd) { | | 1030 | switch (cmd) { |
1007 | #ifdef DIOCGSECTORSIZE | | 1031 | #ifdef DIOCGSECTORSIZE |
1008 | case DIOCGSECTORSIZE: | | 1032 | case DIOCGSECTORSIZE: |
1009 | *(u_int *)data = raidPtr->bytesPerSector; | | 1033 | *(u_int *)data = raidPtr->bytesPerSector; |
1010 | return 0; | | 1034 | return 0; |
1011 | case DIOCGMEDIASIZE: | | 1035 | case DIOCGMEDIASIZE: |
1012 | *(off_t *)data = | | 1036 | *(off_t *)data = |
1013 | (off_t)raidPtr->totalSectors * raidPtr->bytesPerSector; | | 1037 | (off_t)raidPtr->totalSectors * raidPtr->bytesPerSector; |
1014 | return 0; | | 1038 | return 0; |
1015 | #endif | | 1039 | #endif |
1016 | case DIOCSDINFO: | | 1040 | case DIOCSDINFO: |
1017 | case DIOCWDINFO: | | 1041 | case DIOCWDINFO: |
1018 | #ifdef __HAVE_OLD_DISKLABEL | | 1042 | #ifdef __HAVE_OLD_DISKLABEL |
1019 | case ODIOCWDINFO: | | 1043 | case ODIOCWDINFO: |
1020 | case ODIOCSDINFO: | | 1044 | case ODIOCSDINFO: |
1021 | #endif | | 1045 | #endif |
1022 | case DIOCWLABEL: | | 1046 | case DIOCWLABEL: |
1023 | case DIOCAWEDGE: | | 1047 | case DIOCAWEDGE: |
1024 | case DIOCDWEDGE: | | 1048 | case DIOCDWEDGE: |
1025 | if ((flag & FWRITE) == 0) | | 1049 | if ((flag & FWRITE) == 0) |
1026 | return (EBADF); | | 1050 | return (EBADF); |
1027 | } | | 1051 | } |
1028 | | | 1052 | |
1029 | /* Must be initialized for these... */ | | 1053 | /* Must be initialized for these... */ |
1030 | switch (cmd) { | | 1054 | switch (cmd) { |
1031 | case DIOCGDINFO: | | 1055 | case DIOCGDINFO: |
1032 | case DIOCSDINFO: | | 1056 | case DIOCSDINFO: |
1033 | case DIOCWDINFO: | | 1057 | case DIOCWDINFO: |
1034 | #ifdef __HAVE_OLD_DISKLABEL | | 1058 | #ifdef __HAVE_OLD_DISKLABEL |
1035 | case ODIOCGDINFO: | | 1059 | case ODIOCGDINFO: |
1036 | case ODIOCWDINFO: | | 1060 | case ODIOCWDINFO: |
1037 | case ODIOCSDINFO: | | 1061 | case ODIOCSDINFO: |
1038 | case ODIOCGDEFLABEL: | | 1062 | case ODIOCGDEFLABEL: |
1039 | #endif | | 1063 | #endif |
1040 | case DIOCGPART: | | 1064 | case DIOCGPART: |
1041 | case DIOCWLABEL: | | 1065 | case DIOCWLABEL: |
1042 | case DIOCGDEFLABEL: | | 1066 | case DIOCGDEFLABEL: |
1043 | case DIOCAWEDGE: | | 1067 | case DIOCAWEDGE: |
1044 | case DIOCDWEDGE: | | 1068 | case DIOCDWEDGE: |
1045 | case DIOCLWEDGES: | | 1069 | case DIOCLWEDGES: |
1046 | case DIOCCACHESYNC: | | 1070 | case DIOCCACHESYNC: |
1047 | case RAIDFRAME_SHUTDOWN: | | 1071 | case RAIDFRAME_SHUTDOWN: |
1048 | case RAIDFRAME_REWRITEPARITY: | | 1072 | case RAIDFRAME_REWRITEPARITY: |
1049 | case RAIDFRAME_GET_INFO: | | 1073 | case RAIDFRAME_GET_INFO: |
1050 | case RAIDFRAME_RESET_ACCTOTALS: | | 1074 | case RAIDFRAME_RESET_ACCTOTALS: |
1051 | case RAIDFRAME_GET_ACCTOTALS: | | 1075 | case RAIDFRAME_GET_ACCTOTALS: |
1052 | case RAIDFRAME_KEEP_ACCTOTALS: | | 1076 | case RAIDFRAME_KEEP_ACCTOTALS: |
1053 | case RAIDFRAME_GET_SIZE: | | 1077 | case RAIDFRAME_GET_SIZE: |
1054 | case RAIDFRAME_FAIL_DISK: | | 1078 | case RAIDFRAME_FAIL_DISK: |
1055 | case RAIDFRAME_COPYBACK: | | 1079 | case RAIDFRAME_COPYBACK: |
1056 | case RAIDFRAME_CHECK_RECON_STATUS: | | 1080 | case RAIDFRAME_CHECK_RECON_STATUS: |
1057 | case RAIDFRAME_CHECK_RECON_STATUS_EXT: | | 1081 | case RAIDFRAME_CHECK_RECON_STATUS_EXT: |
1058 | case RAIDFRAME_GET_COMPONENT_LABEL: | | 1082 | case RAIDFRAME_GET_COMPONENT_LABEL: |
1059 | case RAIDFRAME_SET_COMPONENT_LABEL: | | 1083 | case RAIDFRAME_SET_COMPONENT_LABEL: |
1060 | case RAIDFRAME_ADD_HOT_SPARE: | | 1084 | case RAIDFRAME_ADD_HOT_SPARE: |
1061 | case RAIDFRAME_REMOVE_HOT_SPARE: | | 1085 | case RAIDFRAME_REMOVE_HOT_SPARE: |
1062 | case RAIDFRAME_INIT_LABELS: | | 1086 | case RAIDFRAME_INIT_LABELS: |
1063 | case RAIDFRAME_REBUILD_IN_PLACE: | | 1087 | case RAIDFRAME_REBUILD_IN_PLACE: |
1064 | case RAIDFRAME_CHECK_PARITY: | | 1088 | case RAIDFRAME_CHECK_PARITY: |
1065 | case RAIDFRAME_CHECK_PARITYREWRITE_STATUS: | | 1089 | case RAIDFRAME_CHECK_PARITYREWRITE_STATUS: |
1066 | case RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT: | | 1090 | case RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT: |
1067 | case RAIDFRAME_CHECK_COPYBACK_STATUS: | | 1091 | case RAIDFRAME_CHECK_COPYBACK_STATUS: |
1068 | case RAIDFRAME_CHECK_COPYBACK_STATUS_EXT: | | 1092 | case RAIDFRAME_CHECK_COPYBACK_STATUS_EXT: |
1069 | case RAIDFRAME_SET_AUTOCONFIG: | | 1093 | case RAIDFRAME_SET_AUTOCONFIG: |
1070 | case RAIDFRAME_SET_ROOT: | | 1094 | case RAIDFRAME_SET_ROOT: |
1071 | case RAIDFRAME_DELETE_COMPONENT: | | 1095 | case RAIDFRAME_DELETE_COMPONENT: |
1072 | case RAIDFRAME_INCORPORATE_HOT_SPARE: | | 1096 | case RAIDFRAME_INCORPORATE_HOT_SPARE: |
1073 | if ((rs->sc_flags & RAIDF_INITED) == 0) | | 1097 | if ((rs->sc_flags & RAIDF_INITED) == 0) |
1074 | return (ENXIO); | | 1098 | return (ENXIO); |
1075 | } | | 1099 | } |
1076 | | | 1100 | |
1077 | switch (cmd) { | | 1101 | switch (cmd) { |
1078 | #ifdef COMPAT_50 | | 1102 | #ifdef COMPAT_50 |
1079 | case RAIDFRAME_GET_INFO50: | | 1103 | case RAIDFRAME_GET_INFO50: |
1080 | return rf_get_info50(raidPtr, data); | | 1104 | return rf_get_info50(raidPtr, data); |
1081 | | | 1105 | |
1082 | case RAIDFRAME_CONFIGURE50: | | 1106 | case RAIDFRAME_CONFIGURE50: |
1083 | if ((retcode = rf_config50(raidPtr, unit, data, &k_cfg)) != 0) | | 1107 | if ((retcode = rf_config50(raidPtr, unit, data, &k_cfg)) != 0) |
1084 | return retcode; | | 1108 | return retcode; |
1085 | goto config; | | 1109 | goto config; |
1086 | #endif | | 1110 | #endif |
1087 | /* configure the system */ | | 1111 | /* configure the system */ |
1088 | case RAIDFRAME_CONFIGURE: | | 1112 | case RAIDFRAME_CONFIGURE: |
1089 | | | 1113 | |
1090 | if (raidPtr->valid) { | | 1114 | if (raidPtr->valid) { |
1091 | /* There is a valid RAID set running on this unit! */ | | 1115 | /* There is a valid RAID set running on this unit! */ |
1092 | printf("raid%d: Device already configured!\n",unit); | | 1116 | printf("raid%d: Device already configured!\n",unit); |
1093 | return(EINVAL); | | 1117 | return(EINVAL); |
1094 | } | | 1118 | } |
1095 | | | 1119 | |
1096 | /* copy-in the configuration information */ | | 1120 | /* copy-in the configuration information */ |
1097 | /* data points to a pointer to the configuration structure */ | | 1121 | /* data points to a pointer to the configuration structure */ |
1098 | | | 1122 | |
1099 | u_cfg = *((RF_Config_t **) data); | | 1123 | u_cfg = *((RF_Config_t **) data); |
1100 | RF_Malloc(k_cfg, sizeof(RF_Config_t), (RF_Config_t *)); | | 1124 | RF_Malloc(k_cfg, sizeof(RF_Config_t), (RF_Config_t *)); |
1101 | if (k_cfg == NULL) { | | 1125 | if (k_cfg == NULL) { |
1102 | return (ENOMEM); | | 1126 | return (ENOMEM); |
1103 | } | | 1127 | } |
1104 | retcode = copyin(u_cfg, k_cfg, sizeof(RF_Config_t)); | | 1128 | retcode = copyin(u_cfg, k_cfg, sizeof(RF_Config_t)); |
1105 | if (retcode) { | | 1129 | if (retcode) { |
1106 | RF_Free(k_cfg, sizeof(RF_Config_t)); | | 1130 | RF_Free(k_cfg, sizeof(RF_Config_t)); |
1107 | db1_printf(("rf_ioctl: retcode=%d copyin.1\n", | | 1131 | db1_printf(("rf_ioctl: retcode=%d copyin.1\n", |
1108 | retcode)); | | 1132 | retcode)); |
1109 | return (retcode); | | 1133 | return (retcode); |
1110 | } | | 1134 | } |
1111 | goto config; | | 1135 | goto config; |
1112 | config: | | 1136 | config: |
1113 | /* allocate a buffer for the layout-specific data, and copy it | | 1137 | /* allocate a buffer for the layout-specific data, and copy it |
1114 | * in */ | | 1138 | * in */ |
1115 | if (k_cfg->layoutSpecificSize) { | | 1139 | if (k_cfg->layoutSpecificSize) { |
1116 | if (k_cfg->layoutSpecificSize > 10000) { | | 1140 | if (k_cfg->layoutSpecificSize > 10000) { |
1117 | /* sanity check */ | | 1141 | /* sanity check */ |
1118 | RF_Free(k_cfg, sizeof(RF_Config_t)); | | 1142 | RF_Free(k_cfg, sizeof(RF_Config_t)); |
1119 | return (EINVAL); | | 1143 | return (EINVAL); |
1120 | } | | 1144 | } |
1121 | RF_Malloc(specific_buf, k_cfg->layoutSpecificSize, | | 1145 | RF_Malloc(specific_buf, k_cfg->layoutSpecificSize, |
1122 | (u_char *)); | | 1146 | (u_char *)); |
1123 | if (specific_buf == NULL) { | | 1147 | if (specific_buf == NULL) { |
1124 | RF_Free(k_cfg, sizeof(RF_Config_t)); | | 1148 | RF_Free(k_cfg, sizeof(RF_Config_t)); |
1125 | return (ENOMEM); | | 1149 | return (ENOMEM); |
1126 | } | | 1150 | } |
1127 | retcode = copyin(k_cfg->layoutSpecific, specific_buf, | | 1151 | retcode = copyin(k_cfg->layoutSpecific, specific_buf, |
1128 | k_cfg->layoutSpecificSize); | | 1152 | k_cfg->layoutSpecificSize); |
1129 | if (retcode) { | | 1153 | if (retcode) { |
1130 | RF_Free(k_cfg, sizeof(RF_Config_t)); | | 1154 | RF_Free(k_cfg, sizeof(RF_Config_t)); |
1131 | RF_Free(specific_buf, | | 1155 | RF_Free(specific_buf, |
1132 | k_cfg->layoutSpecificSize); | | 1156 | k_cfg->layoutSpecificSize); |
1133 | db1_printf(("rf_ioctl: retcode=%d copyin.2\n", | | 1157 | db1_printf(("rf_ioctl: retcode=%d copyin.2\n", |
1134 | retcode)); | | 1158 | retcode)); |
1135 | return (retcode); | | 1159 | return (retcode); |
1136 | } | | 1160 | } |
1137 | } else | | 1161 | } else |
1138 | specific_buf = NULL; | | 1162 | specific_buf = NULL; |
1139 | k_cfg->layoutSpecific = specific_buf; | | 1163 | k_cfg->layoutSpecific = specific_buf; |
1140 | | | 1164 | |
1141 | /* should do some kind of sanity check on the configuration. | | 1165 | /* should do some kind of sanity check on the configuration. |
1142 | * Store the sum of all the bytes in the last byte? */ | | 1166 | * Store the sum of all the bytes in the last byte? */ |
1143 | | | 1167 | |
1144 | /* configure the system */ | | 1168 | /* configure the system */ |
1145 | | | 1169 | |
1146 | /* | | 1170 | /* |
1147 | * Clear the entire RAID descriptor, just to make sure | | 1171 | * Clear the entire RAID descriptor, just to make sure |
1148 | * there is no stale data left in the case of a | | 1172 | * there is no stale data left in the case of a |
1149 | * reconfiguration | | 1173 | * reconfiguration |
1150 | */ | | 1174 | */ |
1151 | memset((char *) raidPtr, 0, sizeof(RF_Raid_t)); | | 1175 | memset((char *) raidPtr, 0, sizeof(RF_Raid_t)); |
1152 | raidPtr->raidid = unit; | | 1176 | raidPtr->raidid = unit; |
1153 | | | 1177 | |
1154 | retcode = rf_Configure(raidPtr, k_cfg, NULL); | | 1178 | retcode = rf_Configure(raidPtr, k_cfg, NULL); |
1155 | | | 1179 | |
1156 | if (retcode == 0) { | | 1180 | if (retcode == 0) { |
1157 | | | 1181 | |
1158 | /* allow this many simultaneous IO's to | | 1182 | /* allow this many simultaneous IO's to |
1159 | this RAID device */ | | 1183 | this RAID device */ |
1160 | raidPtr->openings = RAIDOUTSTANDING; | | 1184 | raidPtr->openings = RAIDOUTSTANDING; |
1161 | | | 1185 | |
1162 | raidinit(raidPtr); | | 1186 | raidinit(raidPtr); |
1163 | rf_markalldirty(raidPtr); | | 1187 | rf_markalldirty(raidPtr); |
1164 | } | | 1188 | } |
1165 | /* free the buffers. No return code here. */ | | 1189 | /* free the buffers. No return code here. */ |
1166 | if (k_cfg->layoutSpecificSize) { | | 1190 | if (k_cfg->layoutSpecificSize) { |
1167 | RF_Free(specific_buf, k_cfg->layoutSpecificSize); | | 1191 | RF_Free(specific_buf, k_cfg->layoutSpecificSize); |
1168 | } | | 1192 | } |
1169 | RF_Free(k_cfg, sizeof(RF_Config_t)); | | 1193 | RF_Free(k_cfg, sizeof(RF_Config_t)); |
1170 | | | 1194 | |
1171 | return (retcode); | | 1195 | return (retcode); |
1172 | | | 1196 | |
1173 | /* shutdown the system */ | | 1197 | /* shutdown the system */ |
1174 | case RAIDFRAME_SHUTDOWN: | | 1198 | case RAIDFRAME_SHUTDOWN: |
1175 | | | 1199 | |
| | | 1200 | part = DISKPART(dev); |
| | | 1201 | pmask = (1 << part); |
| | | 1202 | |
1176 | if ((error = raidlock(rs)) != 0) | | 1203 | if ((error = raidlock(rs)) != 0) |
1177 | return (error); | | 1204 | return (error); |
1178 | | | 1205 | |
1179 | /* | | | |
1180 | * If somebody has a partition mounted, we shouldn't | | | |
1181 | * shutdown. | | | |
1182 | */ | | | |
1183 | | | | |
1184 | part = DISKPART(dev); | | | |
1185 | pmask = (1 << part); | | | |
1186 | if ((rs->sc_dkdev.dk_openmask & ~pmask) || | | 1206 | if ((rs->sc_dkdev.dk_openmask & ~pmask) || |
1187 | ((rs->sc_dkdev.dk_bopenmask & pmask) && | | 1207 | ((rs->sc_dkdev.dk_bopenmask & pmask) && |
1188 | (rs->sc_dkdev.dk_copenmask & pmask))) { | | 1208 | (rs->sc_dkdev.dk_copenmask & pmask))) |
1189 | raidunlock(rs); | | 1209 | retcode = EBUSY; |
1190 | return (EBUSY); | | 1210 | else { |
| | | 1211 | rs->sc_flags |= RAIDF_SHUTDOWN; |
| | | 1212 | rs->sc_dkdev.dk_copenmask &= ~pmask; |
| | | 1213 | rs->sc_dkdev.dk_bopenmask &= ~pmask; |
| | | 1214 | rs->sc_dkdev.dk_openmask &= ~pmask; |
| | | 1215 | retcode = 0; |
1191 | } | | 1216 | } |
1192 | | | 1217 | |
1193 | retcode = rf_Shutdown(raidPtr); | | 1218 | raidunlock(rs); |
1194 | | | 1219 | |
1195 | /* It's no longer initialized... */ | | 1220 | if (retcode != 0) |
1196 | rs->sc_flags &= ~RAIDF_INITED; | | 1221 | return retcode; |
1197 | | | 1222 | |
1198 | /* free the pseudo device attach bits */ | | 1223 | /* free the pseudo device attach bits */ |
1199 | | | 1224 | |
1200 | cf = device_cfdata(rs->sc_dev); | | 1225 | cf = device_cfdata(rs->sc_dev); |
1201 | /* XXX this causes us to not return any errors | | 1226 | if ((retcode = config_detach(rs->sc_dev, DETACH_QUIET)) == 0) |
1202 | from the above call to rf_Shutdown() */ | | 1227 | free(cf, M_RAIDFRAME); |
1203 | retcode = config_detach(rs->sc_dev, DETACH_QUIET); | | | |
1204 | free(cf, M_RAIDFRAME); | | | |
1205 | | | | |
1206 | /* Detach the disk. */ | | | |
1207 | disk_detach(&rs->sc_dkdev); | | | |
1208 | disk_destroy(&rs->sc_dkdev); | | | |
1209 | | | | |
1210 | raidunlock(rs); | | | |
1211 | | | 1228 | |
1212 | return (retcode); | | 1229 | return (retcode); |
1213 | case RAIDFRAME_GET_COMPONENT_LABEL: | | 1230 | case RAIDFRAME_GET_COMPONENT_LABEL: |
1214 | clabel_ptr = (RF_ComponentLabel_t **) data; | | 1231 | clabel_ptr = (RF_ComponentLabel_t **) data; |
1215 | /* need to read the component label for the disk indicated | | 1232 | /* need to read the component label for the disk indicated |
1216 | by row,column in clabel */ | | 1233 | by row,column in clabel */ |
1217 | | | 1234 | |
1218 | /* For practice, let's get it directly fromdisk, rather | | 1235 | /* For practice, let's get it directly fromdisk, rather |
1219 | than from the in-core copy */ | | 1236 | than from the in-core copy */ |
1220 | RF_Malloc( clabel, sizeof( RF_ComponentLabel_t ), | | 1237 | RF_Malloc( clabel, sizeof( RF_ComponentLabel_t ), |
1221 | (RF_ComponentLabel_t *)); | | 1238 | (RF_ComponentLabel_t *)); |
1222 | if (clabel == NULL) | | 1239 | if (clabel == NULL) |
1223 | return (ENOMEM); | | 1240 | return (ENOMEM); |
1224 | | | 1241 | |
1225 | retcode = copyin( *clabel_ptr, clabel, | | 1242 | retcode = copyin( *clabel_ptr, clabel, |
1226 | sizeof(RF_ComponentLabel_t)); | | 1243 | sizeof(RF_ComponentLabel_t)); |
1227 | | | 1244 | |
1228 | if (retcode) { | | 1245 | if (retcode) { |
1229 | RF_Free( clabel, sizeof(RF_ComponentLabel_t)); | | 1246 | RF_Free( clabel, sizeof(RF_ComponentLabel_t)); |
1230 | return(retcode); | | 1247 | return(retcode); |
1231 | } | | 1248 | } |
1232 | | | 1249 | |
1233 | clabel->row = 0; /* Don't allow looking at anything else.*/ | | 1250 | clabel->row = 0; /* Don't allow looking at anything else.*/ |
1234 | | | 1251 | |
1235 | column = clabel->column; | | 1252 | column = clabel->column; |
1236 | | | 1253 | |
1237 | if ((column < 0) || (column >= raidPtr->numCol + | | 1254 | if ((column < 0) || (column >= raidPtr->numCol + |
1238 | raidPtr->numSpare)) { | | 1255 | raidPtr->numSpare)) { |
1239 | RF_Free( clabel, sizeof(RF_ComponentLabel_t)); | | 1256 | RF_Free( clabel, sizeof(RF_ComponentLabel_t)); |
1240 | return(EINVAL); | | 1257 | return(EINVAL); |
1241 | } | | 1258 | } |
1242 | | | 1259 | |
1243 | retcode = raidread_component_label(raidPtr->Disks[column].dev, | | 1260 | retcode = raidread_component_label(raidPtr->Disks[column].dev, |
1244 | raidPtr->raid_cinfo[column].ci_vp, | | 1261 | raidPtr->raid_cinfo[column].ci_vp, |
1245 | clabel ); | | 1262 | clabel ); |
1246 | | | 1263 | |
1247 | if (retcode == 0) { | | 1264 | if (retcode == 0) { |
1248 | retcode = copyout(clabel, *clabel_ptr, | | 1265 | retcode = copyout(clabel, *clabel_ptr, |
1249 | sizeof(RF_ComponentLabel_t)); | | 1266 | sizeof(RF_ComponentLabel_t)); |
1250 | } | | 1267 | } |
1251 | RF_Free(clabel, sizeof(RF_ComponentLabel_t)); | | 1268 | RF_Free(clabel, sizeof(RF_ComponentLabel_t)); |
1252 | return (retcode); | | 1269 | return (retcode); |
1253 | | | 1270 | |
1254 | case RAIDFRAME_SET_COMPONENT_LABEL: | | 1271 | case RAIDFRAME_SET_COMPONENT_LABEL: |
1255 | clabel = (RF_ComponentLabel_t *) data; | | 1272 | clabel = (RF_ComponentLabel_t *) data; |
1256 | | | 1273 | |
1257 | /* XXX check the label for valid stuff... */ | | 1274 | /* XXX check the label for valid stuff... */ |
1258 | /* Note that some things *should not* get modified -- | | 1275 | /* Note that some things *should not* get modified -- |
1259 | the user should be re-initing the labels instead of | | 1276 | the user should be re-initing the labels instead of |
1260 | trying to patch things. | | 1277 | trying to patch things. |
1261 | */ | | 1278 | */ |
1262 | | | 1279 | |
1263 | raidid = raidPtr->raidid; | | 1280 | raidid = raidPtr->raidid; |
1264 | #ifdef DEBUG | | 1281 | #ifdef DEBUG |
1265 | printf("raid%d: Got component label:\n", raidid); | | 1282 | printf("raid%d: Got component label:\n", raidid); |
1266 | printf("raid%d: Version: %d\n", raidid, clabel->version); | | 1283 | printf("raid%d: Version: %d\n", raidid, clabel->version); |
1267 | printf("raid%d: Serial Number: %d\n", raidid, clabel->serial_number); | | 1284 | printf("raid%d: Serial Number: %d\n", raidid, clabel->serial_number); |
1268 | printf("raid%d: Mod counter: %d\n", raidid, clabel->mod_counter); | | 1285 | printf("raid%d: Mod counter: %d\n", raidid, clabel->mod_counter); |
1269 | printf("raid%d: Column: %d\n", raidid, clabel->column); | | 1286 | printf("raid%d: Column: %d\n", raidid, clabel->column); |
1270 | printf("raid%d: Num Columns: %d\n", raidid, clabel->num_columns); | | 1287 | printf("raid%d: Num Columns: %d\n", raidid, clabel->num_columns); |
1271 | printf("raid%d: Clean: %d\n", raidid, clabel->clean); | | 1288 | printf("raid%d: Clean: %d\n", raidid, clabel->clean); |
1272 | printf("raid%d: Status: %d\n", raidid, clabel->status); | | 1289 | printf("raid%d: Status: %d\n", raidid, clabel->status); |
1273 | #endif | | 1290 | #endif |
1274 | clabel->row = 0; | | 1291 | clabel->row = 0; |
1275 | column = clabel->column; | | 1292 | column = clabel->column; |
1276 | | | 1293 | |
1277 | if ((column < 0) || (column >= raidPtr->numCol)) { | | 1294 | if ((column < 0) || (column >= raidPtr->numCol)) { |
1278 | return(EINVAL); | | 1295 | return(EINVAL); |
1279 | } | | 1296 | } |
1280 | | | 1297 | |
1281 | /* XXX this isn't allowed to do anything for now :-) */ | | 1298 | /* XXX this isn't allowed to do anything for now :-) */ |
1282 | | | 1299 | |
1283 | /* XXX and before it is, we need to fill in the rest | | 1300 | /* XXX and before it is, we need to fill in the rest |
1284 | of the fields!?!?!?! */ | | 1301 | of the fields!?!?!?! */ |
1285 | #if 0 | | 1302 | #if 0 |
1286 | raidwrite_component_label( | | 1303 | raidwrite_component_label( |
1287 | raidPtr->Disks[column].dev, | | 1304 | raidPtr->Disks[column].dev, |
1288 | raidPtr->raid_cinfo[column].ci_vp, | | 1305 | raidPtr->raid_cinfo[column].ci_vp, |
1289 | clabel ); | | 1306 | clabel ); |
1290 | #endif | | 1307 | #endif |
1291 | return (0); | | 1308 | return (0); |
1292 | | | 1309 | |
1293 | case RAIDFRAME_INIT_LABELS: | | 1310 | case RAIDFRAME_INIT_LABELS: |
1294 | clabel = (RF_ComponentLabel_t *) data; | | 1311 | clabel = (RF_ComponentLabel_t *) data; |
1295 | /* | | 1312 | /* |
1296 | we only want the serial number from | | 1313 | we only want the serial number from |
1297 | the above. We get all the rest of the information | | 1314 | the above. We get all the rest of the information |
1298 | from the config that was used to create this RAID | | 1315 | from the config that was used to create this RAID |
1299 | set. | | 1316 | set. |
1300 | */ | | 1317 | */ |
1301 | | | 1318 | |
1302 | raidPtr->serial_number = clabel->serial_number; | | 1319 | raidPtr->serial_number = clabel->serial_number; |
1303 | | | 1320 | |
1304 | RF_Malloc(ci_label, sizeof(RF_ComponentLabel_t), | | 1321 | RF_Malloc(ci_label, sizeof(RF_ComponentLabel_t), |
1305 | (RF_ComponentLabel_t *)); | | 1322 | (RF_ComponentLabel_t *)); |
1306 | if (ci_label == NULL) | | 1323 | if (ci_label == NULL) |
1307 | return (ENOMEM); | | 1324 | return (ENOMEM); |
1308 | | | 1325 | |
1309 | raid_init_component_label(raidPtr, ci_label); | | 1326 | raid_init_component_label(raidPtr, ci_label); |
1310 | ci_label->serial_number = clabel->serial_number; | | 1327 | ci_label->serial_number = clabel->serial_number; |
1311 | ci_label->row = 0; /* we dont' pretend to support more */ | | 1328 | ci_label->row = 0; /* we dont' pretend to support more */ |
1312 | | | 1329 | |
1313 | for(column=0;column<raidPtr->numCol;column++) { | | 1330 | for(column=0;column<raidPtr->numCol;column++) { |
1314 | diskPtr = &raidPtr->Disks[column]; | | 1331 | diskPtr = &raidPtr->Disks[column]; |
1315 | if (!RF_DEAD_DISK(diskPtr->status)) { | | 1332 | if (!RF_DEAD_DISK(diskPtr->status)) { |
1316 | ci_label->partitionSize = diskPtr->partitionSize; | | 1333 | ci_label->partitionSize = diskPtr->partitionSize; |
1317 | ci_label->column = column; | | 1334 | ci_label->column = column; |
1318 | raidwrite_component_label( | | 1335 | raidwrite_component_label( |
1319 | raidPtr->Disks[column].dev, | | 1336 | raidPtr->Disks[column].dev, |
1320 | raidPtr->raid_cinfo[column].ci_vp, | | 1337 | raidPtr->raid_cinfo[column].ci_vp, |
1321 | ci_label ); | | 1338 | ci_label ); |
1322 | } | | 1339 | } |
1323 | } | | 1340 | } |
1324 | RF_Free(ci_label, sizeof(RF_ComponentLabel_t)); | | 1341 | RF_Free(ci_label, sizeof(RF_ComponentLabel_t)); |
1325 | | | 1342 | |
1326 | return (retcode); | | 1343 | return (retcode); |
1327 | case RAIDFRAME_SET_AUTOCONFIG: | | 1344 | case RAIDFRAME_SET_AUTOCONFIG: |
1328 | d = rf_set_autoconfig(raidPtr, *(int *) data); | | 1345 | d = rf_set_autoconfig(raidPtr, *(int *) data); |
1329 | printf("raid%d: New autoconfig value is: %d\n", | | 1346 | printf("raid%d: New autoconfig value is: %d\n", |
1330 | raidPtr->raidid, d); | | 1347 | raidPtr->raidid, d); |
1331 | *(int *) data = d; | | 1348 | *(int *) data = d; |
1332 | return (retcode); | | 1349 | return (retcode); |
1333 | | | 1350 | |
1334 | case RAIDFRAME_SET_ROOT: | | 1351 | case RAIDFRAME_SET_ROOT: |
1335 | d = rf_set_rootpartition(raidPtr, *(int *) data); | | 1352 | d = rf_set_rootpartition(raidPtr, *(int *) data); |
1336 | printf("raid%d: New rootpartition value is: %d\n", | | 1353 | printf("raid%d: New rootpartition value is: %d\n", |
1337 | raidPtr->raidid, d); | | 1354 | raidPtr->raidid, d); |
1338 | *(int *) data = d; | | 1355 | *(int *) data = d; |
1339 | return (retcode); | | 1356 | return (retcode); |
1340 | | | 1357 | |
1341 | /* initialize all parity */ | | 1358 | /* initialize all parity */ |
1342 | case RAIDFRAME_REWRITEPARITY: | | 1359 | case RAIDFRAME_REWRITEPARITY: |
1343 | | | 1360 | |
1344 | if (raidPtr->Layout.map->faultsTolerated == 0) { | | 1361 | if (raidPtr->Layout.map->faultsTolerated == 0) { |
1345 | /* Parity for RAID 0 is trivially correct */ | | 1362 | /* Parity for RAID 0 is trivially correct */ |
1346 | raidPtr->parity_good = RF_RAID_CLEAN; | | 1363 | raidPtr->parity_good = RF_RAID_CLEAN; |
1347 | return(0); | | 1364 | return(0); |
1348 | } | | 1365 | } |
1349 | | | 1366 | |
1350 | if (raidPtr->parity_rewrite_in_progress == 1) { | | 1367 | if (raidPtr->parity_rewrite_in_progress == 1) { |
1351 | /* Re-write is already in progress! */ | | 1368 | /* Re-write is already in progress! */ |
1352 | return(EINVAL); | | 1369 | return(EINVAL); |
1353 | } | | 1370 | } |
1354 | | | 1371 | |
1355 | retcode = RF_CREATE_THREAD(raidPtr->parity_rewrite_thread, | | 1372 | retcode = RF_CREATE_THREAD(raidPtr->parity_rewrite_thread, |
1356 | rf_RewriteParityThread, | | 1373 | rf_RewriteParityThread, |
1357 | raidPtr,"raid_parity"); | | 1374 | raidPtr,"raid_parity"); |
1358 | return (retcode); | | 1375 | return (retcode); |
1359 | | | 1376 | |
1360 | | | 1377 | |
1361 | case RAIDFRAME_ADD_HOT_SPARE: | | 1378 | case RAIDFRAME_ADD_HOT_SPARE: |
1362 | sparePtr = (RF_SingleComponent_t *) data; | | 1379 | sparePtr = (RF_SingleComponent_t *) data; |
1363 | memcpy( &component, sparePtr, sizeof(RF_SingleComponent_t)); | | 1380 | memcpy( &component, sparePtr, sizeof(RF_SingleComponent_t)); |
1364 | retcode = rf_add_hot_spare(raidPtr, &component); | | 1381 | retcode = rf_add_hot_spare(raidPtr, &component); |
1365 | return(retcode); | | 1382 | return(retcode); |
1366 | | | 1383 | |
1367 | case RAIDFRAME_REMOVE_HOT_SPARE: | | 1384 | case RAIDFRAME_REMOVE_HOT_SPARE: |
1368 | return(retcode); | | 1385 | return(retcode); |
1369 | | | 1386 | |
1370 | case RAIDFRAME_DELETE_COMPONENT: | | 1387 | case RAIDFRAME_DELETE_COMPONENT: |
1371 | componentPtr = (RF_SingleComponent_t *)data; | | 1388 | componentPtr = (RF_SingleComponent_t *)data; |
1372 | memcpy( &component, componentPtr, | | 1389 | memcpy( &component, componentPtr, |
1373 | sizeof(RF_SingleComponent_t)); | | 1390 | sizeof(RF_SingleComponent_t)); |
1374 | retcode = rf_delete_component(raidPtr, &component); | | 1391 | retcode = rf_delete_component(raidPtr, &component); |
1375 | return(retcode); | | 1392 | return(retcode); |
1376 | | | 1393 | |
1377 | case RAIDFRAME_INCORPORATE_HOT_SPARE: | | 1394 | case RAIDFRAME_INCORPORATE_HOT_SPARE: |
1378 | componentPtr = (RF_SingleComponent_t *)data; | | 1395 | componentPtr = (RF_SingleComponent_t *)data; |
1379 | memcpy( &component, componentPtr, | | 1396 | memcpy( &component, componentPtr, |
1380 | sizeof(RF_SingleComponent_t)); | | 1397 | sizeof(RF_SingleComponent_t)); |
1381 | retcode = rf_incorporate_hot_spare(raidPtr, &component); | | 1398 | retcode = rf_incorporate_hot_spare(raidPtr, &component); |
1382 | return(retcode); | | 1399 | return(retcode); |
1383 | | | 1400 | |
1384 | case RAIDFRAME_REBUILD_IN_PLACE: | | 1401 | case RAIDFRAME_REBUILD_IN_PLACE: |
1385 | | | 1402 | |
1386 | if (raidPtr->Layout.map->faultsTolerated == 0) { | | 1403 | if (raidPtr->Layout.map->faultsTolerated == 0) { |
1387 | /* Can't do this on a RAID 0!! */ | | 1404 | /* Can't do this on a RAID 0!! */ |
1388 | return(EINVAL); | | 1405 | return(EINVAL); |
1389 | } | | 1406 | } |
1390 | | | 1407 | |
1391 | if (raidPtr->recon_in_progress == 1) { | | 1408 | if (raidPtr->recon_in_progress == 1) { |
1392 | /* a reconstruct is already in progress! */ | | 1409 | /* a reconstruct is already in progress! */ |
1393 | return(EINVAL); | | 1410 | return(EINVAL); |
1394 | } | | 1411 | } |
1395 | | | 1412 | |
1396 | componentPtr = (RF_SingleComponent_t *) data; | | 1413 | componentPtr = (RF_SingleComponent_t *) data; |
1397 | memcpy( &component, componentPtr, | | 1414 | memcpy( &component, componentPtr, |
1398 | sizeof(RF_SingleComponent_t)); | | 1415 | sizeof(RF_SingleComponent_t)); |
1399 | component.row = 0; /* we don't support any more */ | | 1416 | component.row = 0; /* we don't support any more */ |
1400 | column = component.column; | | 1417 | column = component.column; |
1401 | | | 1418 | |
1402 | if ((column < 0) || (column >= raidPtr->numCol)) { | | 1419 | if ((column < 0) || (column >= raidPtr->numCol)) { |
1403 | return(EINVAL); | | 1420 | return(EINVAL); |
1404 | } | | 1421 | } |
1405 | | | 1422 | |
1406 | RF_LOCK_MUTEX(raidPtr->mutex); | | 1423 | RF_LOCK_MUTEX(raidPtr->mutex); |
1407 | if ((raidPtr->Disks[column].status == rf_ds_optimal) && | | 1424 | if ((raidPtr->Disks[column].status == rf_ds_optimal) && |
1408 | (raidPtr->numFailures > 0)) { | | 1425 | (raidPtr->numFailures > 0)) { |
1409 | /* XXX 0 above shouldn't be constant!!! */ | | 1426 | /* XXX 0 above shouldn't be constant!!! */ |
1410 | /* some component other than this has failed. | | 1427 | /* some component other than this has failed. |
1411 | Let's not make things worse than they already | | 1428 | Let's not make things worse than they already |
1412 | are... */ | | 1429 | are... */ |
1413 | printf("raid%d: Unable to reconstruct to disk at:\n", | | 1430 | printf("raid%d: Unable to reconstruct to disk at:\n", |
1414 | raidPtr->raidid); | | 1431 | raidPtr->raidid); |
1415 | printf("raid%d: Col: %d Too many failures.\n", | | 1432 | printf("raid%d: Col: %d Too many failures.\n", |
1416 | raidPtr->raidid, column); | | 1433 | raidPtr->raidid, column); |
1417 | RF_UNLOCK_MUTEX(raidPtr->mutex); | | 1434 | RF_UNLOCK_MUTEX(raidPtr->mutex); |
1418 | return (EINVAL); | | 1435 | return (EINVAL); |
1419 | } | | 1436 | } |
1420 | if (raidPtr->Disks[column].status == | | 1437 | if (raidPtr->Disks[column].status == |
1421 | rf_ds_reconstructing) { | | 1438 | rf_ds_reconstructing) { |
1422 | printf("raid%d: Unable to reconstruct to disk at:\n", | | 1439 | printf("raid%d: Unable to reconstruct to disk at:\n", |
1423 | raidPtr->raidid); | | 1440 | raidPtr->raidid); |
1424 | printf("raid%d: Col: %d Reconstruction already occuring!\n", raidPtr->raidid, column); | | 1441 | printf("raid%d: Col: %d Reconstruction already occuring!\n", raidPtr->raidid, column); |
1425 | | | 1442 | |
1426 | RF_UNLOCK_MUTEX(raidPtr->mutex); | | 1443 | RF_UNLOCK_MUTEX(raidPtr->mutex); |
1427 | return (EINVAL); | | 1444 | return (EINVAL); |
1428 | } | | 1445 | } |
1429 | if (raidPtr->Disks[column].status == rf_ds_spared) { | | 1446 | if (raidPtr->Disks[column].status == rf_ds_spared) { |
1430 | RF_UNLOCK_MUTEX(raidPtr->mutex); | | 1447 | RF_UNLOCK_MUTEX(raidPtr->mutex); |
1431 | return (EINVAL); | | 1448 | return (EINVAL); |
1432 | } | | 1449 | } |
1433 | RF_UNLOCK_MUTEX(raidPtr->mutex); | | 1450 | RF_UNLOCK_MUTEX(raidPtr->mutex); |
1434 | | | 1451 | |
1435 | RF_Malloc(rrcopy, sizeof(*rrcopy), (struct rf_recon_req *)); | | 1452 | RF_Malloc(rrcopy, sizeof(*rrcopy), (struct rf_recon_req *)); |
1436 | if (rrcopy == NULL) | | 1453 | if (rrcopy == NULL) |
1437 | return(ENOMEM); | | 1454 | return(ENOMEM); |
1438 | | | 1455 | |
1439 | rrcopy->raidPtr = (void *) raidPtr; | | 1456 | rrcopy->raidPtr = (void *) raidPtr; |
1440 | rrcopy->col = column; | | 1457 | rrcopy->col = column; |
1441 | | | 1458 | |
1442 | retcode = RF_CREATE_THREAD(raidPtr->recon_thread, | | 1459 | retcode = RF_CREATE_THREAD(raidPtr->recon_thread, |
1443 | rf_ReconstructInPlaceThread, | | 1460 | rf_ReconstructInPlaceThread, |
1444 | rrcopy,"raid_reconip"); | | 1461 | rrcopy,"raid_reconip"); |
1445 | return(retcode); | | 1462 | return(retcode); |
1446 | | | 1463 | |
1447 | case RAIDFRAME_GET_INFO: | | 1464 | case RAIDFRAME_GET_INFO: |
1448 | if (!raidPtr->valid) | | 1465 | if (!raidPtr->valid) |
1449 | return (ENODEV); | | 1466 | return (ENODEV); |
1450 | ucfgp = (RF_DeviceConfig_t **) data; | | 1467 | ucfgp = (RF_DeviceConfig_t **) data; |
1451 | RF_Malloc(d_cfg, sizeof(RF_DeviceConfig_t), | | 1468 | RF_Malloc(d_cfg, sizeof(RF_DeviceConfig_t), |
1452 | (RF_DeviceConfig_t *)); | | 1469 | (RF_DeviceConfig_t *)); |
1453 | if (d_cfg == NULL) | | 1470 | if (d_cfg == NULL) |
1454 | return (ENOMEM); | | 1471 | return (ENOMEM); |
1455 | d_cfg->rows = 1; /* there is only 1 row now */ | | 1472 | d_cfg->rows = 1; /* there is only 1 row now */ |
1456 | d_cfg->cols = raidPtr->numCol; | | 1473 | d_cfg->cols = raidPtr->numCol; |
1457 | d_cfg->ndevs = raidPtr->numCol; | | 1474 | d_cfg->ndevs = raidPtr->numCol; |
1458 | if (d_cfg->ndevs >= RF_MAX_DISKS) { | | 1475 | if (d_cfg->ndevs >= RF_MAX_DISKS) { |
1459 | RF_Free(d_cfg, sizeof(RF_DeviceConfig_t)); | | 1476 | RF_Free(d_cfg, sizeof(RF_DeviceConfig_t)); |
1460 | return (ENOMEM); | | 1477 | return (ENOMEM); |
1461 | } | | 1478 | } |
1462 | d_cfg->nspares = raidPtr->numSpare; | | 1479 | d_cfg->nspares = raidPtr->numSpare; |
1463 | if (d_cfg->nspares >= RF_MAX_DISKS) { | | 1480 | if (d_cfg->nspares >= RF_MAX_DISKS) { |
1464 | RF_Free(d_cfg, sizeof(RF_DeviceConfig_t)); | | 1481 | RF_Free(d_cfg, sizeof(RF_DeviceConfig_t)); |
1465 | return (ENOMEM); | | 1482 | return (ENOMEM); |
1466 | } | | 1483 | } |
1467 | d_cfg->maxqdepth = raidPtr->maxQueueDepth; | | 1484 | d_cfg->maxqdepth = raidPtr->maxQueueDepth; |
1468 | d = 0; | | 1485 | d = 0; |
1469 | for (j = 0; j < d_cfg->cols; j++) { | | 1486 | for (j = 0; j < d_cfg->cols; j++) { |
1470 | d_cfg->devs[d] = raidPtr->Disks[j]; | | 1487 | d_cfg->devs[d] = raidPtr->Disks[j]; |
1471 | d++; | | 1488 | d++; |
1472 | } | | 1489 | } |
1473 | for (j = d_cfg->cols, i = 0; i < d_cfg->nspares; i++, j++) { | | 1490 | for (j = d_cfg->cols, i = 0; i < d_cfg->nspares; i++, j++) { |
1474 | d_cfg->spares[i] = raidPtr->Disks[j]; | | 1491 | d_cfg->spares[i] = raidPtr->Disks[j]; |
1475 | } | | 1492 | } |
1476 | retcode = copyout(d_cfg, *ucfgp, sizeof(RF_DeviceConfig_t)); | | 1493 | retcode = copyout(d_cfg, *ucfgp, sizeof(RF_DeviceConfig_t)); |
1477 | RF_Free(d_cfg, sizeof(RF_DeviceConfig_t)); | | 1494 | RF_Free(d_cfg, sizeof(RF_DeviceConfig_t)); |
1478 | | | 1495 | |
1479 | return (retcode); | | 1496 | return (retcode); |
1480 | | | 1497 | |
1481 | case RAIDFRAME_CHECK_PARITY: | | 1498 | case RAIDFRAME_CHECK_PARITY: |
1482 | *(int *) data = raidPtr->parity_good; | | 1499 | *(int *) data = raidPtr->parity_good; |
1483 | return (0); | | 1500 | return (0); |
1484 | | | 1501 | |
1485 | case RAIDFRAME_RESET_ACCTOTALS: | | 1502 | case RAIDFRAME_RESET_ACCTOTALS: |
1486 | memset(&raidPtr->acc_totals, 0, sizeof(raidPtr->acc_totals)); | | 1503 | memset(&raidPtr->acc_totals, 0, sizeof(raidPtr->acc_totals)); |
1487 | return (0); | | 1504 | return (0); |
1488 | | | 1505 | |
1489 | case RAIDFRAME_GET_ACCTOTALS: | | 1506 | case RAIDFRAME_GET_ACCTOTALS: |
1490 | totals = (RF_AccTotals_t *) data; | | 1507 | totals = (RF_AccTotals_t *) data; |
1491 | *totals = raidPtr->acc_totals; | | 1508 | *totals = raidPtr->acc_totals; |
1492 | return (0); | | 1509 | return (0); |
1493 | | | 1510 | |
1494 | case RAIDFRAME_KEEP_ACCTOTALS: | | 1511 | case RAIDFRAME_KEEP_ACCTOTALS: |
1495 | raidPtr->keep_acc_totals = *(int *)data; | | 1512 | raidPtr->keep_acc_totals = *(int *)data; |
1496 | return (0); | | 1513 | return (0); |
1497 | | | 1514 | |
1498 | case RAIDFRAME_GET_SIZE: | | 1515 | case RAIDFRAME_GET_SIZE: |
1499 | *(int *) data = raidPtr->totalSectors; | | 1516 | *(int *) data = raidPtr->totalSectors; |
1500 | return (0); | | 1517 | return (0); |
1501 | | | 1518 | |
1502 | /* fail a disk & optionally start reconstruction */ | | 1519 | /* fail a disk & optionally start reconstruction */ |
1503 | case RAIDFRAME_FAIL_DISK: | | 1520 | case RAIDFRAME_FAIL_DISK: |
1504 | | | 1521 | |
1505 | if (raidPtr->Layout.map->faultsTolerated == 0) { | | 1522 | if (raidPtr->Layout.map->faultsTolerated == 0) { |
1506 | /* Can't do this on a RAID 0!! */ | | 1523 | /* Can't do this on a RAID 0!! */ |
1507 | return(EINVAL); | | 1524 | return(EINVAL); |
1508 | } | | 1525 | } |
1509 | | | 1526 | |
1510 | rr = (struct rf_recon_req *) data; | | 1527 | rr = (struct rf_recon_req *) data; |
1511 | rr->row = 0; | | 1528 | rr->row = 0; |
1512 | if (rr->col < 0 || rr->col >= raidPtr->numCol) | | 1529 | if (rr->col < 0 || rr->col >= raidPtr->numCol) |
1513 | return (EINVAL); | | 1530 | return (EINVAL); |
1514 | | | 1531 | |
1515 | | | 1532 | |
1516 | RF_LOCK_MUTEX(raidPtr->mutex); | | 1533 | RF_LOCK_MUTEX(raidPtr->mutex); |
1517 | if (raidPtr->status == rf_rs_reconstructing) { | | 1534 | if (raidPtr->status == rf_rs_reconstructing) { |
1518 | /* you can't fail a disk while we're reconstructing! */ | | 1535 | /* you can't fail a disk while we're reconstructing! */ |
1519 | /* XXX wrong for RAID6 */ | | 1536 | /* XXX wrong for RAID6 */ |
1520 | RF_UNLOCK_MUTEX(raidPtr->mutex); | | 1537 | RF_UNLOCK_MUTEX(raidPtr->mutex); |
1521 | return (EINVAL); | | 1538 | return (EINVAL); |
1522 | } | | 1539 | } |
1523 | if ((raidPtr->Disks[rr->col].status == | | 1540 | if ((raidPtr->Disks[rr->col].status == |
1524 | rf_ds_optimal) && (raidPtr->numFailures > 0)) { | | 1541 | rf_ds_optimal) && (raidPtr->numFailures > 0)) { |
1525 | /* some other component has failed. Let's not make | | 1542 | /* some other component has failed. Let's not make |
1526 | things worse. XXX wrong for RAID6 */ | | 1543 | things worse. XXX wrong for RAID6 */ |
1527 | RF_UNLOCK_MUTEX(raidPtr->mutex); | | 1544 | RF_UNLOCK_MUTEX(raidPtr->mutex); |
1528 | return (EINVAL); | | 1545 | return (EINVAL); |
1529 | } | | 1546 | } |
1530 | if (raidPtr->Disks[rr->col].status == rf_ds_spared) { | | 1547 | if (raidPtr->Disks[rr->col].status == rf_ds_spared) { |
1531 | /* Can't fail a spared disk! */ | | 1548 | /* Can't fail a spared disk! */ |
1532 | RF_UNLOCK_MUTEX(raidPtr->mutex); | | 1549 | RF_UNLOCK_MUTEX(raidPtr->mutex); |
1533 | return (EINVAL); | | 1550 | return (EINVAL); |
1534 | } | | 1551 | } |
1535 | RF_UNLOCK_MUTEX(raidPtr->mutex); | | 1552 | RF_UNLOCK_MUTEX(raidPtr->mutex); |
1536 | | | 1553 | |
1537 | /* make a copy of the recon request so that we don't rely on | | 1554 | /* make a copy of the recon request so that we don't rely on |
1538 | * the user's buffer */ | | 1555 | * the user's buffer */ |
1539 | RF_Malloc(rrcopy, sizeof(*rrcopy), (struct rf_recon_req *)); | | 1556 | RF_Malloc(rrcopy, sizeof(*rrcopy), (struct rf_recon_req *)); |
1540 | if (rrcopy == NULL) | | 1557 | if (rrcopy == NULL) |
1541 | return(ENOMEM); | | 1558 | return(ENOMEM); |
1542 | memcpy(rrcopy, rr, sizeof(*rr)); | | 1559 | memcpy(rrcopy, rr, sizeof(*rr)); |
1543 | rrcopy->raidPtr = (void *) raidPtr; | | 1560 | rrcopy->raidPtr = (void *) raidPtr; |
1544 | | | 1561 | |
1545 | retcode = RF_CREATE_THREAD(raidPtr->recon_thread, | | 1562 | retcode = RF_CREATE_THREAD(raidPtr->recon_thread, |
1546 | rf_ReconThread, | | 1563 | rf_ReconThread, |
1547 | rrcopy,"raid_recon"); | | 1564 | rrcopy,"raid_recon"); |
1548 | return (0); | | 1565 | return (0); |
1549 | | | 1566 | |
1550 | /* invoke a copyback operation after recon on whatever disk | | 1567 | /* invoke a copyback operation after recon on whatever disk |
1551 | * needs it, if any */ | | 1568 | * needs it, if any */ |
1552 | case RAIDFRAME_COPYBACK: | | 1569 | case RAIDFRAME_COPYBACK: |
1553 | | | 1570 | |
1554 | if (raidPtr->Layout.map->faultsTolerated == 0) { | | 1571 | if (raidPtr->Layout.map->faultsTolerated == 0) { |
1555 | /* This makes no sense on a RAID 0!! */ | | 1572 | /* This makes no sense on a RAID 0!! */ |
1556 | return(EINVAL); | | 1573 | return(EINVAL); |
1557 | } | | 1574 | } |
1558 | | | 1575 | |
1559 | if (raidPtr->copyback_in_progress == 1) { | | 1576 | if (raidPtr->copyback_in_progress == 1) { |
1560 | /* Copyback is already in progress! */ | | 1577 | /* Copyback is already in progress! */ |
1561 | return(EINVAL); | | 1578 | return(EINVAL); |
1562 | } | | 1579 | } |
1563 | | | 1580 | |
1564 | retcode = RF_CREATE_THREAD(raidPtr->copyback_thread, | | 1581 | retcode = RF_CREATE_THREAD(raidPtr->copyback_thread, |
1565 | rf_CopybackThread, | | 1582 | rf_CopybackThread, |
1566 | raidPtr,"raid_copyback"); | | 1583 | raidPtr,"raid_copyback"); |
1567 | return (retcode); | | 1584 | return (retcode); |
1568 | | | 1585 | |
1569 | /* return the percentage completion of reconstruction */ | | 1586 | /* return the percentage completion of reconstruction */ |
1570 | case RAIDFRAME_CHECK_RECON_STATUS: | | 1587 | case RAIDFRAME_CHECK_RECON_STATUS: |
1571 | if (raidPtr->Layout.map->faultsTolerated == 0) { | | 1588 | if (raidPtr->Layout.map->faultsTolerated == 0) { |
1572 | /* This makes no sense on a RAID 0, so tell the | | 1589 | /* This makes no sense on a RAID 0, so tell the |
1573 | user it's done. */ | | 1590 | user it's done. */ |
1574 | *(int *) data = 100; | | 1591 | *(int *) data = 100; |
1575 | return(0); | | 1592 | return(0); |
1576 | } | | 1593 | } |
1577 | if (raidPtr->status != rf_rs_reconstructing) | | 1594 | if (raidPtr->status != rf_rs_reconstructing) |
1578 | *(int *) data = 100; | | 1595 | *(int *) data = 100; |
1579 | else { | | 1596 | else { |
1580 | if (raidPtr->reconControl->numRUsTotal > 0) { | | 1597 | if (raidPtr->reconControl->numRUsTotal > 0) { |
1581 | *(int *) data = (raidPtr->reconControl->numRUsComplete * 100 / raidPtr->reconControl->numRUsTotal); | | 1598 | *(int *) data = (raidPtr->reconControl->numRUsComplete * 100 / raidPtr->reconControl->numRUsTotal); |
1582 | } else { | | 1599 | } else { |
1583 | *(int *) data = 0; | | 1600 | *(int *) data = 0; |
1584 | } | | 1601 | } |
1585 | } | | 1602 | } |
1586 | return (0); | | 1603 | return (0); |
1587 | case RAIDFRAME_CHECK_RECON_STATUS_EXT: | | 1604 | case RAIDFRAME_CHECK_RECON_STATUS_EXT: |
1588 | progressInfoPtr = (RF_ProgressInfo_t **) data; | | 1605 | progressInfoPtr = (RF_ProgressInfo_t **) data; |
1589 | if (raidPtr->status != rf_rs_reconstructing) { | | 1606 | if (raidPtr->status != rf_rs_reconstructing) { |
1590 | progressInfo.remaining = 0; | | 1607 | progressInfo.remaining = 0; |
1591 | progressInfo.completed = 100; | | 1608 | progressInfo.completed = 100; |
1592 | progressInfo.total = 100; | | 1609 | progressInfo.total = 100; |
1593 | } else { | | 1610 | } else { |
1594 | progressInfo.total = | | 1611 | progressInfo.total = |
1595 | raidPtr->reconControl->numRUsTotal; | | 1612 | raidPtr->reconControl->numRUsTotal; |
1596 | progressInfo.completed = | | 1613 | progressInfo.completed = |
1597 | raidPtr->reconControl->numRUsComplete; | | 1614 | raidPtr->reconControl->numRUsComplete; |
1598 | progressInfo.remaining = progressInfo.total - | | 1615 | progressInfo.remaining = progressInfo.total - |
1599 | progressInfo.completed; | | 1616 | progressInfo.completed; |
1600 | } | | 1617 | } |
1601 | retcode = copyout(&progressInfo, *progressInfoPtr, | | 1618 | retcode = copyout(&progressInfo, *progressInfoPtr, |
1602 | sizeof(RF_ProgressInfo_t)); | | 1619 | sizeof(RF_ProgressInfo_t)); |
1603 | return (retcode); | | 1620 | return (retcode); |
1604 | | | 1621 | |
1605 | case RAIDFRAME_CHECK_PARITYREWRITE_STATUS: | | 1622 | case RAIDFRAME_CHECK_PARITYREWRITE_STATUS: |
1606 | if (raidPtr->Layout.map->faultsTolerated == 0) { | | 1623 | if (raidPtr->Layout.map->faultsTolerated == 0) { |
1607 | /* This makes no sense on a RAID 0, so tell the | | 1624 | /* This makes no sense on a RAID 0, so tell the |
1608 | user it's done. */ | | 1625 | user it's done. */ |
1609 | *(int *) data = 100; | | 1626 | *(int *) data = 100; |
1610 | return(0); | | 1627 | return(0); |
1611 | } | | 1628 | } |
1612 | if (raidPtr->parity_rewrite_in_progress == 1) { | | 1629 | if (raidPtr->parity_rewrite_in_progress == 1) { |
1613 | *(int *) data = 100 * | | 1630 | *(int *) data = 100 * |
1614 | raidPtr->parity_rewrite_stripes_done / | | 1631 | raidPtr->parity_rewrite_stripes_done / |
1615 | raidPtr->Layout.numStripe; | | 1632 | raidPtr->Layout.numStripe; |
1616 | } else { | | 1633 | } else { |
1617 | *(int *) data = 100; | | 1634 | *(int *) data = 100; |
1618 | } | | 1635 | } |
1619 | return (0); | | 1636 | return (0); |
1620 | | | 1637 | |
1621 | case RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT: | | 1638 | case RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT: |
1622 | progressInfoPtr = (RF_ProgressInfo_t **) data; | | 1639 | progressInfoPtr = (RF_ProgressInfo_t **) data; |
1623 | if (raidPtr->parity_rewrite_in_progress == 1) { | | 1640 | if (raidPtr->parity_rewrite_in_progress == 1) { |
1624 | progressInfo.total = raidPtr->Layout.numStripe; | | 1641 | progressInfo.total = raidPtr->Layout.numStripe; |
1625 | progressInfo.completed = | | 1642 | progressInfo.completed = |
1626 | raidPtr->parity_rewrite_stripes_done; | | 1643 | raidPtr->parity_rewrite_stripes_done; |
1627 | progressInfo.remaining = progressInfo.total - | | 1644 | progressInfo.remaining = progressInfo.total - |
1628 | progressInfo.completed; | | 1645 | progressInfo.completed; |
1629 | } else { | | 1646 | } else { |
1630 | progressInfo.remaining = 0; | | 1647 | progressInfo.remaining = 0; |
1631 | progressInfo.completed = 100; | | 1648 | progressInfo.completed = 100; |
1632 | progressInfo.total = 100; | | 1649 | progressInfo.total = 100; |
1633 | } | | 1650 | } |
1634 | retcode = copyout(&progressInfo, *progressInfoPtr, | | 1651 | retcode = copyout(&progressInfo, *progressInfoPtr, |
1635 | sizeof(RF_ProgressInfo_t)); | | 1652 | sizeof(RF_ProgressInfo_t)); |
1636 | return (retcode); | | 1653 | return (retcode); |
1637 | | | 1654 | |
1638 | case RAIDFRAME_CHECK_COPYBACK_STATUS: | | 1655 | case RAIDFRAME_CHECK_COPYBACK_STATUS: |
1639 | if (raidPtr->Layout.map->faultsTolerated == 0) { | | 1656 | if (raidPtr->Layout.map->faultsTolerated == 0) { |
1640 | /* This makes no sense on a RAID 0 */ | | 1657 | /* This makes no sense on a RAID 0 */ |
1641 | *(int *) data = 100; | | 1658 | *(int *) data = 100; |
1642 | return(0); | | 1659 | return(0); |
1643 | } | | 1660 | } |
1644 | if (raidPtr->copyback_in_progress == 1) { | | 1661 | if (raidPtr->copyback_in_progress == 1) { |
1645 | *(int *) data = 100 * raidPtr->copyback_stripes_done / | | 1662 | *(int *) data = 100 * raidPtr->copyback_stripes_done / |
1646 | raidPtr->Layout.numStripe; | | 1663 | raidPtr->Layout.numStripe; |
1647 | } else { | | 1664 | } else { |
1648 | *(int *) data = 100; | | 1665 | *(int *) data = 100; |
1649 | } | | 1666 | } |
1650 | return (0); | | 1667 | return (0); |
1651 | | | 1668 | |
1652 | case RAIDFRAME_CHECK_COPYBACK_STATUS_EXT: | | 1669 | case RAIDFRAME_CHECK_COPYBACK_STATUS_EXT: |
1653 | progressInfoPtr = (RF_ProgressInfo_t **) data; | | 1670 | progressInfoPtr = (RF_ProgressInfo_t **) data; |
1654 | if (raidPtr->copyback_in_progress == 1) { | | 1671 | if (raidPtr->copyback_in_progress == 1) { |
1655 | progressInfo.total = raidPtr->Layout.numStripe; | | 1672 | progressInfo.total = raidPtr->Layout.numStripe; |
1656 | progressInfo.completed = | | 1673 | progressInfo.completed = |
1657 | raidPtr->copyback_stripes_done; | | 1674 | raidPtr->copyback_stripes_done; |
1658 | progressInfo.remaining = progressInfo.total - | | 1675 | progressInfo.remaining = progressInfo.total - |
1659 | progressInfo.completed; | | 1676 | progressInfo.completed; |
1660 | } else { | | 1677 | } else { |
1661 | progressInfo.remaining = 0; | | 1678 | progressInfo.remaining = 0; |
1662 | progressInfo.completed = 100; | | 1679 | progressInfo.completed = 100; |
1663 | progressInfo.total = 100; | | 1680 | progressInfo.total = 100; |
1664 | } | | 1681 | } |
1665 | retcode = copyout(&progressInfo, *progressInfoPtr, | | 1682 | retcode = copyout(&progressInfo, *progressInfoPtr, |
1666 | sizeof(RF_ProgressInfo_t)); | | 1683 | sizeof(RF_ProgressInfo_t)); |
1667 | return (retcode); | | 1684 | return (retcode); |
1668 | | | 1685 | |
1669 | /* the sparetable daemon calls this to wait for the kernel to | | 1686 | /* the sparetable daemon calls this to wait for the kernel to |
1670 | * need a spare table. this ioctl does not return until a | | 1687 | * need a spare table. this ioctl does not return until a |
1671 | * spare table is needed. XXX -- calling mpsleep here in the | | 1688 | * spare table is needed. XXX -- calling mpsleep here in the |
1672 | * ioctl code is almost certainly wrong and evil. -- XXX XXX | | 1689 | * ioctl code is almost certainly wrong and evil. -- XXX XXX |
1673 | * -- I should either compute the spare table in the kernel, | | 1690 | * -- I should either compute the spare table in the kernel, |
1674 | * or have a different -- XXX XXX -- interface (a different | | 1691 | * or have a different -- XXX XXX -- interface (a different |
1675 | * character device) for delivering the table -- XXX */ | | 1692 | * character device) for delivering the table -- XXX */ |
1676 | #if 0 | | 1693 | #if 0 |
1677 | case RAIDFRAME_SPARET_WAIT: | | 1694 | case RAIDFRAME_SPARET_WAIT: |
1678 | RF_LOCK_MUTEX(rf_sparet_wait_mutex); | | 1695 | RF_LOCK_MUTEX(rf_sparet_wait_mutex); |
1679 | while (!rf_sparet_wait_queue) | | 1696 | while (!rf_sparet_wait_queue) |
1680 | mpsleep(&rf_sparet_wait_queue, (PZERO + 1) | PCATCH, "sparet wait", 0, (void *) simple_lock_addr(rf_sparet_wait_mutex), MS_LOCK_SIMPLE); | | 1697 | mpsleep(&rf_sparet_wait_queue, (PZERO + 1) | PCATCH, "sparet wait", 0, (void *) simple_lock_addr(rf_sparet_wait_mutex), MS_LOCK_SIMPLE); |
1681 | waitreq = rf_sparet_wait_queue; | | 1698 | waitreq = rf_sparet_wait_queue; |
1682 | rf_sparet_wait_queue = rf_sparet_wait_queue->next; | | 1699 | rf_sparet_wait_queue = rf_sparet_wait_queue->next; |
1683 | RF_UNLOCK_MUTEX(rf_sparet_wait_mutex); | | 1700 | RF_UNLOCK_MUTEX(rf_sparet_wait_mutex); |
1684 | | | 1701 | |
1685 | /* structure assignment */ | | 1702 | /* structure assignment */ |
1686 | *((RF_SparetWait_t *) data) = *waitreq; | | 1703 | *((RF_SparetWait_t *) data) = *waitreq; |
1687 | | | 1704 | |
1688 | RF_Free(waitreq, sizeof(*waitreq)); | | 1705 | RF_Free(waitreq, sizeof(*waitreq)); |
1689 | return (0); | | 1706 | return (0); |
1690 | | | 1707 | |
1691 | /* wakes up a process waiting on SPARET_WAIT and puts an error | | 1708 | /* wakes up a process waiting on SPARET_WAIT and puts an error |
1692 | * code in it that will cause the dameon to exit */ | | 1709 | * code in it that will cause the dameon to exit */ |
1693 | case RAIDFRAME_ABORT_SPARET_WAIT: | | 1710 | case RAIDFRAME_ABORT_SPARET_WAIT: |
1694 | RF_Malloc(waitreq, sizeof(*waitreq), (RF_SparetWait_t *)); | | 1711 | RF_Malloc(waitreq, sizeof(*waitreq), (RF_SparetWait_t *)); |
1695 | waitreq->fcol = -1; | | 1712 | waitreq->fcol = -1; |
1696 | RF_LOCK_MUTEX(rf_sparet_wait_mutex); | | 1713 | RF_LOCK_MUTEX(rf_sparet_wait_mutex); |
1697 | waitreq->next = rf_sparet_wait_queue; | | 1714 | waitreq->next = rf_sparet_wait_queue; |
1698 | rf_sparet_wait_queue = waitreq; | | 1715 | rf_sparet_wait_queue = waitreq; |
1699 | RF_UNLOCK_MUTEX(rf_sparet_wait_mutex); | | 1716 | RF_UNLOCK_MUTEX(rf_sparet_wait_mutex); |
1700 | wakeup(&rf_sparet_wait_queue); | | 1717 | wakeup(&rf_sparet_wait_queue); |
1701 | return (0); | | 1718 | return (0); |
1702 | | | 1719 | |
1703 | /* used by the spare table daemon to deliver a spare table | | 1720 | /* used by the spare table daemon to deliver a spare table |
1704 | * into the kernel */ | | 1721 | * into the kernel */ |
1705 | case RAIDFRAME_SEND_SPARET: | | 1722 | case RAIDFRAME_SEND_SPARET: |
1706 | | | 1723 | |
1707 | /* install the spare table */ | | 1724 | /* install the spare table */ |
1708 | retcode = rf_SetSpareTable(raidPtr, *(void **) data); | | 1725 | retcode = rf_SetSpareTable(raidPtr, *(void **) data); |
1709 | | | 1726 | |
1710 | /* respond to the requestor. the return status of the spare | | 1727 | /* respond to the requestor. the return status of the spare |
1711 | * table installation is passed in the "fcol" field */ | | 1728 | * table installation is passed in the "fcol" field */ |
1712 | RF_Malloc(waitreq, sizeof(*waitreq), (RF_SparetWait_t *)); | | 1729 | RF_Malloc(waitreq, sizeof(*waitreq), (RF_SparetWait_t *)); |
1713 | waitreq->fcol = retcode; | | 1730 | waitreq->fcol = retcode; |
1714 | RF_LOCK_MUTEX(rf_sparet_wait_mutex); | | 1731 | RF_LOCK_MUTEX(rf_sparet_wait_mutex); |
1715 | waitreq->next = rf_sparet_resp_queue; | | 1732 | waitreq->next = rf_sparet_resp_queue; |
1716 | rf_sparet_resp_queue = waitreq; | | 1733 | rf_sparet_resp_queue = waitreq; |
1717 | wakeup(&rf_sparet_resp_queue); | | 1734 | wakeup(&rf_sparet_resp_queue); |
1718 | RF_UNLOCK_MUTEX(rf_sparet_wait_mutex); | | 1735 | RF_UNLOCK_MUTEX(rf_sparet_wait_mutex); |
1719 | | | 1736 | |
1720 | return (retcode); | | 1737 | return (retcode); |
1721 | #endif | | 1738 | #endif |
1722 | | | 1739 | |
1723 | default: | | 1740 | default: |
1724 | break; /* fall through to the os-specific code below */ | | 1741 | break; /* fall through to the os-specific code below */ |
1725 | | | 1742 | |
1726 | } | | 1743 | } |
1727 | | | 1744 | |
1728 | if (!raidPtr->valid) | | 1745 | if (!raidPtr->valid) |
1729 | return (EINVAL); | | 1746 | return (EINVAL); |
1730 | | | 1747 | |
1731 | /* | | 1748 | /* |
1732 | * Add support for "regular" device ioctls here. | | 1749 | * Add support for "regular" device ioctls here. |
1733 | */ | | 1750 | */ |
1734 | | | 1751 | |
1735 | error = disk_ioctl(&rs->sc_dkdev, cmd, data, flag, l); | | 1752 | error = disk_ioctl(&rs->sc_dkdev, cmd, data, flag, l); |
1736 | if (error != EPASSTHROUGH) | | 1753 | if (error != EPASSTHROUGH) |
1737 | return (error); | | 1754 | return (error); |
1738 | | | 1755 | |
1739 | switch (cmd) { | | 1756 | switch (cmd) { |
1740 | case DIOCGDINFO: | | 1757 | case DIOCGDINFO: |
1741 | *(struct disklabel *) data = *(rs->sc_dkdev.dk_label); | | 1758 | *(struct disklabel *) data = *(rs->sc_dkdev.dk_label); |
1742 | break; | | 1759 | break; |
1743 | #ifdef __HAVE_OLD_DISKLABEL | | 1760 | #ifdef __HAVE_OLD_DISKLABEL |
1744 | case ODIOCGDINFO: | | 1761 | case ODIOCGDINFO: |
1745 | newlabel = *(rs->sc_dkdev.dk_label); | | 1762 | newlabel = *(rs->sc_dkdev.dk_label); |
1746 | if (newlabel.d_npartitions > OLDMAXPARTITIONS) | | 1763 | if (newlabel.d_npartitions > OLDMAXPARTITIONS) |
1747 | return ENOTTY; | | 1764 | return ENOTTY; |
1748 | memcpy(data, &newlabel, sizeof (struct olddisklabel)); | | 1765 | memcpy(data, &newlabel, sizeof (struct olddisklabel)); |
1749 | break; | | 1766 | break; |
1750 | #endif | | 1767 | #endif |
1751 | | | 1768 | |
1752 | case DIOCGPART: | | 1769 | case DIOCGPART: |
1753 | ((struct partinfo *) data)->disklab = rs->sc_dkdev.dk_label; | | 1770 | ((struct partinfo *) data)->disklab = rs->sc_dkdev.dk_label; |
1754 | ((struct partinfo *) data)->part = | | 1771 | ((struct partinfo *) data)->part = |
1755 | &rs->sc_dkdev.dk_label->d_partitions[DISKPART(dev)]; | | 1772 | &rs->sc_dkdev.dk_label->d_partitions[DISKPART(dev)]; |
1756 | break; | | 1773 | break; |
1757 | | | 1774 | |
1758 | case DIOCWDINFO: | | 1775 | case DIOCWDINFO: |
1759 | case DIOCSDINFO: | | 1776 | case DIOCSDINFO: |
1760 | #ifdef __HAVE_OLD_DISKLABEL | | 1777 | #ifdef __HAVE_OLD_DISKLABEL |
1761 | case ODIOCWDINFO: | | 1778 | case ODIOCWDINFO: |
1762 | case ODIOCSDINFO: | | 1779 | case ODIOCSDINFO: |
1763 | #endif | | 1780 | #endif |
1764 | { | | 1781 | { |
1765 | struct disklabel *lp; | | 1782 | struct disklabel *lp; |
1766 | #ifdef __HAVE_OLD_DISKLABEL | | 1783 | #ifdef __HAVE_OLD_DISKLABEL |
1767 | if (cmd == ODIOCSDINFO || cmd == ODIOCWDINFO) { | | 1784 | if (cmd == ODIOCSDINFO || cmd == ODIOCWDINFO) { |
1768 | memset(&newlabel, 0, sizeof newlabel); | | 1785 | memset(&newlabel, 0, sizeof newlabel); |
1769 | memcpy(&newlabel, data, sizeof (struct olddisklabel)); | | 1786 | memcpy(&newlabel, data, sizeof (struct olddisklabel)); |
1770 | lp = &newlabel; | | 1787 | lp = &newlabel; |
1771 | } else | | 1788 | } else |
1772 | #endif | | 1789 | #endif |
1773 | lp = (struct disklabel *)data; | | 1790 | lp = (struct disklabel *)data; |
1774 | | | 1791 | |
1775 | if ((error = raidlock(rs)) != 0) | | 1792 | if ((error = raidlock(rs)) != 0) |
1776 | return (error); | | 1793 | return (error); |
1777 | | | 1794 | |
1778 | rs->sc_flags |= RAIDF_LABELLING; | | 1795 | rs->sc_flags |= RAIDF_LABELLING; |
1779 | | | 1796 | |
1780 | error = setdisklabel(rs->sc_dkdev.dk_label, | | 1797 | error = setdisklabel(rs->sc_dkdev.dk_label, |
1781 | lp, 0, rs->sc_dkdev.dk_cpulabel); | | 1798 | lp, 0, rs->sc_dkdev.dk_cpulabel); |
1782 | if (error == 0) { | | 1799 | if (error == 0) { |
1783 | if (cmd == DIOCWDINFO | | 1800 | if (cmd == DIOCWDINFO |
1784 | #ifdef __HAVE_OLD_DISKLABEL | | 1801 | #ifdef __HAVE_OLD_DISKLABEL |
1785 | || cmd == ODIOCWDINFO | | 1802 | || cmd == ODIOCWDINFO |
1786 | #endif | | 1803 | #endif |
1787 | ) | | 1804 | ) |
1788 | error = writedisklabel(RAIDLABELDEV(dev), | | 1805 | error = writedisklabel(RAIDLABELDEV(dev), |
1789 | raidstrategy, rs->sc_dkdev.dk_label, | | 1806 | raidstrategy, rs->sc_dkdev.dk_label, |
1790 | rs->sc_dkdev.dk_cpulabel); | | 1807 | rs->sc_dkdev.dk_cpulabel); |
1791 | } | | 1808 | } |
1792 | rs->sc_flags &= ~RAIDF_LABELLING; | | 1809 | rs->sc_flags &= ~RAIDF_LABELLING; |
1793 | | | 1810 | |
1794 | raidunlock(rs); | | 1811 | raidunlock(rs); |
1795 | | | 1812 | |
1796 | if (error) | | 1813 | if (error) |
1797 | return (error); | | 1814 | return (error); |
1798 | break; | | 1815 | break; |
1799 | } | | 1816 | } |
1800 | | | 1817 | |
1801 | case DIOCWLABEL: | | 1818 | case DIOCWLABEL: |
1802 | if (*(int *) data != 0) | | 1819 | if (*(int *) data != 0) |
1803 | rs->sc_flags |= RAIDF_WLABEL; | | 1820 | rs->sc_flags |= RAIDF_WLABEL; |
1804 | else | | 1821 | else |
1805 | rs->sc_flags &= ~RAIDF_WLABEL; | | 1822 | rs->sc_flags &= ~RAIDF_WLABEL; |
1806 | break; | | 1823 | break; |
1807 | | | 1824 | |
1808 | case DIOCGDEFLABEL: | | 1825 | case DIOCGDEFLABEL: |
1809 | raidgetdefaultlabel(raidPtr, rs, (struct disklabel *) data); | | 1826 | raidgetdefaultlabel(raidPtr, rs, (struct disklabel *) data); |
1810 | break; | | 1827 | break; |
1811 | | | 1828 | |
1812 | #ifdef __HAVE_OLD_DISKLABEL | | 1829 | #ifdef __HAVE_OLD_DISKLABEL |
1813 | case ODIOCGDEFLABEL: | | 1830 | case ODIOCGDEFLABEL: |
1814 | raidgetdefaultlabel(raidPtr, rs, &newlabel); | | 1831 | raidgetdefaultlabel(raidPtr, rs, &newlabel); |
1815 | if (newlabel.d_npartitions > OLDMAXPARTITIONS) | | 1832 | if (newlabel.d_npartitions > OLDMAXPARTITIONS) |
1816 | return ENOTTY; | | 1833 | return ENOTTY; |
1817 | memcpy(data, &newlabel, sizeof (struct olddisklabel)); | | 1834 | memcpy(data, &newlabel, sizeof (struct olddisklabel)); |
1818 | break; | | 1835 | break; |
1819 | #endif | | 1836 | #endif |
1820 | | | 1837 | |
1821 | case DIOCAWEDGE: | | 1838 | case DIOCAWEDGE: |
1822 | case DIOCDWEDGE: | | 1839 | case DIOCDWEDGE: |
1823 | dkw = (void *)data; | | 1840 | dkw = (void *)data; |
1824 | | | 1841 | |
1825 | /* If the ioctl happens here, the parent is us. */ | | 1842 | /* If the ioctl happens here, the parent is us. */ |
1826 | (void)strcpy(dkw->dkw_parent, rs->sc_xname); | | 1843 | (void)strcpy(dkw->dkw_parent, rs->sc_xname); |
1827 | return cmd == DIOCAWEDGE ? dkwedge_add(dkw) : dkwedge_del(dkw); | | 1844 | return cmd == DIOCAWEDGE ? dkwedge_add(dkw) : dkwedge_del(dkw); |
1828 | | | 1845 | |
1829 | case DIOCLWEDGES: | | 1846 | case DIOCLWEDGES: |
1830 | return dkwedge_list(&rs->sc_dkdev, | | 1847 | return dkwedge_list(&rs->sc_dkdev, |
1831 | (struct dkwedge_list *)data, l); | | 1848 | (struct dkwedge_list *)data, l); |
1832 | case DIOCCACHESYNC: | | 1849 | case DIOCCACHESYNC: |
1833 | return rf_sync_component_caches(raidPtr); | | 1850 | return rf_sync_component_caches(raidPtr); |
1834 | default: | | 1851 | default: |
1835 | retcode = ENOTTY; | | 1852 | retcode = ENOTTY; |
1836 | } | | 1853 | } |
1837 | return (retcode); | | 1854 | return (retcode); |
1838 | | | 1855 | |
1839 | } | | 1856 | } |
1840 | | | 1857 | |
1841 | | | 1858 | |
1842 | /* raidinit -- complete the rest of the initialization for the | | 1859 | /* raidinit -- complete the rest of the initialization for the |
1843 | RAIDframe device. */ | | 1860 | RAIDframe device. */ |
1844 | | | 1861 | |
1845 | | | 1862 | |
1846 | static void | | 1863 | static void |
1847 | raidinit(RF_Raid_t *raidPtr) | | 1864 | raidinit(RF_Raid_t *raidPtr) |
1848 | { | | 1865 | { |
1849 | cfdata_t cf; | | 1866 | cfdata_t cf; |
1850 | struct raid_softc *rs; | | 1867 | struct raid_softc *rs; |
1851 | int unit; | | 1868 | int unit; |
1852 | | | 1869 | |
1853 | unit = raidPtr->raidid; | | 1870 | unit = raidPtr->raidid; |
1854 | | | 1871 | |
1855 | rs = &raid_softc[unit]; | | 1872 | rs = &raid_softc[unit]; |
1856 | | | 1873 | |
1857 | /* XXX should check return code first... */ | | 1874 | /* XXX should check return code first... */ |
1858 | rs->sc_flags |= RAIDF_INITED; | | 1875 | rs->sc_flags |= RAIDF_INITED; |
1859 | | | 1876 | |
1860 | /* XXX doesn't check bounds. */ | | 1877 | /* XXX doesn't check bounds. */ |
1861 | snprintf(rs->sc_xname, sizeof(rs->sc_xname), "raid%d", unit); | | 1878 | snprintf(rs->sc_xname, sizeof(rs->sc_xname), "raid%d", unit); |
1862 | | | 1879 | |
1863 | /* attach the pseudo device */ | | 1880 | /* attach the pseudo device */ |
1864 | cf = malloc(sizeof(*cf), M_RAIDFRAME, M_WAITOK); | | 1881 | cf = malloc(sizeof(*cf), M_RAIDFRAME, M_WAITOK); |
1865 | cf->cf_name = raid_cd.cd_name; | | 1882 | cf->cf_name = raid_cd.cd_name; |
1866 | cf->cf_atname = raid_cd.cd_name; | | 1883 | cf->cf_atname = raid_cd.cd_name; |
1867 | cf->cf_unit = unit; | | 1884 | cf->cf_unit = unit; |
1868 | cf->cf_fstate = FSTATE_STAR; | | 1885 | cf->cf_fstate = FSTATE_STAR; |
1869 | | | 1886 | |
1870 | rs->sc_dev = config_attach_pseudo(cf); | | 1887 | rs->sc_dev = config_attach_pseudo(cf); |
1871 | | | 1888 | |
1872 | if (rs->sc_dev==NULL) { | | 1889 | if (rs->sc_dev==NULL) { |
1873 | printf("raid%d: config_attach_pseudo failed\n", | | 1890 | printf("raid%d: config_attach_pseudo failed\n", |
1874 | raidPtr->raidid); | | 1891 | raidPtr->raidid); |
1875 | rs->sc_flags &= ~RAIDF_INITED; | | 1892 | rs->sc_flags &= ~RAIDF_INITED; |
1876 | free(cf, M_RAIDFRAME); | | 1893 | free(cf, M_RAIDFRAME); |
1877 | return; | | 1894 | return; |
1878 | } | | 1895 | } |
1879 | | | 1896 | |
1880 | /* disk_attach actually creates space for the CPU disklabel, among | | 1897 | /* disk_attach actually creates space for the CPU disklabel, among |
1881 | * other things, so it's critical to call this *BEFORE* we try putzing | | 1898 | * other things, so it's critical to call this *BEFORE* we try putzing |
1882 | * with disklabels. */ | | 1899 | * with disklabels. */ |
1883 | | | 1900 | |
1884 | disk_init(&rs->sc_dkdev, rs->sc_xname, &rf_dkdriver); | | 1901 | disk_init(&rs->sc_dkdev, rs->sc_xname, &rf_dkdriver); |
1885 | disk_attach(&rs->sc_dkdev); | | 1902 | disk_attach(&rs->sc_dkdev); |
1886 | | | 1903 | |
1887 | /* XXX There may be a weird interaction here between this, and | | 1904 | /* XXX There may be a weird interaction here between this, and |
1888 | * protectedSectors, as used in RAIDframe. */ | | 1905 | * protectedSectors, as used in RAIDframe. */ |
1889 | | | 1906 | |
1890 | rs->sc_size = raidPtr->totalSectors; | | 1907 | rs->sc_size = raidPtr->totalSectors; |
1891 | | | 1908 | |
1892 | dkwedge_discover(&rs->sc_dkdev); | | 1909 | dkwedge_discover(&rs->sc_dkdev); |
1893 | | | 1910 | |
1894 | rf_set_properties(rs, raidPtr); | | 1911 | rf_set_properties(rs, raidPtr); |
1895 | | | 1912 | |
1896 | } | | 1913 | } |
1897 | #if (RF_INCLUDE_PARITY_DECLUSTERING_DS > 0) | | 1914 | #if (RF_INCLUDE_PARITY_DECLUSTERING_DS > 0) |
1898 | /* wake up the daemon & tell it to get us a spare table | | 1915 | /* wake up the daemon & tell it to get us a spare table |
1899 | * XXX | | 1916 | * XXX |
1900 | * the entries in the queues should be tagged with the raidPtr | | 1917 | * the entries in the queues should be tagged with the raidPtr |
1901 | * so that in the extremely rare case that two recons happen at once, | | 1918 | * so that in the extremely rare case that two recons happen at once, |
1902 | * we know for which device were requesting a spare table | | 1919 | * we know for which device were requesting a spare table |
1903 | * XXX | | 1920 | * XXX |
1904 | * | | 1921 | * |
1905 | * XXX This code is not currently used. GO | | 1922 | * XXX This code is not currently used. GO |
1906 | */ | | 1923 | */ |
1907 | int | | 1924 | int |
1908 | rf_GetSpareTableFromDaemon(RF_SparetWait_t *req) | | 1925 | rf_GetSpareTableFromDaemon(RF_SparetWait_t *req) |
1909 | { | | 1926 | { |
1910 | int retcode; | | 1927 | int retcode; |
1911 | | | 1928 | |
1912 | RF_LOCK_MUTEX(rf_sparet_wait_mutex); | | 1929 | RF_LOCK_MUTEX(rf_sparet_wait_mutex); |
1913 | req->next = rf_sparet_wait_queue; | | 1930 | req->next = rf_sparet_wait_queue; |
1914 | rf_sparet_wait_queue = req; | | 1931 | rf_sparet_wait_queue = req; |
1915 | wakeup(&rf_sparet_wait_queue); | | 1932 | wakeup(&rf_sparet_wait_queue); |
1916 | | | 1933 | |
1917 | /* mpsleep unlocks the mutex */ | | 1934 | /* mpsleep unlocks the mutex */ |
1918 | while (!rf_sparet_resp_queue) { | | 1935 | while (!rf_sparet_resp_queue) { |
1919 | tsleep(&rf_sparet_resp_queue, PRIBIO, | | 1936 | tsleep(&rf_sparet_resp_queue, PRIBIO, |
1920 | "raidframe getsparetable", 0); | | 1937 | "raidframe getsparetable", 0); |
1921 | } | | 1938 | } |
1922 | req = rf_sparet_resp_queue; | | 1939 | req = rf_sparet_resp_queue; |
1923 | rf_sparet_resp_queue = req->next; | | 1940 | rf_sparet_resp_queue = req->next; |
1924 | RF_UNLOCK_MUTEX(rf_sparet_wait_mutex); | | 1941 | RF_UNLOCK_MUTEX(rf_sparet_wait_mutex); |
1925 | | | 1942 | |
1926 | retcode = req->fcol; | | 1943 | retcode = req->fcol; |
1927 | RF_Free(req, sizeof(*req)); /* this is not the same req as we | | 1944 | RF_Free(req, sizeof(*req)); /* this is not the same req as we |
1928 | * alloc'd */ | | 1945 | * alloc'd */ |
1929 | return (retcode); | | 1946 | return (retcode); |
1930 | } | | 1947 | } |
1931 | #endif | | 1948 | #endif |
1932 | | | 1949 | |
1933 | /* a wrapper around rf_DoAccess that extracts appropriate info from the | | 1950 | /* a wrapper around rf_DoAccess that extracts appropriate info from the |
1934 | * bp & passes it down. | | 1951 | * bp & passes it down. |
1935 | * any calls originating in the kernel must use non-blocking I/O | | 1952 | * any calls originating in the kernel must use non-blocking I/O |
1936 | * do some extra sanity checking to return "appropriate" error values for | | 1953 | * do some extra sanity checking to return "appropriate" error values for |
1937 | * certain conditions (to make some standard utilities work) | | 1954 | * certain conditions (to make some standard utilities work) |
1938 | * | | 1955 | * |
1939 | * Formerly known as: rf_DoAccessKernel | | 1956 | * Formerly known as: rf_DoAccessKernel |
1940 | */ | | 1957 | */ |
1941 | void | | 1958 | void |
1942 | raidstart(RF_Raid_t *raidPtr) | | 1959 | raidstart(RF_Raid_t *raidPtr) |
1943 | { | | 1960 | { |
1944 | RF_SectorCount_t num_blocks, pb, sum; | | 1961 | RF_SectorCount_t num_blocks, pb, sum; |
1945 | RF_RaidAddr_t raid_addr; | | 1962 | RF_RaidAddr_t raid_addr; |
1946 | struct partition *pp; | | 1963 | struct partition *pp; |
1947 | daddr_t blocknum; | | 1964 | daddr_t blocknum; |
1948 | int unit; | | 1965 | int unit; |
1949 | struct raid_softc *rs; | | 1966 | struct raid_softc *rs; |
1950 | int do_async; | | 1967 | int do_async; |
1951 | struct buf *bp; | | 1968 | struct buf *bp; |
1952 | int rc; | | 1969 | int rc; |
1953 | | | 1970 | |
1954 | unit = raidPtr->raidid; | | 1971 | unit = raidPtr->raidid; |
1955 | rs = &raid_softc[unit]; | | 1972 | rs = &raid_softc[unit]; |
1956 | | | 1973 | |
1957 | /* quick check to see if anything has died recently */ | | 1974 | /* quick check to see if anything has died recently */ |
1958 | RF_LOCK_MUTEX(raidPtr->mutex); | | 1975 | RF_LOCK_MUTEX(raidPtr->mutex); |
1959 | if (raidPtr->numNewFailures > 0) { | | 1976 | if (raidPtr->numNewFailures > 0) { |
1960 | RF_UNLOCK_MUTEX(raidPtr->mutex); | | 1977 | RF_UNLOCK_MUTEX(raidPtr->mutex); |
1961 | rf_update_component_labels(raidPtr, | | 1978 | rf_update_component_labels(raidPtr, |
1962 | RF_NORMAL_COMPONENT_UPDATE); | | 1979 | RF_NORMAL_COMPONENT_UPDATE); |
1963 | RF_LOCK_MUTEX(raidPtr->mutex); | | 1980 | RF_LOCK_MUTEX(raidPtr->mutex); |
1964 | raidPtr->numNewFailures--; | | 1981 | raidPtr->numNewFailures--; |
1965 | } | | 1982 | } |
1966 | | | 1983 | |
1967 | /* Check to see if we're at the limit... */ | | 1984 | /* Check to see if we're at the limit... */ |
1968 | while (raidPtr->openings > 0) { | | 1985 | while (raidPtr->openings > 0) { |
1969 | RF_UNLOCK_MUTEX(raidPtr->mutex); | | 1986 | RF_UNLOCK_MUTEX(raidPtr->mutex); |
1970 | | | 1987 | |
1971 | /* get the next item, if any, from the queue */ | | 1988 | /* get the next item, if any, from the queue */ |
1972 | if ((bp = bufq_get(rs->buf_queue)) == NULL) { | | 1989 | if ((bp = bufq_get(rs->buf_queue)) == NULL) { |
1973 | /* nothing more to do */ | | 1990 | /* nothing more to do */ |
1974 | return; | | 1991 | return; |
1975 | } | | 1992 | } |
1976 | | | 1993 | |
1977 | /* Ok, for the bp we have here, bp->b_blkno is relative to the | | 1994 | /* Ok, for the bp we have here, bp->b_blkno is relative to the |
1978 | * partition.. Need to make it absolute to the underlying | | 1995 | * partition.. Need to make it absolute to the underlying |
1979 | * device.. */ | | 1996 | * device.. */ |
1980 | | | 1997 | |
1981 | blocknum = bp->b_blkno; | | 1998 | blocknum = bp->b_blkno; |
1982 | if (DISKPART(bp->b_dev) != RAW_PART) { | | 1999 | if (DISKPART(bp->b_dev) != RAW_PART) { |
1983 | pp = &rs->sc_dkdev.dk_label->d_partitions[DISKPART(bp->b_dev)]; | | 2000 | pp = &rs->sc_dkdev.dk_label->d_partitions[DISKPART(bp->b_dev)]; |
1984 | blocknum += pp->p_offset; | | 2001 | blocknum += pp->p_offset; |
1985 | } | | 2002 | } |
1986 | | | 2003 | |
1987 | db1_printf(("Blocks: %d, %d\n", (int) bp->b_blkno, | | 2004 | db1_printf(("Blocks: %d, %d\n", (int) bp->b_blkno, |
1988 | (int) blocknum)); | | 2005 | (int) blocknum)); |
1989 | | | 2006 | |
1990 | db1_printf(("bp->b_bcount = %d\n", (int) bp->b_bcount)); | | 2007 | db1_printf(("bp->b_bcount = %d\n", (int) bp->b_bcount)); |
1991 | db1_printf(("bp->b_resid = %d\n", (int) bp->b_resid)); | | 2008 | db1_printf(("bp->b_resid = %d\n", (int) bp->b_resid)); |
1992 | | | 2009 | |
1993 | /* *THIS* is where we adjust what block we're going to... | | 2010 | /* *THIS* is where we adjust what block we're going to... |
1994 | * but DO NOT TOUCH bp->b_blkno!!! */ | | 2011 | * but DO NOT TOUCH bp->b_blkno!!! */ |
1995 | raid_addr = blocknum; | | 2012 | raid_addr = blocknum; |
1996 | | | 2013 | |
1997 | num_blocks = bp->b_bcount >> raidPtr->logBytesPerSector; | | 2014 | num_blocks = bp->b_bcount >> raidPtr->logBytesPerSector; |
1998 | pb = (bp->b_bcount & raidPtr->sectorMask) ? 1 : 0; | | 2015 | pb = (bp->b_bcount & raidPtr->sectorMask) ? 1 : 0; |
1999 | sum = raid_addr + num_blocks + pb; | | 2016 | sum = raid_addr + num_blocks + pb; |
2000 | if (1 || rf_debugKernelAccess) { | | 2017 | if (1 || rf_debugKernelAccess) { |
2001 | db1_printf(("raid_addr=%d sum=%d num_blocks=%d(+%d) (%d)\n", | | 2018 | db1_printf(("raid_addr=%d sum=%d num_blocks=%d(+%d) (%d)\n", |
2002 | (int) raid_addr, (int) sum, (int) num_blocks, | | 2019 | (int) raid_addr, (int) sum, (int) num_blocks, |
2003 | (int) pb, (int) bp->b_resid)); | | 2020 | (int) pb, (int) bp->b_resid)); |
2004 | } | | 2021 | } |
2005 | if ((sum > raidPtr->totalSectors) || (sum < raid_addr) | | 2022 | if ((sum > raidPtr->totalSectors) || (sum < raid_addr) |
2006 | || (sum < num_blocks) || (sum < pb)) { | | 2023 | || (sum < num_blocks) || (sum < pb)) { |
2007 | bp->b_error = ENOSPC; | | 2024 | bp->b_error = ENOSPC; |
2008 | bp->b_resid = bp->b_bcount; | | 2025 | bp->b_resid = bp->b_bcount; |
2009 | biodone(bp); | | 2026 | biodone(bp); |
2010 | RF_LOCK_MUTEX(raidPtr->mutex); | | 2027 | RF_LOCK_MUTEX(raidPtr->mutex); |
2011 | continue; | | 2028 | continue; |
2012 | } | | 2029 | } |
2013 | /* | | 2030 | /* |
2014 | * XXX rf_DoAccess() should do this, not just DoAccessKernel() | | 2031 | * XXX rf_DoAccess() should do this, not just DoAccessKernel() |
2015 | */ | | 2032 | */ |
2016 | | | 2033 | |
2017 | if (bp->b_bcount & raidPtr->sectorMask) { | | 2034 | if (bp->b_bcount & raidPtr->sectorMask) { |
2018 | bp->b_error = EINVAL; | | 2035 | bp->b_error = EINVAL; |
2019 | bp->b_resid = bp->b_bcount; | | 2036 | bp->b_resid = bp->b_bcount; |
2020 | biodone(bp); | | 2037 | biodone(bp); |
2021 | RF_LOCK_MUTEX(raidPtr->mutex); | | 2038 | RF_LOCK_MUTEX(raidPtr->mutex); |
2022 | continue; | | 2039 | continue; |
2023 | | | 2040 | |
2024 | } | | 2041 | } |
2025 | db1_printf(("Calling DoAccess..\n")); | | 2042 | db1_printf(("Calling DoAccess..\n")); |
2026 | | | 2043 | |
2027 | | | 2044 | |
2028 | RF_LOCK_MUTEX(raidPtr->mutex); | | 2045 | RF_LOCK_MUTEX(raidPtr->mutex); |
2029 | raidPtr->openings--; | | 2046 | raidPtr->openings--; |
2030 | RF_UNLOCK_MUTEX(raidPtr->mutex); | | 2047 | RF_UNLOCK_MUTEX(raidPtr->mutex); |
2031 | | | 2048 | |
2032 | /* | | 2049 | /* |
2033 | * Everything is async. | | 2050 | * Everything is async. |
2034 | */ | | 2051 | */ |
2035 | do_async = 1; | | 2052 | do_async = 1; |
2036 | | | 2053 | |
2037 | disk_busy(&rs->sc_dkdev); | | 2054 | disk_busy(&rs->sc_dkdev); |
2038 | | | 2055 | |
2039 | /* XXX we're still at splbio() here... do we *really* | | 2056 | /* XXX we're still at splbio() here... do we *really* |
2040 | need to be? */ | | 2057 | need to be? */ |
2041 | | | 2058 | |
2042 | /* don't ever condition on bp->b_flags & B_WRITE. | | 2059 | /* don't ever condition on bp->b_flags & B_WRITE. |
2043 | * always condition on B_READ instead */ | | 2060 | * always condition on B_READ instead */ |
2044 | | | 2061 | |
2045 | rc = rf_DoAccess(raidPtr, (bp->b_flags & B_READ) ? | | 2062 | rc = rf_DoAccess(raidPtr, (bp->b_flags & B_READ) ? |
2046 | RF_IO_TYPE_READ : RF_IO_TYPE_WRITE, | | 2063 | RF_IO_TYPE_READ : RF_IO_TYPE_WRITE, |
2047 | do_async, raid_addr, num_blocks, | | 2064 | do_async, raid_addr, num_blocks, |
2048 | bp->b_data, bp, RF_DAG_NONBLOCKING_IO); | | 2065 | bp->b_data, bp, RF_DAG_NONBLOCKING_IO); |
2049 | | | 2066 | |
2050 | if (rc) { | | 2067 | if (rc) { |
2051 | bp->b_error = rc; | | 2068 | bp->b_error = rc; |
2052 | bp->b_resid = bp->b_bcount; | | 2069 | bp->b_resid = bp->b_bcount; |
2053 | biodone(bp); | | 2070 | biodone(bp); |
2054 | /* continue loop */ | | 2071 | /* continue loop */ |
2055 | } | | 2072 | } |
2056 | | | 2073 | |
2057 | RF_LOCK_MUTEX(raidPtr->mutex); | | 2074 | RF_LOCK_MUTEX(raidPtr->mutex); |
2058 | } | | 2075 | } |
2059 | RF_UNLOCK_MUTEX(raidPtr->mutex); | | 2076 | RF_UNLOCK_MUTEX(raidPtr->mutex); |
2060 | } | | 2077 | } |
2061 | | | 2078 | |
2062 | | | 2079 | |
2063 | | | 2080 | |
2064 | | | 2081 | |
2065 | /* invoke an I/O from kernel mode. Disk queue should be locked upon entry */ | | 2082 | /* invoke an I/O from kernel mode. Disk queue should be locked upon entry */ |
2066 | | | 2083 | |
2067 | int | | 2084 | int |
2068 | rf_DispatchKernelIO(RF_DiskQueue_t *queue, RF_DiskQueueData_t *req) | | 2085 | rf_DispatchKernelIO(RF_DiskQueue_t *queue, RF_DiskQueueData_t *req) |
2069 | { | | 2086 | { |
2070 | int op = (req->type == RF_IO_TYPE_READ) ? B_READ : B_WRITE; | | 2087 | int op = (req->type == RF_IO_TYPE_READ) ? B_READ : B_WRITE; |
2071 | struct buf *bp; | | 2088 | struct buf *bp; |
2072 | | | 2089 | |
2073 | req->queue = queue; | | 2090 | req->queue = queue; |
2074 | bp = req->bp; | | 2091 | bp = req->bp; |
2075 | | | 2092 | |
2076 | switch (req->type) { | | 2093 | switch (req->type) { |
2077 | case RF_IO_TYPE_NOP: /* used primarily to unlock a locked queue */ | | 2094 | case RF_IO_TYPE_NOP: /* used primarily to unlock a locked queue */ |
2078 | /* XXX need to do something extra here.. */ | | 2095 | /* XXX need to do something extra here.. */ |
2079 | /* I'm leaving this in, as I've never actually seen it used, | | 2096 | /* I'm leaving this in, as I've never actually seen it used, |
2080 | * and I'd like folks to report it... GO */ | | 2097 | * and I'd like folks to report it... GO */ |
2081 | printf(("WAKEUP CALLED\n")); | | 2098 | printf(("WAKEUP CALLED\n")); |
2082 | queue->numOutstanding++; | | 2099 | queue->numOutstanding++; |
2083 | | | 2100 | |
2084 | bp->b_flags = 0; | | 2101 | bp->b_flags = 0; |
2085 | bp->b_private = req; | | 2102 | bp->b_private = req; |
2086 | | | 2103 | |
2087 | KernelWakeupFunc(bp); | | 2104 | KernelWakeupFunc(bp); |
2088 | break; | | 2105 | break; |
2089 | | | 2106 | |
2090 | case RF_IO_TYPE_READ: | | 2107 | case RF_IO_TYPE_READ: |
2091 | case RF_IO_TYPE_WRITE: | | 2108 | case RF_IO_TYPE_WRITE: |
2092 | #if RF_ACC_TRACE > 0 | | 2109 | #if RF_ACC_TRACE > 0 |
2093 | if (req->tracerec) { | | 2110 | if (req->tracerec) { |
2094 | RF_ETIMER_START(req->tracerec->timer); | | 2111 | RF_ETIMER_START(req->tracerec->timer); |
2095 | } | | 2112 | } |
2096 | #endif | | 2113 | #endif |
2097 | InitBP(bp, queue->rf_cinfo->ci_vp, | | 2114 | InitBP(bp, queue->rf_cinfo->ci_vp, |
2098 | op, queue->rf_cinfo->ci_dev, | | 2115 | op, queue->rf_cinfo->ci_dev, |
2099 | req->sectorOffset, req->numSector, | | 2116 | req->sectorOffset, req->numSector, |
2100 | req->buf, KernelWakeupFunc, (void *) req, | | 2117 | req->buf, KernelWakeupFunc, (void *) req, |
2101 | queue->raidPtr->logBytesPerSector, req->b_proc); | | 2118 | queue->raidPtr->logBytesPerSector, req->b_proc); |
2102 | | | 2119 | |
2103 | if (rf_debugKernelAccess) { | | 2120 | if (rf_debugKernelAccess) { |
2104 | db1_printf(("dispatch: bp->b_blkno = %ld\n", | | 2121 | db1_printf(("dispatch: bp->b_blkno = %ld\n", |
2105 | (long) bp->b_blkno)); | | 2122 | (long) bp->b_blkno)); |
2106 | } | | 2123 | } |
2107 | queue->numOutstanding++; | | 2124 | queue->numOutstanding++; |
2108 | queue->last_deq_sector = req->sectorOffset; | | 2125 | queue->last_deq_sector = req->sectorOffset; |
2109 | /* acc wouldn't have been let in if there were any pending | | 2126 | /* acc wouldn't have been let in if there were any pending |
2110 | * reqs at any other priority */ | | 2127 | * reqs at any other priority */ |
2111 | queue->curPriority = req->priority; | | 2128 | queue->curPriority = req->priority; |
2112 | | | 2129 | |
2113 | db1_printf(("Going for %c to unit %d col %d\n", | | 2130 | db1_printf(("Going for %c to unit %d col %d\n", |
2114 | req->type, queue->raidPtr->raidid, | | 2131 | req->type, queue->raidPtr->raidid, |
2115 | queue->col)); | | 2132 | queue->col)); |
2116 | db1_printf(("sector %d count %d (%d bytes) %d\n", | | 2133 | db1_printf(("sector %d count %d (%d bytes) %d\n", |
2117 | (int) req->sectorOffset, (int) req->numSector, | | 2134 | (int) req->sectorOffset, (int) req->numSector, |
2118 | (int) (req->numSector << | | 2135 | (int) (req->numSector << |
2119 | queue->raidPtr->logBytesPerSector), | | 2136 | queue->raidPtr->logBytesPerSector), |
2120 | (int) queue->raidPtr->logBytesPerSector)); | | 2137 | (int) queue->raidPtr->logBytesPerSector)); |
2121 | | | 2138 | |
2122 | /* | | 2139 | /* |
2123 | * XXX: drop lock here since this can block at | | 2140 | * XXX: drop lock here since this can block at |
2124 | * least with backing SCSI devices. Retake it | | 2141 | * least with backing SCSI devices. Retake it |
2125 | * to minimize fuss with calling interfaces. | | 2142 | * to minimize fuss with calling interfaces. |
2126 | */ | | 2143 | */ |
2127 | | | 2144 | |
2128 | RF_UNLOCK_QUEUE_MUTEX(queue, "unusedparam"); | | 2145 | RF_UNLOCK_QUEUE_MUTEX(queue, "unusedparam"); |
2129 | bdev_strategy(bp); | | 2146 | bdev_strategy(bp); |
2130 | RF_LOCK_QUEUE_MUTEX(queue, "unusedparam"); | | 2147 | RF_LOCK_QUEUE_MUTEX(queue, "unusedparam"); |
2131 | break; | | 2148 | break; |
2132 | | | 2149 | |
2133 | default: | | 2150 | default: |
2134 | panic("bad req->type in rf_DispatchKernelIO"); | | 2151 | panic("bad req->type in rf_DispatchKernelIO"); |
2135 | } | | 2152 | } |
2136 | db1_printf(("Exiting from DispatchKernelIO\n")); | | 2153 | db1_printf(("Exiting from DispatchKernelIO\n")); |
2137 | | | 2154 | |
2138 | return (0); | | 2155 | return (0); |
2139 | } | | 2156 | } |
2140 | /* this is the callback function associated with a I/O invoked from | | 2157 | /* this is the callback function associated with a I/O invoked from |
2141 | kernel code. | | 2158 | kernel code. |
2142 | */ | | 2159 | */ |
2143 | static void | | 2160 | static void |
2144 | KernelWakeupFunc(struct buf *bp) | | 2161 | KernelWakeupFunc(struct buf *bp) |
2145 | { | | 2162 | { |
2146 | RF_DiskQueueData_t *req = NULL; | | 2163 | RF_DiskQueueData_t *req = NULL; |
2147 | RF_DiskQueue_t *queue; | | 2164 | RF_DiskQueue_t *queue; |
2148 | int s; | | 2165 | int s; |
2149 | | | 2166 | |
2150 | s = splbio(); | | 2167 | s = splbio(); |
2151 | db1_printf(("recovering the request queue:\n")); | | 2168 | db1_printf(("recovering the request queue:\n")); |
2152 | req = bp->b_private; | | 2169 | req = bp->b_private; |
2153 | | | 2170 | |
2154 | queue = (RF_DiskQueue_t *) req->queue; | | 2171 | queue = (RF_DiskQueue_t *) req->queue; |
2155 | | | 2172 | |
2156 | #if RF_ACC_TRACE > 0 | | 2173 | #if RF_ACC_TRACE > 0 |
2157 | if (req->tracerec) { | | 2174 | if (req->tracerec) { |
2158 | RF_ETIMER_STOP(req->tracerec->timer); | | 2175 | RF_ETIMER_STOP(req->tracerec->timer); |
2159 | RF_ETIMER_EVAL(req->tracerec->timer); | | 2176 | RF_ETIMER_EVAL(req->tracerec->timer); |
2160 | RF_LOCK_MUTEX(rf_tracing_mutex); | | 2177 | RF_LOCK_MUTEX(rf_tracing_mutex); |
2161 | req->tracerec->diskwait_us += RF_ETIMER_VAL_US(req->tracerec->timer); | | 2178 | req->tracerec->diskwait_us += RF_ETIMER_VAL_US(req->tracerec->timer); |
2162 | req->tracerec->phys_io_us += RF_ETIMER_VAL_US(req->tracerec->timer); | | 2179 | req->tracerec->phys_io_us += RF_ETIMER_VAL_US(req->tracerec->timer); |
2163 | req->tracerec->num_phys_ios++; | | 2180 | req->tracerec->num_phys_ios++; |
2164 | RF_UNLOCK_MUTEX(rf_tracing_mutex); | | 2181 | RF_UNLOCK_MUTEX(rf_tracing_mutex); |
2165 | } | | 2182 | } |
2166 | #endif | | 2183 | #endif |
2167 | | | 2184 | |
2168 | /* XXX Ok, let's get aggressive... If b_error is set, let's go | | 2185 | /* XXX Ok, let's get aggressive... If b_error is set, let's go |
2169 | * ballistic, and mark the component as hosed... */ | | 2186 | * ballistic, and mark the component as hosed... */ |
2170 | | | 2187 | |
2171 | if (bp->b_error != 0) { | | 2188 | if (bp->b_error != 0) { |
2172 | /* Mark the disk as dead */ | | 2189 | /* Mark the disk as dead */ |
2173 | /* but only mark it once... */ | | 2190 | /* but only mark it once... */ |
2174 | /* and only if it wouldn't leave this RAID set | | 2191 | /* and only if it wouldn't leave this RAID set |
2175 | completely broken */ | | 2192 | completely broken */ |
2176 | if (((queue->raidPtr->Disks[queue->col].status == | | 2193 | if (((queue->raidPtr->Disks[queue->col].status == |
2177 | rf_ds_optimal) || | | 2194 | rf_ds_optimal) || |
2178 | (queue->raidPtr->Disks[queue->col].status == | | 2195 | (queue->raidPtr->Disks[queue->col].status == |
2179 | rf_ds_used_spare)) && | | 2196 | rf_ds_used_spare)) && |
2180 | (queue->raidPtr->numFailures < | | 2197 | (queue->raidPtr->numFailures < |
2181 | queue->raidPtr->Layout.map->faultsTolerated)) { | | 2198 | queue->raidPtr->Layout.map->faultsTolerated)) { |
2182 | printf("raid%d: IO Error. Marking %s as failed.\n", | | 2199 | printf("raid%d: IO Error. Marking %s as failed.\n", |
2183 | queue->raidPtr->raidid, | | 2200 | queue->raidPtr->raidid, |
2184 | queue->raidPtr->Disks[queue->col].devname); | | 2201 | queue->raidPtr->Disks[queue->col].devname); |
2185 | queue->raidPtr->Disks[queue->col].status = | | 2202 | queue->raidPtr->Disks[queue->col].status = |
2186 | rf_ds_failed; | | 2203 | rf_ds_failed; |
2187 | queue->raidPtr->status = rf_rs_degraded; | | 2204 | queue->raidPtr->status = rf_rs_degraded; |
2188 | queue->raidPtr->numFailures++; | | 2205 | queue->raidPtr->numFailures++; |
2189 | queue->raidPtr->numNewFailures++; | | 2206 | queue->raidPtr->numNewFailures++; |
2190 | } else { /* Disk is already dead... */ | | 2207 | } else { /* Disk is already dead... */ |
2191 | /* printf("Disk already marked as dead!\n"); */ | | 2208 | /* printf("Disk already marked as dead!\n"); */ |
2192 | } | | 2209 | } |
2193 | | | 2210 | |
2194 | } | | 2211 | } |
2195 | | | 2212 | |
2196 | /* Fill in the error value */ | | 2213 | /* Fill in the error value */ |
2197 | | | 2214 | |
2198 | req->error = bp->b_error; | | 2215 | req->error = bp->b_error; |
2199 | | | 2216 | |
2200 | simple_lock(&queue->raidPtr->iodone_lock); | | 2217 | simple_lock(&queue->raidPtr->iodone_lock); |
2201 | | | 2218 | |
2202 | /* Drop this one on the "finished" queue... */ | | 2219 | /* Drop this one on the "finished" queue... */ |
2203 | TAILQ_INSERT_TAIL(&(queue->raidPtr->iodone), req, iodone_entries); | | 2220 | TAILQ_INSERT_TAIL(&(queue->raidPtr->iodone), req, iodone_entries); |
2204 | | | 2221 | |
2205 | /* Let the raidio thread know there is work to be done. */ | | 2222 | /* Let the raidio thread know there is work to be done. */ |
2206 | wakeup(&(queue->raidPtr->iodone)); | | 2223 | wakeup(&(queue->raidPtr->iodone)); |
2207 | | | 2224 | |
2208 | simple_unlock(&queue->raidPtr->iodone_lock); | | 2225 | simple_unlock(&queue->raidPtr->iodone_lock); |
2209 | | | 2226 | |
| @@ -2624,1084 +2641,1089 @@ rf_update_component_labels(RF_Raid_t *ra | | | @@ -2624,1084 +2641,1089 @@ rf_update_component_labels(RF_Raid_t *ra |
2624 | | | 2641 | |
2625 | */ | | 2642 | */ |
2626 | | | 2643 | |
2627 | for(j=0;j<raidPtr->numCol;j++) { | | 2644 | for(j=0;j<raidPtr->numCol;j++) { |
2628 | if (raidPtr->Disks[j].spareCol == sparecol) { | | 2645 | if (raidPtr->Disks[j].spareCol == sparecol) { |
2629 | scol = j; | | 2646 | scol = j; |
2630 | break; | | 2647 | break; |
2631 | } | | 2648 | } |
2632 | } | | 2649 | } |
2633 | | | 2650 | |
2634 | /* XXX shouldn't *really* need this... */ | | 2651 | /* XXX shouldn't *really* need this... */ |
2635 | raidread_component_label( | | 2652 | raidread_component_label( |
2636 | raidPtr->Disks[sparecol].dev, | | 2653 | raidPtr->Disks[sparecol].dev, |
2637 | raidPtr->raid_cinfo[sparecol].ci_vp, | | 2654 | raidPtr->raid_cinfo[sparecol].ci_vp, |
2638 | &clabel); | | 2655 | &clabel); |
2639 | /* make sure status is noted */ | | 2656 | /* make sure status is noted */ |
2640 | | | 2657 | |
2641 | raid_init_component_label(raidPtr, &clabel); | | 2658 | raid_init_component_label(raidPtr, &clabel); |
2642 | | | 2659 | |
2643 | clabel.mod_counter = raidPtr->mod_counter; | | 2660 | clabel.mod_counter = raidPtr->mod_counter; |
2644 | clabel.column = scol; | | 2661 | clabel.column = scol; |
2645 | clabel.status = rf_ds_optimal; | | 2662 | clabel.status = rf_ds_optimal; |
2646 | clabel.last_unit = raidPtr->raidid; | | 2663 | clabel.last_unit = raidPtr->raidid; |
2647 | | | 2664 | |
2648 | raidwrite_component_label( | | 2665 | raidwrite_component_label( |
2649 | raidPtr->Disks[sparecol].dev, | | 2666 | raidPtr->Disks[sparecol].dev, |
2650 | raidPtr->raid_cinfo[sparecol].ci_vp, | | 2667 | raidPtr->raid_cinfo[sparecol].ci_vp, |
2651 | &clabel); | | 2668 | &clabel); |
2652 | if (final == RF_FINAL_COMPONENT_UPDATE) { | | 2669 | if (final == RF_FINAL_COMPONENT_UPDATE) { |
2653 | if (raidPtr->parity_good == RF_RAID_CLEAN) { | | 2670 | if (raidPtr->parity_good == RF_RAID_CLEAN) { |
2654 | raidmarkclean( raidPtr->Disks[sparecol].dev, | | 2671 | raidmarkclean( raidPtr->Disks[sparecol].dev, |
2655 | raidPtr->raid_cinfo[sparecol].ci_vp, | | 2672 | raidPtr->raid_cinfo[sparecol].ci_vp, |
2656 | raidPtr->mod_counter); | | 2673 | raidPtr->mod_counter); |
2657 | } | | 2674 | } |
2658 | } | | 2675 | } |
2659 | } | | 2676 | } |
2660 | } | | 2677 | } |
2661 | } | | 2678 | } |
2662 | | | 2679 | |
2663 | void | | 2680 | void |
2664 | rf_close_component(RF_Raid_t *raidPtr, struct vnode *vp, int auto_configured) | | 2681 | rf_close_component(RF_Raid_t *raidPtr, struct vnode *vp, int auto_configured) |
2665 | { | | 2682 | { |
2666 | | | 2683 | |
2667 | if (vp != NULL) { | | 2684 | if (vp != NULL) { |
2668 | if (auto_configured == 1) { | | 2685 | if (auto_configured == 1) { |
2669 | vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); | | 2686 | vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); |
2670 | VOP_CLOSE(vp, FREAD | FWRITE, NOCRED); | | 2687 | VOP_CLOSE(vp, FREAD | FWRITE, NOCRED); |
2671 | vput(vp); | | 2688 | vput(vp); |
2672 | | | 2689 | |
2673 | } else { | | 2690 | } else { |
2674 | (void) vn_close(vp, FREAD | FWRITE, curlwp->l_cred); | | 2691 | (void) vn_close(vp, FREAD | FWRITE, curlwp->l_cred); |
2675 | } | | 2692 | } |
2676 | } | | 2693 | } |
2677 | } | | 2694 | } |
2678 | | | 2695 | |
2679 | | | 2696 | |
2680 | void | | 2697 | void |
2681 | rf_UnconfigureVnodes(RF_Raid_t *raidPtr) | | 2698 | rf_UnconfigureVnodes(RF_Raid_t *raidPtr) |
2682 | { | | 2699 | { |
2683 | int r,c; | | 2700 | int r,c; |
2684 | struct vnode *vp; | | 2701 | struct vnode *vp; |
2685 | int acd; | | 2702 | int acd; |
2686 | | | 2703 | |
2687 | | | 2704 | |
2688 | /* We take this opportunity to close the vnodes like we should.. */ | | 2705 | /* We take this opportunity to close the vnodes like we should.. */ |
2689 | | | 2706 | |
2690 | for (c = 0; c < raidPtr->numCol; c++) { | | 2707 | for (c = 0; c < raidPtr->numCol; c++) { |
2691 | vp = raidPtr->raid_cinfo[c].ci_vp; | | 2708 | vp = raidPtr->raid_cinfo[c].ci_vp; |
2692 | acd = raidPtr->Disks[c].auto_configured; | | 2709 | acd = raidPtr->Disks[c].auto_configured; |
2693 | rf_close_component(raidPtr, vp, acd); | | 2710 | rf_close_component(raidPtr, vp, acd); |
2694 | raidPtr->raid_cinfo[c].ci_vp = NULL; | | 2711 | raidPtr->raid_cinfo[c].ci_vp = NULL; |
2695 | raidPtr->Disks[c].auto_configured = 0; | | 2712 | raidPtr->Disks[c].auto_configured = 0; |
2696 | } | | 2713 | } |
2697 | | | 2714 | |
2698 | for (r = 0; r < raidPtr->numSpare; r++) { | | 2715 | for (r = 0; r < raidPtr->numSpare; r++) { |
2699 | vp = raidPtr->raid_cinfo[raidPtr->numCol + r].ci_vp; | | 2716 | vp = raidPtr->raid_cinfo[raidPtr->numCol + r].ci_vp; |
2700 | acd = raidPtr->Disks[raidPtr->numCol + r].auto_configured; | | 2717 | acd = raidPtr->Disks[raidPtr->numCol + r].auto_configured; |
2701 | rf_close_component(raidPtr, vp, acd); | | 2718 | rf_close_component(raidPtr, vp, acd); |
2702 | raidPtr->raid_cinfo[raidPtr->numCol + r].ci_vp = NULL; | | 2719 | raidPtr->raid_cinfo[raidPtr->numCol + r].ci_vp = NULL; |
2703 | raidPtr->Disks[raidPtr->numCol + r].auto_configured = 0; | | 2720 | raidPtr->Disks[raidPtr->numCol + r].auto_configured = 0; |
2704 | } | | 2721 | } |
2705 | } | | 2722 | } |
2706 | | | 2723 | |
2707 | | | 2724 | |
2708 | void | | 2725 | void |
2709 | rf_ReconThread(struct rf_recon_req *req) | | 2726 | rf_ReconThread(struct rf_recon_req *req) |
2710 | { | | 2727 | { |
2711 | int s; | | 2728 | int s; |
2712 | RF_Raid_t *raidPtr; | | 2729 | RF_Raid_t *raidPtr; |
2713 | | | 2730 | |
2714 | s = splbio(); | | 2731 | s = splbio(); |
2715 | raidPtr = (RF_Raid_t *) req->raidPtr; | | 2732 | raidPtr = (RF_Raid_t *) req->raidPtr; |
2716 | raidPtr->recon_in_progress = 1; | | 2733 | raidPtr->recon_in_progress = 1; |
2717 | | | 2734 | |
2718 | rf_FailDisk((RF_Raid_t *) req->raidPtr, req->col, | | 2735 | rf_FailDisk((RF_Raid_t *) req->raidPtr, req->col, |
2719 | ((req->flags & RF_FDFLAGS_RECON) ? 1 : 0)); | | 2736 | ((req->flags & RF_FDFLAGS_RECON) ? 1 : 0)); |
2720 | | | 2737 | |
2721 | RF_Free(req, sizeof(*req)); | | 2738 | RF_Free(req, sizeof(*req)); |
2722 | | | 2739 | |
2723 | raidPtr->recon_in_progress = 0; | | 2740 | raidPtr->recon_in_progress = 0; |
2724 | splx(s); | | 2741 | splx(s); |
2725 | | | 2742 | |
2726 | /* That's all... */ | | 2743 | /* That's all... */ |
2727 | kthread_exit(0); /* does not return */ | | 2744 | kthread_exit(0); /* does not return */ |
2728 | } | | 2745 | } |
2729 | | | 2746 | |
2730 | void | | 2747 | void |
2731 | rf_RewriteParityThread(RF_Raid_t *raidPtr) | | 2748 | rf_RewriteParityThread(RF_Raid_t *raidPtr) |
2732 | { | | 2749 | { |
2733 | int retcode; | | 2750 | int retcode; |
2734 | int s; | | 2751 | int s; |
2735 | | | 2752 | |
2736 | raidPtr->parity_rewrite_stripes_done = 0; | | 2753 | raidPtr->parity_rewrite_stripes_done = 0; |
2737 | raidPtr->parity_rewrite_in_progress = 1; | | 2754 | raidPtr->parity_rewrite_in_progress = 1; |
2738 | s = splbio(); | | 2755 | s = splbio(); |
2739 | retcode = rf_RewriteParity(raidPtr); | | 2756 | retcode = rf_RewriteParity(raidPtr); |
2740 | splx(s); | | 2757 | splx(s); |
2741 | if (retcode) { | | 2758 | if (retcode) { |
2742 | printf("raid%d: Error re-writing parity!\n",raidPtr->raidid); | | 2759 | printf("raid%d: Error re-writing parity!\n",raidPtr->raidid); |
2743 | } else { | | 2760 | } else { |
2744 | /* set the clean bit! If we shutdown correctly, | | 2761 | /* set the clean bit! If we shutdown correctly, |
2745 | the clean bit on each component label will get | | 2762 | the clean bit on each component label will get |
2746 | set */ | | 2763 | set */ |
2747 | raidPtr->parity_good = RF_RAID_CLEAN; | | 2764 | raidPtr->parity_good = RF_RAID_CLEAN; |
2748 | } | | 2765 | } |
2749 | raidPtr->parity_rewrite_in_progress = 0; | | 2766 | raidPtr->parity_rewrite_in_progress = 0; |
2750 | | | 2767 | |
2751 | /* Anyone waiting for us to stop? If so, inform them... */ | | 2768 | /* Anyone waiting for us to stop? If so, inform them... */ |
2752 | if (raidPtr->waitShutdown) { | | 2769 | if (raidPtr->waitShutdown) { |
2753 | wakeup(&raidPtr->parity_rewrite_in_progress); | | 2770 | wakeup(&raidPtr->parity_rewrite_in_progress); |
2754 | } | | 2771 | } |
2755 | | | 2772 | |
2756 | /* That's all... */ | | 2773 | /* That's all... */ |
2757 | kthread_exit(0); /* does not return */ | | 2774 | kthread_exit(0); /* does not return */ |
2758 | } | | 2775 | } |
2759 | | | 2776 | |
2760 | | | 2777 | |
2761 | void | | 2778 | void |
2762 | rf_CopybackThread(RF_Raid_t *raidPtr) | | 2779 | rf_CopybackThread(RF_Raid_t *raidPtr) |
2763 | { | | 2780 | { |
2764 | int s; | | 2781 | int s; |
2765 | | | 2782 | |
2766 | raidPtr->copyback_in_progress = 1; | | 2783 | raidPtr->copyback_in_progress = 1; |
2767 | s = splbio(); | | 2784 | s = splbio(); |
2768 | rf_CopybackReconstructedData(raidPtr); | | 2785 | rf_CopybackReconstructedData(raidPtr); |
2769 | splx(s); | | 2786 | splx(s); |
2770 | raidPtr->copyback_in_progress = 0; | | 2787 | raidPtr->copyback_in_progress = 0; |
2771 | | | 2788 | |
2772 | /* That's all... */ | | 2789 | /* That's all... */ |
2773 | kthread_exit(0); /* does not return */ | | 2790 | kthread_exit(0); /* does not return */ |
2774 | } | | 2791 | } |
2775 | | | 2792 | |
2776 | | | 2793 | |
2777 | void | | 2794 | void |
2778 | rf_ReconstructInPlaceThread(struct rf_recon_req *req) | | 2795 | rf_ReconstructInPlaceThread(struct rf_recon_req *req) |
2779 | { | | 2796 | { |
2780 | int s; | | 2797 | int s; |
2781 | RF_Raid_t *raidPtr; | | 2798 | RF_Raid_t *raidPtr; |
2782 | | | 2799 | |
2783 | s = splbio(); | | 2800 | s = splbio(); |
2784 | raidPtr = req->raidPtr; | | 2801 | raidPtr = req->raidPtr; |
2785 | raidPtr->recon_in_progress = 1; | | 2802 | raidPtr->recon_in_progress = 1; |
2786 | rf_ReconstructInPlace(raidPtr, req->col); | | 2803 | rf_ReconstructInPlace(raidPtr, req->col); |
2787 | RF_Free(req, sizeof(*req)); | | 2804 | RF_Free(req, sizeof(*req)); |
2788 | raidPtr->recon_in_progress = 0; | | 2805 | raidPtr->recon_in_progress = 0; |
2789 | splx(s); | | 2806 | splx(s); |
2790 | | | 2807 | |
2791 | /* That's all... */ | | 2808 | /* That's all... */ |
2792 | kthread_exit(0); /* does not return */ | | 2809 | kthread_exit(0); /* does not return */ |
2793 | } | | 2810 | } |
2794 | | | 2811 | |
2795 | static RF_AutoConfig_t * | | 2812 | static RF_AutoConfig_t * |
2796 | rf_get_component(RF_AutoConfig_t *ac_list, dev_t dev, struct vnode *vp, | | 2813 | rf_get_component(RF_AutoConfig_t *ac_list, dev_t dev, struct vnode *vp, |
2797 | const char *cname, RF_SectorCount_t size) | | 2814 | const char *cname, RF_SectorCount_t size) |
2798 | { | | 2815 | { |
2799 | int good_one = 0; | | 2816 | int good_one = 0; |
2800 | RF_ComponentLabel_t *clabel; | | 2817 | RF_ComponentLabel_t *clabel; |
2801 | RF_AutoConfig_t *ac; | | 2818 | RF_AutoConfig_t *ac; |
2802 | | | 2819 | |
2803 | clabel = malloc(sizeof(RF_ComponentLabel_t), M_RAIDFRAME, M_NOWAIT); | | 2820 | clabel = malloc(sizeof(RF_ComponentLabel_t), M_RAIDFRAME, M_NOWAIT); |
2804 | if (clabel == NULL) { | | 2821 | if (clabel == NULL) { |
2805 | oomem: | | 2822 | oomem: |
2806 | while(ac_list) { | | 2823 | while(ac_list) { |
2807 | ac = ac_list; | | 2824 | ac = ac_list; |
2808 | if (ac->clabel) | | 2825 | if (ac->clabel) |
2809 | free(ac->clabel, M_RAIDFRAME); | | 2826 | free(ac->clabel, M_RAIDFRAME); |
2810 | ac_list = ac_list->next; | | 2827 | ac_list = ac_list->next; |
2811 | free(ac, M_RAIDFRAME); | | 2828 | free(ac, M_RAIDFRAME); |
2812 | } | | 2829 | } |
2813 | printf("RAID auto config: out of memory!\n"); | | 2830 | printf("RAID auto config: out of memory!\n"); |
2814 | return NULL; /* XXX probably should panic? */ | | 2831 | return NULL; /* XXX probably should panic? */ |
2815 | } | | 2832 | } |
2816 | | | 2833 | |
2817 | if (!raidread_component_label(dev, vp, clabel)) { | | 2834 | if (!raidread_component_label(dev, vp, clabel)) { |
2818 | /* Got the label. Does it look reasonable? */ | | 2835 | /* Got the label. Does it look reasonable? */ |
2819 | if (rf_reasonable_label(clabel) && | | 2836 | if (rf_reasonable_label(clabel) && |
2820 | (clabel->partitionSize <= size)) { | | 2837 | (clabel->partitionSize <= size)) { |
2821 | #ifdef DEBUG | | 2838 | #ifdef DEBUG |
2822 | printf("Component on: %s: %llu\n", | | 2839 | printf("Component on: %s: %llu\n", |
2823 | cname, (unsigned long long)size); | | 2840 | cname, (unsigned long long)size); |
2824 | rf_print_component_label(clabel); | | 2841 | rf_print_component_label(clabel); |
2825 | #endif | | 2842 | #endif |
2826 | /* if it's reasonable, add it, else ignore it. */ | | 2843 | /* if it's reasonable, add it, else ignore it. */ |
2827 | ac = malloc(sizeof(RF_AutoConfig_t), M_RAIDFRAME, | | 2844 | ac = malloc(sizeof(RF_AutoConfig_t), M_RAIDFRAME, |
2828 | M_NOWAIT); | | 2845 | M_NOWAIT); |
2829 | if (ac == NULL) { | | 2846 | if (ac == NULL) { |
2830 | free(clabel, M_RAIDFRAME); | | 2847 | free(clabel, M_RAIDFRAME); |
2831 | goto oomem; | | 2848 | goto oomem; |
2832 | } | | 2849 | } |
2833 | strlcpy(ac->devname, cname, sizeof(ac->devname)); | | 2850 | strlcpy(ac->devname, cname, sizeof(ac->devname)); |
2834 | ac->dev = dev; | | 2851 | ac->dev = dev; |
2835 | ac->vp = vp; | | 2852 | ac->vp = vp; |
2836 | ac->clabel = clabel; | | 2853 | ac->clabel = clabel; |
2837 | ac->next = ac_list; | | 2854 | ac->next = ac_list; |
2838 | ac_list = ac; | | 2855 | ac_list = ac; |
2839 | good_one = 1; | | 2856 | good_one = 1; |
2840 | } | | 2857 | } |
2841 | } | | 2858 | } |
2842 | if (!good_one) { | | 2859 | if (!good_one) { |
2843 | /* cleanup */ | | 2860 | /* cleanup */ |
2844 | free(clabel, M_RAIDFRAME); | | 2861 | free(clabel, M_RAIDFRAME); |
2845 | vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); | | 2862 | vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); |
2846 | VOP_CLOSE(vp, FREAD | FWRITE, NOCRED); | | 2863 | VOP_CLOSE(vp, FREAD | FWRITE, NOCRED); |
2847 | vput(vp); | | 2864 | vput(vp); |
2848 | } | | 2865 | } |
2849 | return ac_list; | | 2866 | return ac_list; |
2850 | } | | 2867 | } |
2851 | | | 2868 | |
2852 | RF_AutoConfig_t * | | 2869 | RF_AutoConfig_t * |
2853 | rf_find_raid_components(void) | | 2870 | rf_find_raid_components(void) |
2854 | { | | 2871 | { |
2855 | struct vnode *vp; | | 2872 | struct vnode *vp; |
2856 | struct disklabel label; | | 2873 | struct disklabel label; |
2857 | device_t dv; | | 2874 | device_t dv; |
2858 | dev_t dev; | | 2875 | dev_t dev; |
2859 | int bmajor, bminor, wedge; | | 2876 | int bmajor, bminor, wedge; |
2860 | int error; | | 2877 | int error; |
2861 | int i; | | 2878 | int i; |
2862 | RF_AutoConfig_t *ac_list; | | 2879 | RF_AutoConfig_t *ac_list; |
2863 | | | 2880 | |
2864 | | | 2881 | |
2865 | /* initialize the AutoConfig list */ | | 2882 | /* initialize the AutoConfig list */ |
2866 | ac_list = NULL; | | 2883 | ac_list = NULL; |
2867 | | | 2884 | |
2868 | /* we begin by trolling through *all* the devices on the system */ | | 2885 | /* we begin by trolling through *all* the devices on the system */ |
2869 | | | 2886 | |
2870 | for (dv = alldevs.tqh_first; dv != NULL; | | 2887 | for (dv = alldevs.tqh_first; dv != NULL; |
2871 | dv = dv->dv_list.tqe_next) { | | 2888 | dv = dv->dv_list.tqe_next) { |
2872 | | | 2889 | |
2873 | /* we are only interested in disks... */ | | 2890 | /* we are only interested in disks... */ |
2874 | if (device_class(dv) != DV_DISK) | | 2891 | if (device_class(dv) != DV_DISK) |
2875 | continue; | | 2892 | continue; |
2876 | | | 2893 | |
2877 | /* we don't care about floppies... */ | | 2894 | /* we don't care about floppies... */ |
2878 | if (device_is_a(dv, "fd")) { | | 2895 | if (device_is_a(dv, "fd")) { |
2879 | continue; | | 2896 | continue; |
2880 | } | | 2897 | } |
2881 | | | 2898 | |
2882 | /* we don't care about CD's... */ | | 2899 | /* we don't care about CD's... */ |
2883 | if (device_is_a(dv, "cd")) { | | 2900 | if (device_is_a(dv, "cd")) { |
2884 | continue; | | 2901 | continue; |
2885 | } | | 2902 | } |
2886 | | | 2903 | |
2887 | /* we don't care about md's... */ | | 2904 | /* we don't care about md's... */ |
2888 | if (device_is_a(dv, "md")) { | | 2905 | if (device_is_a(dv, "md")) { |
2889 | continue; | | 2906 | continue; |
2890 | } | | 2907 | } |
2891 | | | 2908 | |
2892 | /* hdfd is the Atari/Hades floppy driver */ | | 2909 | /* hdfd is the Atari/Hades floppy driver */ |
2893 | if (device_is_a(dv, "hdfd")) { | | 2910 | if (device_is_a(dv, "hdfd")) { |
2894 | continue; | | 2911 | continue; |
2895 | } | | 2912 | } |
2896 | | | 2913 | |
2897 | /* fdisa is the Atari/Milan floppy driver */ | | 2914 | /* fdisa is the Atari/Milan floppy driver */ |
2898 | if (device_is_a(dv, "fdisa")) { | | 2915 | if (device_is_a(dv, "fdisa")) { |
2899 | continue; | | 2916 | continue; |
2900 | } | | 2917 | } |
2901 | | | 2918 | |
2902 | /* need to find the device_name_to_block_device_major stuff */ | | 2919 | /* need to find the device_name_to_block_device_major stuff */ |
2903 | bmajor = devsw_name2blk(device_xname(dv), NULL, 0); | | 2920 | bmajor = devsw_name2blk(device_xname(dv), NULL, 0); |
2904 | | | 2921 | |
2905 | /* get a vnode for the raw partition of this disk */ | | 2922 | /* get a vnode for the raw partition of this disk */ |
2906 | | | 2923 | |
2907 | wedge = device_is_a(dv, "dk"); | | 2924 | wedge = device_is_a(dv, "dk"); |
2908 | bminor = minor(device_unit(dv)); | | 2925 | bminor = minor(device_unit(dv)); |
2909 | dev = wedge ? makedev(bmajor, bminor) : | | 2926 | dev = wedge ? makedev(bmajor, bminor) : |
2910 | MAKEDISKDEV(bmajor, bminor, RAW_PART); | | 2927 | MAKEDISKDEV(bmajor, bminor, RAW_PART); |
2911 | if (bdevvp(dev, &vp)) | | 2928 | if (bdevvp(dev, &vp)) |
2912 | panic("RAID can't alloc vnode"); | | 2929 | panic("RAID can't alloc vnode"); |
2913 | | | 2930 | |
2914 | error = VOP_OPEN(vp, FREAD, NOCRED); | | 2931 | error = VOP_OPEN(vp, FREAD, NOCRED); |
2915 | | | 2932 | |
2916 | if (error) { | | 2933 | if (error) { |
2917 | /* "Who cares." Continue looking | | 2934 | /* "Who cares." Continue looking |
2918 | for something that exists*/ | | 2935 | for something that exists*/ |
2919 | vput(vp); | | 2936 | vput(vp); |
2920 | continue; | | 2937 | continue; |
2921 | } | | 2938 | } |
2922 | | | 2939 | |
2923 | if (wedge) { | | 2940 | if (wedge) { |
2924 | struct dkwedge_info dkw; | | 2941 | struct dkwedge_info dkw; |
2925 | error = VOP_IOCTL(vp, DIOCGWEDGEINFO, &dkw, FREAD, | | 2942 | error = VOP_IOCTL(vp, DIOCGWEDGEINFO, &dkw, FREAD, |
2926 | NOCRED); | | 2943 | NOCRED); |
2927 | if (error) { | | 2944 | if (error) { |
2928 | printf("RAIDframe: can't get wedge info for " | | 2945 | printf("RAIDframe: can't get wedge info for " |
2929 | "dev %s (%d)\n", device_xname(dv), error); | | 2946 | "dev %s (%d)\n", device_xname(dv), error); |
2930 | vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); | | 2947 | vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); |
2931 | VOP_CLOSE(vp, FREAD | FWRITE, NOCRED); | | 2948 | VOP_CLOSE(vp, FREAD | FWRITE, NOCRED); |
2932 | vput(vp); | | 2949 | vput(vp); |
2933 | continue; | | 2950 | continue; |
2934 | } | | 2951 | } |
2935 | | | 2952 | |
2936 | if (strcmp(dkw.dkw_ptype, DKW_PTYPE_RAIDFRAME) != 0) { | | 2953 | if (strcmp(dkw.dkw_ptype, DKW_PTYPE_RAIDFRAME) != 0) { |
2937 | vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); | | 2954 | vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); |
2938 | VOP_CLOSE(vp, FREAD | FWRITE, NOCRED); | | 2955 | VOP_CLOSE(vp, FREAD | FWRITE, NOCRED); |
2939 | vput(vp); | | 2956 | vput(vp); |
2940 | continue; | | 2957 | continue; |
2941 | } | | 2958 | } |
2942 | | | 2959 | |
2943 | ac_list = rf_get_component(ac_list, dev, vp, | | 2960 | ac_list = rf_get_component(ac_list, dev, vp, |
2944 | device_xname(dv), dkw.dkw_size); | | 2961 | device_xname(dv), dkw.dkw_size); |
2945 | continue; | | 2962 | continue; |
2946 | } | | 2963 | } |
2947 | | | 2964 | |
2948 | /* Ok, the disk exists. Go get the disklabel. */ | | 2965 | /* Ok, the disk exists. Go get the disklabel. */ |
2949 | error = VOP_IOCTL(vp, DIOCGDINFO, &label, FREAD, NOCRED); | | 2966 | error = VOP_IOCTL(vp, DIOCGDINFO, &label, FREAD, NOCRED); |
2950 | if (error) { | | 2967 | if (error) { |
2951 | /* | | 2968 | /* |
2952 | * XXX can't happen - open() would | | 2969 | * XXX can't happen - open() would |
2953 | * have errored out (or faked up one) | | 2970 | * have errored out (or faked up one) |
2954 | */ | | 2971 | */ |
2955 | if (error != ENOTTY) | | 2972 | if (error != ENOTTY) |
2956 | printf("RAIDframe: can't get label for dev " | | 2973 | printf("RAIDframe: can't get label for dev " |
2957 | "%s (%d)\n", device_xname(dv), error); | | 2974 | "%s (%d)\n", device_xname(dv), error); |
2958 | } | | 2975 | } |
2959 | | | 2976 | |
2960 | /* don't need this any more. We'll allocate it again | | 2977 | /* don't need this any more. We'll allocate it again |
2961 | a little later if we really do... */ | | 2978 | a little later if we really do... */ |
2962 | vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); | | 2979 | vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); |
2963 | VOP_CLOSE(vp, FREAD | FWRITE, NOCRED); | | 2980 | VOP_CLOSE(vp, FREAD | FWRITE, NOCRED); |
2964 | vput(vp); | | 2981 | vput(vp); |
2965 | | | 2982 | |
2966 | if (error) | | 2983 | if (error) |
2967 | continue; | | 2984 | continue; |
2968 | | | 2985 | |
2969 | for (i = 0; i < label.d_npartitions; i++) { | | 2986 | for (i = 0; i < label.d_npartitions; i++) { |
2970 | char cname[sizeof(ac_list->devname)]; | | 2987 | char cname[sizeof(ac_list->devname)]; |
2971 | | | 2988 | |
2972 | /* We only support partitions marked as RAID */ | | 2989 | /* We only support partitions marked as RAID */ |
2973 | if (label.d_partitions[i].p_fstype != FS_RAID) | | 2990 | if (label.d_partitions[i].p_fstype != FS_RAID) |
2974 | continue; | | 2991 | continue; |
2975 | | | 2992 | |
2976 | dev = MAKEDISKDEV(bmajor, device_unit(dv), i); | | 2993 | dev = MAKEDISKDEV(bmajor, device_unit(dv), i); |
2977 | if (bdevvp(dev, &vp)) | | 2994 | if (bdevvp(dev, &vp)) |
2978 | panic("RAID can't alloc vnode"); | | 2995 | panic("RAID can't alloc vnode"); |
2979 | | | 2996 | |
2980 | error = VOP_OPEN(vp, FREAD, NOCRED); | | 2997 | error = VOP_OPEN(vp, FREAD, NOCRED); |
2981 | if (error) { | | 2998 | if (error) { |
2982 | /* Whatever... */ | | 2999 | /* Whatever... */ |
2983 | vput(vp); | | 3000 | vput(vp); |
2984 | continue; | | 3001 | continue; |
2985 | } | | 3002 | } |
2986 | snprintf(cname, sizeof(cname), "%s%c", | | 3003 | snprintf(cname, sizeof(cname), "%s%c", |
2987 | device_xname(dv), 'a' + i); | | 3004 | device_xname(dv), 'a' + i); |
2988 | ac_list = rf_get_component(ac_list, dev, vp, cname, | | 3005 | ac_list = rf_get_component(ac_list, dev, vp, cname, |
2989 | label.d_partitions[i].p_size); | | 3006 | label.d_partitions[i].p_size); |
2990 | } | | 3007 | } |
2991 | } | | 3008 | } |
2992 | return ac_list; | | 3009 | return ac_list; |
2993 | } | | 3010 | } |
2994 | | | 3011 | |
2995 | | | 3012 | |
2996 | static int | | 3013 | static int |
2997 | rf_reasonable_label(RF_ComponentLabel_t *clabel) | | 3014 | rf_reasonable_label(RF_ComponentLabel_t *clabel) |
2998 | { | | 3015 | { |
2999 | | | 3016 | |
3000 | if (((clabel->version==RF_COMPONENT_LABEL_VERSION_1) || | | 3017 | if (((clabel->version==RF_COMPONENT_LABEL_VERSION_1) || |
3001 | (clabel->version==RF_COMPONENT_LABEL_VERSION)) && | | 3018 | (clabel->version==RF_COMPONENT_LABEL_VERSION)) && |
3002 | ((clabel->clean == RF_RAID_CLEAN) || | | 3019 | ((clabel->clean == RF_RAID_CLEAN) || |
3003 | (clabel->clean == RF_RAID_DIRTY)) && | | 3020 | (clabel->clean == RF_RAID_DIRTY)) && |
3004 | clabel->row >=0 && | | 3021 | clabel->row >=0 && |
3005 | clabel->column >= 0 && | | 3022 | clabel->column >= 0 && |
3006 | clabel->num_rows > 0 && | | 3023 | clabel->num_rows > 0 && |
3007 | clabel->num_columns > 0 && | | 3024 | clabel->num_columns > 0 && |
3008 | clabel->row < clabel->num_rows && | | 3025 | clabel->row < clabel->num_rows && |
3009 | clabel->column < clabel->num_columns && | | 3026 | clabel->column < clabel->num_columns && |
3010 | clabel->blockSize > 0 && | | 3027 | clabel->blockSize > 0 && |
3011 | clabel->numBlocks > 0) { | | 3028 | clabel->numBlocks > 0) { |
3012 | /* label looks reasonable enough... */ | | 3029 | /* label looks reasonable enough... */ |
3013 | return(1); | | 3030 | return(1); |
3014 | } | | 3031 | } |
3015 | return(0); | | 3032 | return(0); |
3016 | } | | 3033 | } |
3017 | | | 3034 | |
3018 | | | 3035 | |
3019 | #ifdef DEBUG | | 3036 | #ifdef DEBUG |
3020 | void | | 3037 | void |
3021 | rf_print_component_label(RF_ComponentLabel_t *clabel) | | 3038 | rf_print_component_label(RF_ComponentLabel_t *clabel) |
3022 | { | | 3039 | { |
3023 | printf(" Row: %d Column: %d Num Rows: %d Num Columns: %d\n", | | 3040 | printf(" Row: %d Column: %d Num Rows: %d Num Columns: %d\n", |
3024 | clabel->row, clabel->column, | | 3041 | clabel->row, clabel->column, |
3025 | clabel->num_rows, clabel->num_columns); | | 3042 | clabel->num_rows, clabel->num_columns); |
3026 | printf(" Version: %d Serial Number: %d Mod Counter: %d\n", | | 3043 | printf(" Version: %d Serial Number: %d Mod Counter: %d\n", |
3027 | clabel->version, clabel->serial_number, | | 3044 | clabel->version, clabel->serial_number, |
3028 | clabel->mod_counter); | | 3045 | clabel->mod_counter); |
3029 | printf(" Clean: %s Status: %d\n", | | 3046 | printf(" Clean: %s Status: %d\n", |
3030 | clabel->clean ? "Yes" : "No", clabel->status ); | | 3047 | clabel->clean ? "Yes" : "No", clabel->status ); |
3031 | printf(" sectPerSU: %d SUsPerPU: %d SUsPerRU: %d\n", | | 3048 | printf(" sectPerSU: %d SUsPerPU: %d SUsPerRU: %d\n", |
3032 | clabel->sectPerSU, clabel->SUsPerPU, clabel->SUsPerRU); | | 3049 | clabel->sectPerSU, clabel->SUsPerPU, clabel->SUsPerRU); |
3033 | printf(" RAID Level: %c blocksize: %d numBlocks: %d\n", | | 3050 | printf(" RAID Level: %c blocksize: %d numBlocks: %d\n", |
3034 | (char) clabel->parityConfig, clabel->blockSize, | | 3051 | (char) clabel->parityConfig, clabel->blockSize, |
3035 | clabel->numBlocks); | | 3052 | clabel->numBlocks); |
3036 | printf(" Autoconfig: %s\n", clabel->autoconfigure ? "Yes" : "No" ); | | 3053 | printf(" Autoconfig: %s\n", clabel->autoconfigure ? "Yes" : "No" ); |
3037 | printf(" Contains root partition: %s\n", | | 3054 | printf(" Contains root partition: %s\n", |
3038 | clabel->root_partition ? "Yes" : "No" ); | | 3055 | clabel->root_partition ? "Yes" : "No" ); |
3039 | printf(" Last configured as: raid%d\n", clabel->last_unit ); | | 3056 | printf(" Last configured as: raid%d\n", clabel->last_unit ); |
3040 | #if 0 | | 3057 | #if 0 |
3041 | printf(" Config order: %d\n", clabel->config_order); | | 3058 | printf(" Config order: %d\n", clabel->config_order); |
3042 | #endif | | 3059 | #endif |
3043 | | | 3060 | |
3044 | } | | 3061 | } |
3045 | #endif | | 3062 | #endif |
3046 | | | 3063 | |
3047 | RF_ConfigSet_t * | | 3064 | RF_ConfigSet_t * |
3048 | rf_create_auto_sets(RF_AutoConfig_t *ac_list) | | 3065 | rf_create_auto_sets(RF_AutoConfig_t *ac_list) |
3049 | { | | 3066 | { |
3050 | RF_AutoConfig_t *ac; | | 3067 | RF_AutoConfig_t *ac; |
3051 | RF_ConfigSet_t *config_sets; | | 3068 | RF_ConfigSet_t *config_sets; |
3052 | RF_ConfigSet_t *cset; | | 3069 | RF_ConfigSet_t *cset; |
3053 | RF_AutoConfig_t *ac_next; | | 3070 | RF_AutoConfig_t *ac_next; |
3054 | | | 3071 | |
3055 | | | 3072 | |
3056 | config_sets = NULL; | | 3073 | config_sets = NULL; |
3057 | | | 3074 | |
3058 | /* Go through the AutoConfig list, and figure out which components | | 3075 | /* Go through the AutoConfig list, and figure out which components |
3059 | belong to what sets. */ | | 3076 | belong to what sets. */ |
3060 | ac = ac_list; | | 3077 | ac = ac_list; |
3061 | while(ac!=NULL) { | | 3078 | while(ac!=NULL) { |
3062 | /* we're going to putz with ac->next, so save it here | | 3079 | /* we're going to putz with ac->next, so save it here |
3063 | for use at the end of the loop */ | | 3080 | for use at the end of the loop */ |
3064 | ac_next = ac->next; | | 3081 | ac_next = ac->next; |
3065 | | | 3082 | |
3066 | if (config_sets == NULL) { | | 3083 | if (config_sets == NULL) { |
3067 | /* will need at least this one... */ | | 3084 | /* will need at least this one... */ |
3068 | config_sets = (RF_ConfigSet_t *) | | 3085 | config_sets = (RF_ConfigSet_t *) |
3069 | malloc(sizeof(RF_ConfigSet_t), | | 3086 | malloc(sizeof(RF_ConfigSet_t), |
3070 | M_RAIDFRAME, M_NOWAIT); | | 3087 | M_RAIDFRAME, M_NOWAIT); |
3071 | if (config_sets == NULL) { | | 3088 | if (config_sets == NULL) { |
3072 | panic("rf_create_auto_sets: No memory!"); | | 3089 | panic("rf_create_auto_sets: No memory!"); |
3073 | } | | 3090 | } |
3074 | /* this one is easy :) */ | | 3091 | /* this one is easy :) */ |
3075 | config_sets->ac = ac; | | 3092 | config_sets->ac = ac; |
3076 | config_sets->next = NULL; | | 3093 | config_sets->next = NULL; |
3077 | config_sets->rootable = 0; | | 3094 | config_sets->rootable = 0; |
3078 | ac->next = NULL; | | 3095 | ac->next = NULL; |
3079 | } else { | | 3096 | } else { |
3080 | /* which set does this component fit into? */ | | 3097 | /* which set does this component fit into? */ |
3081 | cset = config_sets; | | 3098 | cset = config_sets; |
3082 | while(cset!=NULL) { | | 3099 | while(cset!=NULL) { |
3083 | if (rf_does_it_fit(cset, ac)) { | | 3100 | if (rf_does_it_fit(cset, ac)) { |
3084 | /* looks like it matches... */ | | 3101 | /* looks like it matches... */ |
3085 | ac->next = cset->ac; | | 3102 | ac->next = cset->ac; |
3086 | cset->ac = ac; | | 3103 | cset->ac = ac; |
3087 | break; | | 3104 | break; |
3088 | } | | 3105 | } |
3089 | cset = cset->next; | | 3106 | cset = cset->next; |
3090 | } | | 3107 | } |
3091 | if (cset==NULL) { | | 3108 | if (cset==NULL) { |
3092 | /* didn't find a match above... new set..*/ | | 3109 | /* didn't find a match above... new set..*/ |
3093 | cset = (RF_ConfigSet_t *) | | 3110 | cset = (RF_ConfigSet_t *) |
3094 | malloc(sizeof(RF_ConfigSet_t), | | 3111 | malloc(sizeof(RF_ConfigSet_t), |
3095 | M_RAIDFRAME, M_NOWAIT); | | 3112 | M_RAIDFRAME, M_NOWAIT); |
3096 | if (cset == NULL) { | | 3113 | if (cset == NULL) { |
3097 | panic("rf_create_auto_sets: No memory!"); | | 3114 | panic("rf_create_auto_sets: No memory!"); |
3098 | } | | 3115 | } |
3099 | cset->ac = ac; | | 3116 | cset->ac = ac; |
3100 | ac->next = NULL; | | 3117 | ac->next = NULL; |
3101 | cset->next = config_sets; | | 3118 | cset->next = config_sets; |
3102 | cset->rootable = 0; | | 3119 | cset->rootable = 0; |
3103 | config_sets = cset; | | 3120 | config_sets = cset; |
3104 | } | | 3121 | } |
3105 | } | | 3122 | } |
3106 | ac = ac_next; | | 3123 | ac = ac_next; |
3107 | } | | 3124 | } |
3108 | | | 3125 | |
3109 | | | 3126 | |
3110 | return(config_sets); | | 3127 | return(config_sets); |
3111 | } | | 3128 | } |
3112 | | | 3129 | |
3113 | static int | | 3130 | static int |
3114 | rf_does_it_fit(RF_ConfigSet_t *cset, RF_AutoConfig_t *ac) | | 3131 | rf_does_it_fit(RF_ConfigSet_t *cset, RF_AutoConfig_t *ac) |
3115 | { | | 3132 | { |
3116 | RF_ComponentLabel_t *clabel1, *clabel2; | | 3133 | RF_ComponentLabel_t *clabel1, *clabel2; |
3117 | | | 3134 | |
3118 | /* If this one matches the *first* one in the set, that's good | | 3135 | /* If this one matches the *first* one in the set, that's good |
3119 | enough, since the other members of the set would have been | | 3136 | enough, since the other members of the set would have been |
3120 | through here too... */ | | 3137 | through here too... */ |
3121 | /* note that we are not checking partitionSize here.. | | 3138 | /* note that we are not checking partitionSize here.. |
3122 | | | 3139 | |
3123 | Note that we are also not checking the mod_counters here. | | 3140 | Note that we are also not checking the mod_counters here. |
3124 | If everything else matches execpt the mod_counter, that's | | 3141 | If everything else matches execpt the mod_counter, that's |
3125 | good enough for this test. We will deal with the mod_counters | | 3142 | good enough for this test. We will deal with the mod_counters |
3126 | a little later in the autoconfiguration process. | | 3143 | a little later in the autoconfiguration process. |
3127 | | | 3144 | |
3128 | (clabel1->mod_counter == clabel2->mod_counter) && | | 3145 | (clabel1->mod_counter == clabel2->mod_counter) && |
3129 | | | 3146 | |
3130 | The reason we don't check for this is that failed disks | | 3147 | The reason we don't check for this is that failed disks |
3131 | will have lower modification counts. If those disks are | | 3148 | will have lower modification counts. If those disks are |
3132 | not added to the set they used to belong to, then they will | | 3149 | not added to the set they used to belong to, then they will |
3133 | form their own set, which may result in 2 different sets, | | 3150 | form their own set, which may result in 2 different sets, |
3134 | for example, competing to be configured at raid0, and | | 3151 | for example, competing to be configured at raid0, and |
3135 | perhaps competing to be the root filesystem set. If the | | 3152 | perhaps competing to be the root filesystem set. If the |
3136 | wrong ones get configured, or both attempt to become /, | | 3153 | wrong ones get configured, or both attempt to become /, |
3137 | weird behaviour and or serious lossage will occur. Thus we | | 3154 | weird behaviour and or serious lossage will occur. Thus we |
3138 | need to bring them into the fold here, and kick them out at | | 3155 | need to bring them into the fold here, and kick them out at |
3139 | a later point. | | 3156 | a later point. |
3140 | | | 3157 | |
3141 | */ | | 3158 | */ |
3142 | | | 3159 | |
3143 | clabel1 = cset->ac->clabel; | | 3160 | clabel1 = cset->ac->clabel; |
3144 | clabel2 = ac->clabel; | | 3161 | clabel2 = ac->clabel; |
3145 | if ((clabel1->version == clabel2->version) && | | 3162 | if ((clabel1->version == clabel2->version) && |
3146 | (clabel1->serial_number == clabel2->serial_number) && | | 3163 | (clabel1->serial_number == clabel2->serial_number) && |
3147 | (clabel1->num_rows == clabel2->num_rows) && | | 3164 | (clabel1->num_rows == clabel2->num_rows) && |
3148 | (clabel1->num_columns == clabel2->num_columns) && | | 3165 | (clabel1->num_columns == clabel2->num_columns) && |
3149 | (clabel1->sectPerSU == clabel2->sectPerSU) && | | 3166 | (clabel1->sectPerSU == clabel2->sectPerSU) && |
3150 | (clabel1->SUsPerPU == clabel2->SUsPerPU) && | | 3167 | (clabel1->SUsPerPU == clabel2->SUsPerPU) && |
3151 | (clabel1->SUsPerRU == clabel2->SUsPerRU) && | | 3168 | (clabel1->SUsPerRU == clabel2->SUsPerRU) && |
3152 | (clabel1->parityConfig == clabel2->parityConfig) && | | 3169 | (clabel1->parityConfig == clabel2->parityConfig) && |
3153 | (clabel1->maxOutstanding == clabel2->maxOutstanding) && | | 3170 | (clabel1->maxOutstanding == clabel2->maxOutstanding) && |
3154 | (clabel1->blockSize == clabel2->blockSize) && | | 3171 | (clabel1->blockSize == clabel2->blockSize) && |
3155 | (clabel1->numBlocks == clabel2->numBlocks) && | | 3172 | (clabel1->numBlocks == clabel2->numBlocks) && |
3156 | (clabel1->autoconfigure == clabel2->autoconfigure) && | | 3173 | (clabel1->autoconfigure == clabel2->autoconfigure) && |
3157 | (clabel1->root_partition == clabel2->root_partition) && | | 3174 | (clabel1->root_partition == clabel2->root_partition) && |
3158 | (clabel1->last_unit == clabel2->last_unit) && | | 3175 | (clabel1->last_unit == clabel2->last_unit) && |
3159 | (clabel1->config_order == clabel2->config_order)) { | | 3176 | (clabel1->config_order == clabel2->config_order)) { |
3160 | /* if it get's here, it almost *has* to be a match */ | | 3177 | /* if it get's here, it almost *has* to be a match */ |
3161 | } else { | | 3178 | } else { |
3162 | /* it's not consistent with somebody in the set.. | | 3179 | /* it's not consistent with somebody in the set.. |
3163 | punt */ | | 3180 | punt */ |
3164 | return(0); | | 3181 | return(0); |
3165 | } | | 3182 | } |
3166 | /* all was fine.. it must fit... */ | | 3183 | /* all was fine.. it must fit... */ |
3167 | return(1); | | 3184 | return(1); |
3168 | } | | 3185 | } |
3169 | | | 3186 | |
3170 | int | | 3187 | int |
3171 | rf_have_enough_components(RF_ConfigSet_t *cset) | | 3188 | rf_have_enough_components(RF_ConfigSet_t *cset) |
3172 | { | | 3189 | { |
3173 | RF_AutoConfig_t *ac; | | 3190 | RF_AutoConfig_t *ac; |
3174 | RF_AutoConfig_t *auto_config; | | 3191 | RF_AutoConfig_t *auto_config; |
3175 | RF_ComponentLabel_t *clabel; | | 3192 | RF_ComponentLabel_t *clabel; |
3176 | int c; | | 3193 | int c; |
3177 | int num_cols; | | 3194 | int num_cols; |
3178 | int num_missing; | | 3195 | int num_missing; |
3179 | int mod_counter; | | 3196 | int mod_counter; |
3180 | int mod_counter_found; | | 3197 | int mod_counter_found; |
3181 | int even_pair_failed; | | 3198 | int even_pair_failed; |
3182 | char parity_type; | | 3199 | char parity_type; |
3183 | | | 3200 | |
3184 | | | 3201 | |
3185 | /* check to see that we have enough 'live' components | | 3202 | /* check to see that we have enough 'live' components |
3186 | of this set. If so, we can configure it if necessary */ | | 3203 | of this set. If so, we can configure it if necessary */ |
3187 | | | 3204 | |
3188 | num_cols = cset->ac->clabel->num_columns; | | 3205 | num_cols = cset->ac->clabel->num_columns; |
3189 | parity_type = cset->ac->clabel->parityConfig; | | 3206 | parity_type = cset->ac->clabel->parityConfig; |
3190 | | | 3207 | |
3191 | /* XXX Check for duplicate components!?!?!? */ | | 3208 | /* XXX Check for duplicate components!?!?!? */ |
3192 | | | 3209 | |
3193 | /* Determine what the mod_counter is supposed to be for this set. */ | | 3210 | /* Determine what the mod_counter is supposed to be for this set. */ |
3194 | | | 3211 | |
3195 | mod_counter_found = 0; | | 3212 | mod_counter_found = 0; |
3196 | mod_counter = 0; | | 3213 | mod_counter = 0; |
3197 | ac = cset->ac; | | 3214 | ac = cset->ac; |
3198 | while(ac!=NULL) { | | 3215 | while(ac!=NULL) { |
3199 | if (mod_counter_found==0) { | | 3216 | if (mod_counter_found==0) { |
3200 | mod_counter = ac->clabel->mod_counter; | | 3217 | mod_counter = ac->clabel->mod_counter; |
3201 | mod_counter_found = 1; | | 3218 | mod_counter_found = 1; |
3202 | } else { | | 3219 | } else { |
3203 | if (ac->clabel->mod_counter > mod_counter) { | | 3220 | if (ac->clabel->mod_counter > mod_counter) { |
3204 | mod_counter = ac->clabel->mod_counter; | | 3221 | mod_counter = ac->clabel->mod_counter; |
3205 | } | | 3222 | } |
3206 | } | | 3223 | } |
3207 | ac = ac->next; | | 3224 | ac = ac->next; |
3208 | } | | 3225 | } |
3209 | | | 3226 | |
3210 | num_missing = 0; | | 3227 | num_missing = 0; |
3211 | auto_config = cset->ac; | | 3228 | auto_config = cset->ac; |
3212 | | | 3229 | |
3213 | even_pair_failed = 0; | | 3230 | even_pair_failed = 0; |
3214 | for(c=0; c<num_cols; c++) { | | 3231 | for(c=0; c<num_cols; c++) { |
3215 | ac = auto_config; | | 3232 | ac = auto_config; |
3216 | while(ac!=NULL) { | | 3233 | while(ac!=NULL) { |
3217 | if ((ac->clabel->column == c) && | | 3234 | if ((ac->clabel->column == c) && |
3218 | (ac->clabel->mod_counter == mod_counter)) { | | 3235 | (ac->clabel->mod_counter == mod_counter)) { |
3219 | /* it's this one... */ | | 3236 | /* it's this one... */ |
3220 | #ifdef DEBUG | | 3237 | #ifdef DEBUG |
3221 | printf("Found: %s at %d\n", | | 3238 | printf("Found: %s at %d\n", |
3222 | ac->devname,c); | | 3239 | ac->devname,c); |
3223 | #endif | | 3240 | #endif |
3224 | break; | | 3241 | break; |
3225 | } | | 3242 | } |
3226 | ac=ac->next; | | 3243 | ac=ac->next; |
3227 | } | | 3244 | } |
3228 | if (ac==NULL) { | | 3245 | if (ac==NULL) { |
3229 | /* Didn't find one here! */ | | 3246 | /* Didn't find one here! */ |
3230 | /* special case for RAID 1, especially | | 3247 | /* special case for RAID 1, especially |
3231 | where there are more than 2 | | 3248 | where there are more than 2 |
3232 | components (where RAIDframe treats | | 3249 | components (where RAIDframe treats |
3233 | things a little differently :( ) */ | | 3250 | things a little differently :( ) */ |
3234 | if (parity_type == '1') { | | 3251 | if (parity_type == '1') { |
3235 | if (c%2 == 0) { /* even component */ | | 3252 | if (c%2 == 0) { /* even component */ |
3236 | even_pair_failed = 1; | | 3253 | even_pair_failed = 1; |
3237 | } else { /* odd component. If | | 3254 | } else { /* odd component. If |
3238 | we're failed, and | | 3255 | we're failed, and |
3239 | so is the even | | 3256 | so is the even |
3240 | component, it's | | 3257 | component, it's |
3241 | "Good Night, Charlie" */ | | 3258 | "Good Night, Charlie" */ |
3242 | if (even_pair_failed == 1) { | | 3259 | if (even_pair_failed == 1) { |
3243 | return(0); | | 3260 | return(0); |
3244 | } | | 3261 | } |
3245 | } | | 3262 | } |
3246 | } else { | | 3263 | } else { |
3247 | /* normal accounting */ | | 3264 | /* normal accounting */ |
3248 | num_missing++; | | 3265 | num_missing++; |
3249 | } | | 3266 | } |
3250 | } | | 3267 | } |
3251 | if ((parity_type == '1') && (c%2 == 1)) { | | 3268 | if ((parity_type == '1') && (c%2 == 1)) { |
3252 | /* Just did an even component, and we didn't | | 3269 | /* Just did an even component, and we didn't |
3253 | bail.. reset the even_pair_failed flag, | | 3270 | bail.. reset the even_pair_failed flag, |
3254 | and go on to the next component.... */ | | 3271 | and go on to the next component.... */ |
3255 | even_pair_failed = 0; | | 3272 | even_pair_failed = 0; |
3256 | } | | 3273 | } |
3257 | } | | 3274 | } |
3258 | | | 3275 | |
3259 | clabel = cset->ac->clabel; | | 3276 | clabel = cset->ac->clabel; |
3260 | | | 3277 | |
3261 | if (((clabel->parityConfig == '0') && (num_missing > 0)) || | | 3278 | if (((clabel->parityConfig == '0') && (num_missing > 0)) || |
3262 | ((clabel->parityConfig == '4') && (num_missing > 1)) || | | 3279 | ((clabel->parityConfig == '4') && (num_missing > 1)) || |
3263 | ((clabel->parityConfig == '5') && (num_missing > 1))) { | | 3280 | ((clabel->parityConfig == '5') && (num_missing > 1))) { |
3264 | /* XXX this needs to be made *much* more general */ | | 3281 | /* XXX this needs to be made *much* more general */ |
3265 | /* Too many failures */ | | 3282 | /* Too many failures */ |
3266 | return(0); | | 3283 | return(0); |
3267 | } | | 3284 | } |
3268 | /* otherwise, all is well, and we've got enough to take a kick | | 3285 | /* otherwise, all is well, and we've got enough to take a kick |
3269 | at autoconfiguring this set */ | | 3286 | at autoconfiguring this set */ |
3270 | return(1); | | 3287 | return(1); |
3271 | } | | 3288 | } |
3272 | | | 3289 | |
3273 | void | | 3290 | void |
3274 | rf_create_configuration(RF_AutoConfig_t *ac, RF_Config_t *config, | | 3291 | rf_create_configuration(RF_AutoConfig_t *ac, RF_Config_t *config, |
3275 | RF_Raid_t *raidPtr) | | 3292 | RF_Raid_t *raidPtr) |
3276 | { | | 3293 | { |
3277 | RF_ComponentLabel_t *clabel; | | 3294 | RF_ComponentLabel_t *clabel; |
3278 | int i; | | 3295 | int i; |
3279 | | | 3296 | |
3280 | clabel = ac->clabel; | | 3297 | clabel = ac->clabel; |
3281 | | | 3298 | |
3282 | /* 1. Fill in the common stuff */ | | 3299 | /* 1. Fill in the common stuff */ |
3283 | config->numRow = clabel->num_rows = 1; | | 3300 | config->numRow = clabel->num_rows = 1; |
3284 | config->numCol = clabel->num_columns; | | 3301 | config->numCol = clabel->num_columns; |
3285 | config->numSpare = 0; /* XXX should this be set here? */ | | 3302 | config->numSpare = 0; /* XXX should this be set here? */ |
3286 | config->sectPerSU = clabel->sectPerSU; | | 3303 | config->sectPerSU = clabel->sectPerSU; |
3287 | config->SUsPerPU = clabel->SUsPerPU; | | 3304 | config->SUsPerPU = clabel->SUsPerPU; |
3288 | config->SUsPerRU = clabel->SUsPerRU; | | 3305 | config->SUsPerRU = clabel->SUsPerRU; |
3289 | config->parityConfig = clabel->parityConfig; | | 3306 | config->parityConfig = clabel->parityConfig; |
3290 | /* XXX... */ | | 3307 | /* XXX... */ |
3291 | strcpy(config->diskQueueType,"fifo"); | | 3308 | strcpy(config->diskQueueType,"fifo"); |
3292 | config->maxOutstandingDiskReqs = clabel->maxOutstanding; | | 3309 | config->maxOutstandingDiskReqs = clabel->maxOutstanding; |
3293 | config->layoutSpecificSize = 0; /* XXX ?? */ | | 3310 | config->layoutSpecificSize = 0; /* XXX ?? */ |
3294 | | | 3311 | |
3295 | while(ac!=NULL) { | | 3312 | while(ac!=NULL) { |
3296 | /* row/col values will be in range due to the checks | | 3313 | /* row/col values will be in range due to the checks |
3297 | in reasonable_label() */ | | 3314 | in reasonable_label() */ |
3298 | strcpy(config->devnames[0][ac->clabel->column], | | 3315 | strcpy(config->devnames[0][ac->clabel->column], |
3299 | ac->devname); | | 3316 | ac->devname); |
3300 | ac = ac->next; | | 3317 | ac = ac->next; |
3301 | } | | 3318 | } |
3302 | | | 3319 | |
3303 | for(i=0;i<RF_MAXDBGV;i++) { | | 3320 | for(i=0;i<RF_MAXDBGV;i++) { |
3304 | config->debugVars[i][0] = 0; | | 3321 | config->debugVars[i][0] = 0; |
3305 | } | | 3322 | } |
3306 | } | | 3323 | } |
3307 | | | 3324 | |
3308 | int | | 3325 | int |
3309 | rf_set_autoconfig(RF_Raid_t *raidPtr, int new_value) | | 3326 | rf_set_autoconfig(RF_Raid_t *raidPtr, int new_value) |
3310 | { | | 3327 | { |
3311 | RF_ComponentLabel_t clabel; | | 3328 | RF_ComponentLabel_t clabel; |
3312 | struct vnode *vp; | | 3329 | struct vnode *vp; |
3313 | dev_t dev; | | 3330 | dev_t dev; |
3314 | int column; | | 3331 | int column; |
3315 | int sparecol; | | 3332 | int sparecol; |
3316 | | | 3333 | |
3317 | raidPtr->autoconfigure = new_value; | | 3334 | raidPtr->autoconfigure = new_value; |
3318 | | | 3335 | |
3319 | for(column=0; column<raidPtr->numCol; column++) { | | 3336 | for(column=0; column<raidPtr->numCol; column++) { |
3320 | if (raidPtr->Disks[column].status == rf_ds_optimal) { | | 3337 | if (raidPtr->Disks[column].status == rf_ds_optimal) { |
3321 | dev = raidPtr->Disks[column].dev; | | 3338 | dev = raidPtr->Disks[column].dev; |
3322 | vp = raidPtr->raid_cinfo[column].ci_vp; | | 3339 | vp = raidPtr->raid_cinfo[column].ci_vp; |
3323 | raidread_component_label(dev, vp, &clabel); | | 3340 | raidread_component_label(dev, vp, &clabel); |
3324 | clabel.autoconfigure = new_value; | | 3341 | clabel.autoconfigure = new_value; |
3325 | raidwrite_component_label(dev, vp, &clabel); | | 3342 | raidwrite_component_label(dev, vp, &clabel); |
3326 | } | | 3343 | } |
3327 | } | | 3344 | } |
3328 | for(column = 0; column < raidPtr->numSpare ; column++) { | | 3345 | for(column = 0; column < raidPtr->numSpare ; column++) { |
3329 | sparecol = raidPtr->numCol + column; | | 3346 | sparecol = raidPtr->numCol + column; |
3330 | if (raidPtr->Disks[sparecol].status == rf_ds_used_spare) { | | 3347 | if (raidPtr->Disks[sparecol].status == rf_ds_used_spare) { |
3331 | dev = raidPtr->Disks[sparecol].dev; | | 3348 | dev = raidPtr->Disks[sparecol].dev; |
3332 | vp = raidPtr->raid_cinfo[sparecol].ci_vp; | | 3349 | vp = raidPtr->raid_cinfo[sparecol].ci_vp; |
3333 | raidread_component_label(dev, vp, &clabel); | | 3350 | raidread_component_label(dev, vp, &clabel); |
3334 | clabel.autoconfigure = new_value; | | 3351 | clabel.autoconfigure = new_value; |
3335 | raidwrite_component_label(dev, vp, &clabel); | | 3352 | raidwrite_component_label(dev, vp, &clabel); |
3336 | } | | 3353 | } |
3337 | } | | 3354 | } |
3338 | return(new_value); | | 3355 | return(new_value); |
3339 | } | | 3356 | } |
3340 | | | 3357 | |
3341 | int | | 3358 | int |
3342 | rf_set_rootpartition(RF_Raid_t *raidPtr, int new_value) | | 3359 | rf_set_rootpartition(RF_Raid_t *raidPtr, int new_value) |
3343 | { | | 3360 | { |
3344 | RF_ComponentLabel_t clabel; | | 3361 | RF_ComponentLabel_t clabel; |
3345 | struct vnode *vp; | | 3362 | struct vnode *vp; |
3346 | dev_t dev; | | 3363 | dev_t dev; |
3347 | int column; | | 3364 | int column; |
3348 | int sparecol; | | 3365 | int sparecol; |
3349 | | | 3366 | |
3350 | raidPtr->root_partition = new_value; | | 3367 | raidPtr->root_partition = new_value; |
3351 | for(column=0; column<raidPtr->numCol; column++) { | | 3368 | for(column=0; column<raidPtr->numCol; column++) { |
3352 | if (raidPtr->Disks[column].status == rf_ds_optimal) { | | 3369 | if (raidPtr->Disks[column].status == rf_ds_optimal) { |
3353 | dev = raidPtr->Disks[column].dev; | | 3370 | dev = raidPtr->Disks[column].dev; |
3354 | vp = raidPtr->raid_cinfo[column].ci_vp; | | 3371 | vp = raidPtr->raid_cinfo[column].ci_vp; |
3355 | raidread_component_label(dev, vp, &clabel); | | 3372 | raidread_component_label(dev, vp, &clabel); |
3356 | clabel.root_partition = new_value; | | 3373 | clabel.root_partition = new_value; |
3357 | raidwrite_component_label(dev, vp, &clabel); | | 3374 | raidwrite_component_label(dev, vp, &clabel); |
3358 | } | | 3375 | } |
3359 | } | | 3376 | } |
3360 | for(column = 0; column < raidPtr->numSpare ; column++) { | | 3377 | for(column = 0; column < raidPtr->numSpare ; column++) { |
3361 | sparecol = raidPtr->numCol + column; | | 3378 | sparecol = raidPtr->numCol + column; |
3362 | if (raidPtr->Disks[sparecol].status == rf_ds_used_spare) { | | 3379 | if (raidPtr->Disks[sparecol].status == rf_ds_used_spare) { |
3363 | dev = raidPtr->Disks[sparecol].dev; | | 3380 | dev = raidPtr->Disks[sparecol].dev; |
3364 | vp = raidPtr->raid_cinfo[sparecol].ci_vp; | | 3381 | vp = raidPtr->raid_cinfo[sparecol].ci_vp; |
3365 | raidread_component_label(dev, vp, &clabel); | | 3382 | raidread_component_label(dev, vp, &clabel); |
3366 | clabel.root_partition = new_value; | | 3383 | clabel.root_partition = new_value; |
3367 | raidwrite_component_label(dev, vp, &clabel); | | 3384 | raidwrite_component_label(dev, vp, &clabel); |
3368 | } | | 3385 | } |
3369 | } | | 3386 | } |
3370 | return(new_value); | | 3387 | return(new_value); |
3371 | } | | 3388 | } |
3372 | | | 3389 | |
3373 | void | | 3390 | void |
3374 | rf_release_all_vps(RF_ConfigSet_t *cset) | | 3391 | rf_release_all_vps(RF_ConfigSet_t *cset) |
3375 | { | | 3392 | { |
3376 | RF_AutoConfig_t *ac; | | 3393 | RF_AutoConfig_t *ac; |
3377 | | | 3394 | |
3378 | ac = cset->ac; | | 3395 | ac = cset->ac; |
3379 | while(ac!=NULL) { | | 3396 | while(ac!=NULL) { |
3380 | /* Close the vp, and give it back */ | | 3397 | /* Close the vp, and give it back */ |
3381 | if (ac->vp) { | | 3398 | if (ac->vp) { |
3382 | vn_lock(ac->vp, LK_EXCLUSIVE | LK_RETRY); | | 3399 | vn_lock(ac->vp, LK_EXCLUSIVE | LK_RETRY); |
3383 | VOP_CLOSE(ac->vp, FREAD, NOCRED); | | 3400 | VOP_CLOSE(ac->vp, FREAD, NOCRED); |
3384 | vput(ac->vp); | | 3401 | vput(ac->vp); |
3385 | ac->vp = NULL; | | 3402 | ac->vp = NULL; |
3386 | } | | 3403 | } |
3387 | ac = ac->next; | | 3404 | ac = ac->next; |
3388 | } | | 3405 | } |
3389 | } | | 3406 | } |
3390 | | | 3407 | |
3391 | | | 3408 | |
3392 | void | | 3409 | void |
3393 | rf_cleanup_config_set(RF_ConfigSet_t *cset) | | 3410 | rf_cleanup_config_set(RF_ConfigSet_t *cset) |
3394 | { | | 3411 | { |
3395 | RF_AutoConfig_t *ac; | | 3412 | RF_AutoConfig_t *ac; |
3396 | RF_AutoConfig_t *next_ac; | | 3413 | RF_AutoConfig_t *next_ac; |
3397 | | | 3414 | |
3398 | ac = cset->ac; | | 3415 | ac = cset->ac; |
3399 | while(ac!=NULL) { | | 3416 | while(ac!=NULL) { |
3400 | next_ac = ac->next; | | 3417 | next_ac = ac->next; |
3401 | /* nuke the label */ | | 3418 | /* nuke the label */ |
3402 | free(ac->clabel, M_RAIDFRAME); | | 3419 | free(ac->clabel, M_RAIDFRAME); |
3403 | /* cleanup the config structure */ | | 3420 | /* cleanup the config structure */ |
3404 | free(ac, M_RAIDFRAME); | | 3421 | free(ac, M_RAIDFRAME); |
3405 | /* "next.." */ | | 3422 | /* "next.." */ |
3406 | ac = next_ac; | | 3423 | ac = next_ac; |
3407 | } | | 3424 | } |
3408 | /* and, finally, nuke the config set */ | | 3425 | /* and, finally, nuke the config set */ |
3409 | free(cset, M_RAIDFRAME); | | 3426 | free(cset, M_RAIDFRAME); |
3410 | } | | 3427 | } |
3411 | | | 3428 | |
3412 | | | 3429 | |
3413 | void | | 3430 | void |
3414 | raid_init_component_label(RF_Raid_t *raidPtr, RF_ComponentLabel_t *clabel) | | 3431 | raid_init_component_label(RF_Raid_t *raidPtr, RF_ComponentLabel_t *clabel) |
3415 | { | | 3432 | { |
3416 | /* current version number */ | | 3433 | /* current version number */ |
3417 | clabel->version = RF_COMPONENT_LABEL_VERSION; | | 3434 | clabel->version = RF_COMPONENT_LABEL_VERSION; |
3418 | clabel->serial_number = raidPtr->serial_number; | | 3435 | clabel->serial_number = raidPtr->serial_number; |
3419 | clabel->mod_counter = raidPtr->mod_counter; | | 3436 | clabel->mod_counter = raidPtr->mod_counter; |
3420 | clabel->num_rows = 1; | | 3437 | clabel->num_rows = 1; |
3421 | clabel->num_columns = raidPtr->numCol; | | 3438 | clabel->num_columns = raidPtr->numCol; |
3422 | clabel->clean = RF_RAID_DIRTY; /* not clean */ | | 3439 | clabel->clean = RF_RAID_DIRTY; /* not clean */ |
3423 | clabel->status = rf_ds_optimal; /* "It's good!" */ | | 3440 | clabel->status = rf_ds_optimal; /* "It's good!" */ |
3424 | | | 3441 | |
3425 | clabel->sectPerSU = raidPtr->Layout.sectorsPerStripeUnit; | | 3442 | clabel->sectPerSU = raidPtr->Layout.sectorsPerStripeUnit; |
3426 | clabel->SUsPerPU = raidPtr->Layout.SUsPerPU; | | 3443 | clabel->SUsPerPU = raidPtr->Layout.SUsPerPU; |
3427 | clabel->SUsPerRU = raidPtr->Layout.SUsPerRU; | | 3444 | clabel->SUsPerRU = raidPtr->Layout.SUsPerRU; |
3428 | | | 3445 | |
3429 | clabel->blockSize = raidPtr->bytesPerSector; | | 3446 | clabel->blockSize = raidPtr->bytesPerSector; |
3430 | clabel->numBlocks = raidPtr->sectorsPerDisk; | | 3447 | clabel->numBlocks = raidPtr->sectorsPerDisk; |
3431 | | | 3448 | |
3432 | /* XXX not portable */ | | 3449 | /* XXX not portable */ |
3433 | clabel->parityConfig = raidPtr->Layout.map->parityConfig; | | 3450 | clabel->parityConfig = raidPtr->Layout.map->parityConfig; |
3434 | clabel->maxOutstanding = raidPtr->maxOutstanding; | | 3451 | clabel->maxOutstanding = raidPtr->maxOutstanding; |
3435 | clabel->autoconfigure = raidPtr->autoconfigure; | | 3452 | clabel->autoconfigure = raidPtr->autoconfigure; |
3436 | clabel->root_partition = raidPtr->root_partition; | | 3453 | clabel->root_partition = raidPtr->root_partition; |
3437 | clabel->last_unit = raidPtr->raidid; | | 3454 | clabel->last_unit = raidPtr->raidid; |
3438 | clabel->config_order = raidPtr->config_order; | | 3455 | clabel->config_order = raidPtr->config_order; |
3439 | } | | 3456 | } |
3440 | | | 3457 | |
3441 | int | | 3458 | int |
3442 | rf_auto_config_set(RF_ConfigSet_t *cset, int *unit) | | 3459 | rf_auto_config_set(RF_ConfigSet_t *cset, int *unit) |
3443 | { | | 3460 | { |
3444 | RF_Raid_t *raidPtr; | | 3461 | RF_Raid_t *raidPtr; |
3445 | RF_Config_t *config; | | 3462 | RF_Config_t *config; |
3446 | int raidID; | | 3463 | int raidID; |
3447 | int retcode; | | 3464 | int retcode; |
3448 | | | 3465 | |
3449 | #ifdef DEBUG | | 3466 | #ifdef DEBUG |
3450 | printf("RAID autoconfigure\n"); | | 3467 | printf("RAID autoconfigure\n"); |
3451 | #endif | | 3468 | #endif |
3452 | | | 3469 | |
3453 | retcode = 0; | | 3470 | retcode = 0; |
3454 | *unit = -1; | | 3471 | *unit = -1; |
3455 | | | 3472 | |
3456 | /* 1. Create a config structure */ | | 3473 | /* 1. Create a config structure */ |
3457 | | | 3474 | |
3458 | config = (RF_Config_t *)malloc(sizeof(RF_Config_t), | | 3475 | config = (RF_Config_t *)malloc(sizeof(RF_Config_t), |
3459 | M_RAIDFRAME, | | 3476 | M_RAIDFRAME, |
3460 | M_NOWAIT); | | 3477 | M_NOWAIT); |
3461 | if (config==NULL) { | | 3478 | if (config==NULL) { |
3462 | printf("Out of mem!?!?\n"); | | 3479 | printf("Out of mem!?!?\n"); |
3463 | /* XXX do something more intelligent here. */ | | 3480 | /* XXX do something more intelligent here. */ |
3464 | return(1); | | 3481 | return(1); |
3465 | } | | 3482 | } |
3466 | | | 3483 | |
3467 | memset(config, 0, sizeof(RF_Config_t)); | | 3484 | memset(config, 0, sizeof(RF_Config_t)); |
3468 | | | 3485 | |
3469 | /* | | 3486 | /* |
3470 | 2. Figure out what RAID ID this one is supposed to live at | | 3487 | 2. Figure out what RAID ID this one is supposed to live at |
3471 | See if we can get the same RAID dev that it was configured | | 3488 | See if we can get the same RAID dev that it was configured |
3472 | on last time.. | | 3489 | on last time.. |
3473 | */ | | 3490 | */ |
3474 | | | 3491 | |
3475 | raidID = cset->ac->clabel->last_unit; | | 3492 | raidID = cset->ac->clabel->last_unit; |
3476 | if ((raidID < 0) || (raidID >= numraid)) { | | 3493 | if ((raidID < 0) || (raidID >= numraid)) { |
3477 | /* let's not wander off into lala land. */ | | 3494 | /* let's not wander off into lala land. */ |
3478 | raidID = numraid - 1; | | 3495 | raidID = numraid - 1; |
3479 | } | | 3496 | } |
3480 | if (raidPtrs[raidID]->valid != 0) { | | 3497 | if (raidPtrs[raidID]->valid != 0) { |
3481 | | | 3498 | |
3482 | /* | | 3499 | /* |
3483 | Nope... Go looking for an alternative... | | 3500 | Nope... Go looking for an alternative... |
3484 | Start high so we don't immediately use raid0 if that's | | 3501 | Start high so we don't immediately use raid0 if that's |
3485 | not taken. | | 3502 | not taken. |
3486 | */ | | 3503 | */ |
3487 | | | 3504 | |
3488 | for(raidID = numraid - 1; raidID >= 0; raidID--) { | | 3505 | for(raidID = numraid - 1; raidID >= 0; raidID--) { |
3489 | if (raidPtrs[raidID]->valid == 0) { | | 3506 | if (raidPtrs[raidID]->valid == 0) { |
3490 | /* can use this one! */ | | 3507 | /* can use this one! */ |
3491 | break; | | 3508 | break; |
3492 | } | | 3509 | } |
3493 | } | | 3510 | } |
3494 | } | | 3511 | } |
3495 | | | 3512 | |
3496 | if (raidID < 0) { | | 3513 | if (raidID < 0) { |
3497 | /* punt... */ | | 3514 | /* punt... */ |
3498 | printf("Unable to auto configure this set!\n"); | | 3515 | printf("Unable to auto configure this set!\n"); |
3499 | printf("(Out of RAID devs!)\n"); | | 3516 | printf("(Out of RAID devs!)\n"); |
3500 | free(config, M_RAIDFRAME); | | 3517 | free(config, M_RAIDFRAME); |
3501 | return(1); | | 3518 | return(1); |
3502 | } | | 3519 | } |
3503 | | | 3520 | |
3504 | #ifdef DEBUG | | 3521 | #ifdef DEBUG |
3505 | printf("Configuring raid%d:\n",raidID); | | 3522 | printf("Configuring raid%d:\n",raidID); |
3506 | #endif | | 3523 | #endif |
3507 | | | 3524 | |
3508 | raidPtr = raidPtrs[raidID]; | | 3525 | raidPtr = raidPtrs[raidID]; |
3509 | | | 3526 | |
3510 | /* XXX all this stuff should be done SOMEWHERE ELSE! */ | | 3527 | /* XXX all this stuff should be done SOMEWHERE ELSE! */ |
3511 | raidPtr->raidid = raidID; | | 3528 | raidPtr->raidid = raidID; |
3512 | raidPtr->openings = RAIDOUTSTANDING; | | 3529 | raidPtr->openings = RAIDOUTSTANDING; |
3513 | | | 3530 | |
3514 | /* 3. Build the configuration structure */ | | 3531 | /* 3. Build the configuration structure */ |
3515 | rf_create_configuration(cset->ac, config, raidPtr); | | 3532 | rf_create_configuration(cset->ac, config, raidPtr); |
3516 | | | 3533 | |
3517 | /* 4. Do the configuration */ | | 3534 | /* 4. Do the configuration */ |
3518 | retcode = rf_Configure(raidPtr, config, cset->ac); | | 3535 | retcode = rf_Configure(raidPtr, config, cset->ac); |
3519 | | | 3536 | |
3520 | if (retcode == 0) { | | 3537 | if (retcode == 0) { |
3521 | | | 3538 | |
3522 | raidinit(raidPtrs[raidID]); | | 3539 | raidinit(raidPtrs[raidID]); |
3523 | | | 3540 | |
3524 | rf_markalldirty(raidPtrs[raidID]); | | 3541 | rf_markalldirty(raidPtrs[raidID]); |
3525 | raidPtrs[raidID]->autoconfigure = 1; /* XXX do this here? */ | | 3542 | raidPtrs[raidID]->autoconfigure = 1; /* XXX do this here? */ |
3526 | if (cset->ac->clabel->root_partition==1) { | | 3543 | if (cset->ac->clabel->root_partition==1) { |
3527 | /* everything configured just fine. Make a note | | 3544 | /* everything configured just fine. Make a note |
3528 | that this set is eligible to be root. */ | | 3545 | that this set is eligible to be root. */ |
3529 | cset->rootable = 1; | | 3546 | cset->rootable = 1; |
3530 | /* XXX do this here? */ | | 3547 | /* XXX do this here? */ |
3531 | raidPtrs[raidID]->root_partition = 1; | | 3548 | raidPtrs[raidID]->root_partition = 1; |
3532 | } | | 3549 | } |
3533 | } | | 3550 | } |
3534 | | | 3551 | |
3535 | /* 5. Cleanup */ | | 3552 | /* 5. Cleanup */ |
3536 | free(config, M_RAIDFRAME); | | 3553 | free(config, M_RAIDFRAME); |
3537 | | | 3554 | |
3538 | *unit = raidID; | | 3555 | *unit = raidID; |
3539 | return(retcode); | | 3556 | return(retcode); |
3540 | } | | 3557 | } |
3541 | | | 3558 | |
3542 | void | | 3559 | void |
3543 | rf_disk_unbusy(RF_RaidAccessDesc_t *desc) | | 3560 | rf_disk_unbusy(RF_RaidAccessDesc_t *desc) |
3544 | { | | 3561 | { |
3545 | struct buf *bp; | | 3562 | struct buf *bp; |
3546 | | | 3563 | |
3547 | bp = (struct buf *)desc->bp; | | 3564 | bp = (struct buf *)desc->bp; |
3548 | disk_unbusy(&raid_softc[desc->raidPtr->raidid].sc_dkdev, | | 3565 | disk_unbusy(&raid_softc[desc->raidPtr->raidid].sc_dkdev, |
3549 | (bp->b_bcount - bp->b_resid), (bp->b_flags & B_READ)); | | 3566 | (bp->b_bcount - bp->b_resid), (bp->b_flags & B_READ)); |
3550 | } | | 3567 | } |
3551 | | | 3568 | |
3552 | void | | 3569 | void |
3553 | rf_pool_init(struct pool *p, size_t size, const char *w_chan, | | 3570 | rf_pool_init(struct pool *p, size_t size, const char *w_chan, |
3554 | size_t xmin, size_t xmax) | | 3571 | size_t xmin, size_t xmax) |
3555 | { | | 3572 | { |
3556 | pool_init(p, size, 0, 0, 0, w_chan, NULL, IPL_BIO); | | 3573 | pool_init(p, size, 0, 0, 0, w_chan, NULL, IPL_BIO); |
3557 | pool_sethiwat(p, xmax); | | 3574 | pool_sethiwat(p, xmax); |
3558 | pool_prime(p, xmin); | | 3575 | pool_prime(p, xmin); |
3559 | pool_setlowat(p, xmin); | | 3576 | pool_setlowat(p, xmin); |
3560 | } | | 3577 | } |
3561 | | | 3578 | |
3562 | /* | | 3579 | /* |
3563 | * rf_buf_queue_check(int raidid) -- looks into the buf_queue to see | | 3580 | * rf_buf_queue_check(int raidid) -- looks into the buf_queue to see |
3564 | * if there is IO pending and if that IO could possibly be done for a | | 3581 | * if there is IO pending and if that IO could possibly be done for a |
3565 | * given RAID set. Returns 0 if IO is waiting and can be done, 1 | | 3582 | * given RAID set. Returns 0 if IO is waiting and can be done, 1 |
3566 | * otherwise. | | 3583 | * otherwise. |
3567 | * | | 3584 | * |
3568 | */ | | 3585 | */ |
3569 | | | 3586 | |
3570 | int | | 3587 | int |
3571 | rf_buf_queue_check(int raidid) | | 3588 | rf_buf_queue_check(int raidid) |
3572 | { | | 3589 | { |
3573 | if ((bufq_peek(raid_softc[raidid].buf_queue) != NULL) && | | 3590 | if ((bufq_peek(raid_softc[raidid].buf_queue) != NULL) && |
3574 | raidPtrs[raidid]->openings > 0) { | | 3591 | raidPtrs[raidid]->openings > 0) { |
3575 | /* there is work to do */ | | 3592 | /* there is work to do */ |
3576 | return 0; | | 3593 | return 0; |
3577 | } | | 3594 | } |
3578 | /* default is nothing to do */ | | 3595 | /* default is nothing to do */ |
3579 | return 1; | | 3596 | return 1; |
3580 | } | | 3597 | } |
3581 | | | 3598 | |
3582 | int | | 3599 | int |
3583 | rf_getdisksize(struct vnode *vp, struct lwp *l, RF_RaidDisk_t *diskPtr) | | 3600 | rf_getdisksize(struct vnode *vp, struct lwp *l, RF_RaidDisk_t *diskPtr) |
3584 | { | | 3601 | { |
3585 | struct partinfo dpart; | | 3602 | struct partinfo dpart; |
3586 | struct dkwedge_info dkw; | | 3603 | struct dkwedge_info dkw; |
3587 | int error; | | 3604 | int error; |
3588 | | | 3605 | |
3589 | error = VOP_IOCTL(vp, DIOCGPART, &dpart, FREAD, l->l_cred); | | 3606 | error = VOP_IOCTL(vp, DIOCGPART, &dpart, FREAD, l->l_cred); |
3590 | if (error == 0) { | | 3607 | if (error == 0) { |
3591 | diskPtr->blockSize = dpart.disklab->d_secsize; | | 3608 | diskPtr->blockSize = dpart.disklab->d_secsize; |
3592 | diskPtr->numBlocks = dpart.part->p_size - rf_protectedSectors; | | 3609 | diskPtr->numBlocks = dpart.part->p_size - rf_protectedSectors; |
3593 | diskPtr->partitionSize = dpart.part->p_size; | | 3610 | diskPtr->partitionSize = dpart.part->p_size; |
3594 | return 0; | | 3611 | return 0; |
3595 | } | | 3612 | } |
3596 | | | 3613 | |
3597 | error = VOP_IOCTL(vp, DIOCGWEDGEINFO, &dkw, FREAD, l->l_cred); | | 3614 | error = VOP_IOCTL(vp, DIOCGWEDGEINFO, &dkw, FREAD, l->l_cred); |
3598 | if (error == 0) { | | 3615 | if (error == 0) { |
3599 | diskPtr->blockSize = 512; /* XXX */ | | 3616 | diskPtr->blockSize = 512; /* XXX */ |
3600 | diskPtr->numBlocks = dkw.dkw_size - rf_protectedSectors; | | 3617 | diskPtr->numBlocks = dkw.dkw_size - rf_protectedSectors; |
3601 | diskPtr->partitionSize = dkw.dkw_size; | | 3618 | diskPtr->partitionSize = dkw.dkw_size; |
3602 | return 0; | | 3619 | return 0; |
3603 | } | | 3620 | } |
3604 | return error; | | 3621 | return error; |
3605 | } | | 3622 | } |
3606 | | | 3623 | |
3607 | static int | | 3624 | static int |
3608 | raid_match(device_t self, cfdata_t cfdata, void *aux) | | 3625 | raid_match(device_t self, cfdata_t cfdata, void *aux) |
3609 | { | | 3626 | { |
3610 | return 1; | | 3627 | return 1; |
3611 | } | | 3628 | } |
3612 | | | 3629 | |
3613 | static void | | 3630 | static void |
3614 | raid_attach(device_t parent, device_t self, void *aux) | | 3631 | raid_attach(device_t parent, device_t self, void *aux) |
3615 | { | | 3632 | { |
3616 | | | 3633 | |
3617 | } | | 3634 | } |
3618 | | | 3635 | |
3619 | | | 3636 | |
3620 | static int | | 3637 | static int |
3621 | raid_detach(device_t self, int flags) | | 3638 | raid_detach(device_t self, int flags) |
3622 | { | | 3639 | { |
3623 | struct raid_softc *rs = device_private(self); | | 3640 | int error; |
| | | 3641 | struct raid_softc *rs = &raid_softc[device_unit(self)]; |
3624 | | | 3642 | |
3625 | if (rs->sc_flags & RAIDF_INITED) | | 3643 | if ((error = raidlock(rs)) != 0) |
3626 | return EBUSY; | | 3644 | return (error); |
3627 | | | 3645 | |
3628 | return 0; | | 3646 | error = raid_detach_unlocked(rs); |
| | | 3647 | |
| | | 3648 | raidunlock(rs); |
| | | 3649 | |
| | | 3650 | return error; |
3629 | } | | 3651 | } |
3630 | | | 3652 | |
3631 | static void | | 3653 | static void |
3632 | rf_set_properties(struct raid_softc *rs, RF_Raid_t *raidPtr) | | 3654 | rf_set_properties(struct raid_softc *rs, RF_Raid_t *raidPtr) |
3633 | { | | 3655 | { |
3634 | prop_dictionary_t disk_info, odisk_info, geom; | | 3656 | prop_dictionary_t disk_info, odisk_info, geom; |
3635 | disk_info = prop_dictionary_create(); | | 3657 | disk_info = prop_dictionary_create(); |
3636 | geom = prop_dictionary_create(); | | 3658 | geom = prop_dictionary_create(); |
3637 | prop_dictionary_set_uint64(geom, "sectors-per-unit", | | 3659 | prop_dictionary_set_uint64(geom, "sectors-per-unit", |
3638 | raidPtr->totalSectors); | | 3660 | raidPtr->totalSectors); |
3639 | prop_dictionary_set_uint32(geom, "sector-size", | | 3661 | prop_dictionary_set_uint32(geom, "sector-size", |
3640 | raidPtr->bytesPerSector); | | 3662 | raidPtr->bytesPerSector); |
3641 | | | 3663 | |
3642 | prop_dictionary_set_uint16(geom, "sectors-per-track", | | 3664 | prop_dictionary_set_uint16(geom, "sectors-per-track", |
3643 | raidPtr->Layout.dataSectorsPerStripe); | | 3665 | raidPtr->Layout.dataSectorsPerStripe); |
3644 | prop_dictionary_set_uint16(geom, "tracks-per-cylinder", | | 3666 | prop_dictionary_set_uint16(geom, "tracks-per-cylinder", |
3645 | 4 * raidPtr->numCol); | | 3667 | 4 * raidPtr->numCol); |
3646 | | | 3668 | |
3647 | prop_dictionary_set_uint64(geom, "cylinders-per-unit", | | 3669 | prop_dictionary_set_uint64(geom, "cylinders-per-unit", |
3648 | raidPtr->totalSectors / (raidPtr->Layout.dataSectorsPerStripe * | | 3670 | raidPtr->totalSectors / (raidPtr->Layout.dataSectorsPerStripe * |
3649 | (4 * raidPtr->numCol))); | | 3671 | (4 * raidPtr->numCol))); |
3650 | | | 3672 | |
3651 | prop_dictionary_set(disk_info, "geometry", geom); | | 3673 | prop_dictionary_set(disk_info, "geometry", geom); |
3652 | prop_object_release(geom); | | 3674 | prop_object_release(geom); |
3653 | prop_dictionary_set(device_properties(rs->sc_dev), | | 3675 | prop_dictionary_set(device_properties(rs->sc_dev), |
3654 | "disk-info", disk_info); | | 3676 | "disk-info", disk_info); |
3655 | odisk_info = rs->sc_dkdev.dk_info; | | 3677 | odisk_info = rs->sc_dkdev.dk_info; |
3656 | rs->sc_dkdev.dk_info = disk_info; | | 3678 | rs->sc_dkdev.dk_info = disk_info; |
3657 | if (odisk_info) | | 3679 | if (odisk_info) |
3658 | prop_object_release(odisk_info); | | 3680 | prop_object_release(odisk_info); |
3659 | } | | 3681 | } |
3660 | | | 3682 | |
3661 | /* | | 3683 | /* |
3662 | * Implement forwarding of the DIOCCACHESYNC ioctl to each of the components. | | 3684 | * Implement forwarding of the DIOCCACHESYNC ioctl to each of the components. |
3663 | * We end up returning whatever error was returned by the first cache flush | | 3685 | * We end up returning whatever error was returned by the first cache flush |
3664 | * that fails. | | 3686 | * that fails. |
3665 | */ | | 3687 | */ |
3666 | | | 3688 | |
3667 | static int | | 3689 | static int |
3668 | rf_sync_component_caches(RF_Raid_t *raidPtr) | | 3690 | rf_sync_component_caches(RF_Raid_t *raidPtr) |
3669 | { | | 3691 | { |
3670 | int c, sparecol; | | 3692 | int c, sparecol; |
3671 | int e,error; | | 3693 | int e,error; |
3672 | int force = 1; | | 3694 | int force = 1; |
3673 | | | 3695 | |
3674 | error = 0; | | 3696 | error = 0; |
3675 | for (c = 0; c < raidPtr->numCol; c++) { | | 3697 | for (c = 0; c < raidPtr->numCol; c++) { |
3676 | if (raidPtr->Disks[c].status == rf_ds_optimal) { | | 3698 | if (raidPtr->Disks[c].status == rf_ds_optimal) { |
3677 | e = VOP_IOCTL(raidPtr->raid_cinfo[c].ci_vp, DIOCCACHESYNC, | | 3699 | e = VOP_IOCTL(raidPtr->raid_cinfo[c].ci_vp, DIOCCACHESYNC, |
3678 | &force, FWRITE, NOCRED); | | 3700 | &force, FWRITE, NOCRED); |
3679 | if (e) { | | 3701 | if (e) { |
3680 | if (e != ENODEV) | | 3702 | if (e != ENODEV) |
3681 | printf("raid%d: cache flush to component %s failed.\n", | | 3703 | printf("raid%d: cache flush to component %s failed.\n", |
3682 | raidPtr->raidid, raidPtr->Disks[c].devname); | | 3704 | raidPtr->raidid, raidPtr->Disks[c].devname); |
3683 | if (error == 0) { | | 3705 | if (error == 0) { |
3684 | error = e; | | 3706 | error = e; |
3685 | } | | 3707 | } |
3686 | } | | 3708 | } |
3687 | } | | 3709 | } |
3688 | } | | 3710 | } |
3689 | | | 3711 | |
3690 | for( c = 0; c < raidPtr->numSpare ; c++) { | | 3712 | for( c = 0; c < raidPtr->numSpare ; c++) { |
3691 | sparecol = raidPtr->numCol + c; | | 3713 | sparecol = raidPtr->numCol + c; |
3692 | /* Need to ensure that the reconstruct actually completed! */ | | 3714 | /* Need to ensure that the reconstruct actually completed! */ |
3693 | if (raidPtr->Disks[sparecol].status == rf_ds_used_spare) { | | 3715 | if (raidPtr->Disks[sparecol].status == rf_ds_used_spare) { |
3694 | e = VOP_IOCTL(raidPtr->raid_cinfo[sparecol].ci_vp, | | 3716 | e = VOP_IOCTL(raidPtr->raid_cinfo[sparecol].ci_vp, |
3695 | DIOCCACHESYNC, &force, FWRITE, NOCRED); | | 3717 | DIOCCACHESYNC, &force, FWRITE, NOCRED); |
3696 | if (e) { | | 3718 | if (e) { |
3697 | if (e != ENODEV) | | 3719 | if (e != ENODEV) |
3698 | printf("raid%d: cache flush to component %s failed.\n", | | 3720 | printf("raid%d: cache flush to component %s failed.\n", |
3699 | raidPtr->raidid, raidPtr->Disks[sparecol].devname); | | 3721 | raidPtr->raidid, raidPtr->Disks[sparecol].devname); |
3700 | if (error == 0) { | | 3722 | if (error == 0) { |
3701 | error = e; | | 3723 | error = e; |
3702 | } | | 3724 | } |
3703 | } | | 3725 | } |
3704 | } | | 3726 | } |
3705 | } | | 3727 | } |
3706 | return error; | | 3728 | return error; |
3707 | } | | 3729 | } |