1 /* $OpenBSD: softraidvar.h,v 1.32 2007/06/06 23:06:02 deraadt Exp $ */
2 /*
3 * Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #include <dev/biovar.h>
19
20 #include <sys/buf.h>
21 #include <sys/queue.h>
22 #include <sys/rwlock.h>
23
24 #include <scsi/scsi_all.h>
25 #include <scsi/scsi_disk.h>
26 #include <scsi/scsiconf.h>
27
28 #define DEVNAME(_s) ((_s)->sc_dev.dv_xname)
29
30 /* #define SR_DEBUG */
31 #ifdef SR_DEBUG
32 extern u_int32_t sr_debug;
33 #define DPRINTF(x...) do { if (sr_debug) printf(x); } while(0)
34 #define DNPRINTF(n,x...) do { if (sr_debug & n) printf(x); } while(0)
35 #define SR_D_CMD 0x0001
36 #define SR_D_INTR 0x0002
37 #define SR_D_MISC 0x0004
38 #define SR_D_IOCTL 0x0008
39 #define SR_D_CCB 0x0010
40 #define SR_D_WU 0x0020
41 #define SR_D_META 0x0040
42 #define SR_D_DIS 0x0080
43 #define SR_D_STATE 0x0100
44 #else
45 #define DPRINTF(x...)
46 #define DNPRINTF(n,x...)
47 #endif
48
49 #define SR_MAXFER MAXPHYS
50 #define SR_MAX_LD 1
51 #define SR_MAX_CMDS 16
52 #define SR_MAX_STATES 7
53
54 /* forward define to prevent dependency goo */
55 struct sr_softc;
56
57 #define SR_UUID_MAX 4
58 struct sr_uuid {
59 u_int32_t sui_id[SR_UUID_MAX];
60 } __packed;
61
62 struct sr_ccb {
63 struct buf ccb_buf; /* MUST BE FIRST!! */
64
65 struct sr_workunit *ccb_wu;
66 struct sr_discipline *ccb_dis;
67
68 int ccb_target;
69 int ccb_state;
70 #define SR_CCB_FREE 0
71 #define SR_CCB_INPROGRESS 1
72 #define SR_CCB_OK 2
73 #define SR_CCB_FAILED 3
74
75 TAILQ_ENTRY(sr_ccb) ccb_link;
76 } __packed;
77
78 TAILQ_HEAD(sr_ccb_list, sr_ccb);
79
80 struct sr_workunit {
81 struct scsi_xfer *swu_xs;
82 struct sr_discipline *swu_dis;
83
84 int swu_state;
85 #define SR_WU_FREE 0
86 #define SR_WU_INPROGRESS 1
87 #define SR_WU_OK 2
88 #define SR_WU_FAILED 3
89 #define SR_WU_PARTIALLYFAILED 4
90 #define SR_WU_DEFERRED 5
91 #define SR_WU_PENDING 6
92 #define SR_WU_RESTART 7
93 #define SR_WU_REQUEUE 8
94
95 int swu_fake; /* faked wu */
96 /* workunit io range */
97 daddr64_t swu_blk_start;
98 daddr64_t swu_blk_end;
99
100 /* in flight totals */
101 u_int32_t swu_ios_complete;
102 u_int32_t swu_ios_failed;
103 u_int32_t swu_ios_succeeded;
104
105 /* number of ios that makes up the whole work unit */
106 u_int32_t swu_io_count;
107
108 /* colliding wu */
109 struct sr_workunit *swu_collider;
110
111 /* all ios that make up this workunit */
112 struct sr_ccb_list swu_ccb;
113
114 TAILQ_ENTRY(sr_workunit) swu_link;
115 };
116
117 TAILQ_HEAD(sr_wu_list, sr_workunit);
118
119 /* RAID 1 */
120 #define SR_RAID1_NOWU 16
121 struct sr_raid1 {
122 u_int32_t sr1_counter;
123 };
124
125 /* RAID C */
126 #define SR_RAIDC_NOWU 16
127 struct sr_raidc {
128 u_int64_t src_sid;
129 char src_key[64];
130 };
131
132 #define SR_META_SIZE 32 /* save space at chunk beginning */
133 #define SR_META_OFFSET 16 /* skip 8192 bytes at chunk beginning */
134 #define SR_META_VERSION 1 /* bump when sr_metadata changes */
135 struct sr_metadata {
136 /* do not change order of ssd_magic, ssd_version & ssd_checksum */
137 u_int64_t ssd_magic; /* magic id */
138 #define SR_MAGIC 0x4d4152436372616dLLU
139 u_int8_t ssd_version; /* meta data version */
140 u_int8_t ssd_pad1[3];
141 u_int32_t ssd_flags; /* flags */
142
143 /* meta-data */
144 u_int32_t ssd_checksum; /* xor of the structure */
145 u_int32_t ssd_size; /* sizeof(sr_metadata) */
146 u_int32_t ssd_ondisk; /* on disk version counter */
147 u_int32_t ssd_pad2;
148 struct sr_uuid ssd_uuid; /* unique identifier */
149
150 /* virtual disk data */
151 u_int32_t ssd_vd_ver; /* vd structure version */
152 u_int32_t ssd_vd_size; /* vd structure size */
153 u_int32_t ssd_vd_volid; /* volume id */
154 u_int32_t ssd_vd_chk; /* vd structure xor */
155
156 /* chunk data */
157 u_int32_t ssd_chunk_ver; /* chunk structure version */
158 u_int32_t ssd_chunk_no; /* number of chunks */
159 u_int32_t ssd_chunk_size; /* chunk structure size */
160 u_int32_t ssd_chunk_id; /* chunk identifier */
161 u_int32_t ssd_chunk_chk; /* chunk structure xor */
162 u_int32_t ssd_pad3;
163
164 /* optional metadata */
165 u_int32_t ssd_opt_ver; /* optinal meta version */
166 u_int32_t ssd_opt_no; /* nr of optional md elements */
167 u_int32_t ssd_opt_size; /* sizeof optional metadata */
168 u_int32_t ssd_opt_chk; /* optional metadata xor */
169 } __packed;
170
171 struct sr_metadata_list {
172 struct sr_metadata *sml_metadata;
173 dev_t sml_mm;
174 int sml_used;
175
176 SLIST_ENTRY(sr_metadata_list) sml_link;
177 };
178
179 SLIST_HEAD(sr_metadata_list_head, sr_metadata_list);
180
181 #define SR_OPT_VERSION 1 /* bump when sr_opt_meta changes */
182 struct sr_opt_meta {
183 u_int32_t som_type;
184 u_int32_t som_pad;
185 #define SR_OPT_INVALID 0x00
186 #define SR_OPT_CRYPTO 0x01
187 union {
188 struct sr_raidc smm_crypto;
189 } som_meta;
190 };
191
192 #define SR_CHUNK_VERSION 1 /* bump when sr_chunk_meta changes */
193 struct sr_chunk_meta {
194 u_int32_t scm_volid; /* vd we belong to */
195 u_int32_t scm_chunk_id; /* chunk id */
196 u_int32_t scm_status; /* use bio bioc_disk status */
197 u_int32_t scm_pad1;
198 char scm_devname[32];/* /dev/XXXXX */
199 int64_t scm_size; /* size of partition */
200 int64_t scm_coerced_size; /* coerced size of part */
201 struct sr_uuid scm_uuid; /* unique identifier */
202 } __packed;
203
204 struct sr_chunk {
205 struct sr_chunk_meta src_meta; /* chunk meta data */
206
207 /* runtime data */
208 dev_t src_dev_mm; /* major/minor */
209
210 /* helper members before metadata makes it onto the chunk */
211 int src_meta_ondisk;/* set when meta is on disk */
212 char src_devname[32];
213 int64_t src_size;
214
215 SLIST_ENTRY(sr_chunk) src_link;
216 };
217
218 SLIST_HEAD(sr_chunk_head, sr_chunk);
219
220 #define SR_VOL_VERSION 1 /* bump when sr_vol_meta changes */
221 struct sr_vol_meta {
222 u_int32_t svm_volid; /* volume id */
223 u_int32_t svm_status; /* use bioc_vol status */
224 u_int32_t svm_flags; /* flags */
225 #define SR_VOL_DIRTY 0x01
226 u_int32_t svm_level; /* raid level */
227 int64_t svm_size; /* virtual disk size */
228 char svm_devname[32];/* /dev/XXXXX */
229 char svm_vendor[8]; /* scsi vendor */
230 char svm_product[16];/* scsi product */
231 char svm_revision[4];/* scsi revision */
232 u_int32_t svm_no_chunk; /* number of chunks */
233 struct sr_uuid svm_uuid; /* volume unique identifier */
234 } __packed;
235
236 struct sr_volume {
237 struct sr_vol_meta sv_meta; /* meta data */
238
239 /* runtime data */
240 struct sr_chunk_head sv_chunk_list; /* linked list of all chunks */
241 struct sr_chunk **sv_chunks; /* array to same chunks */
242
243 /* sensors */
244 struct ksensor sv_sensor;
245 struct ksensordev sv_sensordev;
246 int sv_sensor_valid;
247 };
248
249 struct sr_discipline {
250 struct sr_softc *sd_sc; /* link back to sr softc */
251 u_int8_t sd_type; /* type of discipline */
252 #define SR_MD_RAID0 0
253 #define SR_MD_RAID1 1
254 #define SR_MD_RAID5 2
255 #define SR_MD_CACHE 3
256 #define SR_MD_RAIDC 4
257 char sd_name[10]; /* human readable dis name */
258 u_int8_t sd_scsibus; /* scsibus discipline uses */
259 struct scsi_link sd_link; /* link to midlayer */
260
261 union {
262 struct sr_raid1 mdd_raid1;
263 struct sr_raidc mdd_raidc;
264 } sd_dis_specific;/* dis specific members */
265 #define mds sd_dis_specific
266
267 /* discipline metadata */
268 struct sr_metadata *sd_meta; /* in memory copy of metadata */
269 u_int32_t sd_meta_flags;
270
271 int sd_sync;
272 int sd_must_flush;
273
274 struct device *sd_scsibus_dev;
275 void (*sd_shutdownhook)(void *);
276
277 /* discipline volume */
278 struct sr_volume sd_vol; /* volume associated */
279
280 /* discipline resources */
281 struct sr_ccb *sd_ccb;
282 struct sr_ccb_list sd_ccb_freeq;
283 u_int32_t sd_max_ccb_per_wu;
284
285 struct sr_workunit *sd_wu; /* all workunits */
286 u_int32_t sd_max_wu;
287
288 struct sr_wu_list sd_wu_freeq; /* free wu queue */
289 struct sr_wu_list sd_wu_pendq; /* pending wu queue */
290 struct sr_wu_list sd_wu_defq; /* deferred wu queue */
291
292 /* discipline stats */
293 int sd_wu_pending;
294 u_int64_t sd_wu_collisions;
295
296 /* discipline functions */
297 int (*sd_alloc_resources)(struct sr_discipline *);
298 int (*sd_assemble_volume)(void *);
299 int (*sd_bringup_volume)(void *);
300 int (*sd_shutdown_volume)(void *);
301 int (*sd_free_resources)(struct sr_discipline *);
302 int (*sd_quiesce_io)(struct sr_discipline *);
303 void (*sd_set_chunk_state)(struct sr_discipline *,
304 int, int);
305 void (*sd_set_vol_state)(struct sr_discipline *);
306
307 /* SCSI emulation */
308 struct scsi_sense_data sd_scsi_sense;
309 int (*sd_scsi_rw)(struct sr_workunit *);
310 int (*sd_scsi_sync)(struct sr_workunit *);
311 int (*sd_scsi_tur)(struct sr_workunit *);
312 int (*sd_scsi_start_stop)(struct sr_workunit *);
313 int (*sd_scsi_inquiry)(struct sr_workunit *);
314 int (*sd_scsi_read_cap)(struct sr_workunit *);
315 int (*sd_scsi_req_sense)(struct sr_workunit *);
316 };
317
318 struct sr_softc {
319 struct device sc_dev;
320
321 int (*sc_ioctl)(struct device *, u_long, caddr_t);
322
323 struct rwlock sc_lock;
324
325 int sc_sensors_running;
326 /*
327 * during scsibus attach this is the discipline that is in use
328 * this variable is protected by sc_lock and splhigh
329 */
330 struct sr_discipline *sc_attach_dis;
331
332 /*
333 * XXX expensive, alternative would be nice but has to be cheap
334 * since the scsibus lookup happens on each IO
335 */
336 #define SR_MAXSCSIBUS 256
337 struct sr_discipline *sc_dis[SR_MAXSCSIBUS]; /* scsibus is u_int8_t */
338 };