Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / sys / dev / raid / vinum / request.h
1 /*-
2  * Copyright (c) 1997, 1998
3  *      Nan Yang Computer Services Limited.  All rights reserved.
4  *
5  *  This software is distributed under the so-called ``Berkeley
6  *  License'':
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by Nan Yang Computer
19  *      Services Limited.
20  * 4. Neither the name of the Company nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * This software is provided ``as is'', and any express or implied
25  * warranties, including, but not limited to, the implied warranties of
26  * merchantability and fitness for a particular purpose are disclaimed.
27  * In no event shall the company or contributors be liable for any
28  * direct, indirect, incidental, special, exemplary, or consequential
29  * damages (including, but not limited to, procurement of substitute
30  * goods or services; loss of use, data, or profits; or business
31  * interruption) however caused and on any theory of liability, whether
32  * in contract, strict liability, or tort (including negligence or
33  * otherwise) arising in any way out of the use of this software, even if
34  * advised of the possibility of such damage.
35  *
36  * $Id: request.h,v 1.19 2000/11/24 03:41:51 grog Exp grog $
37  * $FreeBSD: src/sys/dev/vinum/request.h,v 1.17.2.1 2001/03/13 02:59:42 grog Exp $
38  * $DragonFly: src/sys/dev/raid/vinum/request.h,v 1.2 2003/06/17 04:28:33 dillon Exp $
39  */
40
41 /* Information needed to set up a transfer */
42
43 enum xferinfo {
44     XFR_NORMAL_READ = 1,
45     XFR_NORMAL_WRITE = 2,                                   /* write request in normal mode */
46     XFR_RECOVERY_READ = 4,
47     XFR_DEGRADED_WRITE = 8,
48     XFR_PARITYLESS_WRITE = 0x10,
49     XFR_NO_PARITY_STRIPE = 0x20,                            /* parity stripe is not available */
50     XFR_DATA_BLOCK = 0x40,                                  /* data block in request */
51     XFR_PARITY_BLOCK = 0x80,                                /* parity block in request */
52     XFR_BAD_SUBDISK = 0x100,                                /* this subdisk is dead */
53     XFR_MALLOCED = 0x200,                                   /* this buffer is malloced */
54 #if VINUMDEBUG
55     XFR_PHASE2 = 0x800,                                     /* documentation only: 2nd phase write */
56 #endif
57     XFR_REVIVECONFLICT = 0x1000,                            /* possible conflict with a revive operation */
58     XFR_BUFLOCKED = 0x2000,                                 /* BUF_LOCK performed on this buffer */
59     /* operations that need a parity block */
60     XFR_PARITYOP = (XFR_NORMAL_WRITE | XFR_RECOVERY_READ | XFR_DEGRADED_WRITE),
61     /* operations that use the group parameters */
62     XFR_GROUPOP = (XFR_DEGRADED_WRITE | XFR_RECOVERY_READ),
63     /* operations that that use the data parameters */
64     XFR_DATAOP = (XFR_NORMAL_READ | XFR_NORMAL_WRITE | XFR_PARITYLESS_WRITE),
65     /* operations requiring read before write */
66     XFR_RBW = (XFR_NORMAL_WRITE | XFR_DEGRADED_WRITE),
67     /* operations that need a malloced buffer */
68     XFR_NEEDS_MALLOC = (XFR_NORMAL_WRITE | XFR_RECOVERY_READ | XFR_DEGRADED_WRITE)
69 };
70
71 /*
72  * Describe one low-level request, part of a
73  * high-level request.  This is an extended
74  * struct buf buffer, and the first element
75  * *must* be a struct buf.  We pass this
76  * structure to the I/O routines instead of a
77  * struct buf in order to be able to locate the
78  * high-level request when it completes.
79  *
80  * All offsets and lengths are in sectors.
81  */
82
83 struct rqelement {
84     struct buf b;                                           /* buf structure */
85     struct rqgroup *rqg;                                    /* pointer to our group */
86     /* Information about the transfer */
87     daddr_t sdoffset;                                       /* offset in subdisk */
88     int useroffset;                                         /* offset in user buffer of normal data */
89     /*
90      * dataoffset and datalen refer to "individual" data
91      * transfers which involve only this drive (normal read,
92      * parityless write) and also degraded write.
93      *
94      * groupoffset and grouplen refer to the other "group"
95      * operations (normal write, recovery read) which involve
96      * more than one drive.  Both the offsets are relative to
97      * the start of the local buffer.
98      */
99     int dataoffset;                                         /* offset in buffer of the normal data */
100     int groupoffset;                                        /* offset in buffer of group data */
101     short datalen;                                          /* length of normal data (sectors) */
102     short grouplen;                                         /* length of group data (sectors) */
103     short buflen;                                           /* total buffer length to allocate */
104     short flags;                                            /* really enum xferinfo (see above) */
105     /* Ways to find other components */
106     short sdno;                                             /* subdisk number */
107     short driveno;                                          /* drive number */
108 };
109
110 /*
111  * A group of requests built to satisfy an I/O
112  * transfer on a single plex.
113  */
114 struct rqgroup {
115     struct rqgroup *next;                                   /* pointer to next group */
116     struct request *rq;                                     /* pointer to the request */
117     short count;                                            /* number of requests in this group */
118     short active;                                           /* and number active */
119     short plexno;                                           /* index of plex */
120     int badsdno;                                            /* index of bad subdisk or -1 */
121     enum xferinfo flags;                                    /* description of transfer */
122     struct rangelock *lock;                                 /* lock for this transfer */
123     daddr_t lockbase;                                       /* and lock address */
124     struct rqelement rqe[0];                                /* and the elements of this request */
125 };
126
127 /*
128  * Describe one high-level request and the
129  * work we have to do to satisfy it.
130  */
131 struct request {
132     struct buf *bp;                                         /* pointer to the high-level request */
133     enum xferinfo flags;
134     union {
135         int volno;                                          /* volume index */
136         int plexno;                                         /* or plex index */
137     } volplex;
138     int error;                                              /* current error indication */
139     int sdno;                                               /* reviving subdisk (XFR_REVIVECONFLICT) */
140     short isplex;                                           /* set if this is a plex request */
141     short active;                                           /* number of subrequests still active */
142     struct rqgroup *rqg;                                    /* pointer to the first group of requests */
143     struct rqgroup *lrqg;                                   /* and to the last group of requests */
144     struct request *next;                                   /* link of waiting requests */
145 };
146
147 /*
148  * Extended buffer header for subdisk I/O.  Includes
149  * a pointer to the user I/O request.
150  */
151 struct sdbuf {
152     struct buf b;                                           /* our buffer */
153     struct buf *bp;                                         /* and pointer to parent */
154     short driveno;                                          /* drive index */
155     short sdno;                                             /* and subdisk index */
156 };
157
158 /*
159  * Values returned by rqe and friends.  Be careful
160  * with these: they are in order of increasing
161  * seriousness.  Some routines check for
162  * > REQUEST_RECOVERED to indicate a failed request. XXX
163  */
164 enum requeststatus {
165     REQUEST_OK,                                             /* request built OK */
166     REQUEST_RECOVERED,                                      /* request OK, but involves RAID5 recovery */
167     REQUEST_DEGRADED,                                       /* parts of request failed */
168     REQUEST_EOF,                                            /* parts of request failed: outside plex */
169     REQUEST_DOWN,                                           /* all of request failed: subdisk(s) down */
170     REQUEST_ENOMEM                                          /* all of request failed: ran out of memory */
171 };
172
173 #ifdef VINUMDEBUG
174 /* Trace entry for request info (DEBUG_LASTREQS) */
175 enum rqinfo_type {
176     loginfo_unused,                                         /* never been used */
177     loginfo_user_bp,                                        /* this is the bp when strategy is called */
178     loginfo_user_bpl,                                       /* and this is the bp at launch time */
179     loginfo_rqe,                                            /* user RQE */
180     loginfo_iodone,                                         /* iodone */
181     loginfo_raid5_data,                                     /* write RAID-5 data block */
182     loginfo_raid5_parity,                                   /* write RAID-5 parity block */
183     loginfo_sdio,                                           /* subdisk I/O */
184     loginfo_sdiol,                                          /* subdisk I/O launch */
185     loginfo_sdiodone,                                       /* subdisk iodone */
186     loginfo_lockwait,                                       /* wait for range lock */
187     loginfo_lock,                                           /* lock range */
188     loginfo_unlock,                                         /* unlock range */
189 };
190
191 union rqinfou {                                             /* info to pass to logrq */
192     struct buf *bp;
193     struct rqelement *rqe;                                  /* address of request, for correlation */
194     struct rangelock *lockinfo;
195 };
196
197 struct rqinfo {
198     enum rqinfo_type type;                                  /* kind of event */
199     struct timeval timestamp;                               /* time it happened */
200     struct buf *bp;                                         /* point to user buffer */
201     int devmajor;                                           /* major and minor device info */
202     int devminor;
203     union {
204         struct buf b;                                       /* yup, the *whole* buffer header */
205         struct rqelement rqe;                               /* and the whole rqe */
206         struct rangelock lockinfo;
207     } info;
208 };
209
210 #define RQINFO_SIZE 128                                     /* number of info slots in buffer */
211
212 void logrq(enum rqinfo_type type, union rqinfou info, struct buf *ubp);
213 #endif
214
215 /* Structures for the daemon */
216
217 /* types of request to the daemon */
218 enum daemonrq {
219     daemonrq_none,                                          /* dummy to catch bugs */
220     daemonrq_ioerror,                                       /* error occurred on I/O */
221     daemonrq_saveconfig,                                    /* save configuration */
222     daemonrq_return,                                        /* return to userland */
223     daemonrq_ping,                                          /* show sign of life */
224     daemonrq_init,                                          /* initialize a plex */
225     daemonrq_revive,                                        /* revive a subdisk */
226     daemonrq_closedrive,                                    /* close a drive */
227 };
228
229 /* info field for daemon requests */
230 union daemoninfo {                                          /* and the request information */
231     struct request *rq;                                     /* for daemonrq_ioerror */
232     struct sd *sd;                                          /* for daemonrq_revive */
233     struct plex *plex;                                      /* for daemonrq_init */
234     struct drive *drive;                                    /* for daemonrq_closedrive */
235     int nothing;                                            /* for passing NULL */
236 };
237
238 struct daemonq {
239     struct daemonq *next;                                   /* pointer to next element in queue */
240     enum daemonrq type;                                     /* type of request */
241     int privateinuse;                                       /* private element, being used */
242     union daemoninfo info;                                  /* and the request information */
243 };
244
245 void queue_daemon_request(enum daemonrq type, union daemoninfo info);
246
247 extern int daemon_options;
248
249 enum daemon_option {
250     daemon_verbose = 1,                                     /* talk about what we're doing */
251     daemon_stopped = 2,
252     daemon_noupdate = 4,                                    /* don't update the disk config, for recovery */
253 };
254
255 void freerq(struct request *rq);
256 void unlockrange(int plexno, struct rangelock *);
257 /* Local Variables: */
258 /* fill-column: 50 */
259 /* End: */