Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev Make md(4) mp-safe.
details: https://anonhg.NetBSD.org/src/rev/bbdc8cc4aa54
branches: trunk
changeset: 758992:bbdc8cc4aa54
user: hannken <hannken%NetBSD.org@localhost>
date: Tue Nov 23 09:30:43 2010 +0000
description:
Make md(4) mp-safe.
diffstat:
sys/dev/md.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 47 insertions(+), 14 deletions(-)
diffs (230 lines):
diff -r 3636f6849487 -r bbdc8cc4aa54 sys/dev/md.c
--- a/sys/dev/md.c Tue Nov 23 08:44:23 2010 +0000
+++ b/sys/dev/md.c Tue Nov 23 09:30:43 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: md.c,v 1.64 2010/11/22 21:10:10 pooka Exp $ */
+/* $NetBSD: md.c,v 1.65 2010/11/23 09:30:43 hannken Exp $ */
/*
* Copyright (c) 1995 Gordon W. Ross, Leo Weppelman.
@@ -40,7 +40,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: md.c,v 1.64 2010/11/22 21:10:10 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: md.c,v 1.65 2010/11/23 09:30:43 hannken Exp $");
#ifdef _KERNEL_OPT
#include "opt_md.h"
@@ -84,6 +84,8 @@
device_t sc_dev; /* Self. */
struct disk sc_dkdev; /* hook for generic disk handling */
struct md_conf sc_md;
+ kmutex_t sc_lock; /* Protect self. */
+ kcondvar_t sc_cv; /* Signal work. */
struct bufq_state *sc_buflist;
};
/* shorthand for fields in sc_md: */
@@ -105,7 +107,7 @@
static dev_type_size(mdsize);
const struct bdevsw md_bdevsw = {
- mdopen, mdclose, mdstrategy, mdioctl, nodump, mdsize, D_DISK
+ mdopen, mdclose, mdstrategy, mdioctl, nodump, mdsize, D_DISK | D_MPSAFE
};
const struct cdevsw md_cdevsw = {
@@ -144,6 +146,8 @@
struct md_softc *sc = device_private(self);
sc->sc_dev = self;
+ mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
+ cv_init(&sc->sc_cv, "mdidle");
bufq_alloc(&sc->sc_buflist, "fcfs", 0);
/* XXX - Could accept aux info here to set the config. */
@@ -190,6 +194,8 @@
disk_detach(&sc->sc_dkdev);
disk_destroy(&sc->sc_dkdev);
bufq_free(sc->sc_buflist);
+ mutex_destroy(&sc->sc_lock);
+ cv_destroy(&sc->sc_cv);
return 0;
}
@@ -211,15 +217,20 @@
mdsize(dev_t dev)
{
struct md_softc *sc;
+ int res;
sc = device_lookup_private(&md_cd, MD_UNIT(dev));
if (sc == NULL)
return 0;
+ mutex_enter(&sc->sc_lock);
if (sc->sc_type == MD_UNCONFIGURED)
- return 0;
+ res = 0;
+ else
+ res = sc->sc_size >> DEV_BSHIFT;
+ mutex_exit(&sc->sc_lock);
- return (sc->sc_size >> DEV_BSHIFT);
+ return res;
}
static int
@@ -373,6 +384,8 @@
sc = device_lookup_private(&md_cd, MD_UNIT(bp->b_dev));
+ mutex_enter(&sc->sc_lock);
+
if (sc == NULL || sc->sc_type == MD_UNCONFIGURED) {
bp->b_error = ENXIO;
goto done;
@@ -383,7 +396,8 @@
case MD_UMEM_SERVER:
/* Just add this job to the server's queue. */
bufq_put(sc->sc_buflist, bp);
- wakeup((void *)sc);
+ cv_signal(&sc->sc_cv);
+ mutex_exit(&sc->sc_lock);
/* see md_server_loop() */
/* no biodone in this case */
return;
@@ -421,6 +435,8 @@
}
done:
biodone(bp);
+
+ mutex_exit(&sc->sc_lock);
}
static int
@@ -430,15 +446,18 @@
struct md_conf *umd;
struct disklabel *lp;
struct partinfo *pp;
+ int error;
if ((sc = device_lookup_private(&md_cd, MD_UNIT(dev))) == NULL)
return ENXIO;
+ mutex_enter(&sc->sc_lock);
if (sc->sc_type != MD_UNCONFIGURED) {
switch (cmd) {
case DIOCGDINFO:
lp = (struct disklabel *)data;
*lp = *sc->sc_dkdev.dk_label;
+ mutex_exit(&sc->sc_lock);
return 0;
case DIOCGPART:
@@ -446,19 +465,24 @@
pp->disklab = sc->sc_dkdev.dk_label;
pp->part =
&sc->sc_dkdev.dk_label->d_partitions[DISKPART(dev)];
+ mutex_exit(&sc->sc_lock);
return 0;
}
}
/* If this is not the raw partition, punt! */
- if (DISKPART(dev) != RAW_PART)
+ if (DISKPART(dev) != RAW_PART) {
+ mutex_exit(&sc->sc_lock);
return ENOTTY;
+ }
umd = (struct md_conf *)data;
+ error = EINVAL;
switch (cmd) {
case MD_GETCONF:
*umd = sc->sc_md;
- return 0;
+ error = 0;
+ break;
case MD_SETCONF:
/* Can only set it once. */
@@ -466,17 +490,20 @@
break;
switch (umd->md_type) {
case MD_KMEM_ALLOCATED:
- return md_ioctl_kalloc(sc, umd, l);
+ error = md_ioctl_kalloc(sc, umd, l);
+ break;
#if MEMORY_DISK_SERVER
case MD_UMEM_SERVER:
- return md_ioctl_server(sc, umd, l);
+ error = md_ioctl_server(sc, umd, l);
+ break;
#endif /* MEMORY_DISK_SERVER */
default:
break;
}
break;
}
- return EINVAL;
+ mutex_exit(&sc->sc_lock);
+ return error;
}
static void
@@ -534,6 +561,8 @@
vaddr_t addr;
vsize_t size;
+ KASSERT(mutex_owned(&sc->sc_lock));
+
/* Sanity check the size. */
size = umd->md_size;
addr = uvm_km_alloc(kernel_map, size, 0, UVM_KMF_WIRED|UVM_KMF_ZERO);
@@ -561,6 +590,8 @@
vaddr_t end;
int error;
+ KASSERT(mutex_owned(&sc->sc_lock));
+
/* Sanity check addr, size. */
end = (vaddr_t) ((char *)umd->md_addr + umd->md_size);
@@ -585,8 +616,6 @@
return (error);
}
-static int md_sleep_pri = PWAIT | PCATCH;
-
static int
md_server_loop(struct md_softc *sc)
{
@@ -597,15 +626,18 @@
int error;
bool is_read;
+ KASSERT(mutex_owned(&sc->sc_lock));
+
for (;;) {
/* Wait for some work to arrive. */
while ((bp = bufq_get(sc->sc_buflist)) == NULL) {
- error = tsleep((void *)sc, md_sleep_pri, "md_idle", 0);
+ error = cv_wait_sig(&sc->sc_cv, &sc->sc_lock);
if (error)
return error;
}
/* Do the transfer to/from user space. */
+ mutex_exit(&sc->sc_lock);
error = 0;
is_read = ((bp->b_flags & B_READ) == B_READ);
bp->b_resid = bp->b_bcount;
@@ -634,6 +666,7 @@
bp->b_error = error;
}
biodone(bp);
+ mutex_enter(&sc->sc_lock);
}
}
#endif /* MEMORY_DISK_SERVER */
Home |
Main Index |
Thread Index |
Old Index