summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_disklabel.c
diff options
context:
space:
mode:
authorbde <bde@FreeBSD.org>2002-03-30 16:02:43 +0000
committerbde <bde@FreeBSD.org>2002-03-30 16:02:43 +0000
commit2f7ae9b73937f5da2e6cdcd3158a0213362e9c74 (patch)
tree84c5bdc9a9c91fae12fe65485a4465be0578aaf6 /sys/kern/subr_disklabel.c
parenta9b7c63b296732c9bc02f0f35e74d6c6d58165c3 (diff)
downloadFreeBSD-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.
Diffstat (limited to 'sys/kern/subr_disklabel.c')
-rw-r--r--sys/kern/subr_disklabel.c6
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));
OpenPOWER on IntegriCloud