c4f583ab45
config_drive: Catch an instance of anonymous drives. Doubtless many remain. interrupt.c: complete_rqe: Call logrq to log iodone events if DEBUG_LASTREQS is set. Call set_sd_state with setstate_noupdate to avoid buffered I/O out of interrupt context. Use define DEBUG_RESID instead of constant. memory.c: Remove dead expandrq() function Malloc: Remove directory component of file names in malloc table. Add function vinum_rqinfo (part of the request tracing stuff). request.c: Add function logrq (part of the request tracing stuff). vinumstrategy: Check whether config needs to be written to disk, do it if so. This is a stopgap until the Vinum daemon (bacchusd? oenologistd?) is written. If DEBUG_LASTREQS is set, call logrq to log user buffer headers. launch_requests: Correct format of debug output to console. If DEBUG_LASTREQS is set, call logrq to log request elements. request.h: Add definitions for request trace. state.c: set_sd_state: Check flags for setstate_noupdate. If set, don't write the config to disk, just set global VF_DIRTYCONFIG flag. This is part of the kludge to avoid writing config from an interrupt context. vinumext.h: Add declaration for vinum_rqinfo, put inside #ifdef DEBUG Remove dead macro expandrq vinumio.h: Increase maximum ioctl reply length to 4 kB if DEBUG is set. Define VINUM_RQINFO ioctl if DEBUG is set. vinumioctl.c: vinumioctl: Change implementation of VINUM_DEBUG ioctl: use a debug flag (DEBUG_REMOTEGDB) to decide whether to go into remote debugging or not. Implement VINUM_RQINFO. vinumkw.h: Define kw_info even when not debugging. vinumvar.h: Define VF_DIRTYCONFIG Add pointers to request info to vinum_info if DEBUG is set. Define setstate_noupdate Define additional debug bits DEBUG_RESID, DEBUG_LASTREQS and DEBUG_REMOTEGDB.
192 lines
8.2 KiB
C
192 lines
8.2 KiB
C
/*-
|
|
* Copyright (c) 1997, 1998
|
|
* Nan Yang Computer Services Limited. All rights reserved.
|
|
*
|
|
* This software is distributed under the so-called ``Berkeley
|
|
* License'':
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
* must display the following acknowledgement:
|
|
* This product includes software developed by Nan Yang Computer
|
|
* Services Limited.
|
|
* 4. Neither the name of the Company nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* This software is provided ``as is'', and any express or implied
|
|
* warranties, including, but not limited to, the implied warranties of
|
|
* merchantability and fitness for a particular purpose are disclaimed.
|
|
* In no event shall the company or contributors be liable for any
|
|
* direct, indirect, incidental, special, exemplary, or consequential
|
|
* damages (including, but not limited to, procurement of substitute
|
|
* goods or services; loss of use, data, or profits; or business
|
|
* interruption) however caused and on any theory of liability, whether
|
|
* in contract, strict liability, or tort (including negligence or
|
|
* otherwise) arising in any way out of the use of this software, even if
|
|
* advised of the possibility of such damage.
|
|
*
|
|
* $Id: request.h,v 1.10 1998/08/03 07:15:26 grog Exp grog $
|
|
*/
|
|
|
|
/* Information needed to set up a transfer */
|
|
|
|
/* struct buf is surprisingly big (about 300
|
|
* bytes), and it's part of the request, so this
|
|
* value is really important. Most requests
|
|
* don't need more than 2 subrequests per
|
|
* plex. The table is automatically extended if
|
|
* this value is too small. */
|
|
#define RQELTS 2 /* default of 2 requests per transfer */
|
|
|
|
enum xferinfo {
|
|
XFR_NORMAL_READ = 1,
|
|
XFR_NORMAL_WRITE = 2, /* write request in normal mode */
|
|
XFR_RECOVERY_READ = 4,
|
|
XFR_DEGRADED_WRITE = 8,
|
|
XFR_PARITYLESS_WRITE = 0x10,
|
|
XFR_NO_PARITY_STRIPE = 0x20, /* parity stripe is not available */
|
|
XFR_DATA_BLOCK = 0x40, /* data block in request */
|
|
XFR_PARITY_BLOCK = 0x80, /* parity block in request */
|
|
XFR_BAD_SUBDISK = 0x100, /* this subdisk is dead */
|
|
XFR_MALLOCED = 0x200, /* this buffer is malloced */
|
|
#if DEBUG
|
|
XFR_PHASE2 = 0x800, /* documentation only: 2nd phase write */
|
|
#endif
|
|
XFR_REVIVECONFLICT = 0x1000, /* possible conflict with a revive operation */
|
|
/* operations that need a parity block */
|
|
XFR_PARITYOP = (XFR_NORMAL_WRITE | XFR_RECOVERY_READ | XFR_DEGRADED_WRITE),
|
|
/* operations that use the group parameters */
|
|
XFR_GROUPOP = (XFR_DEGRADED_WRITE | XFR_RECOVERY_READ),
|
|
/* operations that that use the data parameters */
|
|
XFR_DATAOP = (XFR_NORMAL_READ | XFR_NORMAL_WRITE | XFR_PARITYLESS_WRITE),
|
|
/* operations requiring read before write */
|
|
XFR_RBW = (XFR_NORMAL_WRITE | XFR_DEGRADED_WRITE),
|
|
/* operations that need a malloced buffer */
|
|
XFR_NEEDS_MALLOC = (XFR_NORMAL_WRITE | XFR_RECOVERY_READ | XFR_DEGRADED_WRITE)
|
|
};
|
|
|
|
/* Describe one low-level request, part
|
|
* of a high-level request. This is an
|
|
* extended struct buf buffer, and the first
|
|
* element *must* be a struct buf. We pass this structure
|
|
* to the I/O routines instead of a struct buf in oder
|
|
* to be able to locate the high-level request when it
|
|
* completes.
|
|
*
|
|
* All offsets and lengths are in "blocks", i.e. sectors */
|
|
struct rqelement {
|
|
struct buf b; /* buf structure */
|
|
struct rqgroup *rqg; /* pointer to our group */
|
|
/* Information about the transfer */
|
|
daddr_t sdoffset; /* offset in subdisk */
|
|
int useroffset; /* offset in user buffer of normal data */
|
|
/* dataoffset and datalen refer to "individual"
|
|
* data transfers (normal read, parityless write)
|
|
* and also degraded write.
|
|
*
|
|
* groupoffset and grouplen refer to the other
|
|
* "group" operations (normal write, recovery read)
|
|
* Both the offsets are relative to the start of the
|
|
* local buffer */
|
|
int dataoffset; /* offset in buffer of the normal data */
|
|
int groupoffset; /* offset in buffer of group data */
|
|
short datalen; /* length of normal data (sectors) */
|
|
short grouplen; /* length of group data (sectors) */
|
|
short buflen; /* total buffer length to allocate */
|
|
short flags; /* really enum xferinfo (see above) */
|
|
/* Ways to find other components */
|
|
short sdno; /* subdisk number */
|
|
short driveno; /* drive number */
|
|
};
|
|
|
|
/* A group of requests built to satisfy a certain
|
|
* component of a user request */
|
|
struct rqgroup {
|
|
struct rqgroup *next; /* pointer to next group */
|
|
struct request *rq; /* pointer to the request */
|
|
short count; /* number of requests in this group */
|
|
short active; /* and number active */
|
|
short plexno; /* index of plex */
|
|
int badsdno; /* index of bad subdisk or -1 */
|
|
enum xferinfo flags; /* description of transfer */
|
|
struct rqelement rqe[0]; /* and the elements of this request */
|
|
};
|
|
|
|
/* Describe one high-level request and the
|
|
* work we have to do to satisfy it */
|
|
struct request {
|
|
struct buf *bp; /* pointer to the high-level request */
|
|
int flags;
|
|
union {
|
|
int volno; /* volume index */
|
|
int plexno; /* or plex index */
|
|
} volplex;
|
|
int error; /* current error indication */
|
|
short isplex; /* set if this is a plex request */
|
|
short active; /* number of subrequests still active */
|
|
struct rqgroup *rqg; /* pointer to the first group of requests */
|
|
struct rqgroup *lrqg; /* and to the first group of requests */
|
|
struct request *next; /* link of waiting requests */
|
|
};
|
|
|
|
/* Extended buffer header for subdisk I/O. Includes
|
|
* a pointer to the user I/O request. */
|
|
struct sdbuf {
|
|
struct buf b; /* our buffer */
|
|
struct buf *bp; /* and pointer to parent */
|
|
short driveno; /* drive index */
|
|
short sdno; /* and subdisk index */
|
|
};
|
|
|
|
/* Values returned by rqe and friends.
|
|
* Be careful with these: they are in order of increasing
|
|
* seriousness. Some routines check for > REQUEST_RECOVERED
|
|
* to indicate a completely failed request. */
|
|
enum requeststatus {
|
|
REQUEST_OK, /* request built OK */
|
|
REQUEST_RECOVERED, /* request OK, but involves RAID5 recovery */
|
|
REQUEST_EOF, /* request failed: outside plex */
|
|
REQUEST_DOWN, /* request failed: subdisk down */
|
|
REQUEST_ENOMEM /* ran out of memory */
|
|
};
|
|
|
|
#ifdef DEBUG
|
|
/* Trace entry for request info (DEBUG_LASTREQS) */
|
|
enum rqinfo_type {
|
|
loginfo_unused, /* never been used */
|
|
loginfo_user_bp, /* this is the bp when strategy is called */
|
|
loginfo_user_bpl, /* and this is the bp at launch time */
|
|
loginfo_rqe, /* user RQE */
|
|
loginfo_iodone, /* iodone */
|
|
loginfo_raid5_data, /* write RAID-5 data block */
|
|
loginfo_raid5_parity /* write RAID-5 parity block */
|
|
};
|
|
|
|
union rqinfou { /* info to pass to logrq */
|
|
struct buf *bp;
|
|
struct rqelement *rqe; /* address of request, for correlation */
|
|
};
|
|
|
|
struct rqinfo {
|
|
enum rqinfo_type type; /* kind of event */
|
|
struct timeval timestamp; /* time it happened */
|
|
struct buf *bp; /* point to user buffer */
|
|
union {
|
|
struct buf b; /* yup, the *whole* buffer header */
|
|
struct rqelement rqe; /* and the whole rqe */
|
|
} info;
|
|
};
|
|
|
|
#define RQINFO_SIZE 64 /* number of info slots in buffer */
|
|
|
|
void logrq(enum rqinfo_type type, union rqinfou info, struct buf *ubp);
|
|
#endif
|