/* * Collect up the data into tape record sized buffers and output them. */ void ufs2_blksout(daddr_t *blkp, int frags, ino_t ino) { daddr_t *bp; int i, j, count, blks, tbperdb; blks = howmany(frags * sblock->fs_fsize, TP_BSIZE); tbperdb = sblock->fs_bsize >> tp_bshift; for (i = 0; i < blks; i += TP_NINDIR) { if (i + TP_NINDIR > blks) count = blks; else count = i + TP_NINDIR; for (j = i; j < count; j++) if (blkp[j / tbperdb] != 0) spcl.c_addr[j - i] = 1; else spcl.c_addr[j - i] = 0; spcl.c_count = count - i; writeheader(ino); bp = &blkp[i / tbperdb]; for (j = i; j < count; j += tbperdb, bp++) if (*bp != 0) { if (j + tbperdb <= count) dumpblock(*bp, (int)sblock->fs_bsize); else dumpblock(*bp, (count - j) * TP_BSIZE); } spcl.c_type = TS_ADDR; } }
/* * Dump the extended attribute data. If there was room in the file * header, then all we need to do is output the data blocks. If there * was not room in the file header, then an additional TS_ADDR header * is created to hold the attribute data. */ static void writeextdata(union dinode *dp, ino_t ino, int added) { int i, frags, blks, tbperdb, last; ufs2_daddr_t *bp; off_t size; /* * If no extended attributes, there is nothing to do. */ if (spcl.c_extsize == 0) return; /* * If there was no room in the file block for the attributes, * dump them out in a new block, otherwise just dump the data. */ if (added == 0) { if (spcl.c_extsize > NXADDR * sblock->fs_bsize) { frags = NXADDR * sblock->fs_frag; last = 0; } else { frags = howmany(spcl.c_extsize, sblock->fs_fsize); last = 1; } ufs2_blksout(dp, &dp->dp2.di_extb[0], frags, ino, last); } else { if (spcl.c_extsize > NXADDR * sblock->fs_bsize) blks = howmany(NXADDR * sblock->fs_bsize, TP_BSIZE); else blks = howmany(spcl.c_extsize, TP_BSIZE); tbperdb = sblock->fs_bsize >> tp_bshift; for (i = 0; i < blks; i += tbperdb) { bp = &dp->dp2.di_extb[i / tbperdb]; if (*bp != 0) { if (i + tbperdb <= blks) dumpblock(*bp, (int)sblock->fs_bsize); else dumpblock(*bp, (blks - i) * TP_BSIZE); } } } /* * If an indirect block is added for extended attributes, then * di_exti below should be changed to the structure element * that references the extended attribute indirect block. This * definition is here only to make it compile without complaint. */ #define di_exti di_spare[0] /* * If the extended attributes fall into an indirect block, * dump it as well. */ if ((size = spcl.c_extsize - NXADDR * sblock->fs_bsize) > 0) dmpindir(dp, ino, dp->dp2.di_exti, 0, &size); }
/* * Collect up the data into tape record sized buffers and output them. */ static void ufs2_blksout(union dinode *dp, ufs2_daddr_t *blkp, int frags, ino_t ino, int last) { ufs2_daddr_t *bp; int i, j, count, resid, blks, tbperdb, added; static int writingextdata = 0; /* * Calculate the number of TP_BSIZE blocks to be dumped. * For filesystems with a fragment size bigger than TP_BSIZE, * only part of the final fragment may need to be dumped. */ blks = howmany(frags * sblock->fs_fsize, TP_BSIZE); if (last) { resid = howmany(fragoff(sblock, dp->dp2.di_size), TP_BSIZE); if (resid > 0) blks -= howmany(sblock->fs_fsize, TP_BSIZE) - resid; } tbperdb = sblock->fs_bsize >> tp_bshift; for (i = 0; i < blks; i += TP_NINDIR) { if (i + TP_NINDIR > blks) count = blks; else count = i + TP_NINDIR; for (j = i; j < count; j++) if (blkp[j / tbperdb] != 0) spcl.c_addr[j - i] = 1; else spcl.c_addr[j - i] = 0; spcl.c_count = count - i; if (last && count == blks && !writingextdata) added = appendextdata(dp); writeheader(ino); bp = &blkp[i / tbperdb]; for (j = i; j < count; j += tbperdb, bp++) if (*bp != 0) { if (j + tbperdb <= count) dumpblock(*bp, (int)sblock->fs_bsize); else dumpblock(*bp, (count - j) * TP_BSIZE); } spcl.c_type = TS_ADDR; spcl.c_count = 0; if (last && count == blks && !writingextdata) { writingextdata = 1; writeextdata(dp, ino, added); writingextdata = 0; } } }
/* * process to copy dump blocks from * cache to worm. it runs flat out when * it gets work, but only looks for * work every 10 seconds. */ void wormcopy(void *) { int f, dorecalc = 1; Timet dt, t = 0, nddate = 0, ntoytime = 0; Filsys *fs; for (;;) { if (dorecalc) { dorecalc = 0; t = time(nil); nddate = nextdump(t); /* chatters */ ntoytime = time(nil); } dt = time(nil) - t; if(dt < 0 || dt > MINUTE(100)) { if(dt < 0) print("time went back\n"); else print("time jumped ahead\n"); dorecalc = 1; continue; } t += dt; f = 0; if(t > ntoytime) ntoytime = time(nil) + HOUR(1); else if(t > nddate) { if(!conf.nodump) { print("automatic dump %T\n", t); for(fs=filsys; fs->name; fs++) if(fs->dev->type == Devcw) cfsdump(fs); } dorecalc = 1; } else { rlock(&mainlock); for(fs=filsys; fs->name; fs++) if(fs->dev->type == Devcw) f |= dumpblock(fs->dev); runlock(&mainlock); if(!f) delay(10000); wormprobe(); } } }
static int readblks(int fd, size_t alignment) { __uint64_t offset; char *buffer, *tmp; unsigned int xfer, block, i; int err=0; if (alloconly) return 0; xfer = READ_XFER*blocksize; if (posix_memalign((void **) &buffer, alignment, xfer)) { perror("malloc"); exit(1); } memset(buffer, 0, xfer); if (verbose) printf("\n"); if (lseek64(fd, fileoffset, SEEK_SET) < 0) { perror("lseek"); exit(1); } block = 0; offset = 0; while (offset < filesize) { if ((i = read(fd, buffer, xfer) < xfer)) { if (i < 2) break; perror("read"); exit(1); } tmp = buffer; for (i = 0; i < READ_XFER; i++) { __uint64_t want; __uint64_t first; __uint64_t second; if (verbose && ((block % 100) == 0)) { printf("+"); fflush(stdout); } want = BITVAL(valid, block) ? offset : 0; first = *(__uint64_t *) tmp; second = *(__uint64_t *) (tmp + 256); if (first != want || second != want) { printf("mismatched data at offset=0x%" PRIx64 ", expected 0x%" PRIx64 ", got 0x%" PRIx64 " and 0x%" PRIx64 "\n", fileoffset + offset, want, first, second); err++; } if (verbose > 2) { printf("block %d blocksize %d\n", block, blocksize); dumpblock((int *)tmp, fileoffset + offset, blocksize); } block++; offset += blocksize; tmp += blocksize; } } if (verbose) printf("\n"); free(buffer); return err; }