Changeset View
Changeset View
Standalone View
Standalone View
sbin/dump/tape.c
Context not available. | |||||
static int atomic(ssize_t (*)(), int, char *, int); | static int atomic(ssize_t (*)(), int, char *, int); | ||||
static void worker(int, int); | static void worker(int, int); | ||||
static void enworker(void); | static void create_workers(void); | ||||
static void flushtape(void); | static void flushtape(void); | ||||
static void killall(void); | static void killall(void); | ||||
static void rollforward(void); | static void rollforward(void); | ||||
Context not available. | |||||
char (*tblock)[TP_BSIZE]; /* buffer for data blocks */ | char (*tblock)[TP_BSIZE]; /* buffer for data blocks */ | ||||
struct req *req; /* buffer for requests */ | struct req *req; /* buffer for requests */ | ||||
} workers[WORKERS+1]; | } workers[WORKERS+1]; | ||||
static struct worker *mlp; | static struct worker *wp; | ||||
static char (*nextblock)[TP_BSIZE]; | static char (*nextblock)[TP_BSIZE]; | ||||
Context not available. | |||||
(((long)&buf[ntrec + 1] + pgoff) &~ pgoff); | (((long)&buf[ntrec + 1] + pgoff) &~ pgoff); | ||||
workers[i].req = (struct req *)workers[i].tblock - ntrec - 1; | workers[i].req = (struct req *)workers[i].tblock - ntrec - 1; | ||||
} | } | ||||
mlp = &workers[0]; | wp = &workers[0]; | ||||
mlp->count = 1; | wp->count = 1; | ||||
mlp->tapea = 0; | wp->tapea = 0; | ||||
mlp->firstrec = 0; | wp->firstrec = 0; | ||||
nextblock = mlp->tblock; | nextblock = wp->tblock; | ||||
return(1); | return(1); | ||||
} | } | ||||
Context not available. | |||||
writerec(char *dp, int isspcl) | writerec(char *dp, int isspcl) | ||||
{ | { | ||||
mlp->req[trecno].dblk = (ufs2_daddr_t)0; | wp->req[trecno].dblk = (ufs2_daddr_t)0; | ||||
mlp->req[trecno].count = 1; | wp->req[trecno].count = 1; | ||||
/* Can't do a structure assignment due to alignment problems */ | /* Can't do a structure assignment due to alignment problems */ | ||||
bcopy(dp, *(nextblock)++, sizeof (union u_spcl)); | bcopy(dp, *(nextblock)++, sizeof (union u_spcl)); | ||||
if (isspcl) | if (isspcl) | ||||
Context not available. | |||||
dblkno = fsbtodb(sblock, blkno); | dblkno = fsbtodb(sblock, blkno); | ||||
tpblks = size >> tp_bshift; | tpblks = size >> tp_bshift; | ||||
while ((avail = MIN(tpblks, ntrec - trecno)) > 0) { | while ((avail = MIN(tpblks, ntrec - trecno)) > 0) { | ||||
mlp->req[trecno].dblk = dblkno; | wp->req[trecno].dblk = dblkno; | ||||
mlp->req[trecno].count = avail; | wp->req[trecno].count = avail; | ||||
trecno += avail; | trecno += avail; | ||||
spcl.c_tapea += avail; | spcl.c_tapea += avail; | ||||
if (trecno >= ntrec) | if (trecno >= ntrec) | ||||
Context not available. | |||||
int i, blks, got; | int i, blks, got; | ||||
int64_t lastfirstrec; | int64_t lastfirstrec; | ||||
int siz = (char *)nextblock - (char *)mlp->req; | int siz = (char *)nextblock - (char *)wp->req; | ||||
mlp->req[trecno].count = 0; /* Sentinel */ | wp->req[trecno].count = 0; /* Sentinel */ | ||||
if (atomic(write, mlp->fd, (char *)mlp->req, siz) != siz) | if (atomic(write, wp->fd, (char *)wp->req, siz) != siz) | ||||
quit("error writing command pipe: %s\n", strerror(errno)); | quit("error writing command pipe: %s\n", strerror(errno)); | ||||
mlp->sent = 1; /* we sent a request, read the response later */ | wp->sent = 1; /* we sent a request, read the response later */ | ||||
lastfirstrec = mlp->firstrec; | lastfirstrec = wp->firstrec; | ||||
if (++mlp >= &workers[WORKERS]) | if (++wp >= &workers[WORKERS]) | ||||
mlp = &workers[0]; | wp = &workers[0]; | ||||
/* Read results back from next worker */ | /* Read results back from next worker */ | ||||
if (mlp->sent) { | if (wp->sent) { | ||||
if (atomic(read, mlp->fd, (char *)&got, sizeof got) | if (atomic(read, wp->fd, (char *)&got, sizeof got) | ||||
!= sizeof got) { | != sizeof got) { | ||||
perror(" DUMP: error reading command pipe in master"); | perror(" DUMP: error reading command pipe in master"); | ||||
dumpabort(0); | dumpabort(0); | ||||
} | } | ||||
mlp->sent = 0; | wp->sent = 0; | ||||
/* Check for end of tape */ | /* Check for end of tape */ | ||||
if (got < writesize) { | if (got < writesize) { | ||||
Context not available. | |||||
if (spcl.c_addr[i] != 0) | if (spcl.c_addr[i] != 0) | ||||
blks++; | blks++; | ||||
} | } | ||||
mlp->count = lastspclrec + blks + 1 - spcl.c_tapea; | wp->count = lastspclrec + blks + 1 - spcl.c_tapea; | ||||
mlp->tapea = spcl.c_tapea; | wp->tapea = spcl.c_tapea; | ||||
mlp->firstrec = lastfirstrec + ntrec; | wp->firstrec = lastfirstrec + ntrec; | ||||
mlp->inode = curino; | wp->inode = curino; | ||||
nextblock = mlp->tblock; | nextblock = wp->tblock; | ||||
trecno = 0; | trecno = 0; | ||||
asize += tenths; | asize += tenths; | ||||
blockswritten += ntrec; | blockswritten += ntrec; | ||||
Context not available. | |||||
rollforward(void) | rollforward(void) | ||||
{ | { | ||||
struct req *p, *q, *prev; | struct req *p, *q, *prev; | ||||
struct worker *tmlp; | struct worker *twp; | ||||
int i, size, got; | int i, size, got; | ||||
int64_t savedtapea; | int64_t savedtapea; | ||||
union u_spcl *ntb, *otb; | union u_spcl *ntb, *otb; | ||||
tmlp = &workers[WORKERS]; | twp = &workers[WORKERS]; | ||||
ntb = (union u_spcl *)tmlp->tblock[1]; | ntb = (union u_spcl *)twp->tblock[1]; | ||||
/* | /* | ||||
* Each of the N workers should have requests that need to | * Each of the N workers should have requests that need to | ||||
Context not available. | |||||
* each worker in turn. | * each worker in turn. | ||||
*/ | */ | ||||
for (i = 0; i < WORKERS; i++) { | for (i = 0; i < WORKERS; i++) { | ||||
q = &tmlp->req[1]; | q = &twp->req[1]; | ||||
otb = (union u_spcl *)mlp->tblock; | otb = (union u_spcl *)wp->tblock; | ||||
/* | /* | ||||
* For each request in the current worker, copy it to tmlp. | * For each request in the current worker, copy it to twp. | ||||
*/ | */ | ||||
prev = NULL; | prev = NULL; | ||||
for (p = mlp->req; p->count > 0; p += p->count) { | for (p = wp->req; p->count > 0; p += p->count) { | ||||
*q = *p; | *q = *p; | ||||
if (p->dblk == 0) | if (p->dblk == 0) | ||||
*ntb++ = *otb++; /* copy the datablock also */ | *ntb++ = *otb++; /* copy the datablock also */ | ||||
Context not available. | |||||
ntb--; | ntb--; | ||||
q -= 1; | q -= 1; | ||||
q->count = 0; | q->count = 0; | ||||
q = &tmlp->req[0]; | q = &twp->req[0]; | ||||
if (i == 0) { | if (i == 0) { | ||||
q->dblk = 0; | q->dblk = 0; | ||||
q->count = 1; | q->count = 1; | ||||
trecno = 0; | trecno = 0; | ||||
nextblock = tmlp->tblock; | nextblock = twp->tblock; | ||||
savedtapea = spcl.c_tapea; | savedtapea = spcl.c_tapea; | ||||
spcl.c_tapea = mlp->tapea; | spcl.c_tapea = wp->tapea; | ||||
startnewtape(0); | startnewtape(0); | ||||
spcl.c_tapea = savedtapea; | spcl.c_tapea = savedtapea; | ||||
lastspclrec = savedtapea - 1; | lastspclrec = savedtapea - 1; | ||||
} | } | ||||
size = (char *)ntb - (char *)q; | size = (char *)ntb - (char *)q; | ||||
if (atomic(write, mlp->fd, (char *)q, size) != size) { | if (atomic(write, wp->fd, (char *)q, size) != size) { | ||||
perror(" DUMP: error writing command pipe"); | perror(" DUMP: error writing command pipe"); | ||||
dumpabort(0); | dumpabort(0); | ||||
} | } | ||||
mlp->sent = 1; | wp->sent = 1; | ||||
if (++mlp >= &workers[WORKERS]) | if (++wp >= &workers[WORKERS]) | ||||
mlp = &workers[0]; | wp = &workers[0]; | ||||
q->count = 1; | q->count = 1; | ||||
Context not available. | |||||
*/ | */ | ||||
q->dblk = prev->dblk + | q->dblk = prev->dblk + | ||||
prev->count * (TP_BSIZE / DEV_BSIZE); | prev->count * (TP_BSIZE / DEV_BSIZE); | ||||
ntb = (union u_spcl *)tmlp->tblock; | ntb = (union u_spcl *)twp->tblock; | ||||
} else { | } else { | ||||
/* | /* | ||||
* It wasn't a disk block. Copy the data to its | * It wasn't a disk block. Copy the data to its | ||||
Context not available. | |||||
* new location in the buffer. | * new location in the buffer. | ||||
*/ | */ | ||||
q->dblk = 0; | q->dblk = 0; | ||||
*((union u_spcl *)tmlp->tblock) = *ntb; | *((union u_spcl *)twp->tblock) = *ntb; | ||||
ntb = (union u_spcl *)tmlp->tblock[1]; | ntb = (union u_spcl *)twp->tblock[1]; | ||||
} | } | ||||
} | } | ||||
mlp->req[0] = *q; | wp->req[0] = *q; | ||||
nextblock = mlp->tblock; | nextblock = wp->tblock; | ||||
if (q->dblk == 0) | if (q->dblk == 0) | ||||
nextblock++; | nextblock++; | ||||
trecno = 1; | trecno = 1; | ||||
Context not available. | |||||
* Clear the first workers' response. One hopes that it | * Clear the first workers' response. One hopes that it | ||||
* worked ok, otherwise the tape is much too short! | * worked ok, otherwise the tape is much too short! | ||||
*/ | */ | ||||
if (mlp->sent) { | if (wp->sent) { | ||||
if (atomic(read, mlp->fd, (char *)&got, sizeof got) | if (atomic(read, wp->fd, (char *)&got, sizeof got) | ||||
!= sizeof got) { | != sizeof got) { | ||||
perror(" DUMP: error reading command pipe in master"); | perror(" DUMP: error reading command pipe in master"); | ||||
dumpabort(0); | dumpabort(0); | ||||
} | } | ||||
mlp->sent = 0; | wp->sent = 0; | ||||
if (got != writesize) { | if (got != writesize) { | ||||
quit("EOT detected at start of the tape!\n"); | quit("EOT detected at start of the tape!\n"); | ||||
Context not available. | |||||
} | } | ||||
} | } | ||||
enworker(); /* Share open tape file descriptor with workers */ | create_workers(); /* Share open tape file descriptor with workers */ | ||||
if (popenout) | if (popenout) | ||||
close(tapefd); /* Give up our copy of it. */ | close(tapefd); /* Give up our copy of it. */ | ||||
signal(SIGINFO, infosch); | signal(SIGINFO, infosch); | ||||
Context not available. | |||||
blocksthisvol = 0; | blocksthisvol = 0; | ||||
if (top) | if (top) | ||||
newtape++; /* new tape signal */ | newtape++; /* new tape signal */ | ||||
spcl.c_count = mlp->count; | spcl.c_count = wp->count; | ||||
/* | /* | ||||
* measure firstrec in TP_BSIZE units since restore doesn't | * measure firstrec in TP_BSIZE units since restore doesn't | ||||
* know the correct ntrec value... | * know the correct ntrec value... | ||||
*/ | */ | ||||
spcl.c_firstrec = mlp->firstrec; | spcl.c_firstrec = wp->firstrec; | ||||
spcl.c_volume++; | spcl.c_volume++; | ||||
spcl.c_type = TS_TAPE; | spcl.c_type = TS_TAPE; | ||||
writeheader((ino_t)mlp->inode); | writeheader((ino_t)wp->inode); | ||||
if (tapeno > 1) | if (tapeno > 1) | ||||
msg("Volume %d begins with blocks from inode %d\n", | msg("Volume %d begins with blocks from inode %d\n", | ||||
tapeno, mlp->inode); | tapeno, wp->inode); | ||||
} | } | ||||
} | } | ||||
Context not available. | |||||
} | } | ||||
void | void | ||||
enworker(void) | create_workers(void) | ||||
{ | { | ||||
int cmd[2]; | int cmd[2]; | ||||
int i, j; | int i, j; | ||||
Context not available. | |||||
signal(SIGUSR2, proceed); /* Worker sends SIGUSR2 to next worker */ | signal(SIGUSR2, proceed); /* Worker sends SIGUSR2 to next worker */ | ||||
for (i = 0; i < WORKERS; i++) { | for (i = 0; i < WORKERS; i++) { | ||||
if (i == mlp - &workers[0]) { | if (i == wp - &workers[0]) { | ||||
caught = 1; | caught = 1; | ||||
} else { | } else { | ||||
caught = 0; | caught = 0; | ||||
Context not available. | |||||
/* | /* | ||||
* Get list of blocks to dump, read the blocks into tape buffer | * Get list of blocks to dump, read the blocks into tape buffer | ||||
*/ | */ | ||||
while ((nread = atomic(read, cmd, (char *)mlp->req, reqsiz)) == reqsiz) { | while ((nread = atomic(read, cmd, (char *)wp->req, reqsiz)) == reqsiz) { | ||||
struct req *p = mlp->req; | struct req *p = wp->req; | ||||
for (trecno = 0; trecno < ntrec; | for (trecno = 0; trecno < ntrec; | ||||
trecno += p->count, p += p->count) { | trecno += p->count, p += p->count) { | ||||
if (p->dblk) { | if (p->dblk) { | ||||
blkread(p->dblk, mlp->tblock[trecno], | blkread(p->dblk, wp->tblock[trecno], | ||||
p->count * TP_BSIZE); | p->count * TP_BSIZE); | ||||
} else { | } else { | ||||
if (p->count != 1 || atomic(read, cmd, | if (p->count != 1 || atomic(read, cmd, | ||||
(char *)mlp->tblock[trecno], | (char *)wp->tblock[trecno], | ||||
TP_BSIZE) != TP_BSIZE) | TP_BSIZE) != TP_BSIZE) | ||||
quit("master/worker protocol botched.\n"); | quit("master/worker protocol botched.\n"); | ||||
} | } | ||||
Context not available. | |||||
while (eot_count < 10 && size < writesize) { | while (eot_count < 10 && size < writesize) { | ||||
#ifdef RDUMP | #ifdef RDUMP | ||||
if (host) | if (host) | ||||
wrote = rmtwrite(mlp->tblock[0]+size, | wrote = rmtwrite(wp->tblock[0]+size, | ||||
writesize-size); | writesize-size); | ||||
else | else | ||||
#endif | #endif | ||||
wrote = write(tapefd, mlp->tblock[0]+size, | wrote = write(tapefd, wp->tblock[0]+size, | ||||
writesize-size); | writesize-size); | ||||
#ifdef WRITEDEBUG | #ifdef WRITEDEBUG | ||||
printf("worker %d wrote %d\n", worker_number, wrote); | printf("worker %d wrote %d\n", worker_number, wrote); | ||||
Context not available. |