config.c:

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.
This commit is contained in:
Greg Lehey 1998-10-21 08:32:32 +00:00
parent 1a8efde980
commit 721fbc5ae0
22 changed files with 376 additions and 112 deletions

View File

@ -44,7 +44,7 @@
* otherwise) arising in any way out of the use of this software, even if
* advised of the possibility of such damage.
*
* $Id: config.c,v 1.17 1998/08/14 04:49:26 grog Exp grog $
* $Id: config.c,v 1.19 1998/10/05 02:48:15 grog Exp grog $
*/
#define STATIC /* nothing while we're testing XXX */
@ -488,7 +488,7 @@ get_empty_drive(void)
/* Find the named drive in vinum_conf.drive, return a pointer
* return the index in vinum_conf.drive.
* Don't mark the drive as allocated (XXX MP)
* Don't mark the drive as allocated (XXX SMP)
* If create != 0, create an entry if it doesn't exist
*/
/* XXX check if we have it open from attach */
@ -936,9 +936,10 @@ config_drive(void)
}
}
if (drive->devicename[0] == '\0')
if (drive->devicename[0] == '\0') {
drive->state = drive_unallocated; /* deallocate the drive */
throw_rude_remark(EINVAL, "No device name for %s", drive->label.name);
}
}
/* Handle a subdisk definition. We store the information in the global variable

View File

@ -69,14 +69,19 @@ complete_rqe(struct buf *bp)
rqe = (struct rqelement *) bp; /* point to the element element that completed */
rqg = rqe->rqg; /* and the request group */
rq = rqg->rq; /* and the complete request */
ubp = rq->bp; /* user buffer */
#ifdef DEBUG
if (debug & DEBUG_LASTREQS)
logrq(loginfo_iodone, rqe, ubp);
#endif
if ((bp->b_flags & B_ERROR) != 0) { /* transfer in error */
if (bp->b_error != 0) /* did it return a number? */
rq->error = bp->b_error; /* yes, put it in. */
else if (rq->error == 0) /* no: do we have one already? */
rq->error = EIO; /* no: catchall "I/O error" */
if (rq->error == EIO) /* I/O error, */
set_sd_state(rqe->sdno, sd_crashed, setstate_force); /* take the subdisk down */
set_sd_state(rqe->sdno, sd_crashed, setstate_force | setstate_noupdate); /* take the subdisk down */
}
/* Now update the statistics */
if (bp->b_flags & B_READ) { /* read operation */
@ -94,13 +99,12 @@ complete_rqe(struct buf *bp)
PLEX[rqe->rqg->plexno].writes++;
PLEX[rqe->rqg->plexno].bytes_written += bp->b_bcount;
}
ubp = rq->bp; /* user buffer */
rqg->active--; /* one less request active */
if (rqg->active == 0) /* request group finished, */
rq->active--; /* one less */
if (rq->active == 0) { /* request finished, */
#if DEBUG
if (debug & 4) {
if (debug & DEBUG_RESID) {
if (ubp->b_resid != 0) /* still something to transfer? */
Debugger("resid");

View File

@ -1,4 +1,3 @@
/*-
* Copyright (c) 1997, 1998
* Nan Yang Computer Services Limited. All rights reserved.
@ -34,7 +33,7 @@
* otherwise) arising in any way out of the use of this software, even if
* advised of the possibility of such damage.
*
* $Id: memory.c,v 1.16 1998/08/08 04:43:22 grog Exp grog $
* $Id: memory.c,v 1.17 1998/09/29 05:18:09 grog Exp grog $
*/
#define REALLYKERNEL
@ -43,6 +42,12 @@
extern jmp_buf command_fail; /* return on a failed command */
#ifdef DEBUG
#include "request.h"
extern struct rqinfo rqinfo[];
extern struct rqinfo *rqip;
#endif
#if __FreeBSD__ >= 3
/* Why aren't these declared anywhere? XXX */
int setjmp(jmp_buf);
@ -68,20 +73,6 @@ expand_table(void **table, int oldsize, int newsize)
}
}
#ifndef DEBUG
/* increase the size of a request block */
void
expandrq(struct plexrq *prq)
{
expand_table((void **) &prq->rqe,
prq->requests * sizeof(struct rqelement),
(prq->requests + RQELTS) * sizeof(struct rqelement));
bzero(&prq->rqe[prq->requests], RQELTS * sizeof(struct rqelement)); /* clear the new part */
prq->rqcount += RQELTS;
}
#endif
#if DEBUG /* XXX debug */
#define MALLOCENTRIES 16384
int malloccount = 0;
@ -115,6 +106,10 @@ MMalloc(int size, char *file, int line)
Debugger("Malloc overlap");
}
if (result) {
char *f = index(file, '/'); /* chop off dirname if present */
if (f == NULL)
f = file;
i = malloccount++;
total_malloced += size;
malloced[i].address = result;
@ -123,7 +118,7 @@ MMalloc(int size, char *file, int line)
malloced[i].seq = seq++;
malloced[i].flags = me.flags;
malloced[i].databuf = me.databuf; /* only used with kva alloc */
bcopy(file, malloced[i].file, min(strlen(file) + 1, 16));
bcopy(f, malloced[i].file, min(strlen(f) + 1, 16));
}
if (malloccount > highwater)
highwater = malloccount;
@ -183,4 +178,21 @@ vinum_mallocinfo(caddr_t data)
return 0;
}
/* return the nth request trace buffer entry. This
* is indexed back from the current entry (which
* has index 0) */
int
vinum_rqinfo(caddr_t data)
{
struct rqinfo *rq = (struct rqinfo *) data;
int ent = *(int *) data; /* 1st word is index */
int lastent = rqip - rqinfo; /* entry number of current entry */
if (ent >= RQINFO_SIZE) /* out of the table */
return ENOENT;
if ((ent = lastent - ent - 1) < 0)
ent += RQINFO_SIZE; /* roll over backwards */
bcopy(&rqinfo[ent], rq, sizeof(struct rqinfo));
return 0;
}
#endif

