Dump is hard-wired to believe that it can read disks on

1024-byte boundaries. For many years this was a reasonable
assumption. However, in recent years we have begun seeing
devices with 2048-byte sectors. These devices return errors
when dump tries to read starting in the middle of a sector
or when it tries to read only the first half of a sector.
Rather than change the native block size used by dump (and
thus create an incompatible dump format), this fix checks
for transfer requests that start and/or end on a non-sector
boundary. When such a read is detected, the new code reads
the entire sector and copies out just the part that dump
needs.

Reviewed by:	Poul-Henning Kamp <phk@critter.freebsd.dk>
Approved by:	re (John Baldwin <jhb@FreeBSD.org>)
Sponsored by:   DARPA & NAI Labs.
This commit is contained in:
mckusick 2003-05-07 18:27:09 +00:00
parent 1d8f58ae39
commit 2e1c393dfc
2 changed files with 48 additions and 4 deletions

View File

@ -388,6 +388,7 @@ main(int argc, char *argv[])
sync();
sblock = (struct fs *)sblock_buf;
for (i = 0; sblock_try[i] != -1; i++) {
sblock->fs_fsize = SBLOCKSIZE; /* needed in bread */
bread(sblock_try[i] >> dev_bshift, (char *) sblock, SBLOCKSIZE);
if ((sblock->fs_magic == FS_UFS1_MAGIC ||
(sblock->fs_magic == FS_UFS2_MAGIC &&

View File

@ -736,12 +736,55 @@ int breaderrors = 0;
void
bread(ufs2_daddr_t blkno, char *buf, int size)
{
int cnt, i;
int secsize, bytes, resid, xfer, base, cnt, i;
static char *tmpbuf;
off_t offset;
loop:
cnt = cread(diskfd, buf, size, ((off_t)blkno << dev_bshift));
if (cnt == size)
return;
offset = blkno << dev_bshift;
secsize = sblock->fs_fsize;
base = offset % secsize;
resid = size % secsize;
/*
* If the transfer request starts or ends on a non-sector
* boundary, we must read the entire sector and copy out
* just the part that we need.
*/
if (base == 0 && resid == 0) {
cnt = cread(diskfd, buf, size, offset);
if (cnt == size)
return;
} else {
if (tmpbuf == NULL && (tmpbuf = malloc(secsize)) == 0)
quit("buffer malloc failed\n");
xfer = 0;
bytes = size;
if (base != 0) {
cnt = cread(diskfd, tmpbuf, secsize, offset - base);
if (cnt != secsize)
goto bad;
xfer = secsize - base;
offset += xfer;
bytes -= xfer;
resid = bytes % secsize;
memcpy(buf, &tmpbuf[base], xfer);
}
if (bytes >= secsize) {
cnt = cread(diskfd, &buf[xfer], bytes - resid, offset);
if (cnt != bytes - resid)
goto bad;
xfer += cnt;
offset += cnt;
}
if (resid == 0)
return;
cnt = cread(diskfd, tmpbuf, secsize, offset);
if (cnt == secsize) {
memcpy(&buf[xfer], tmpbuf, resid);
return;
}
}
bad:
if (blkno + (size / dev_bsize) > fsbtodb(sblock, sblock->fs_size)) {
/*
* Trying to read the final fragment.