DF-2831 / fixinst.diff
--- subr_diskslice.c.orig +++ subr_diskslice.c @@ -769,6 +769,8 @@ ssp = *sspp; dev->si_bsize_phys = info->d_media_blksize; slice = dkslice(dev); + if (slice >= ssp->dss_nslices) + return (EINVAL); part = dkpart(dev); sp = &ssp->dss_slices[slice]; dssetmask(sp, part); @@ -852,20 +854,33 @@ if (dev_dopen(dev, FREAD, S_IFCHR, proc0.p_ucred, NULL, NULL) != 0) { + kprintf("DF2831 -1 openfail %s\n", devtoname(dev)); return (-1); } dev_dclose(dev, FREAD, S_IFCHR, NULL); ssp = *sspp; } + /* + * The re-open above may have serialized with a reprobe; the + * reloaded (or original) ssp must be revalidated before use. + */ + if (slice >= ssp->dss_nslices) { + kprintf("DF2831 -1 nslices %s slice=%d ns=%d\n", + devtoname(dev), slice, ssp->dss_nslices); + return (-1); + } lp = ssp->dss_slices[slice].ds_label; if (part == WHOLE_SLICE_PART) { blocks = ssp->dss_slices[slice].ds_size; } else if (lp.opaque == NULL) { + kprintf("DF2831 blocks=-1 nolabel %s\n", devtoname(dev)); blocks = (u_int64_t)-1; } else { ops = ssp->dss_slices[slice].ds_ops; - if (ops->op_getpartbounds(ssp, lp, part, &start, &blocks)) + if (ops->op_getpartbounds(ssp, lp, part, &start, &blocks)) { + kprintf("DF2831 -1 bounds %s\n", devtoname(dev)); return (-1); + } } return ((int64_t)blocks); } --- subr_disk.c.orig +++ subr_disk.c @@ -1265,10 +1265,23 @@ if (dp == NULL) return(ENODEV); + /* + * dssize() walks dp->d_slice (and the per-slice disklabel) with no + * internal serialization while disk_probe()/disk_msg_core replace + * and dsgone() those structures under ds_token (DF-2831). Run the + * whole walk under ds_token like diskopen/diskclose/diskioctl do. + * Token acquisition is recursive for the dev_dopen() path inside + * dssize() (diskopen takes ds_token itself), and blocking inside + * the token (sync reprobe messages) releases/reacquires it. + */ + lwkt_gettoken(&ds_token); ap->a_result = dssize(dev, &dp->d_slice); + lwkt_reltoken(&ds_token); if ((ap->a_result == -1) && (dp->d_info.d_dsflags & DSO_RAWPSIZE)) { + kprintf("DF2831 RAWPSIZE fallback %s -> raw whole-disk size\n", + devtoname(dev)); ap->a_head.a_dev = dp->d_rawdev; return dev_doperate(&ap->a_head); } |