Skip to contentSkip to conversation

dm: add asymmetric stripe target device dirver

PATCH In review [email protected] 2 participants 3 messages Dec 26, 2017

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 dm: add asymmetric stripe target device dirver

From: liuchaowei <[email protected]>

This asymmetric stripe target device driver can achieve better io performance between those devices which possess different io performance

There are 2 storage device or flash devices: A and B, their sequential read permance are 220M/s and 315M/s inspectively, so their sequential read speed could be approximately equal to 2:3, if we use stripe type to combine these two devices, their layout could be showed below:
--------------------------------------------------------
| A1 | A2 | B1 | B2 | B3 |
--------------------------------------------------------

If we seletect asymmetric stripe type, their layout could be illustrated follow:
--------------------------------------------------------
| A1 | B1 |
--------------------------------------------------------

The former has 5 stripe devices and each stripe device has also equal chunk size, e.g.: 256secs. If there is a data block which size is 1280secs, so transfer the data to this stripe defvice will be split to 5 ios which io size is 256secs. But if we use the asymmetric stripe device, it only has two stripe devices and each one has be setting in optimal chunk size, e.g.: ratio is 2:3, the first one optimal chunk size is 512secs, the second is 768secs. And same 1280secs data block just only be splited two ios, this can be achieve perfect io performance.

Change-Id Iebaee3480e27022e2b3a7edbfb65425b1166274e
---
 Documentation/device-mapper/asymmetric-striped.txt |  85 ++++
 drivers/md/Kconfig                                 |  11 +
 drivers/md/Makefile                                |   1 +
 drivers/md/dm-asymmetric-stripe.c                  | 523 +++++++++++++++++++++
 drivers/md/dm.c                                    |   5 +
 include/linux/device-mapper.h                      |  15 +
 6 files changed, 640 insertions(+)
 create mode 100644 Documentation/device-mapper/asymmetric-striped.txt
 create mode 100644 drivers/md/dm-asymmetric-stripe.c
Documentation/device-mapper/asymmetric-striped.txt new file +85 -0
new file mode 100644
index 000000000000..0412a224a49e
@@ -0,0 +1,85 @@
+dm-asymmetric-stripe
+=========
+
+Device-Mapper's "asm-striped" target is used to create a striped (i.e. RAID-0)
+device across one or more underlying devices. Data is written in "chunks",
+with consecutive chunks rotating among the underlying devices. This can
+potentially provide improved I/O throughput by utilizing several physical
+devices in parallel. However, in order to gain maximum I/O performance bewteen
+slow and fast device, there is a ratio to set up the chunk size among these
+device.
+
+Parameters: <num devs> <chunk size> <ratio> [<dev path> <offset>]+
+<num devs>: Number of underlying devices.
+<chunk size>: Size of each chunk of data. Must be at least as
+large as the system's PAGE_SIZE.
+<ratio>: The proportion of per io size, it is the times as much
+as 1 chunk size
+<dev path>: Full pathname to the underlying block-device, or a
+"major:minor" device-number.
+<offset>: Starting sector within the device.
+
+One or more underlying devices can be specified. The striped device
+size must be a multiple of the chunk size multiplied by the number of underlying
+devices. However, there is a ratio can be setting, e.g.: 2:3 means the first one
+striped device optimal width size is 2 time as much as 1 chunk size, the second
+striped device is 3.
+
+
+Example scripts
+===============
+
+[[
+#!/usr/bin/perl -w
+# Create a striped device across any number of underlying devices. The device
+# will be called "stripe_dev" and have a chunk-size of 128k.
+
+my $chunk_size = 128 * 2;
+my $ratio = "2:3";
+my $dev_name = "stripe_dev";
+my $num_devs = @ARGV;
+my @devs = @ARGV;
+
+if ($num_devs < 2) {
+die("Specify at least two devices\n");
+}
+
+
+$stripe_average_size = 1073741824
+$stripe_dev_size = $stripe_average_size * 5;
+
+$table = "0 $stripe_dev_size asm-striped $num_devs $chunk_size $ratio";
+for ($i = 0; $i < $num_devs; $i++) {
+$table .= " $devs[$i] 0";
+}
+
+`echo $table | dmsetup create $dev_name`;
+]]
+
+
+Why asymmetric striped
+=======================
+Considering one case:
+There are 2 storage device or flash devices: A and B, their sequential
+read permance are 220M/s and 315M/s inspectively, so their sequential
+read speed could be approximately equal to 2:3, if we use stripe type
+to combine these two devices, their layout could be showed below:
+--------------------------------------------------------
+|    A1    |    A2    |    B1    |    B2    |    B3    |
+--------------------------------------------------------
+
+If we seletect asymmetric stripe type, their layout could be illustrated
+follow:
+--------------------------------------------------------
+|         A1          |               B1               |
+--------------------------------------------------------
+
+The former has 5 stripe devices and each stripe device has also equal
+chunk size, e.g.: 256secs. If there is a data block which size is 1280secs,
+so transfer the data to this stripe defvice will be split to 5 ios which io
+size is 256secs. But if we use the asymmetric stripe device, it only has two
+stripe devices and each one has be setting in optimal chunk size, e.g.: ratio
+is 2:3, the first one optimal chunk size is 512secs, the second is 768secs.
+And same 1280secs data block just only be splited two ios, this can be achieve
+perfect io performance.
+
drivers/md/Kconfig +11 -0
index 7d5aa2c5c81d..4232b929c2f3 100644
@@ -455,6 +455,17 @@ config DM_FLAKEY
        ---help---
          A target that intermittently fails I/O for debugging purposes.
 
