summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhaad <haad@NetBSD.org>2009-12-29 23:37:47 +0000
committerhaad <haad@NetBSD.org>2009-12-29 23:37:47 +0000
commit36fe06980c4de693c4e63ba30ee873aed0ffdb2a (patch)
tree906fe69a97a881b567a79d8475aef82f22cfa366
parent35ea637d2bf4404c222f8ef069227516d1135ba1 (diff)
Add private lock to dm_dev_t used for mutual exclusion for diks(9) api
routines. This change fixes PR kern/42532.
-rw-r--r--sys/dev/dm/device-mapper.c14
-rw-r--r--sys/dev/dm/dm.h6
-rw-r--r--sys/dev/dm/dm_dev.c27
-rw-r--r--sys/dev/dm/dm_ioctl.c3
4 files changed, 43 insertions, 7 deletions
diff --git a/sys/dev/dm/device-mapper.c b/sys/dev/dm/device-mapper.c
index 57331c137a0..99777a0679a 100644
--- a/sys/dev/dm/device-mapper.c
+++ b/sys/dev/dm/device-mapper.c
@@ -1,4 +1,4 @@
-/* $NetBSD: device-mapper.c,v 1.10 2009/12/06 14:33:46 haad Exp $ */
+/* $NetBSD: device-mapper.c,v 1.11 2009/12/29 23:37:47 haad Exp $ */
/*
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -402,8 +402,13 @@ dmstrategy(struct buf *bp)
return;
}
- /* FIXME: have to be called with IPL_BIO*/
+ /*
+ * disk(9) is part of device structure and it can't be used without
+ * mutual exclusion, use diskp_mtx until it will be fixed.
+ */
+ mutex_enter(&dmv->diskp_mtx);
disk_busy(dmv->diskp);
+ mutex_exit(&dmv->diskp_mtx);
/* Select active table */
tbl = dm_table_get_entry(&dmv->table_head, DM_TABLE_ACTIVE);
@@ -459,9 +464,10 @@ dmstrategy(struct buf *bp)
if (issued_len < buf_len)
nestiobuf_done(bp, buf_len - issued_len, EINVAL);
- /* FIXME have to be called with SPL_BIO*/
+ mutex_enter(&dmv->diskp_mtx);
disk_unbusy(dmv->diskp, buf_len, bp != NULL ? bp->b_flags & B_READ : 0);
-
+ mutex_exit(&dmv->diskp_mtx);
+
dm_table_release(&dmv->table_head, DM_TABLE_ACTIVE);
dm_dev_unbusy(dmv);
diff --git a/sys/dev/dm/dm.h b/sys/dev/dm/dm.h
index 2f966af0b84..1cb6b9c71a9 100644
--- a/sys/dev/dm/dm.h
+++ b/sys/dev/dm/dm.h
@@ -1,4 +1,4 @@
-/* $NetBSD: dm.h,v 1.16 2009/12/06 14:31:16 haad Exp $ */
+/* $NetBSD: dm.h,v 1.17 2009/12/29 23:37:48 haad Exp $ */
/*
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -43,6 +43,7 @@
#include <sys/rwlock.h>
#include <sys/queue.h>
+#include <sys/device.h>
#include <sys/disklabel.h>
#include <prop/proplib.h>
@@ -120,6 +121,7 @@ typedef struct dm_dev {
char name[DM_NAME_LEN];
char uuid[DM_UUID_LEN];
+ device_t devt; /* pointer to autoconf device_t structure */
uint64_t minor;
uint32_t flags; /* store communication protocol flags */
@@ -136,6 +138,7 @@ typedef struct dm_dev {
struct dm_dev_head upcalls;
struct disk *diskp;
+ kmutex_t diskp_mtx;
TAILQ_ENTRY(dm_dev) next_upcall; /* LIST of mirrored, snapshoted devices. */
@@ -357,6 +360,7 @@ void dm_table_head_destroy(dm_table_head_t *);
dm_dev_t* dm_dev_alloc(void);
void dm_dev_busy(dm_dev_t *);
int dm_dev_destroy(void);
+dm_dev_t* dm_dev_detach(device_t);
int dm_dev_free(dm_dev_t *);
int dm_dev_init(void);
int dm_dev_insert(dm_dev_t *);
diff --git a/sys/dev/dm/dm_dev.c b/sys/dev/dm/dm_dev.c
index 6392d086b49..dc1b50ce9f9 100644
--- a/sys/dev/dm/dm_dev.c
+++ b/sys/dev/dm/dm_dev.c
@@ -1,4 +1,4 @@
-/* $NetBSD: dm_dev.c,v 1.6 2009/09/09 22:38:49 haad Exp $ */
+/* $NetBSD: dm_dev.c,v 1.7 2009/12/29 23:37:48 haad Exp $ */
/*
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -50,6 +50,7 @@ TAILQ_HEAD_INITIALIZER(dm_dev_list);
kmutex_t dm_dev_mutex;
+/* dm_dev_mutex must be holdby caller before using disable_dev. */
__inline static void
disable_dev(dm_dev_t *dmv)
{
@@ -220,6 +221,29 @@ dm_dev_test_minor(int dm_dev_minor)
}
#endif
+/*
+ * dm_dev_lookup_devt look for selected device_t. We keep this routine
+ * outside of dm_dev_lookup because it is a temporally solution.
+ *
+ * TODO: This is a hack autoconf should be more flexible.
+ */
+dm_dev_t *
+dm_dev_detach(device_t devt)
+{
+ dm_dev_t *dmv;
+
+ mutex_enter(&dm_dev_mutex);
+ TAILQ_FOREACH(dmv, &dm_dev_list, next_devlist){
+ if (devt == dmv->devt){
+ disable_dev(dmv);
+ return dmv;
+ }
+ }
+ mutex_exit(&dm_dev_mutex);
+
+ return NULL;
+}
+
/*
* Remove device selected with dm_dev from global list of devices.
*/
@@ -321,6 +345,7 @@ dm_dev_free(dm_dev_t *dmv)
KASSERT(dmv != NULL);
mutex_destroy(&dmv->dev_mtx);
+ mutex_destroy(&dmv->diskp_mtx);
cv_destroy(&dmv->dev_cv);
if(dmv->diskp != NULL)
diff --git a/sys/dev/dm/dm_ioctl.c b/sys/dev/dm/dm_ioctl.c
index a51486f2ab6..7d93d7455d5 100644
--- a/sys/dev/dm/dm_ioctl.c
+++ b/sys/dev/dm/dm_ioctl.c
@@ -1,5 +1,5 @@
-/* $NetBSD: dm_ioctl.c,v 1.17 2009/12/06 14:33:46 haad Exp $ */
+/* $NetBSD: dm_ioctl.c,v 1.18 2009/12/29 23:37:48 haad Exp $ */
/*
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -237,6 +237,7 @@ dm_dev_create_ioctl(prop_dictionary_t dm_dict)
dmv->dev_type = 0;
mutex_init(&dmv->dev_mtx, MUTEX_DEFAULT, IPL_NONE);
+ mutex_init(&dmv->diskp_mtx, MUTEX_DEFAULT, IPL_NONE);
cv_init(&dmv->dev_cv, "dm_dev");
dm_table_head_init(&dmv->table_head);