aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorPoul-Henning Kamp <phk@FreeBSD.org>2004-11-28 20:57:25 +0000
committerPoul-Henning Kamp <phk@FreeBSD.org>2004-11-28 20:57:25 +0000
commitd4dbba5f8383967093c80fcaa0a82195ebc2f4b1 (patch)
tree5101bc5f3387c4e5965140bbaebd9fcd72f5270e /sys
parentefe39f955cdab3f2fb9d2fabdfcbf9a7e9999800 (diff)
downloadsrc-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.c18
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);