[dm-devel] [RFC PATCH 1/4] dm_queue: add dm_queue and generic worker thread

Kiyoshi Ueda k-ueda at ct.jp.nec.com
Fri Jun 23 21:47:00 UTC 2006


This patch adds device-mapper generic queue feature (dm_queue)
so that targets can use it instead of using its own queuing mechanism.

The patch is for 2.6.17-rc6-mm1 + Alasdair's patches which was sent
to this ML (Subject: "Next set of device-mapper patches").

Regards,
Kiyoshi Ueda


Signed-off-by: Kiyoshi Ueda <k-ueda at ct.jp.nec.com>
Signed-off-by: Jun'ichi Nomura <j-nomura at ce.jp.nec.com>

diff -rupN 2.6.17-rc6-mm1.agk/drivers/md/dm-queue.c 2.6.17-rc6-mm1.agk.moveq/drivers/md/dm-queue.c
--- 2.6.17-rc6-mm1.agk/drivers/md/dm-queue.c	1969-12-31 19:00:00.000000000 -0500
+++ 2.6.17-rc6-mm1.agk.moveq/drivers/md/dm-queue.c	2006-06-23 11:36:04.000000000 -0400
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2006 NEC Corporation
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm.h"
+#include "dm-bio-list.h"
+
+#include <linux/workqueue.h>
+
+struct workqueue_struct *kdmqd;
+
+struct dm_queue {
+	spinlock_t lock; /* protects .bios and .size */
+	struct bio_list bios;
+	unsigned int size;
+
+	struct dm_target *ti;
+	struct work_struct work;
+};
+
+int dm_queue_init()
+{
+	kdmqd = create_workqueue("dm_queue");
+	if (!kdmqd)
+		return -ENOMEM;
+
+	return 0;
+}
+
+void dm_queue_exit()
+{
+	destroy_workqueue(kdmqd);
+}
+
+struct dm_queue *dm_queue_alloc(int nr)
+{
+	struct dm_queue *qs;
+
+	if (!nr)
+		return NULL;
+
+	qs = kzalloc(sizeof(struct dm_queue) * nr, GFP_KERNEL);
+
+	return qs;
+}
+EXPORT_SYMBOL_GPL(dm_queue_alloc);
+
+void dm_queue_free(struct dm_queue *qs)
+{
+	if (qs)
+		kfree(qs);
+}
+EXPORT_SYMBOL_GPL(dm_queue_free);
+
+void dm_queue_flush(struct dm_queue *q)
+{
+	/*
+	 * The work queue is shared by multiple targets and we cannot
+	 * flush the specific queue.
+	 */
+	flush_workqueue(kdmqd);
+}
+EXPORT_SYMBOL_GPL(dm_queue_flush);
+
+struct dm_queue *dm_queue_find(struct dm_queue *qs, unsigned int index)
+{
+	if (!qs)
+		return NULL;
+
+	return qs + index;
+}
+EXPORT_SYMBOL_GPL(dm_queue_find);
+
+int dm_queue_setup(struct dm_queue *q, void (*work)(void *),
+		    struct dm_target *ti)
+{
+	spin_lock_init(&q->lock);
+	bio_list_init(&q->bios);
+	q->size = 0;
+	q->ti = ti;
+	INIT_WORK(&q->work, work, q);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dm_queue_setup);
+
+int dm_queue_add_bio(struct dm_queue *q, struct bio *bio)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&q->lock, flags);
+	bio_list_add(&q->bios, bio);
+	q->size++;
+	spin_unlock_irqrestore(&q->lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dm_queue_add_bio);
+
+struct bio *dm_queue_pop_bio(struct dm_queue *q)
+{
+	struct bio *bio = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&q->lock, flags);
+
+	bio = bio_list_pop(&q->bios);
+	if (bio)
+		q->size--;
+
+	spin_unlock_irqrestore(&q->lock, flags);
+
+	return bio;
+}
+EXPORT_SYMBOL_GPL(dm_queue_pop_bio);
+
+struct bio *dm_queue_get_bios(struct dm_queue *q)
+{
+	struct bio *bio = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&q->lock, flags);
+
+	bio = bio_list_get(&q->bios);
+	q->size = 0;
+
+	spin_unlock_irqrestore(&q->lock, flags);
+
+	return bio;
+}
+EXPORT_SYMBOL_GPL(dm_queue_get_bios);
+
+unsigned int dm_queue_size(struct dm_queue *q)
+{
+	unsigned int s;
+	unsigned long flags;
+
+	spin_lock_irqsave(&q->lock, flags);
+	s = q->size;
+	spin_unlock_irqrestore(&q->lock, flags);
+
+	return s;
+}
+EXPORT_SYMBOL_GPL(dm_queue_size);
+
+struct dm_target *dm_queue_get_target(struct dm_queue *q)
+{
+	return q->ti;
+}
+EXPORT_SYMBOL_GPL(dm_queue_get_target);
+
+void dm_queue_process(struct dm_queue *q)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&q->lock, flags);
+
+	if (!q->size)
+		goto out;
+
+	queue_work(kdmqd, &q->work);
+
+out:
+	spin_unlock_irqrestore(&q->lock, flags);
+}
+EXPORT_SYMBOL_GPL(dm_queue_process);
diff -rupN 2.6.17-rc6-mm1.agk/include/linux/device-mapper.h 2.6.17-rc6-mm1.agk.moveq/include/linux/device-mapper.h
--- 2.6.17-rc6-mm1.agk/include/linux/device-mapper.h	2006-06-09 16:50:42.000000000 -0400
+++ 2.6.17-rc6-mm1.agk.moveq/include/linux/device-mapper.h	2006-06-23 11:29:00.000000000 -0400
@@ -10,6 +10,7 @@
 
 #ifdef __KERNEL__
 
