Module Name:    src
Committed By:   mlelstv
Date:           Wed Jun  2 15:59:08 UTC 2021

Modified Files:
        src/sys/dev/dkwedge: dk.c

Log Message:
Copy mode of open wedges with the same parent and validate it.
Remove race on mode value when closing.


To generate a diff of this commit:
cvs rdiff -u -r1.103 -r1.104 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.103 src/sys/dev/dkwedge/dk.c:1.104
--- src/sys/dev/dkwedge/dk.c:1.103	Sat May 22 13:43:50 2021
+++ src/sys/dev/dkwedge/dk.c	Wed Jun  2 15:59:08 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: dk.c,v 1.103 2021/05/22 13:43:50 mlelstv Exp $	*/
+/*	$NetBSD: dk.c,v 1.104 2021/06/02 15:59:08 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.103 2021/05/22 13:43:50 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dk.c,v 1.104 2021/06/02 15:59:08 mlelstv Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_dkwedge.h"
@@ -1137,6 +1137,7 @@ static int
 dkopen(dev_t dev, int flags, int fmt, struct lwp *l)
 {
 	struct dkwedge_softc *sc = dkwedge_lookup(dev);
+	struct dkwedge_softc *nsc;
 	struct vnode *vp;
 	int error = 0;
 	int mode;
@@ -1169,13 +1170,24 @@ dkopen(dev_t dev, int flags, int fmt, st
 			}
 			if (error)
 				goto popen_fail;
-			/* remember open mode */
-			sc->sc_mode = mode;
 			sc->sc_parent->dk_rawvp = vp;
+		} else {
+			/*
+			 * Retrieve mode from an already opened wedge.
+			 */
+			mode = 0;
+			LIST_FOREACH(nsc, &sc->sc_parent->dk_wedges, sc_plink) {
+				if (nsc == sc || nsc->sc_dk.dk_openmask == 0)
+					continue;
+				mode = nsc->sc_mode;
+				break;
+			}
 		}
+		sc->sc_mode = mode;
 		sc->sc_parent->dk_rawopens++;
-	} else if (flags & ~sc->sc_mode & FWRITE) {
-		/* parent is opened read-only, cannot open read-write */
+	}
+	KASSERT(sc->sc_mode != 0);
+	if (flags & ~sc->sc_mode & FWRITE) {
 		error = EROFS;
 		goto popen_fail;
 	}
@@ -1199,7 +1211,9 @@ static int
 dklastclose(struct dkwedge_softc *sc)
 {
 	struct vnode *vp;
-	int error = 0;
+	int error = 0, mode;
+
+	mode = sc->sc_mode;
 
 	vp = NULL;
 	if (sc->sc_parent->dk_rawopens > 0) {
@@ -1214,7 +1228,7 @@ dklastclose(struct dkwedge_softc *sc)
 	mutex_exit(&sc->sc_dk.dk_openlock);
 
 	if (vp) {
-		dk_close_parent(vp, sc->sc_mode);
+		dk_close_parent(vp, mode);
 	}
 
 	return error;
@@ -1248,9 +1262,11 @@ dkclose(dev_t dev, int flags, int fmt, s
 	sc->sc_dk.dk_openmask =
 	    sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask;
 
-	if (sc->sc_dk.dk_openmask == 0)
+	if (sc->sc_dk.dk_openmask == 0) {
 		error = dklastclose(sc); /* releases locks */
-	else {
+		sc->sc_mode = 0;
+	} else {
+		sc->sc_mode = 0;
 		mutex_exit(&sc->sc_parent->dk_rawlock);
 		mutex_exit(&sc->sc_dk.dk_openlock);
 	}

Reply via email to