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;