diff options
author | bde <bde@FreeBSD.org> | 1995-05-08 16:24:08 +0000 |
---|---|---|
committer | bde <bde@FreeBSD.org> | 1995-05-08 16:24:08 +0000 |
commit | ca5a771ab4feb790451ce6b6df11c4e337429d00 (patch) | |
tree | 58f74f520482b632c77312db3ae2e4386c4a11ac | |
parent | 7d2ee025c4a44816fde0015b84f73d374b27a3c0 (diff) | |
download | FreeBSD-src-ca5a771ab4feb790451ce6b6df11c4e337429d00.zip FreeBSD-src-ca5a771ab4feb790451ce6b6df11c4e337429d00.tar.gz |
Fix reopening of open subdevices for DIOCSYNCSLICEINFO:
Reopen the bdev for the raw partition and not the cdev if only the bdev
was open.
Don't use a bogus limit for the number of partitions to possibly reopen
(bug found by Julian).
Add function dssize() to help fix wdsize() and sdsize(). The slice
layer knows more about (un)open partitions and partition sizes than
the driver layer.
-rw-r--r-- | sys/kern/subr_diskslice.c | 53 |
1 files changed, 45 insertions, 8 deletions
diff --git a/sys/kern/subr_diskslice.c b/sys/kern/subr_diskslice.c index 0362851..0b6bf03 100644 --- a/sys/kern/subr_diskslice.c +++ b/sys/kern/subr_diskslice.c @@ -43,7 +43,7 @@ * from: wd.c,v 1.55 1994/10/22 01:57:12 phk Exp $ * from: @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91 * from: ufs_disksubr.c,v 1.8 1994/06/07 01:21:39 phk Exp $ - * $Id: subr_diskslice.c,v 1.10 1995/04/24 17:06:59 bde Exp $ + * $Id: subr_diskslice.c,v 1.11 1995/04/30 15:16:02 bde Exp $ */ #include <sys/param.h> @@ -385,20 +385,28 @@ dsioctl(dname, dev, cmd, data, flags, sspp, strat, setgeom) *sspp = NULL; lp = malloc(sizeof *lp, M_DEVBUF, M_WAITOK); *lp = *ssp->dss_slices[WHOLE_DISK_SLICE].ds_label; - error = dsopen(dname, dev, S_IFCHR, sspp, lp, strat, setgeom); + error = dsopen(dname, dev, + ssp->dss_slices[WHOLE_DISK_SLICE].ds_copenmask + & (1 << RAW_PART) ? S_IFCHR : S_IFBLK, + sspp, lp, strat, setgeom); if (error != 0) { free(lp, M_DEVBUF); *sspp = ssp; return (error); } + /* + * Reopen everything. This is a no-op except in the "force" + * case and when the raw bdev and cdev are both open. Abort + * if anything fails. + */ for (slice = 0; slice < ssp->dss_nslices; slice++) { u_char openmask; int part; - openmask = ssp->dss_slices[slice].ds_bopenmask; - for (part = 0; part < ssp->dss_nslices; part++) { - if (!(openmask & (1 << part))) + for (openmask = ssp->dss_slices[slice].ds_bopenmask, + part = 0; openmask; openmask >>= 1, part++) { + if (!(openmask & 1)) continue; error = dsopen(dname, dkmodslice(dkmodpart(dev, part), @@ -411,9 +419,9 @@ dsioctl(dname, dev, cmd, data, flags, sspp, strat, setgeom) return (EBUSY); } } - openmask = ssp->dss_slices[slice].ds_copenmask; - for (part = 0; part < ssp->dss_nslices; part++) { - if (!(openmask & (1 << part))) + for (openmask = ssp->dss_slices[slice].ds_copenmask, + part = 0; openmask; openmask >>= 1, part++) { + if (!(openmask & 1)) continue; error = dsopen(dname, dkmodslice(dkmodpart(dev, part), @@ -427,6 +435,7 @@ dsioctl(dname, dev, cmd, data, flags, sspp, strat, setgeom) } } } + free(lp, M_DEVBUF); dsgone(&ssp); return (0); @@ -678,6 +687,34 @@ out: return (0); } +int +dssize(dev, sspp, dopen, dclose) + dev_t dev; + struct diskslices **sspp; + d_open_t dopen; + d_close_t dclose; +{ + struct disklabel *lp; + int part; + int slice; + struct diskslices *ssp; + + slice = dkslice(dev); + part = dkpart(dev); + ssp = *sspp; + if (ssp == NULL || slice >= ssp->dss_nslices + || !(ssp->dss_slices[slice].ds_bopenmask & (1 << part))) { + if (dopen(dev, FREAD, S_IFBLK, (struct proc *)NULL) != 0) + return (-1); + dclose(dev, FREAD, S_IFBLK, (struct proc *)NULL); + ssp = *sspp; + } + lp = ssp->dss_slices[slice].ds_label; + if (lp == NULL) + return (-1); + return ((int)lp->d_partitions[part].p_size); +} + static char * fixlabel(sname, sp, lp, writeflag) char *sname; |