diff options
author | bde <bde@FreeBSD.org> | 2002-03-30 16:02:43 +0000 |
---|---|---|
committer | bde <bde@FreeBSD.org> | 2002-03-30 16:02:43 +0000 |
commit | 2f7ae9b73937f5da2e6cdcd3158a0213362e9c74 (patch) | |
tree | 84c5bdc9a9c91fae12fe65485a4465be0578aaf6 | |
parent | a9b7c63b296732c9bc02f0f35e74d6c6d58165c3 (diff) | |
download | FreeBSD-src-2f7ae9b73937f5da2e6cdcd3158a0213362e9c74.zip FreeBSD-src-2f7ae9b73937f5da2e6cdcd3158a0213362e9c74.tar.gz |
Fixed handling of short reads in readdisklabel() and writedisklabel().
These functions use DEV_STRATEGY() which can easily return a short
count (with no error) for reads near EOF. EOF happens for "disks" too
small to contain a label sector (mainly for empty slices). The functions
didn't understand this at all, and looked for labels in the garbage
in the buffer beyond what DEV_STRATEGY() returned. The recent UMA
changes combined with my local changes and configuration resulted in
the garbage often containing a valid but garbage label left over from
a previous call.
Bugs in EOF handling in -current limited the problem to "disks" with
size precisely LABELSECTOR sectors. LABELSECTOR happens to be a very
unusual "disk" size since it is only 0 for non-i386 arches that don't
usually have disks with DOS MBRs.
-rw-r--r-- | sys/kern/subr_disklabel.c | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/sys/kern/subr_disklabel.c b/sys/kern/subr_disklabel.c index 05339cb..d69e906 100644 --- a/sys/kern/subr_disklabel.c +++ b/sys/kern/subr_disklabel.c @@ -219,6 +219,8 @@ readdisklabel(dev, lp) DEV_STRATEGY(bp, 1); if (bufwait(bp)) msg = "I/O error"; + else if (bp->b_resid != 0) + msg = "disk too small for a label"; else for (dlp = (struct disklabel *)bp->b_data; dlp <= (struct disklabel *)((char *)bp->b_data + lp->d_secsize - sizeof(*dlp)); @@ -323,6 +325,10 @@ writedisklabel(dev, lp) error = bufwait(bp); if (error) goto done; + if (bp->b_resid != 0) { + error = ENOSPC; + goto done; + } for (dlp = (struct disklabel *)bp->b_data; dlp <= (struct disklabel *) ((char *)bp->b_data + lp->d_secsize - sizeof(*dlp)); |