+config DM_ASYMMETRIC_STRIPE
+	tristate "DM asymmetric stripe(asymmetric raid0)"
+	depends on BLK_DEV_DM
+	---help---
+	  This device-mapper target creates a asymmetric raid0/stripe device that
+          support asymmetric stripe chunk size and can gain same performance as
+          raid0 device
+
+          You must configure the accurate ratio between different physical storage
+          device respectively
+
 config DM_VERITY
 	tristate "Verity target support"
 	depends on BLK_DEV_DM
drivers/md/Makefile +1 -0
index 2b2ba36638cd..0f0ea7bd7737 100644
@@ -62,6 +62,7 @@ obj-$(CONFIG_DM_ERA)		+= dm-era.o
 obj-$(CONFIG_DM_LOG_WRITES)	+= dm-log-writes.o
 obj-$(CONFIG_DM_REQ_CRYPT)	+= dm-req-crypt.o
 obj-$(CONFIG_DM_ANDROID_VERITY) += dm-android-verity.o
+obj-$(CONFIG_DM_ASYMMETRIC_STRIPE) += dm-asymmetric-stripe.o
 
 ifeq ($(CONFIG_DM_UEVENT),y)
 dm-mod-objs			+= dm-uevent.o
drivers/md/dm-asymmetric-stripe.c new file +523 -0

523 lines not on this page · raw message

