Increase the whimsy in this file by famring dump's work out to minions. Adjust

variables accordingly. Thankfully, we are able to do this without additional
banana expenditures.
This commit is contained in:
Warner Losh 2020-06-20 04:19:17 +00:00
parent e245e555fa
commit 0447cda0cb

View File

@ -75,19 +75,19 @@ static char *nexttape;
static FILE *popenfp = NULL;
static int atomic(ssize_t (*)(), int, char *, int);
static void doslave(int, int);
static void enslave(void);
static void dominion(int, int);
static void enminion(void);
static void flushtape(void);
static void killall(void);
static void rollforward(void);
/*
* Concurrent dump mods (Caltech) - disk block reading and tape writing
* are exported to several slave processes. While one slave writes the
* are exported to several minion processes. While one minion writes the
* tape, the others read disk blocks; they pass control of the tape in
* a ring via signals. The parent process traverses the file system and
* sends writeheader()'s and lists of daddr's to the slaves via pipes.
* The following structure defines the instruction packets sent to slaves.
* sends writeheader()'s and lists of daddr's to the minions via pipes.
* The following structure defines the instruction packets sent to minions.
*/
struct req {
ufs2_daddr_t dblk;
@ -95,20 +95,20 @@ struct req {
};
static int reqsiz;
#define SLAVES 3 /* 1 slave writing, 1 reading, 1 for slack */
static struct slave {
#define MINIONS 3 /* 1 minion writing, 1 reading, 1 for slack */
static struct minion {
int64_t tapea; /* header number at start of this chunk */
int64_t firstrec; /* record number of this block */
int count; /* count to next header (used for TS_TAPE */
/* after EOT) */
int inode; /* inode that we are currently dealing with */
int fd; /* FD for this slave */
int pid; /* PID for this slave */
int sent; /* 1 == we've sent this slave requests */
int fd; /* FD for this minion */
int pid; /* PID for this minion */
int sent; /* 1 == we've sent this minion requests */
char (*tblock)[TP_BSIZE]; /* buffer for data blocks */
struct req *req; /* buffer for requests */
} slaves[SLAVES+1];
static struct slave *slp;
} minions[MINIONS+1];
static struct minion *mlp;
static char (*nextblock)[TP_BSIZE];
@ -116,9 +116,9 @@ static int master; /* pid of master, for sending error signals */
static int tenths; /* length of tape used per block written */
static volatile sig_atomic_t caught; /* have we caught the signal to proceed? */
static volatile sig_atomic_t ready; /* reached the lock point without having */
/* received the SIGUSR2 signal from the prev slave? */
/* received the SIGUSR2 signal from the prev minion? */
static jmp_buf jmpbuf; /* where to jump to if we are ready when the */
/* SIGUSR2 arrives from the previous slave */
/* SIGUSR2 arrives from the previous minion */
int
alloctape(void)
@ -143,20 +143,20 @@ alloctape(void)
* packets, so flushtape() can write them together with one write().
* Align tape buffer on page boundary to speed up tape write().
*/
for (i = 0; i <= SLAVES; i++) {
for (i = 0; i <= MINIONS; i++) {
buf = (char *)
malloc((unsigned)(reqsiz + writesize + pgoff + TP_BSIZE));
if (buf == NULL)
return(0);
slaves[i].tblock = (char (*)[TP_BSIZE])
minions[i].tblock = (char (*)[TP_BSIZE])
(((long)&buf[ntrec + 1] + pgoff) &~ pgoff);
slaves[i].req = (struct req *)slaves[i].tblock - ntrec - 1;
minions[i].req = (struct req *)minions[i].tblock - ntrec - 1;
}
slp = &slaves[0];
slp->count = 1;
slp->tapea = 0;
slp->firstrec = 0;
nextblock = slp->tblock;
mlp = &minions[0];
mlp->count = 1;
mlp->tapea = 0;
mlp->firstrec = 0;
nextblock = mlp->tblock;
return(1);
}
@ -164,8 +164,8 @@ void
writerec(char *dp, int isspcl)
{
slp->req[trecno].dblk = (ufs2_daddr_t)0;
slp->req[trecno].count = 1;
mlp->req[trecno].dblk = (ufs2_daddr_t)0;
mlp->req[trecno].count = 1;
/* Can't do a structure assignment due to alignment problems */
bcopy(dp, *(nextblock)++, sizeof (union u_spcl));
if (isspcl)
@ -185,8 +185,8 @@ dumpblock(ufs2_daddr_t blkno, int size)
dblkno = fsbtodb(sblock, blkno);
tpblks = size >> tp_bshift;
while ((avail = MIN(tpblks, ntrec - trecno)) > 0) {
slp->req[trecno].dblk = dblkno;
slp->req[trecno].count = avail;
mlp->req[trecno].dblk = dblkno;
mlp->req[trecno].count = avail;
trecno += avail;
spcl.c_tapea += avail;
if (trecno >= ntrec)
@ -232,27 +232,27 @@ flushtape(void)
int i, blks, got;
int64_t lastfirstrec;
int siz = (char *)nextblock - (char *)slp->req;
int siz = (char *)nextblock - (char *)mlp->req;
slp->req[trecno].count = 0; /* Sentinel */
mlp->req[trecno].count = 0; /* Sentinel */
if (atomic(write, slp->fd, (char *)slp->req, siz) != siz)
if (atomic(write, mlp->fd, (char *)mlp->req, siz) != siz)
quit("error writing command pipe: %s\n", strerror(errno));
slp->sent = 1; /* we sent a request, read the response later */
mlp->sent = 1; /* we sent a request, read the response later */
lastfirstrec = slp->firstrec;
lastfirstrec = mlp->firstrec;
if (++slp >= &slaves[SLAVES])
slp = &slaves[0];
if (++mlp >= &minions[MINIONS])
mlp = &minions[0];
/* Read results back from next slave */
if (slp->sent) {
if (atomic(read, slp->fd, (char *)&got, sizeof got)
/* Read results back from next minion */
if (mlp->sent) {
if (atomic(read, mlp->fd, (char *)&got, sizeof got)
!= sizeof got) {
perror(" DUMP: error reading command pipe in master");
dumpabort(0);
}
slp->sent = 0;
mlp->sent = 0;
/* Check for end of tape */
if (got < writesize) {
@ -262,15 +262,15 @@ flushtape(void)
* Drain the results, don't care what the values were.
* If we read them here then trewind won't...
*/
for (i = 0; i < SLAVES; i++) {
if (slaves[i].sent) {
if (atomic(read, slaves[i].fd,
for (i = 0; i < MINIONS; i++) {
if (minions[i].sent) {
if (atomic(read, minions[i].fd,
(char *)&got, sizeof got)
!= sizeof got) {
perror(" DUMP: error reading command pipe in master");
dumpabort(0);
}
slaves[i].sent = 0;
minions[i].sent = 0;
}
}
@ -288,11 +288,11 @@ flushtape(void)
if (spcl.c_addr[i] != 0)
blks++;
}
slp->count = lastspclrec + blks + 1 - spcl.c_tapea;
slp->tapea = spcl.c_tapea;
slp->firstrec = lastfirstrec + ntrec;
slp->inode = curino;
nextblock = slp->tblock;
mlp->count = lastspclrec + blks + 1 - spcl.c_tapea;
mlp->tapea = spcl.c_tapea;
mlp->firstrec = lastfirstrec + ntrec;
mlp->inode = curino;
nextblock = mlp->tblock;
trecno = 0;
asize += tenths;
blockswritten += ntrec;
@ -312,7 +312,7 @@ trewind(void)
int f;
int got;
for (f = 0; f < SLAVES; f++) {
for (f = 0; f < MINIONS; f++) {
/*
* Drain the results, but unlike EOT we DO (or should) care
* what the return values were, since if we detect EOT after
@ -321,22 +321,22 @@ trewind(void)
*
* fixme: punt for now.
*/
if (slaves[f].sent) {
if (atomic(read, slaves[f].fd, (char *)&got, sizeof got)
if (minions[f].sent) {
if (atomic(read, minions[f].fd, (char *)&got, sizeof got)
!= sizeof got) {
perror(" DUMP: error reading command pipe in master");
dumpabort(0);
}
slaves[f].sent = 0;
minions[f].sent = 0;
if (got != writesize) {
msg("EOT detected in last 2 tape records!\n");
msg("Use a longer tape, decrease the size estimate\n");
quit("or use no size estimate at all.\n");
}
}
(void) close(slaves[f].fd);
(void) close(minions[f].fd);
}
while (wait((int *)NULL) >= 0) /* wait for any signals from slaves */
while (wait((int *)NULL) >= 0) /* wait for any signals from minions */
/* void */;
if (pipeout)
@ -396,29 +396,29 @@ void
rollforward(void)
{
struct req *p, *q, *prev;
struct slave *tslp;
struct minion *tmlp;
int i, size, got;
int64_t savedtapea;
union u_spcl *ntb, *otb;
tslp = &slaves[SLAVES];
ntb = (union u_spcl *)tslp->tblock[1];
tmlp = &minions[MINIONS];
ntb = (union u_spcl *)tmlp->tblock[1];
/*
* Each of the N slaves should have requests that need to
* be replayed on the next tape. Use the extra slave buffers
* (slaves[SLAVES]) to construct request lists to be sent to
* each slave in turn.
* Each of the N minions should have requests that need to
* be replayed on the next tape. Use the extra minion buffers
* (minions[MINIONS]) to construct request lists to be sent to
* each minion in turn.
*/
for (i = 0; i < SLAVES; i++) {
q = &tslp->req[1];
otb = (union u_spcl *)slp->tblock;
for (i = 0; i < MINIONS; i++) {
q = &tmlp->req[1];
otb = (union u_spcl *)mlp->tblock;
/*
* For each request in the current slave, copy it to tslp.
* For each request in the current minion, copy it to tmlp.
*/
prev = NULL;
for (p = slp->req; p->count > 0; p += p->count) {
for (p = mlp->req; p->count > 0; p += p->count) {
*q = *p;
if (p->dblk == 0)
*ntb++ = *otb++; /* copy the datablock also */
@ -433,26 +433,26 @@ rollforward(void)
ntb--;
q -= 1;
q->count = 0;
q = &tslp->req[0];
q = &tmlp->req[0];
if (i == 0) {
q->dblk = 0;
q->count = 1;
trecno = 0;
nextblock = tslp->tblock;
nextblock = tmlp->tblock;
savedtapea = spcl.c_tapea;
spcl.c_tapea = slp->tapea;
spcl.c_tapea = mlp->tapea;
startnewtape(0);
spcl.c_tapea = savedtapea;
lastspclrec = savedtapea - 1;
}
size = (char *)ntb - (char *)q;
if (atomic(write, slp->fd, (char *)q, size) != size) {
if (atomic(write, mlp->fd, (char *)q, size) != size) {
perror(" DUMP: error writing command pipe");
dumpabort(0);
}
slp->sent = 1;
if (++slp >= &slaves[SLAVES])
slp = &slaves[0];
mlp->sent = 1;
if (++mlp >= &minions[MINIONS])
mlp = &minions[0];
q->count = 1;
@ -464,34 +464,34 @@ rollforward(void)
*/
q->dblk = prev->dblk +
prev->count * (TP_BSIZE / DEV_BSIZE);
ntb = (union u_spcl *)tslp->tblock;
ntb = (union u_spcl *)tmlp->tblock;
} else {
/*
* It wasn't a disk block. Copy the data to its
* new location in the buffer.
*/
q->dblk = 0;
*((union u_spcl *)tslp->tblock) = *ntb;
ntb = (union u_spcl *)tslp->tblock[1];
*((union u_spcl *)tmlp->tblock) = *ntb;
ntb = (union u_spcl *)tmlp->tblock[1];
}
}
slp->req[0] = *q;
nextblock = slp->tblock;
mlp->req[0] = *q;
nextblock = mlp->tblock;
if (q->dblk == 0)
nextblock++;
trecno = 1;
/*
* Clear the first slaves' response. One hopes that it
* Clear the first minions' response. One hopes that it
* worked ok, otherwise the tape is much too short!
*/
if (slp->sent) {
if (atomic(read, slp->fd, (char *)&got, sizeof got)
if (mlp->sent) {
if (atomic(read, mlp->fd, (char *)&got, sizeof got)
!= sizeof got) {
perror(" DUMP: error reading command pipe in master");
dumpabort(0);
}
slp->sent = 0;
mlp->sent = 0;
if (got != writesize) {
quit("EOT detected at start of the tape!\n");
@ -634,7 +634,7 @@ startnewtape(int top)
}
}
enslave(); /* Share open tape file descriptor with slaves */
enminion(); /* Share open tape file descriptor with minions */
if (popenout)
close(tapefd); /* Give up our copy of it. */
signal(SIGINFO, infosch);
@ -643,18 +643,18 @@ startnewtape(int top)
blocksthisvol = 0;
if (top)
newtape++; /* new tape signal */
spcl.c_count = slp->count;
spcl.c_count = mlp->count;
/*
* measure firstrec in TP_BSIZE units since restore doesn't
* know the correct ntrec value...
*/
spcl.c_firstrec = slp->firstrec;
spcl.c_firstrec = mlp->firstrec;
spcl.c_volume++;
spcl.c_type = TS_TAPE;
writeheader((ino_t)slp->inode);
writeheader((ino_t)mlp->inode);
if (tapeno > 1)
msg("Volume %d begins with blocks from inode %d\n",
tapeno, slp->inode);
tapeno, mlp->inode);
}
}
@ -687,7 +687,7 @@ Exit(status)
}
/*
* proceed - handler for SIGUSR2, used to synchronize IO between the slaves.
* proceed - handler for SIGUSR2, used to synchronize IO between the minions.
*/
void
proceed(int signo __unused)
@ -699,45 +699,45 @@ proceed(int signo __unused)
}
void
enslave(void)
enminion(void)
{
int cmd[2];
int i, j;
master = getpid();
signal(SIGTERM, dumpabort); /* Slave sends SIGTERM on dumpabort() */
signal(SIGTERM, dumpabort); /* Minion sends SIGTERM on dumpabort() */
signal(SIGPIPE, sigpipe);
signal(SIGUSR1, tperror); /* Slave sends SIGUSR1 on tape errors */
signal(SIGUSR2, proceed); /* Slave sends SIGUSR2 to next slave */
signal(SIGUSR1, tperror); /* Minion sends SIGUSR1 on tape errors */
signal(SIGUSR2, proceed); /* Minion sends SIGUSR2 to next minion */
for (i = 0; i < SLAVES; i++) {
if (i == slp - &slaves[0]) {
for (i = 0; i < MINIONS; i++) {
if (i == mlp - &minions[0]) {
caught = 1;
} else {
caught = 0;
}
if (socketpair(AF_UNIX, SOCK_STREAM, 0, cmd) < 0 ||
(slaves[i].pid = fork()) < 0)
quit("too many slaves, %d (recompile smaller): %s\n",
(minions[i].pid = fork()) < 0)
quit("too many minions, %d (recompile smaller): %s\n",
i, strerror(errno));
slaves[i].fd = cmd[1];
slaves[i].sent = 0;
if (slaves[i].pid == 0) { /* Slave starts up here */
minions[i].fd = cmd[1];
minions[i].sent = 0;
if (minions[i].pid == 0) { /* Minion starts up here */
for (j = 0; j <= i; j++)
(void) close(slaves[j].fd);
(void) close(minions[j].fd);
signal(SIGINT, SIG_IGN); /* Master handles this */
doslave(cmd[0], i);
dominion(cmd[0], i);
Exit(X_FINOK);
}
}
for (i = 0; i < SLAVES; i++)
(void) atomic(write, slaves[i].fd,
(char *) &slaves[(i + 1) % SLAVES].pid,
sizeof slaves[0].pid);
for (i = 0; i < MINIONS; i++)
(void) atomic(write, minions[i].fd,
(char *) &minions[(i + 1) % MINIONS].pid,
sizeof minions[0].pid);
master = 0;
}
@ -747,10 +747,10 @@ killall(void)
{
int i;
for (i = 0; i < SLAVES; i++)
if (slaves[i].pid > 0) {
(void) kill(slaves[i].pid, SIGKILL);
slaves[i].sent = 0;
for (i = 0; i < MINIONS; i++)
if (minions[i].pid > 0) {
(void) kill(minions[i].pid, SIGKILL);
minions[i].sent = 0;
}
}
@ -762,42 +762,42 @@ killall(void)
* get the lock back for the next cycle by swapping descriptors.
*/
static void
doslave(int cmd, int slave_number)
dominion(int cmd, int minion_number)
{
int nread;
int nextslave, size, wrote, eot_count;
int nextminion, size, wrote, eot_count;
/*
* Need our own seek pointer.
*/
(void) close(diskfd);
if ((diskfd = open(disk, O_RDONLY)) < 0)
quit("slave couldn't reopen disk: %s\n", strerror(errno));
quit("minion couldn't reopen disk: %s\n", strerror(errno));
/*
* Need the pid of the next slave in the loop...
* Need the pid of the next minion in the loop...
*/
if ((nread = atomic(read, cmd, (char *)&nextslave, sizeof nextslave))
!= sizeof nextslave) {
quit("master/slave protocol botched - didn't get pid of next slave.\n");
if ((nread = atomic(read, cmd, (char *)&nextminion, sizeof nextminion))
!= sizeof nextminion) {
quit("master/minion protocol botched - didn't get pid of next minion.\n");
}
/*
* Get list of blocks to dump, read the blocks into tape buffer
*/
while ((nread = atomic(read, cmd, (char *)slp->req, reqsiz)) == reqsiz) {
struct req *p = slp->req;
while ((nread = atomic(read, cmd, (char *)mlp->req, reqsiz)) == reqsiz) {
struct req *p = mlp->req;
for (trecno = 0; trecno < ntrec;
trecno += p->count, p += p->count) {
if (p->dblk) {
blkread(p->dblk, slp->tblock[trecno],
blkread(p->dblk, mlp->tblock[trecno],
p->count * TP_BSIZE);
} else {
if (p->count != 1 || atomic(read, cmd,
(char *)slp->tblock[trecno],
(char *)mlp->tblock[trecno],
TP_BSIZE) != TP_BSIZE)
quit("master/slave protocol botched.\n");
quit("master/minion protocol botched.\n");
}
}
if (setjmp(jmpbuf) == 0) {
@ -816,14 +816,14 @@ doslave(int cmd, int slave_number)
while (eot_count < 10 && size < writesize) {
#ifdef RDUMP
if (host)
wrote = rmtwrite(slp->tblock[0]+size,
wrote = rmtwrite(mlp->tblock[0]+size,
writesize-size);
else
#endif
wrote = write(tapefd, slp->tblock[0]+size,
wrote = write(tapefd, mlp->tblock[0]+size,
writesize-size);
#ifdef WRITEDEBUG
printf("slave %d wrote %d\n", slave_number, wrote);
printf("minion %d wrote %d\n", minion_number, wrote);
#endif
if (wrote < 0)
break;
@ -834,8 +834,8 @@ doslave(int cmd, int slave_number)
#ifdef WRITEDEBUG
if (size != writesize)
printf("slave %d only wrote %d out of %d bytes and gave up.\n",
slave_number, size, writesize);
printf("minion %d only wrote %d out of %d bytes and gave up.\n",
minion_number, size, writesize);
#endif
/*
@ -862,10 +862,10 @@ doslave(int cmd, int slave_number)
}
/*
* If partial write, don't want next slave to go.
* If partial write, don't want next minion to go.
* Also jolts him awake.
*/
(void) kill(nextslave, SIGUSR2);
(void) kill(nextminion, SIGUSR2);
}
if (nread != 0)
quit("error reading command pipe: %s\n", strerror(errno));