Module Name: src
Committed By: mlelstv
Date: Sat May 22 13:43:50 UTC 2021
Modified Files:
src/sys/dev/dkwedge: dk.c
Log Message:
Handle read-only parent devices.
Currently this only affects xbd(4). Other disk drivers succeed opening
read-only disks as read-write and only fail subsequent write requests.
To generate a diff of this commit:
cvs rdiff -u -r1.102 -r1.103 src/sys/dev/dkwedge/dk.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/dkwedge/dk.c
diff -u src/sys/dev/dkwedge/dk.c:1.102 src/sys/dev/dkwedge/dk.c:1.103
--- src/sys/dev/dkwedge/dk.c:1.102 Tue Oct 6 15:05:54 2020
+++ src/sys/dev/dkwedge/dk.c Sat May 22 13:43:50 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: dk.c,v 1.102 2020/10/06 15:05:54 mlelstv Exp $ */
+/* $NetBSD: dk.c,v 1.103 2021/05/22 13:43:50 mlelstv Exp $ */
/*-
* Copyright (c) 2004, 2005, 2006, 2007 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dk.c,v 1.102 2020/10/06 15:05:54 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dk.c,v 1.103 2021/05/22 13:43:50 mlelstv Exp $");
#ifdef _KERNEL_OPT
#include "opt_dkwedge.h"
@@ -90,6 +90,7 @@ struct dkwedge_softc {
kcondvar_t sc_dkdrn;
u_int sc_iopend; /* I/Os pending */
int sc_flags; /* flags (sc_iolock) */
+ int sc_mode; /* parent open mode */
};
#define DK_F_WAIT_DRAIN 0x0001 /* waiting for I/O to drain */
@@ -1138,6 +1139,7 @@ dkopen(dev_t dev, int flags, int fmt, st
struct dkwedge_softc *sc = dkwedge_lookup(dev);
struct vnode *vp;
int error = 0;
+ int mode;
if (sc == NULL)
return (ENODEV);
@@ -1155,12 +1157,27 @@ dkopen(dev_t dev, int flags, int fmt, st
if (sc->sc_dk.dk_openmask == 0) {
if (sc->sc_parent->dk_rawopens == 0) {
KASSERT(sc->sc_parent->dk_rawvp == NULL);
- error = dk_open_parent(sc->sc_pdev, FREAD | FWRITE, &vp);
+ /*
+ * Try open read-write. If this fails for EROFS
+ * and wedge is read-only, retry to open read-only.
+ */
+ mode = FREAD | FWRITE;
+ error = dk_open_parent(sc->sc_pdev, mode, &vp);
+ if (error == EROFS && (flags & FWRITE) == 0) {
+ mode &= ~FWRITE;
+ error = dk_open_parent(sc->sc_pdev, mode, &vp);
+ }
if (error)
goto popen_fail;
+ /* remember open mode */
+ sc->sc_mode = mode;
sc->sc_parent->dk_rawvp = vp;
}
sc->sc_parent->dk_rawopens++;
+ } else if (flags & ~sc->sc_mode & FWRITE) {
+ /* parent is opened read-only, cannot open read-write */
+ error = EROFS;
+ goto popen_fail;
}
if (fmt == S_IFCHR)
sc->sc_dk.dk_copenmask |= 1;
@@ -1197,7 +1214,7 @@ dklastclose(struct dkwedge_softc *sc)
mutex_exit(&sc->sc_dk.dk_openlock);
if (vp) {
- dk_close_parent(vp, FREAD | FWRITE);
+ dk_close_parent(vp, sc->sc_mode);
}
return error;