Hello,
I've noticed that the size of softraid(4) disks is one sector too large.
In the following description, the native disk is sd4c (which is of type
RAID), and the corresponding virtual softraid(4) disk will be sd5. I
will assume that sd5 is of discipline CRYPTO, but the problem should be
the same for all disciplines.
The size for sd5 gets eventually stored in struct sr_metadata as
sd_meta->ssdi.ssd_size in function sr_crypto_create
(dev/softraid_crypto.c). Its value gets initially calculated in function
sr_meta_native_probe (dev/softraid.c):
size = DL_GETPSIZE(&label.d_partitions[part]) - SR_DATA_OFFSET;
where SR_DATA_OFFSET = 528
If the size (as shown via disklabel(8)) of the underlying disk sd4c is
'n', the variable 'size' will be calculated as 'n - 528'. However,
according to disklabel(8), the resulting softraid(4) disk sd5c will be
of size 'n - 528 + 1'. I think this is because function scsi_size in
scsi/scsi_base.c returns 'max_addr + 1' where max_addr corresponds to
sd_meta->ssdi.ssd_size.
For example, newfs(8) on /dev/rsd5c tries to write to the last sector of
sd5 (first wtfs call in mkfs.c) which is one sector beyond the native
disk size of sd4. This gives an error if label sd4c was used as the
native device. It results in a kernel panic in case another label of sd4
was used as the underlying native device (i.e., sd4a).
The attached diff fixes the problem for all newly created softraid volumes.
TODO: fixing the problem for existing softraid(4) volumes would require
to update sd_meta->ssdi.ssd_size to the correct size (and probably some
other metadata for consistency).
Best regards
Andreas
Index: softraid.c
===================================================================
RCS file: /usr/cvsync/cvs/src/sys/dev/softraid.c,v
retrieving revision 1.216
diff -u -r1.216 softraid.c
--- softraid.c 6 Nov 2010 23:01:56 -0000 1.216
+++ softraid.c 19 Dec 2010 13:01:14 -0000
@@ -1386,7 +1386,7 @@
goto unwind;
}
- size = DL_GETPSIZE(&label.d_partitions[part]) - SR_DATA_OFFSET;
+ size = DL_GETPSIZE(&label.d_partitions[part]) - SR_DATA_OFFSET - 1;
if (size <= 0) {
DNPRINTF(SR_D_META, "%s: %s partition too small\n", DEVNAME(sc),
devname);