+struct dm_queue;
 struct dm_target;
 struct dm_table;
 struct dm_dev;
@@ -131,6 +132,10 @@ struct dm_target {
 
 	/* Used to provide an error string from the ctr */
 	char *error;
+
+	/* Generic queue for target */
+	struct dm_queue *queues;
+	unsigned int num_queues;
 };
 
 int dm_register_target(struct target_type *t);
@@ -238,5 +243,54 @@ int dm_swap_table(struct mapped_device *
  */
 int dm_create_error_table(struct dm_table **result, struct mapped_device *md);
 
+
+/*-----------------------------------------------------------------
+ * Functions for manipulating device-mapper queues.
+ *---------------------------------------------------------------*/
+
+/*
+ * First alloc queues.
+ */
+struct dm_queue *dm_queue_alloc(int nr);
+
+/*
+ * Then call this to get a specific queue from the allocated queues.
+ */
+struct dm_queue *dm_queue_find(struct dm_queue *qs, unsigned int index);
+
+/*
+ * Finally call this to make the queue ready for use.
+ */
+int dm_queue_setup(struct dm_queue *q, void (*fn)(void *),
+		   struct dm_target *ti);
+
+/*
+ * Free allocated queues.
+ */
+void dm_queue_free(struct dm_queue *qs);
+
+/*
+ * Flush the queue.
+ */
+void dm_queue_flush(struct dm_queue *q);
+
+/*
+ * Manipulations.
+ */
+int dm_queue_add_bio(struct dm_queue *q, struct bio *bio);
+struct bio *dm_queue_pop_bio(struct dm_queue *q);
+struct bio *dm_queue_get_bios(struct dm_queue *q);
+
+/*
+ * Info.
+ */
+unsigned int dm_queue_size(struct dm_queue *q);
+struct dm_target *dm_queue_get_target(struct dm_queue *q);
+
+/*
+ * Start processing a queue.
+ */
+void dm_queue_process(struct dm_queue *q);
+
 #endif	/* __KERNEL__ */
 #endif	/* _LINUX_DEVICE_MAPPER_H */
diff -rupN 2.6.17-rc6-mm1.agk/drivers/md/dm.h 2.6.17-rc6-mm1.agk.moveq/drivers/md/dm.h
--- 2.6.17-rc6-mm1.agk/drivers/md/dm.h	2006-06-09 16:50:42.000000000 -0400
+++ 2.6.17-rc6-mm1.agk.moveq/drivers/md/dm.h	2006-06-23 11:18:54.000000000 -0400
@@ -39,6 +39,7 @@ struct dm_dev {
 };
 
 struct dm_table;
+struct dm_queue;
 
 /*-----------------------------------------------------------------
  * Internal table functions.
@@ -57,6 +58,12 @@ void dm_table_unplug_all(struct dm_table
 int dm_table_flush_all(struct dm_table *t);
 
 /*-----------------------------------------------------------------
+ * Queue functions.
+ *---------------------------------------------------------------*/
+int dm_queue_init(void);
+void dm_queue_exit(void);
+
+/*-----------------------------------------------------------------
  * A registry of target types.
  *---------------------------------------------------------------*/
 int dm_target_init(void);
diff -rupN 2.6.17-rc6-mm1.agk/drivers/md/dm.c 2.6.17-rc6-mm1.agk.moveq/drivers/md/dm.c
--- 2.6.17-rc6-mm1.agk/drivers/md/dm.c	2006-06-21 16:32:06.000000000 -0400
+++ 2.6.17-rc6-mm1.agk.moveq/drivers/md/dm.c	2006-06-23 11:17:29.000000000 -0400
@@ -176,6 +176,7 @@ static void local_exit(void)
 
 int (*_inits[])(void) __initdata = {
 	local_init,
+	dm_queue_init,
 	dm_target_init,
 	dm_linear_init,
 	dm_stripe_init,
@@ -184,6 +185,7 @@ int (*_inits[])(void) __initdata = {
 
 void (*_exits[])(void) = {
 	local_exit,
+	dm_queue_exit,
 	dm_target_exit,
 	dm_linear_exit,
 	dm_stripe_exit,
diff -rupN 2.6.17-rc6-mm1.agk/drivers/md/Makefile 2.6.17-rc6-mm1.agk.moveq/drivers/md/Makefile
--- 2.6.17-rc6-mm1.agk/drivers/md/Makefile	2006-06-05 20:57:02.000000000 -0400
+++ 2.6.17-rc6-mm1.agk.moveq/drivers/md/Makefile	2006-06-20 18:48:01.000000000 -0400
@@ -3,7 +3,7 @@
 #
 
 dm-mod-objs	:= dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \
-		   dm-ioctl.o dm-io.o kcopyd.o
+		   dm-ioctl.o dm-io.o kcopyd.o dm-queue.o
 dm-multipath-objs := dm-hw-handler.o dm-path-selector.o dm-mpath.o
 dm-snapshot-objs := dm-snap.o dm-exception-store.o
 dm-mirror-objs	:= dm-log.o dm-raid1.o




More information about the dm-devel mailing list