summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authordyoung <dyoung@NetBSD.org>2007-06-09 02:26:27 +0000
committerdyoung <dyoung@NetBSD.org>2007-06-09 02:26:27 +0000
commitf6eded5ef76b021f1d0d6678aa90e461e9af3092 (patch)
tree94461e44cd1aad7c687e81fe0d093e094c1720f1 /sys/dev
parent48beaaeef091fc80a9b5485ad4e31a444e42f2db (diff)
Fix two bugs:
1 In dkopen(), do not leave dk_rawopens > 0 if the open ultimately failed for some reason. 2 Add a dkdump() implementation by Martin Husemann for writing system dumps to wedges. Tiny modifications by me. Lightly tested on an evbmips box.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/dkwedge/dk.c50
1 files changed, 43 insertions, 7 deletions
diff --git a/sys/dev/dkwedge/dk.c b/sys/dev/dkwedge/dk.c
index 739e614252f..4fdbd0c3fcb 100644
--- a/sys/dev/dkwedge/dk.c
+++ b/sys/dev/dkwedge/dk.c
@@ -1,4 +1,4 @@
-/* $NetBSD: dk.c,v 1.22 2007/03/04 06:01:45 christos Exp $ */
+/* $NetBSD: dk.c,v 1.23 2007/06/09 02:26:27 dyoung Exp $ */
/*-
* Copyright (c) 2004 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dk.c,v 1.22 2007/03/04 06:01:45 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dk.c,v 1.23 2007/06/09 02:26:27 dyoung Exp $");
#include "opt_dkwedge.h"
@@ -901,7 +901,7 @@ dkopen(dev_t dev, int flags, int fmt, struct lwp *l)
(void) lockmgr(&sc->sc_dk.dk_openlock, LK_EXCLUSIVE, NULL);
(void) lockmgr(&sc->sc_parent->dk_rawlock, LK_EXCLUSIVE, NULL);
if (sc->sc_dk.dk_openmask == 0) {
- if (sc->sc_parent->dk_rawopens++ == 0) {
+ if (sc->sc_parent->dk_rawopens == 0) {
KASSERT(sc->sc_parent->dk_rawvp == NULL);
error = bdevvp(sc->sc_pdev, &vp);
if (error)
@@ -920,6 +920,7 @@ dkopen(dev_t dev, int flags, int fmt, struct lwp *l)
vp->v_writecount++;
VOP_UNLOCK(vp, 0);
sc->sc_parent->dk_rawvp = vp;
+ sc->sc_parent->dk_rawopens++;
}
}
if (fmt == S_IFCHR)
@@ -1251,10 +1252,45 @@ dksize(dev_t dev)
* Perform a crash dump to a wedge.
*/
static int
-dkdump(dev_t dev, daddr_t blkno, void *va,
- size_t size)
+dkdump(dev_t dev, daddr_t blkno, void *va, size_t size)
{
+ struct dkwedge_softc *sc = dkwedge_lookup(dev);
+ const struct bdevsw *bdev;
+ int rv = 0;
+
+ if (sc == NULL)
+ return (-1);
+
+ if (sc->sc_state != DKW_STATE_RUNNING)
+ return (ENXIO);
+
+ (void) lockmgr(&sc->sc_dk.dk_openlock, LK_EXCLUSIVE, NULL);
+ (void) lockmgr(&sc->sc_parent->dk_rawlock, LK_EXCLUSIVE, NULL);
+
+ /* Our content type is static, no need to open the device. */
+
+ if (strcmp(sc->sc_ptype, DKW_PTYPE_SWAP) != 0) {
+ rv = ENXIO;
+ goto out;
+ }
+ if (size % DEV_BSIZE != 0) {
+ rv = EINVAL;
+ goto out;
+ }
+ if (blkno + size / DEV_BSIZE > sc->sc_size) {
+ printf("%s: blkno (%" PRIu64 ") + size / DEV_BSIZE (%zu) > "
+ "sc->sc_size (%" PRIu64 ")\n", __func__, blkno,
+ size / DEV_BSIZE, sc->sc_size);
+ rv = EINVAL;
+ goto out;
+ }
+
+ bdev = bdevsw_lookup(sc->sc_pdev);
+ rv = (*bdev->d_dump)(sc->sc_pdev, blkno + sc->sc_offset, va, size);
+
+out:
+ (void) lockmgr(&sc->sc_parent->dk_rawlock, LK_RELEASE, NULL);
+ (void) lockmgr(&sc->sc_dk.dk_openlock, LK_RELEASE, NULL);
- /* XXX */
- return (ENXIO);
+ return rv;
}