drivers/md/dm.c +5 -0
index 36a20ff5d195..9c5b05db3180 100644
@@ -1393,6 +1393,7 @@ static sector_t max_io_len(sector_t sector, struct dm_target *ti)
 {
 	sector_t len = max_io_len_target_boundary(sector, ti);
 	sector_t offset, max_len;
+	sector_t optimal_len;
 
 	/*
 	 * Does the target need to split even further?
@@ -1407,6 +1408,10 @@ static sector_t max_io_len(sector_t sector, struct dm_target *ti)
 
 		if (len > max_len)
 			len = max_len;
+	} else if (ti->asymmetric_chunk_supported) {
+		offset = dm_target_offset(ti, sector);
+		ti->type->io_calculate(ti, offset, &optimal_len);
+		len = optimal_len;
 	}
 
 	return len;
include/linux/device-mapper.h +15 -0
index 5c720864db89..ec6fc5e6b884 100644
@@ -109,6 +109,14 @@ typedef int (*dm_iterate_devices_fn) (struct dm_target *ti,
 typedef void (*dm_io_hints_fn) (struct dm_target *ti,
 				struct queue_limits *limits);
 
+/*
+ * This function will recalculate io size per bio if this target support
+ * asymmetric chunk size
+ */
+typedef void (*dm_io_len_calculate_fn) (struct dm_target *ti,
+				sector_t offset,
+				sector_t *optimal_len);
+
 /*
  * Returns:
  *    0: The target can handle the next I/O immediately.
@@ -162,6 +170,7 @@ struct target_type {
 	dm_busy_fn busy;
 	dm_iterate_devices_fn iterate_devices;
 	dm_io_hints_fn io_hints;
+	dm_io_len_calculate_fn io_calculate;
 
 	/* For internal device-mapper use. */
 	struct list_head list;
@@ -273,6 +282,12 @@ struct dm_target {
 	 * Set if this target does not return zeroes on discarded blocks.
 	 */
 	bool discard_zeroes_data_unsupported:1;
+
+	/*
+	 * Set if this target supported asymmetric chunk size.
+	 */
+	bool asymmetric_chunk_supported:1;
+
 };
 
 /* Each target can link one of these into the table */
Signature · 1 line
2.15.1
reviewer
#1 lore raw
Quoted 7 lines · On 12/25/2017 07:52 PM, [email protected] wrote:

From: liuchaowei <[email protected]>

This asymmetric stripe target device driver can achieve better io performance between those devices which possess different io performance

There are 2 storage device or flash devices: A and B, their sequential read permance are 220M/s and 315M/s inspectively, so their sequential

performance respectively,

Quoted 7 lines

read speed could be approximately equal to 2:3, if we use stripe type to combine these two devices, their layout could be showed below:
--------------------------------------------------------
| A1 | A2 | B1 | B2 | B3 |
--------------------------------------------------------

If we seletect asymmetric stripe type, their layout could be illustrated

select

Quoted 8 lines

follow:
--------------------------------------------------------
| A1 | B1 |
--------------------------------------------------------

The former has 5 stripe devices and each stripe device has also equal chunk size, e.g.: 256secs. If there is a data block which size is 1280secs, so transfer the data to this stripe defvice will be split

device

Quoted 5 lines

to 5 ios which io size is 256secs. But if we use the asymmetric stripe device, it only has two stripe devices and each one has be setting in optimal chunk size, e.g.: ratio is 2:3, the first one optimal chunk size is 512secs, the second is 768secs. And same 1280secs data block just only be splited two ios, this can be achieve

split into two ios,

Quoted 21 lines

perfect io performance.

Change-Id Iebaee3480e27022e2b3a7edbfb65425b1166274e
---
 Documentation/device-mapper/asymmetric-striped.txt |  85 ++++
 drivers/md/Kconfig                                 |  11 +
 drivers/md/Makefile                                |   1 +
 drivers/md/dm-asymmetric-stripe.c                  | 523 +++++++++++++++++++++
 drivers/md/dm.c                                    |   5 +
 include/linux/device-mapper.h                      |  15 +
 6 files changed, 640 insertions(+)
 create mode 100644 Documentation/device-mapper/asymmetric-striped.txt
 create mode 100644 drivers/md/dm-asymmetric-stripe.c
Documentation/device-mapper/asymmetric-striped.txt new file +0 -0
new file mode 100644
index 000000000000..0412a224a49e

Documentation/device-mapper/asymmetric-striped.txt line 8

Quoted 8 lines
Documentation/device-mapper/asymmetric-striped.txt new file +8 -0
@@ -0,0 +1,85 @@
+dm-asymmetric-stripe
+=========
+
+Device-Mapper's "asm-striped" target is used to create a striped (i.e. RAID-0)
+device across one or more underlying devices. Data is written in "chunks",
+with consecutive chunks rotating among the underlying devices. This can
+potentially provide improved I/O throughput by utilizing several physical
+devices in parallel. However, in order to gain maximum I/O performance bewteen

between

Quoted 6 lines
Documentation/device-mapper/asymmetric-striped.txt new file +6 -0
+slow and fast device, there is a ratio to set up the chunk size among these
+device.
+
+Parameters: <num devs> <chunk size> <ratio> [<dev path> <offset>]+
+<num devs>: Number of underlying devices.
+<chunk size>: Size of each chunk of data. Must be at least as

Documentation/device-mapper/asymmetric-striped.txt line 24

Quoted 10 lines
Documentation/device-mapper/asymmetric-striped.txt new file +10 -0
+large as the system's PAGE_SIZE.
+<ratio>: The proportion of per io size, it is the times as much
+as 1 chunk size
+<dev path>: Full pathname to the underlying block-device, or a
+"major:minor" device-number.
+<offset>: Starting sector within the device.
+
+One or more underlying devices can be specified. The striped device
+size must be a multiple of the chunk size multiplied by the number of underlying
+devices. However, there is a ratio can be setting, e.g.: 2:3 means the first one

there is a ratio that can be set,

Documentation/device-mapper/asymmetric-striped.txt line 25

Quoted 1 line
Documentation/device-mapper/asymmetric-striped.txt new file +1 -0
+striped device optimal width size is 2 time as much as 1 chunk size, the second

times

Quoted 29 lines
Documentation/device-mapper/asymmetric-striped.txt new file +29 -0
+striped device is 3.
+
+
+Example scripts
+===============
+
+[[
+#!/usr/bin/perl -w
+# Create a striped device across any number of underlying devices. The device
+# will be called "stripe_dev" and have a chunk-size of 128k.
+
+my $chunk_size = 128 * 2;
+my $ratio = "2:3";
+my $dev_name = "stripe_dev";
+my $num_devs = @ARGV;
+my @devs = @ARGV;
+
+if ($num_devs < 2) {
+die("Specify at least two devices\n");
+}
+
+
+$stripe_average_size = 1073741824
+$stripe_dev_size = $stripe_average_size * 5;
+
+$table = "0 $stripe_dev_size asm-striped $num_devs $chunk_size $ratio";
+for ($i = 0; $i < $num_devs; $i++) {
+$table .= " $devs[$i] 0";
+}

Documentation/device-mapper/asymmetric-striped.txt line 64

Quoted 10 lines
Documentation/device-mapper/asymmetric-striped.txt new file +10 -0
+
+`echo $table | dmsetup create $dev_name`;
+]]
+
+
+Why asymmetric striped
+=======================
+Considering one case:
+There are 2 storage device or flash devices: A and B, their sequential
+read permance are 220M/s and 315M/s inspectively, so their sequential

performance respectively,

Documentation/device-mapper/asymmetric-striped.txt line 71

Quoted 7 lines
Documentation/device-mapper/asymmetric-striped.txt new file +7 -0
+read speed could be approximately equal to 2:3, if we use stripe type
+to combine these two devices, their layout could be showed below:
+--------------------------------------------------------
+|    A1    |    A2    |    B1    |    B2    |    B3    |
+--------------------------------------------------------
+
+If we seletect asymmetric stripe type, their layout could be illustrated

select

Documentation/device-mapper/asymmetric-striped.txt line 79

Quoted 8 lines
Documentation/device-mapper/asymmetric-striped.txt new file +8 -0
+follow:
+--------------------------------------------------------
+|         A1          |               B1               |
+--------------------------------------------------------
+
+The former has 5 stripe devices and each stripe device has also equal
+chunk size, e.g.: 256secs. If there is a data block which size is 1280secs,
+so transfer the data to this stripe defvice will be split to 5 ios which io

device

Documentation/device-mapper/asymmetric-striped.txt line 83

Quoted 4 lines
Documentation/device-mapper/asymmetric-striped.txt new file +4 -0
+size is 256secs. But if we use the asymmetric stripe device, it only has two
+stripe devices and each one has be setting in optimal chunk size, e.g.: ratio
+is 2:3, the first one optimal chunk size is 512secs, the second is 768secs.
+And same 1280secs data block just only be splited two ios, this can be achieve

split into two ios,

Quoted 7 lines
Documentation/device-mapper/asymmetric-striped.txt new file +2 -0
+perfect io performance.
+
drivers/md/Kconfig +0 -0
index 7d5aa2c5c81d..4232b929c2f3 100644

drivers/md/Kconfig config DM_FLAKEY · line 464

Quoted 10 lines
drivers/md/Kconfig +7 -0
@@ -455,6 +455,17 @@ config DM_FLAKEY
        ---help---
          A target that intermittently fails I/O for debugging purposes.
 
+config DM_ASYMMETRIC_STRIPE
+	tristate "DM asymmetric stripe(asymmetric raid0)"
+	depends on BLK_DEV_DM
+	---help---
+	  This device-mapper target creates a asymmetric raid0/stripe device that
+          support asymmetric stripe chunk size and can gain same performance as
+          raid0 device

Align "support" and "raid0" under "This". And end the sentence with a period (".").

drivers/md/Kconfig config DM_FLAKEY · line 467

Quoted 3 lines
drivers/md/Kconfig +3 -0
+
+          You must configure the accurate ratio between different physical storage
+          device respectively

End sentence with a period.

Quoted 22 lines
drivers/md/Kconfig +1 -0
+
 config DM_VERITY
 	tristate "Verity target support"
 	depends on BLK_DEV_DM
drivers/md/dm-asymmetric-stripe.c new file +11 -0
new file mode 100644
index 000000000000..4ef3915b435a
@@ -0,0 +1,523 @@
+/*
+ * Copyright (C) 2018 Smartisan, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.

drivers/md/dm-asymmetric-stripe.c line 21

Quoted 10 lines
drivers/md/dm-asymmetric-stripe.c new file +10 -0
+ *
+ * Author: <[email protected]>
+ * Name: Henry Liu
+ *
+ */
+
+
+#include "dm.h"
+#include <linux/device-mapper.h>
+

#include <linux/atomic.h>

drivers/md/dm-asymmetric-stripe.c line 23

Quoted 2 lines
drivers/md/dm-asymmetric-stripe.c new file +2 -0
+#include <linux/module.h>
+#include <linux/init.h>

#include <linux/kernel.h>

drivers/md/dm-asymmetric-stripe.c line 25

Quoted 2 lines
drivers/md/dm-asymmetric-stripe.c new file +2 -0
+#include <linux/blkdev.h>
+#include <linux/bio.h>

#include <linux/bitops.h>

drivers/md/dm-asymmetric-stripe.c line 27

Quoted 2 lines
drivers/md/dm-asymmetric-stripe.c new file +2 -0
+#include <linux/slab.h>
+#include <linux/log2.h>

#include <linux/workqueue.h>

Quoted 6 lines
drivers/md/dm-asymmetric-stripe.c new file +5 -0
+
+#define DM_MSG_PREFIX "asm-striped"
+#define DM_IO_ERROR_THRESHOLD 15
 
+/*
+ * An event is triggered whenever a drive

drivers/md/dm-asymmetric-stripe.c line 77

Quoted 10 lines
drivers/md/dm-asymmetric-stripe.c new file +10 -0
+ * drops out of a stripe volume.
+ */
+static void trigger_event(struct work_struct *work)
+{
+	asm_stripe_c *sc = container_of(work, asm_stripe_c, trigger_event);
+
+	dm_table_event(sc->ti->table);
+}
+
+	static inline

Above line should not be indented.
Above and below should be on one line if <= 80 characters.

Quoted 37 lines
drivers/md/dm-asymmetric-stripe.c new file +36 -0
+asm_stripe_c *alloc_context(unsigned int stripes)
+{
+	size_t len;
+
+	if (dm_array_too_big(sizeof(asm_stripe_c),
+				sizeof(asm_stripe),
+				stripes))
+		return NULL;
+
+	len = sizeof(asm_stripe_c) + (sizeof(asm_stripe) * stripes);
+
+	return kmalloc(len, GFP_KERNEL);
+}
 
+static int set_stripe_ratio(struct dm_target *ti,
+		asm_stripe_c *sc,
+		char *ratio_str)
+{
+	char *p;
+	unsigned int i;
+	uint32_t r = 0, ratio;
+	char *tmp_ratio = ratio_str;
+
+	if (sizeof(sc->ratio_str) < strlen(ratio_str)) {
+		ti->error = "Too big stripe ratio string";
+		return -ENOMEM;
+	}
+
+	strlcpy(sc->ratio_str, ratio_str, strlen(ratio_str) + 1);
+	for (i = 0; i < sc->stripes; i++) {
+		p  = strsep(&tmp_ratio, ":");
+		if (p == NULL)
+			return -EINVAL;
+
+		if (kstrtouint(p, 10, &ratio) || !ratio)
+			return -EINVAL;
+

drivers/md/dm-asymmetric-stripe.c line 152

Quoted 10 lines
drivers/md/dm-asymmetric-stripe.c new file +10 -0
+		sc->stripe[i].ratio = ratio;
+		r += ratio;
+	}
+
+	sc->total_ratio = r;
+	sc->avg_width = ti->len / r;
+	sc->stripe_size = r * sc->chunk_size;
+
+	return 0;
+}

Insert blank line here.

Quoted 8 lines
drivers/md/dm-asymmetric-stripe.c new file +8 -0
+/*
+ * Construct a striped mapping.
+ * <number of stripes> <chunk size> <ratio> [<dev_path> <offset>]+
+ */
+static int asymmetric_stripe_ctr(struct dm_target *ti,
+		unsigned int argc,
+		char **argv)
+{

[snip]

Quoted 6 lines
drivers/md/dm-asymmetric-stripe.c new file +6 -0
+static void asymmetric_stripe_map_range_sector(asm_stripe_c *sc,
+		sector_t sector,
+		uint32_t target_stripe,
+		sector_t *result)
+{
+	sector_t width_offset;

drivers/md/dm-asymmetric-stripe.c line 310

Quoted 10 lines
drivers/md/dm-asymmetric-stripe.c new file +10 -0
+	uint32_t stripe;
+
+	width_offset = stripe_index_fetch(sc, &sector, &stripe);
+
+	*result = sector * sc->stripe[target_stripe].opt_io_size;
+
+	if (target_stripe < stripe)
+		*result += sc->stripe[target_stripe].opt_io_size;
+	else if (target_stripe == stripe)
+		*result += width_offset;

Here you don't expect target_stripe ever to be > stripe, right? Then the last "else if" can just be "else"...

Quoted 2 lines
drivers/md/dm-asymmetric-stripe.c new file +2 -0
+}
+
Signature · 1 line
~Randy
author
#2 lore raw

No, I don't think so, "target_stripe > stripe" is another condition, but I do nothing here. If I use "else" the condition "target_strie > stripe" can not be handled.

2017-12-26 12:22 GMT+08:00 Randy Dunlap <[email protected]>:

Quoted 374 lines · On 12/25/2017 07:52 PM, [email protected] wrote:
Quoted 7 lines

From: liuchaowei <[email protected]>

This asymmetric stripe target device driver can achieve better io performance between those devices which possess different io performance

There are 2 storage device or flash devices: A and B, their sequential read permance are 220M/s and 315M/s inspectively, so their sequential

performance respectively,

Quoted 7 lines

read speed could be approximately equal to 2:3, if we use stripe type to combine these two devices, their layout could be showed below:
--------------------------------------------------------
| A1 | A2 | B1 | B2 | B3 |
--------------------------------------------------------

If we seletect asymmetric stripe type, their layout could be illustrated

select

Quoted 8 lines

follow:
--------------------------------------------------------
| A1 | B1 |
--------------------------------------------------------

The former has 5 stripe devices and each stripe device has also equal chunk size, e.g.: 256secs. If there is a data block which size is 1280secs, so transfer the data to this stripe defvice will be split

device

Quoted 5 lines

to 5 ios which io size is 256secs. But if we use the asymmetric stripe device, it only has two stripe devices and each one has be setting in optimal chunk size, e.g.: ratio is 2:3, the first one optimal chunk size is 512secs, the second is 768secs. And same 1280secs data block just only be splited two ios, this can be achieve

split into two ios,

Quoted 9 lines

perfect io performance.

Change-Id Iebaee3480e27022e2b3a7edbfb65425b1166274e
---
 Documentation/device-mapper/asymmetric-striped.txt |  85 ++++
 drivers/md/Kconfig                                 |  11 +
 drivers/md/Makefile                                |   1 +
 drivers/md/dm-asymmetric-stripe.c                  | 523

+++++++++++++++++++++

Review

Quoted 7 lines
 drivers/md/dm.c                                    |   5 +
 include/linux/device-mapper.h                      |  15 +
 6 files changed, 640 insertions(+)
 create mode 100644 Documentation/device-mapper/asymmetric-striped.txt
 create mode 100644 drivers/md/dm-asymmetric-stripe.c
(quoted diff) +0 -0

b/Documentation/device-mapper/asymmetric-striped.txt

Documentation/device-mapper/asymmetric-striped.txt line 4

Quoted 9 lines

new file mode 100644
index 000000000000..0412a224a49e

Documentation/device-mapper/asymmetric-striped.txt new file +4 -0
@@ -0,0 +1,85 @@
+dm-asymmetric-stripe
+=========
+
+Device-Mapper's "asm-striped" target is used to create a striped (i.e.

RAID-0)

Documentation/device-mapper/asymmetric-striped.txt line 5

Quoted 1 line
Documentation/device-mapper/asymmetric-striped.txt new file +1 -0
+device across one or more underlying devices. Data is written in

"chunks",

Documentation/device-mapper/asymmetric-striped.txt line 7

Quoted 2 lines
Documentation/device-mapper/asymmetric-striped.txt new file +2 -0
+with consecutive chunks rotating among the underlying devices. This can
+potentially provide improved I/O throughput by utilizing several

physical

Documentation/device-mapper/asymmetric-striped.txt line 8

Quoted 1 line
Documentation/device-mapper/asymmetric-striped.txt new file +1 -0
+devices in parallel. However, in order to gain maximum I/O performance

bewteen

between

Documentation/device-mapper/asymmetric-striped.txt line 9

Quoted 1 line
Documentation/device-mapper/asymmetric-striped.txt new file +1 -0
+slow and fast device, there is a ratio to set up the chunk size among

these

Quoted 4 lines
Documentation/device-mapper/asymmetric-striped.txt new file +4 -0
+device.
+
+Parameters: <num devs> <chunk size> <ratio> [<dev path> <offset>]+
+<num devs>: Number of underlying devices.

Documentation/device-mapper/asymmetric-striped.txt

Quoted 10 lines
Documentation/device-mapper/asymmetric-striped.txt new file +10 -0
+<chunk size>: Size of each chunk of data. Must be at least as
+large as the system's PAGE_SIZE.
+<ratio>: The proportion of per io size, it is the times as much
+as 1 chunk size
+<dev path>: Full pathname to the underlying block-device, or a
+"major:minor" device-number.
+<offset>: Starting sector within the device.
+
+One or more underlying devices can be specified. The striped device
+size must be a multiple of the chunk size multiplied by the number of

underlying

Documentation/device-mapper/asymmetric-striped.txt line 24

Quoted 1 line
Documentation/device-mapper/asymmetric-striped.txt new file +1 -0
+devices. However, there is a ratio can be setting, e.g.: 2:3 means the

first one

there is a ratio that can be set,

Documentation/device-mapper/asymmetric-striped.txt line 25

Quoted 1 line
Documentation/device-mapper/asymmetric-striped.txt new file +1 -0
+striped device optimal width size is 2 time as much as 1 chunk size,

the second

times

Documentation/device-mapper/asymmetric-striped.txt

Quoted 9 lines
Documentation/device-mapper/asymmetric-striped.txt new file +9 -0
+striped device is 3.
+
+
+Example scripts
+===============
+
+[[
+#!/usr/bin/perl -w
+# Create a striped device across any number of underlying devices. The

device

Quoted 20 lines
Documentation/device-mapper/asymmetric-striped.txt new file +20 -0
+# will be called "stripe_dev" and have a chunk-size of 128k.
+
+my $chunk_size = 128 * 2;
+my $ratio = "2:3";
+my $dev_name = "stripe_dev";
+my $num_devs = @ARGV;
+my @devs = @ARGV;
+
+if ($num_devs < 2) {
+die("Specify at least two devices\n");
+}
+
+
+$stripe_average_size = 1073741824
+$stripe_dev_size = $stripe_average_size * 5;
+
+$table = "0 $stripe_dev_size asm-striped $num_devs $chunk_size $ratio";
+for ($i = 0; $i < $num_devs; $i++) {
+$table .= " $devs[$i] 0";
+}

Documentation/device-mapper/asymmetric-striped.txt line 64

Quoted 10 lines
Documentation/device-mapper/asymmetric-striped.txt new file +10 -0
+
+`echo $table | dmsetup create $dev_name`;
+]]
+
+
+Why asymmetric striped
+=======================
+Considering one case:
+There are 2 storage device or flash devices: A and B, their sequential
+read permance are 220M/s and 315M/s inspectively, so their sequential

performance respectively,

Documentation/device-mapper/asymmetric-striped.txt line 71

Quoted 7 lines
Documentation/device-mapper/asymmetric-striped.txt new file +7 -0
+read speed could be approximately equal to 2:3, if we use stripe type
+to combine these two devices, their layout could be showed below:
+--------------------------------------------------------
+|    A1    |    A2    |    B1    |    B2    |    B3    |
+--------------------------------------------------------
+
+If we seletect asymmetric stripe type, their layout could be illustrated

select

Documentation/device-mapper/asymmetric-striped.txt

Quoted 7 lines
Documentation/device-mapper/asymmetric-striped.txt new file +7 -0
+follow:
+--------------------------------------------------------
+|         A1          |               B1               |
+--------------------------------------------------------
+
+The former has 5 stripe devices and each stripe device has also equal
+chunk size, e.g.: 256secs. If there is a data block which size is

1280secs,

Documentation/device-mapper/asymmetric-striped.txt line 79

Quoted 1 line
Documentation/device-mapper/asymmetric-striped.txt new file +1 -0
+so transfer the data to this stripe defvice will be split to 5 ios

which io

device

Documentation/device-mapper/asymmetric-striped.txt line 80

Quoted 1 line
Documentation/device-mapper/asymmetric-striped.txt new file +1 -0
+size is 256secs. But if we use the asymmetric stripe device, it only

has two

Documentation/device-mapper/asymmetric-striped.txt line 81

Quoted 1 line
Documentation/device-mapper/asymmetric-striped.txt new file +1 -0
+stripe devices and each one has be setting in optimal chunk size, e.g.:

ratio

Documentation/device-mapper/asymmetric-striped.txt line 82

Quoted 1 line
Documentation/device-mapper/asymmetric-striped.txt new file +1 -0
+is 2:3, the first one optimal chunk size is 512secs, the second is

768secs.

Documentation/device-mapper/asymmetric-striped.txt line 83

Quoted 1 line
Documentation/device-mapper/asymmetric-striped.txt new file +1 -0
+And same 1280secs data block just only be splited two ios, this can be

achieve

split into two ios,

Quoted 7 lines
Documentation/device-mapper/asymmetric-striped.txt new file +2 -0
+perfect io performance.
+
drivers/md/Kconfig +0 -0
index 7d5aa2c5c81d..4232b929c2f3 100644

drivers/md/Kconfig config DM_FLAKEY · line 462

Quoted 8 lines
drivers/md/Kconfig +5 -0
@@ -455,6 +455,17 @@ config DM_FLAKEY
        ---help---
          A target that intermittently fails I/O for debugging purposes.
 
+config DM_ASYMMETRIC_STRIPE
+     tristate "DM asymmetric stripe(asymmetric raid0)"
+     depends on BLK_DEV_DM
+     ---help---
+       This device-mapper target creates a asymmetric raid0/stripe

device that

drivers/md/Kconfig config DM_FLAKEY · line 463

Quoted 1 line
drivers/md/Kconfig +1 -0
+          support asymmetric stripe chunk size and can gain same

performance as

drivers/md/Kconfig config DM_FLAKEY · line 464

Quoted 1 line
drivers/md/Kconfig +1 -0
+          raid0 device

Align "support" and "raid0" under "This". And end the sentence with a period (".").

drivers/md/Kconfig config DM_FLAKEY · line 466

Quoted 2 lines
drivers/md/Kconfig +2 -0
+
+          You must configure the accurate ratio between different

physical storage

drivers/md/Kconfig config DM_FLAKEY · line 467

Quoted 1 line
drivers/md/Kconfig +1 -0
+          device respectively

End sentence with a period.

Review

Quoted 6 lines
drivers/md/Kconfig +1 -0
+
 config DM_VERITY
      tristate "Verity target support"
      depends on BLK_DEV_DM
(quoted diff) +0 -0

b/drivers/md/dm-asymmetric-stripe.c

Quoted 16 lines

new file mode 100644
index 000000000000..4ef3915b435a

drivers/md/dm-asymmetric-stripe.c new file +11 -0
@@ -0,0 +1,523 @@
+/*
+ * Copyright (C) 2018 Smartisan, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.

drivers/md/dm-asymmetric-stripe.c line 21

Quoted 10 lines
drivers/md/dm-asymmetric-stripe.c new file +10 -0
+ *
+ * Author: <[email protected]>
+ * Name: Henry Liu
+ *
+ */
+
+
+#include "dm.h"
+#include <linux/device-mapper.h>
+

#include <linux/atomic.h>

drivers/md/dm-asymmetric-stripe.c line 23

Quoted 2 lines
drivers/md/dm-asymmetric-stripe.c new file +2 -0
+#include <linux/module.h>
+#include <linux/init.h>

#include <linux/kernel.h>

drivers/md/dm-asymmetric-stripe.c line 25

Quoted 2 lines
drivers/md/dm-asymmetric-stripe.c new file +2 -0
+#include <linux/blkdev.h>
+#include <linux/bio.h>

#include <linux/bitops.h>

drivers/md/dm-asymmetric-stripe.c line 27

Quoted 2 lines
drivers/md/dm-asymmetric-stripe.c new file +2 -0
+#include <linux/slab.h>
+#include <linux/log2.h>

#include <linux/workqueue.h>

Quoted 6 lines
drivers/md/dm-asymmetric-stripe.c new file +5 -0
+
+#define DM_MSG_PREFIX "asm-striped"
+#define DM_IO_ERROR_THRESHOLD 15
 
+/*
+ * An event is triggered whenever a drive

drivers/md/dm-asymmetric-stripe.c line 77

Quoted 10 lines
drivers/md/dm-asymmetric-stripe.c new file +10 -0
+ * drops out of a stripe volume.
+ */
+static void trigger_event(struct work_struct *work)
+{
+     asm_stripe_c *sc = container_of(work, asm_stripe_c, trigger_event);
+
+     dm_table_event(sc->ti->table);
+}
+
+     static inline

Above line should not be indented.
Above and below should be on one line if <= 80 characters.

Quoted 37 lines
drivers/md/dm-asymmetric-stripe.c new file +36 -0
+asm_stripe_c *alloc_context(unsigned int stripes)
+{
+     size_t len;
+
+     if (dm_array_too_big(sizeof(asm_stripe_c),
+                             sizeof(asm_stripe),
+                             stripes))
+             return NULL;
+
+     len = sizeof(asm_stripe_c) + (sizeof(asm_stripe) * stripes);
+
+     return kmalloc(len, GFP_KERNEL);
+}
 
+static int set_stripe_ratio(struct dm_target *ti,
+             asm_stripe_c *sc,
+             char *ratio_str)
+{
+     char *p;
+     unsigned int i;
+     uint32_t r = 0, ratio;
+     char *tmp_ratio = ratio_str;
+
+     if (sizeof(sc->ratio_str) < strlen(ratio_str)) {
+             ti->error = "Too big stripe ratio string";
+             return -ENOMEM;
+     }
+
+     strlcpy(sc->ratio_str, ratio_str, strlen(ratio_str) + 1);
+     for (i = 0; i < sc->stripes; i++) {
+             p  = strsep(&tmp_ratio, ":");
+             if (p == NULL)
+                     return -EINVAL;
+
+             if (kstrtouint(p, 10, &ratio) || !ratio)
+                     return -EINVAL;
+

drivers/md/dm-asymmetric-stripe.c line 152

Quoted 10 lines
drivers/md/dm-asymmetric-stripe.c new file +10 -0
+             sc->stripe[i].ratio = ratio;
+             r += ratio;
+     }
+
+     sc->total_ratio = r;
+     sc->avg_width = ti->len / r;
+     sc->stripe_size = r * sc->chunk_size;
+
+     return 0;
+}

Insert blank line here.

Quoted 8 lines
drivers/md/dm-asymmetric-stripe.c new file +8 -0
+/*
+ * Construct a striped mapping.
+ * <number of stripes> <chunk size> <ratio> [<dev_path> <offset>]+
+ */
+static int asymmetric_stripe_ctr(struct dm_target *ti,
+             unsigned int argc,
+             char **argv)
+{

[snip]

Quoted 6 lines
drivers/md/dm-asymmetric-stripe.c new file +6 -0
+static void asymmetric_stripe_map_range_sector(asm_stripe_c *sc,
+             sector_t sector,
+             uint32_t target_stripe,
+             sector_t *result)
+{
+     sector_t width_offset;

drivers/md/dm-asymmetric-stripe.c line 310

Quoted 10 lines
drivers/md/dm-asymmetric-stripe.c new file +10 -0
+     uint32_t stripe;
+
+     width_offset = stripe_index_fetch(sc, &sector, &stripe);
+
+     *result = sector * sc->stripe[target_stripe].opt_io_size;
+
+     if (target_stripe < stripe)
+             *result += sc->stripe[target_stripe].opt_io_size;
+     else if (target_stripe == stripe)
+             *result += width_offset;

Here you don't expect target_stripe ever to be > stripe, right? Then the last "else if" can just be "else"...

drivers/md/dm-asymmetric-stripe.c

Quoted 2 lines
drivers/md/dm-asymmetric-stripe.c new file +2 -0
+}
+

--
~Randy