View File

@ -37,7 +37,7 @@
* otherwise) arising in any way out of the use of this software, even if
* advised of the possibility of such damage.
*
* $Id: request.c,v 1.17 1998/08/13 06:04:47 grog Exp grog $
* $Id: request.c,v 1.18 1998/08/31 23:45:35 grog Exp grog $
*/
#define REALLYKERNEL
@ -73,6 +73,50 @@ int vinum_bounds_check(struct buf *bp, struct volume *vol);
caddr_t allocdatabuf(struct rqelement *rqe);
void freedatabuf(struct rqelement *rqe);
#ifdef DEBUG
struct rqinfo rqinfo[RQINFO_SIZE];
struct rqinfo *rqip = rqinfo;
void
logrq(enum rqinfo_type type, union rqinfou info, struct buf *ubp)
{
BROKEN_GDB;
int s = splhigh();
vinum_conf.rqipp = &rqip; /* XXX for broken gdb */
vinum_conf.rqinfop = rqinfo; /* XXX for broken gdb */
#if __FreeBSD__ < 3
rqip->timestamp = time; /* when did this happen? */
#else
microtime(&rqip->timestamp); /* when did this happen? */
#endif
rqip->type = type;
rqip->bp = ubp; /* user buffer */
switch (type) {
case loginfo_user_bp:
case loginfo_user_bpl:
bcopy(info.bp, &rqip->info.b, sizeof(struct buf));
break;
case loginfo_iodone:
case loginfo_rqe:
case loginfo_raid5_data:
case loginfo_raid5_parity:
bcopy(info.rqe, &rqip->info.rqe, sizeof(struct rqelement));
break;
case loginfo_unused:
break;
}
rqip++;
if (rqip >= &rqinfo[RQINFO_SIZE]) /* wrap around */
rqip = rqinfo;
splx(s);
}
#endif
void
vinumstrategy(struct buf *bp)
{
@ -83,6 +127,17 @@ vinumstrategy(struct buf *bp)
struct devcode *device = (struct devcode *) &bp->b_dev; /* decode device number */
enum requeststatus status;
/* We may have changed the configuration in
* an interrupt context. Update it now. It
* could change again, so do it in a loop.
* XXX this is broken and contains a race condition.
* The correct way is to hand it off the the Vinum
* daemon, but I haven't found a name for it yet */
while (vinum_conf.flags & VF_DIRTYCONFIG) { /* config is dirty, save it now */
vinum_conf.flags &= ~VF_DIRTYCONFIG; /* turn it off */
save_config();
}
switch (device->type) {
case VINUM_SD_TYPE:
sdio(bp);
@ -142,6 +197,11 @@ vinumstart(struct buf *bp, int reviveok)
int rqno; /* index in request list */
enum requeststatus status;
#if DEBUG
if (debug & DEBUG_LASTREQS)
logrq(loginfo_user_bp, bp, bp);
#endif
/* XXX In these routines, we're assuming that
* we will always be called with bp->b_bcount
* which is a multiple of the sector size. This
@ -218,8 +278,8 @@ vinumstart(struct buf *bp, int reviveok)
biodone(bp);
freerq(rq);
return -1;
}
return launch_requests(rq, reviveok); /* now start the requests if we can */
}
return launch_requests(rq, reviveok); /* now start the requests if we can */
} else
/* This is a write operation. We write to all
* plexes. If this is a RAID 5 plex, we must also
@ -248,8 +308,8 @@ vinumstart(struct buf *bp, int reviveok)
biodone(bp);
freerq(rq);
return -1;
}
return launch_requests(rq, reviveok); /* start the requests */
}
return launch_requests (rq, reviveok); /* start the requests */
}
}
@ -296,13 +356,16 @@ launch_requests(struct request *rq, int reviveok)
}
#if DEBUG
if (debug & DEBUG_ADDRESSES)
printf("Request: %x\nWrite dev 0x%x, offset 0x%x, length %ld\n",
printf("Request: %x\n%s dev 0x%x, offset 0x%x, length %ld\n",
(u_int) rq,
rq->bp->b_flags & B_READ ? "Read" : "Write",
rq->bp->b_dev,
rq->bp->b_blkno,
rq->bp->b_bcount); /* XXX */
vinum_conf.lastrq = (int) rq;
vinum_conf.lastbuf = rq->bp;
if (debug & DEBUG_LASTREQS)
logrq(loginfo_user_bpl, rq->bp, rq->bp);
#endif
for (rqg = rq->rqg; rqg != NULL; rqg = rqg->next) { /* through the whole request chain */
rqg->active = rqg->count; /* they're all active */
@ -328,6 +391,8 @@ launch_requests(struct request *rq, int reviveok)
printf(" vinumstart sd %d numoutput %ld\n",
rqe->sdno,
rqe->b.b_vp->v_numoutput);
if (debug & DEBUG_LASTREQS)
logrq(loginfo_rqe, rqe, rq->bp);
#endif
/* fire off the request */
s = splbio();

View File

@ -157,3 +157,35 @@ enum requeststatus {
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

View File

@ -164,8 +164,12 @@ set_sd_state(int sdno, enum sdstate state, enum setstateflags flags)
printf("vinum: subdisk %s is %s\n", sd->name, sd_state(sd->state));
if ((flags & setstate_norecurse) == 0)
set_plex_state(sd->plexno, plex_up, setstate_recursing); /* update plex state */
if ((flags & (setstate_configuring | setstate_recursing)) == 0) /* save config now */
save_config();
if ((flags & (setstate_configuring | setstate_recursing)) == 0) { /* save config now */
if (setstate_noupdate) /* we can't update now, */
vinum_conf.flags |= VF_DIRTYCONFIG; /* wait until later */
else
save_config();
}
return status;
}

View File

@ -33,7 +33,7 @@
* otherwise) arising in any way out of the use of this software, even if
* advised of the possibility of such damage.
*
* $Id: vinumext.h,v 1.14 1998/08/11 00:03:57 grog Exp grog $
* $Id: vinumext.h,v 1.15 1998/09/29 05:17:56 grog Exp grog $
*/
/* vinumext.h: external definitions */
@ -136,9 +136,12 @@ int launch_requests(struct request *rq, int reviveok);
/* XXX Do we need this? */
int vinumpart(dev_t);
/* Memory allocation */
#ifdef DEBUG
/* Memory allocation and request tracing */
void vinum_meminfo(caddr_t data);
int vinum_mallocinfo(caddr_t data);
int vinum_rqinfo(caddr_t data);
#endif
void expand_table(void **, int, int);
@ -199,16 +202,3 @@ int lockrange(struct plex *plex, off_t first, off_t last);
void unlockrange(struct plex *plex, off_t first, off_t last);
int lock_config(void);
void unlock_config(void);
#ifdef DEBUG
#define expandrq(prq) \
{ \
expand_table ((void **) &prq->rqe, \
prq->requests * sizeof (struct rqelement), \
(prq->requests + RQELTS) * sizeof (struct rqelement) ); \
bzero (&prq->rqe [prq->requests], RQELTS * sizeof (struct rqelement)); \
prq->rqcount += RQELTS; \
}
#else
void expandrq(struct plexrq *);
#endif

View File

@ -36,7 +36,12 @@
* $Id: vinumio.h,v 1.10 1998/08/10 05:46:19 grog Exp grog $
*/
#ifdef DEBUG
#define MAX_IOCTL_REPLY 4096
#else
#define MAX_IOCTL_REPLY 256
#endif
#define L 'F' /* ID letter of our ioctls */
/* VINUM_CREATE returns a buffer of this kind */
struct _ioctl_reply {
@ -130,3 +135,7 @@ struct vinum_rename_msg {
#define VINUM_RENAME _IOC(IOC_IN | IOC_OUT, L, 89, MAX_IOCTL_REPLY) /* reset object stats */
#define VINUM_REPLACE _IOC(IOC_IN | IOC_OUT, L, 90, MAX_IOCTL_REPLY) /* reset object stats */
#ifdef DEBUG
#define VINUM_RQINFO _IOWR(L, 91, struct rqinfo) /* get request info [i] from trace buffer */
#endif

View File

@ -35,7 +35,7 @@
* otherwise) arising in any way out of the use of this software, even if
* advised of the possibility of such damage.
*
* $Id: vinumioctl.c,v 1.1 1998/08/14 08:46:10 grog Exp grog $
* $Id: vinumioctl.c,v 1.3 1998/09/29 05:26:37 grog Exp grog $
*/
#define STATIC /* nothing while we're testing XXX */
@ -45,6 +45,7 @@
#include "sys/sysproto.h" /* for sync(2) */
#ifdef DEBUG
#include <sys/reboot.h>
#include "request.h"
#endif
jmp_buf command_fail; /* return on a failed command */
@ -97,17 +98,21 @@ vinumioctl(dev_t dev,
if (error) /* bombed out */
return 0; /* the reply will contain meaningful info */
switch (cmd) {
/* XXX #ifdef DEBUG */
#ifdef DEBUG
case VINUM_DEBUG:
boothowto |= RB_GDB; /* serial debug line */
if (((struct debuginfo *) data)->changeit) /* change debug settings */
debug = (((struct debuginfo *) data)->param);
else
else {
if (debug & DEBUG_REMOTEGDB)
boothowto |= RB_GDB; /* serial debug line */
else
boothowto &= ~RB_GDB; /* local ddb */
Debugger("vinum debug");
}
ioctl_reply = (struct _ioctl_reply *) data; /* reinstate the address to reply to */
ioctl_reply->error = 0;
return 0;
/* XXX #endif */
#endif
case VINUM_CREATE: /* create a vinum object */
error = lock_config(); /* get the config for us alone */
@ -222,6 +227,9 @@ vinumioctl(dev_t dev,
case VINUM_MALLOCINFO:
return vinum_mallocinfo(data);
case VINUM_RQINFO:
return vinum_rqinfo(data);
case VINUM_LABEL: /* label a volume */
ioctl_reply->error = write_volume_label(*(int *) data); /* index of the volume to label */
ioctl_reply->msg[0] = '\0'; /* no message */

View File

@ -33,7 +33,7 @@
* otherwise) arising in any way out of the use of this software, even if
* advised of the possibility of such damage.
*
* $Id: vinumkw.h,v 1.7 1998/08/07 02:35:51 grog Exp grog $
* $Id: vinumkw.h,v 1.8 1998/09/29 05:17:39 grog Exp grog $
*/
/* Command keywords that vinum knows. These include both user-level
@ -98,8 +98,8 @@ enum keyword {
kw_detached,
#ifdef DEBUG
kw_debug, /* go into debugger */
kw_info,
#endif
kw_info,
kw_invalid_keyword = -1
};

View File

@ -185,6 +185,7 @@ enum objflags {
VF_CONFIG_SETUPSTATE = 0x2000, /* set a volume up if all plexes are empty */
VF_READING_CONFIG = 0x4000, /* we're reading config database from disk */
VF_KERNELOP = 0x8000, /* we're performing ops from kernel space */
VF_DIRTYCONFIG = 0x10000, /* config needs updating */
};
/* Global configuration information for the vinum subsystem */
@ -212,6 +213,8 @@ struct _vinum_conf {
#if DEBUG
int lastrq;
struct buf *lastbuf;
struct rqinfo **rqipp;
struct rqinfo *rqinfop;
#endif
};
@ -226,7 +229,7 @@ struct _vinum_conf {
* Vinum drives start with this structure:
*
* Sector
*\ Sector
* |--------------------------------------|
* | PDP-11 memorial boot block | 0
* |--------------------------------------|
@ -500,11 +503,15 @@ enum setstateflags {
setstate_force = 1, /* force the state change */
setstate_configuring = 2, /* we're currently configuring, don't save */
setstate_recursing = 4, /* we're called from another setstate function */
setstate_norecurse = 8 /* don't call other setstate functions */
setstate_norecurse = 8, /* don't call other setstate functions */
setstate_noupdate = 16 /* don't update config */
};
#ifdef DEBUG
/* Debugging stuff */
#define DEBUG_ADDRESSES 1
#define DEBUG_NUMOUTPUT 2
#define DEBUG_RESID 4 /* go into debugger in complete_rqe */
#define DEBUG_LASTREQS 8 /* keep a circular buffer of last requests */
#define DEBUG_REMOTEGDB 256 /* go into remote gdb */
#endif

View File

@ -157,3 +157,35 @@ enum requeststatus {
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

View File

@ -44,7 +44,7 @@
* otherwise) arising in any way out of the use of this software, even if
* advised of the possibility of such damage.
*
* $Id: config.c,v 1.17 1998/08/14 04:49:26 grog Exp grog $
* $Id: config.c,v 1.19 1998/10/05 02:48:15 grog Exp grog $
*/
#define STATIC /* nothing while we're testing XXX */
@ -488,7 +488,7 @@ get_empty_drive(void)
/* Find the named drive in vinum_conf.drive, return a pointer
* return the index in vinum_conf.drive.
* Don't mark the drive as allocated (XXX MP)
* Don't mark the drive as allocated (XXX SMP)
* If create != 0, create an entry if it doesn't exist
*/
/* XXX check if we have it open from attach */
@ -936,9 +936,10 @@ config_drive(void)
}
}
if (drive->devicename[0] == '\0')
if (drive->devicename[0] == '\0') {
drive->state = drive_unallocated; /* deallocate the drive */
throw_rude_remark(EINVAL, "No device name for %s", drive->label.name);
}
}
/* Handle a subdisk definition. We store the information in the global variable

View File

@ -33,7 +33,7 @@
* otherwise) arising in any way out of the use of this software, even if
* advised of the possibility of such damage.
*
* $Id: vinumext.h,v 1.14 1998/08/11 00:03:57 grog Exp grog $
* $Id: vinumext.h,v 1.15 1998/09/29 05:17:56 grog Exp grog $
*/
/* vinumext.h: external definitions */
@ -136,9 +136,12 @@ int launch_requests(struct request *rq, int reviveok);
/* XXX Do we need this? */
int vinumpart(dev_t);
/* Memory allocation */
#ifdef DEBUG
/* Memory allocation and request tracing */
void vinum_meminfo(caddr_t data);
int vinum_mallocinfo(caddr_t data);
int vinum_rqinfo(caddr_t data);
#endif
void expand_table(void **, int, int);
@ -199,16 +202,3 @@ int lockrange(struct plex *plex, off_t first, off_t last);
void unlockrange(struct plex *plex, off_t first, off_t last);
int lock_config(void);
void unlock_config(void);
#ifdef DEBUG
#define expandrq(prq) \
{ \
expand_table ((void **) &prq->rqe, \
prq->requests * sizeof (struct rqelement), \
(prq->requests + RQELTS) * sizeof (struct rqelement) ); \
bzero (&prq->rqe [prq->requests], RQELTS * sizeof (struct rqelement)); \
prq->rqcount += RQELTS; \
}
#else
void expandrq(struct plexrq *);
#endif

View File

@ -69,14 +69,19 @@ complete_rqe(struct buf *bp)
rqe = (struct rqelement *) bp; /* point to the element element that completed */
rqg = rqe->rqg; /* and the request group */
rq = rqg->rq; /* and the complete request */
ubp = rq->bp; /* user buffer */
#ifdef DEBUG
if (debug & DEBUG_LASTREQS)
logrq(loginfo_iodone, rqe, ubp);
#endif
if ((bp->b_flags & B_ERROR) != 0) { /* transfer in error */
if (bp->b_error != 0) /* did it return a number? */
rq->error = bp->b_error; /* yes, put it in. */
else if (rq->error == 0) /* no: do we have one already? */
rq->error = EIO; /* no: catchall "I/O error" */
if (rq->error == EIO) /* I/O error, */
set_sd_state(rqe->sdno, sd_crashed, setstate_force); /* take the subdisk down */
set_sd_state(rqe->sdno, sd_crashed, setstate_force | setstate_noupdate); /* take the subdisk down */
}
/* Now update the statistics */
if (bp->b_flags & B_READ) { /* read operation */
@ -94,13 +99,12 @@ complete_rqe(struct buf *bp)
PLEX[rqe->rqg->plexno].writes++;
PLEX[rqe->rqg->plexno].bytes_written += bp->b_bcount;
}
ubp = rq->bp; /* user buffer */
rqg->active--; /* one less request active */
if (rqg->active == 0) /* request group finished, */
rq->active--; /* one less */
if (rq->active == 0) { /* request finished, */
#if DEBUG
if (debug & 4) {
if (debug & DEBUG_RESID) {
if (ubp->b_resid != 0) /* still something to transfer? */
Debugger("resid");

View File

@ -36,7 +36,12 @@
* $Id: vinumio.h,v 1.10 1998/08/10 05:46:19 grog Exp grog $
*/
#ifdef DEBUG
#define MAX_IOCTL_REPLY 4096
#else
#define MAX_IOCTL_REPLY 256
#endif
#define L 'F' /* ID letter of our ioctls */
/* VINUM_CREATE returns a buffer of this kind */
struct _ioctl_reply {
@ -130,3 +135,7 @@ struct vinum_rename_msg {
#define VINUM_RENAME _IOC(IOC_IN | IOC_OUT, L, 89, MAX_IOCTL_REPLY) /* reset object stats */
#define VINUM_REPLACE _IOC(IOC_IN | IOC_OUT, L, 90, MAX_IOCTL_REPLY) /* reset object stats */
#ifdef DEBUG
#define VINUM_RQINFO _IOWR(L, 91, struct rqinfo) /* get request info [i] from trace buffer */
#endif

View File

@ -35,7 +35,7 @@
* otherwise) arising in any way out of the use of this software, even if
* advised of the possibility of such damage.
*
* $Id: vinumioctl.c,v 1.1 1998/08/14 08:46:10 grog Exp grog $
* $Id: vinumioctl.c,v 1.3 1998/09/29 05:26:37 grog Exp grog $
*/
#define STATIC /* nothing while we're testing XXX */
@ -45,6 +45,7 @@
#include "sys/sysproto.h" /* for sync(2) */
#ifdef DEBUG
#include <sys/reboot.h>
#include "request.h"
#endif
jmp_buf command_fail; /* return on a failed command */
@ -97,17 +98,21 @@ vinumioctl(dev_t dev,
if (error) /* bombed out */
return 0; /* the reply will contain meaningful info */
switch (cmd) {
/* XXX #ifdef DEBUG */
#ifdef DEBUG
case VINUM_DEBUG:
boothowto |= RB_GDB; /* serial debug line */
if (((struct debuginfo *) data)->changeit) /* change debug settings */
debug = (((struct debuginfo *) data)->param);
else
else {
if (debug & DEBUG_REMOTEGDB)
boothowto |= RB_GDB; /* serial debug line */
else
boothowto &= ~RB_GDB; /* local ddb */
Debugger("vinum debug");
}
ioctl_reply = (struct _ioctl_reply *) data; /* reinstate the address to reply to */
ioctl_reply->error = 0;
return 0;
/* XXX #endif */
#endif
case VINUM_CREATE: /* create a vinum object */
error = lock_config(); /* get the config for us alone */
@ -222,6 +227,9 @@ vinumioctl(dev_t dev,
case VINUM_MALLOCINFO:
return vinum_mallocinfo(data);
case VINUM_RQINFO:
return vinum_rqinfo(data);
case VINUM_LABEL: /* label a volume */
ioctl_reply->error = write_volume_label(*(int *) data); /* index of the volume to label */
ioctl_reply->msg[0] = '\0'; /* no message */

View File

@ -33,7 +33,7 @@
* otherwise) arising in any way out of the use of this software, even if
* advised of the possibility of such damage.
*
* $Id: vinumkw.h,v 1.7 1998/08/07 02:35:51 grog Exp grog $
* $Id: vinumkw.h,v 1.8 1998/09/29 05:17:39 grog Exp grog $
*/
/* Command keywords that vinum knows. These include both user-level
@ -98,8 +98,8 @@ enum keyword {
kw_detached,
#ifdef DEBUG
kw_debug, /* go into debugger */
kw_info,
#endif
kw_info,
kw_invalid_keyword = -1
};

View File

@ -1,4 +1,3 @@
/*-
* Copyright (c) 1997, 1998
* Nan Yang Computer Services Limited. All rights reserved.
@ -34,7 +33,7 @@
* otherwise) arising in any way out of the use of this software, even if
* advised of the possibility of such damage.
*
* $Id: memory.c,v 1.16 1998/08/08 04:43:22 grog Exp grog $
* $Id: memory.c,v 1.17 1998/09/29 05:18:09 grog Exp grog $
*/
#define REALLYKERNEL
@ -43,6 +42,12 @@
extern jmp_buf command_fail; /* return on a failed command */
#ifdef DEBUG
#include "request.h"
extern struct rqinfo rqinfo[];
extern struct rqinfo *rqip;
#endif
#if __FreeBSD__ >= 3
/* Why aren't these declared anywhere? XXX */
int setjmp(jmp_buf);
@ -68,20 +73,6 @@ expand_table(void **table, int oldsize, int newsize)
}
}
#ifndef DEBUG
/* increase the size of a request block */
void
expandrq(struct plexrq *prq)
{
expand_table((void **) &prq->rqe,
prq->requests * sizeof(struct rqelement),
(prq->requests + RQELTS) * sizeof(struct rqelement));
bzero(&prq->rqe[prq->requests], RQELTS * sizeof(struct rqelement)); /* clear the new part */
prq->rqcount += RQELTS;
}
#endif
#if DEBUG /* XXX debug */
#define MALLOCENTRIES 16384
int malloccount = 0;
@ -115,6 +106,10 @@ MMalloc(int size, char *file, int line)
Debugger("Malloc overlap");
}
if (result) {
char *f = index(file, '/'); /* chop off dirname if present */
if (f == NULL)
f = file;
i = malloccount++;
total_malloced += size;
malloced[i].address = result;
@ -123,7 +118,7 @@ MMalloc(int size, char *file, int line)
malloced[i].seq = seq++;
malloced[i].flags = me.flags;
malloced[i].databuf = me.databuf; /* only used with kva alloc */
bcopy(file, malloced[i].file, min(strlen(file) + 1, 16));
bcopy(f, malloced[i].file, min(strlen(f) + 1, 16));
}
if (malloccount > highwater)
highwater = malloccount;
@ -183,4 +178,21 @@ vinum_mallocinfo(caddr_t data)
return 0;
}
/* return the nth request trace buffer entry. This
* is indexed back from the current entry (which
* has index 0) */
int
vinum_rqinfo(caddr_t data)
{
struct rqinfo *rq = (struct rqinfo *) data;
int ent = *(int *) data; /* 1st word is index */
int lastent = rqip - rqinfo; /* entry number of current entry */
if (ent >= RQINFO_SIZE) /* out of the table */
return ENOENT;
if ((ent = lastent - ent - 1) < 0)
ent += RQINFO_SIZE; /* roll over backwards */
bcopy(&rqinfo[ent], rq, sizeof(struct rqinfo));
return 0;
}
#endif

View File

@ -37,7 +37,7 @@
* otherwise) arising in any way out of the use of this software, even if
* advised of the possibility of such damage.
*
* $Id: request.c,v 1.17 1998/08/13 06:04:47 grog Exp grog $
* $Id: request.c,v 1.18 1998/08/31 23:45:35 grog Exp grog $
*/
#define REALLYKERNEL
@ -73,6 +73,50 @@ int vinum_bounds_check(struct buf *bp, struct volume *vol);
caddr_t allocdatabuf(struct rqelement *rqe);
void freedatabuf(struct rqelement *rqe);
#ifdef DEBUG
struct rqinfo rqinfo[RQINFO_SIZE];
struct rqinfo *rqip = rqinfo;
void
logrq(enum rqinfo_type type, union rqinfou info, struct buf *ubp)
{
BROKEN_GDB;
int s = splhigh();
vinum_conf.rqipp = &rqip; /* XXX for broken gdb */
vinum_conf.rqinfop = rqinfo; /* XXX for broken gdb */
#if __FreeBSD__ < 3
rqip->timestamp = time; /* when did this happen? */
#else
microtime(&rqip->timestamp); /* when did this happen? */
#endif
rqip->type = type;
rqip->bp = ubp; /* user buffer */
switch (type) {
case loginfo_user_bp:
case loginfo_user_bpl:
bcopy(info.bp, &rqip->info.b, sizeof(struct buf));
break;
case loginfo_iodone:
case loginfo_rqe:
case loginfo_raid5_data:
case loginfo_raid5_parity:
bcopy(info.rqe, &rqip->info.rqe, sizeof(struct rqelement));
break;
case loginfo_unused:
break;
}
rqip++;
if (rqip >= &rqinfo[RQINFO_SIZE]) /* wrap around */
rqip = rqinfo;
splx(s);
}
#endif
void
vinumstrategy(struct buf *bp)
{
@ -83,6 +127,17 @@ vinumstrategy(struct buf *bp)
struct devcode *device = (struct devcode *) &bp->b_dev; /* decode device number */
enum requeststatus status;
/* We may have changed the configuration in
* an interrupt context. Update it now. It
* could change again, so do it in a loop.
* XXX this is broken and contains a race condition.
* The correct way is to hand it off the the Vinum
* daemon, but I haven't found a name for it yet */
while (vinum_conf.flags & VF_DIRTYCONFIG) { /* config is dirty, save it now */
vinum_conf.flags &= ~VF_DIRTYCONFIG; /* turn it off */
save_config();
}
switch (device->type) {
case VINUM_SD_TYPE:
sdio(bp);
@ -142,6 +197,11 @@ vinumstart(struct buf *bp, int reviveok)
int rqno; /* index in request list */
enum requeststatus status;
#if DEBUG
if (debug & DEBUG_LASTREQS)
logrq(loginfo_user_bp, bp, bp);
#endif
/* XXX In these routines, we're assuming that
* we will always be called with bp->b_bcount
* which is a multiple of the sector size. This
@ -218,8 +278,8 @@ vinumstart(struct buf *bp, int reviveok)
biodone(bp);
freerq(rq);
return -1;
}
return launch_requests(rq, reviveok); /* now start the requests if we can */
}
return launch_requests(rq, reviveok); /* now start the requests if we can */
} else
/* This is a write operation. We write to all
* plexes. If this is a RAID 5 plex, we must also
@ -248,8 +308,8 @@ vinumstart(struct buf *bp, int reviveok)
biodone(bp);
freerq(rq);
return -1;
}
return launch_requests(rq, reviveok); /* start the requests */
}
return launch_requests (rq, reviveok); /* start the requests */
}
}
@ -296,13 +356,16 @@ launch_requests(struct request *rq, int reviveok)
}
#if DEBUG
if (debug & DEBUG_ADDRESSES)
printf("Request: %x\nWrite dev 0x%x, offset 0x%x, length %ld\n",
printf("Request: %x\n%s dev 0x%x, offset 0x%x, length %ld\n",
(u_int) rq,
rq->bp->b_flags & B_READ ? "Read" : "Write",
rq->bp->b_dev,
rq->bp->b_blkno,
rq->bp->b_bcount); /* XXX */
vinum_conf.lastrq = (int) rq;
vinum_conf.lastbuf = rq->bp;
if (debug & DEBUG_LASTREQS)
logrq(loginfo_user_bpl, rq->bp, rq->bp);
#endif
for (rqg = rq->rqg; rqg != NULL; rqg = rqg->next) { /* through the whole request chain */
rqg->active = rqg->count; /* they're all active */
@ -328,6 +391,8 @@ launch_requests(struct request *rq, int reviveok)
printf(" vinumstart sd %d numoutput %ld\n",
rqe->sdno,
rqe->b.b_vp->v_numoutput);
if (debug & DEBUG_LASTREQS)
logrq(loginfo_rqe, rqe, rq->bp);
#endif
/* fire off the request */
s = splbio();

View File

@ -164,8 +164,12 @@ set_sd_state(int sdno, enum sdstate state, enum setstateflags flags)
printf("vinum: subdisk %s is %s\n", sd->name, sd_state(sd->state));
if ((flags & setstate_norecurse) == 0)
set_plex_state(sd->plexno, plex_up, setstate_recursing); /* update plex state */
if ((flags & (setstate_configuring | setstate_recursing)) == 0) /* save config now */
save_config();
if ((flags & (setstate_configuring | setstate_recursing)) == 0) { /* save config now */
if (setstate_noupdate) /* we can't update now, */
vinum_conf.flags |= VF_DIRTYCONFIG; /* wait until later */
else
save_config();
}
return status;
}

View File

@ -185,6 +185,7 @@ enum objflags {
VF_CONFIG_SETUPSTATE = 0x2000, /* set a volume up if all plexes are empty */
VF_READING_CONFIG = 0x4000, /* we're reading config database from disk */
VF_KERNELOP = 0x8000, /* we're performing ops from kernel space */
VF_DIRTYCONFIG = 0x10000, /* config needs updating */
};
/* Global configuration information for the vinum subsystem */
@ -212,6 +213,8 @@ struct _vinum_conf {
#if DEBUG
int lastrq;
struct buf *lastbuf;
struct rqinfo **rqipp;
struct rqinfo *rqinfop;
#endif
};
@ -226,7 +229,7 @@ struct _vinum_conf {
* Vinum drives start with this structure:
*
* Sector
*\ Sector
* |--------------------------------------|
* | PDP-11 memorial boot block | 0
* |--------------------------------------|
@ -500,11 +503,15 @@ enum setstateflags {
setstate_force = 1, /* force the state change */
setstate_configuring = 2, /* we're currently configuring, don't save */
setstate_recursing = 4, /* we're called from another setstate function */
setstate_norecurse = 8 /* don't call other setstate functions */
setstate_norecurse = 8, /* don't call other setstate functions */
setstate_noupdate = 16 /* don't update config */
};
#ifdef DEBUG
/* Debugging stuff */
#define DEBUG_ADDRESSES 1
#define DEBUG_NUMOUTPUT 2
#define DEBUG_RESID 4 /* go into debugger in complete_rqe */
#define DEBUG_LASTREQS 8 /* keep a circular buffer of last requests */
#define DEBUG_REMOTEGDB 256 /* go into remote gdb */
#endif