Module Name: src Committed By: martin Date: Tue Sep 8 12:02:33 UTC 2015
Modified Files: src/sys/dev/dkwedge [netbsd-7]: dk.c Log Message: Pull up following revision(s) (requested by mlelstv in ticket #967): sys/dev/dkwedge/dk.c: revision 1.82 No longer access the disk driver directly. If there is an open wedge, temporarily reference its vnode. Otherwise try to open the block device. To generate a diff of this commit: cvs rdiff -u -r1.72.2.3 -r1.72.2.4 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.72.2.3 src/sys/dev/dkwedge/dk.c:1.72.2.4 --- src/sys/dev/dkwedge/dk.c:1.72.2.3 Tue Dec 9 20:17:16 2014 +++ src/sys/dev/dkwedge/dk.c Tue Sep 8 12:02:33 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: dk.c,v 1.72.2.3 2014/12/09 20:17:16 martin Exp $ */ +/* $NetBSD: dk.c,v 1.72.2.4 2015/09/08 12:02:33 martin 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.72.2.3 2014/12/09 20:17:16 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: dk.c,v 1.72.2.4 2015/09/08 12:02:33 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_dkwedge.h" @@ -102,6 +102,8 @@ static int dkwedge_cleanup_parent(struct static int dkwedge_detach(device_t, int); static void dkwedge_delall1(struct disk *, bool); static int dkwedge_del1(struct dkwedge_info *, int); +static struct vnode *dk_open_parent(dev_t, int); +static int dk_close_parent(struct vnode *, int); static dev_type_open(dkopen); static dev_type_close(dkclose); @@ -946,34 +948,58 @@ dkwedge_read(struct disk *pdk, struct vn { buf_t *bp; int error; + bool isopen; + dev_t bdev; + struct vnode *bdevvp; /* * The kernel cannot read from a character device vnode * as physio() only handles user memory. * - * Determine the corresponding block device and call into - * the driver directly. + * If the block device has already been opened by a wedge + * use that vnode and temporarily bump the open counter. + * + * Otherwise try to open the block device. */ - bp = getiobuf(vp, true); + bdev = devsw_chr2blk(vp->v_rdev); + + mutex_enter(&pdk->dk_rawlock); + if (pdk->dk_rawopens != 0) { + KASSERT(pdk->dk_rawvp != NULL); + isopen = true; + ++pdk->dk_rawopens; + bdevvp = pdk->dk_rawvp; + } else { + isopen = false; + bdevvp = dk_open_parent(bdev, FREAD); + } + mutex_exit(&pdk->dk_rawlock); + + if (bdevvp == NULL) + return EBUSY; + + bp = getiobuf(bdevvp, true); bp->b_flags = B_READ; bp->b_cflags = BC_BUSY; - bp->b_dev = devsw_chr2blk(vp->v_rdev); + bp->b_dev = bdev; bp->b_data = tbuf; bp->b_bufsize = bp->b_bcount = len; bp->b_blkno = blkno; bp->b_cylinder = 0; bp->b_error = 0; - error = bdev_open(bp->b_dev, FREAD, S_IFBLK, curlwp); - if (error) - return error; - - bdev_strategy(bp); + VOP_STRATEGY(bdevvp, bp); error = biowait(bp); putiobuf(bp); - bdev_close(bp->b_dev, FREAD, S_IFBLK, curlwp); + mutex_enter(&pdk->dk_rawlock); + if (isopen) { + --pdk->dk_rawopens; + } else { + dk_close_parent(bdevvp, FREAD); + } + mutex_exit(&pdk->dk_rawlock); return error; } @@ -996,6 +1022,48 @@ dkwedge_lookup(dev_t dev) return (dkwedges[unit]); } +static struct vnode * +dk_open_parent(dev_t dev, int mode) +{ + struct vnode *vp; + int error; + + error = bdevvp(dev, &vp); + if (error) + return NULL; + + error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + if (error) { + vrele(vp); + return NULL; + } + error = VOP_OPEN(vp, mode, NOCRED); + if (error) { + vput(vp); + return NULL; + } + + /* VOP_OPEN() doesn't do this for us. */ + if (mode & FWRITE) { + mutex_enter(vp->v_interlock); + vp->v_writecount++; + mutex_exit(vp->v_interlock); + } + + VOP_UNLOCK(vp); + + return vp; +} + +static int +dk_close_parent(struct vnode *vp, int mode) +{ + int error; + + error = vn_close(vp, mode, NOCRED); + return error; +} + /* * dkopen: [devsw entry point] * @@ -1024,24 +1092,9 @@ 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 = bdevvp(sc->sc_pdev, &vp); - if (error) - goto popen_fail; - error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); - if (error) { - vrele(vp); + vp = dk_open_parent(sc->sc_pdev, FREAD | FWRITE); + if (vp == NULL) goto popen_fail; - } - error = VOP_OPEN(vp, FREAD | FWRITE, NOCRED); - if (error) { - vput(vp); - goto popen_fail; - } - /* VOP_OPEN() doesn't do this for us. */ - mutex_enter(vp->v_interlock); - vp->v_writecount++; - mutex_exit(vp->v_interlock); - VOP_UNLOCK(vp); sc->sc_parent->dk_rawvp = vp; } sc->sc_parent->dk_rawopens++; @@ -1077,8 +1130,7 @@ dklastclose(struct dkwedge_softc *sc) if (doclose) { KASSERT(sc->sc_parent->dk_rawvp != NULL); - error = vn_close(sc->sc_parent->dk_rawvp, - FREAD | FWRITE, NOCRED); + dk_close_parent(sc->sc_parent->dk_rawvp, FREAD | FWRITE); sc->sc_parent->dk_rawvp = NULL; }