diff options
author | Poul-Henning Kamp <phk@FreeBSD.org> | 2004-11-28 20:57:25 +0000 |
---|---|---|
committer | Poul-Henning Kamp <phk@FreeBSD.org> | 2004-11-28 20:57:25 +0000 |
commit | d4dbba5f8383967093c80fcaa0a82195ebc2f4b1 (patch) | |
tree | 5101bc5f3387c4e5965140bbaebd9fcd72f5270e /sys | |
parent | efe39f955cdab3f2fb9d2fabdfcbf9a7e9999800 (diff) | |
download | src-d4dbba5f8383967093c80fcaa0a82195ebc2f4b1.tar.gz src-d4dbba5f8383967093c80fcaa0a82195ebc2f4b1.zip |
Fix a long standing bug in geom_mbr which is only now exposed by the
correct open/close behaviour of filesystems:
When an ioctl to modify the MBR arrives, we cannot take for granted that
we have the consumer open.
The symptom is that one cannot run 'boot0cfg -s2 /dev/ad0' in single-user
mode because / is the only open partition in only open r1w0e1.
If it is not, we attempt to increase the write count by one and
decrease it again afterwards.
Presumably most if not all other slices suffer from the same problem.
Notes
Notes:
svn path=/head/; revision=138171
Diffstat (limited to 'sys')
-rw-r--r-- | sys/geom/geom_mbr.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/sys/geom/geom_mbr.c b/sys/geom/geom_mbr.c index 3f8daef8f4e6..2e1975742435 100644 --- a/sys/geom/geom_mbr.c +++ b/sys/geom/geom_mbr.c @@ -159,20 +159,30 @@ g_mbr_ioctl(struct g_provider *pp, u_long cmd, void *data, struct thread *td) struct g_mbr_softc *ms; struct g_slicer *gsp; struct g_consumer *cp; - int error; + int error, opened; gp = pp->geom; gsp = gp->softc; ms = gsp->softc; + opened = 0; + error = 0; switch(cmd) { case DIOCSMBR: { DROP_GIANT(); g_topology_lock(); - /* Validate and modify our slicer instance to match. */ - error = g_mbr_modify(gp, ms, data); cp = LIST_FIRST(&gp->consumer); - error = g_write_data(cp, 0, data, 512); + if (cp->acw == 0) { + error = g_access(cp, 0, 1, 0); + if (error == 0) + opened = 1; + } + if (!error) + error = g_mbr_modify(gp, ms, data); + if (!error) + error = g_write_data(cp, 0, data, 512); + if (opened) + g_access(cp, 0, -1 , 0); g_topology_unlock(); PICKUP_GIANT(); return(error); |