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:
parent
1a8efde980
commit
721fbc5ae0
@ -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
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user