<div dir="ltr">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. </div><div class="gmail_extra"><br><div class="gmail_quote">2017-12-26 12:22 GMT+08:00 Randy Dunlap <span dir="ltr"><<a href="mailto:rdunlap@infradead.org" target="_blank">rdunlap@infradead.org</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On 12/25/2017 07:52 PM, <a href="mailto:tgvlcw@gmail.com">tgvlcw@gmail.com</a> wrote:<br>
> From: liuchaowei <<a href="mailto:tgvlcw@gmail.com">tgvlcw@gmail.com</a>><br>
><br>
> This asymmetric stripe target device driver can achieve better io<br>
> performance between those devices which possess different io performance<br>
><br>
> There are 2 storage device or flash devices: A and B, their sequential<br>
> read permance are 220M/s and 315M/s inspectively, so their sequential<br>
<br>
       performance                    respectively,<br>
<br>
> read speed could be approximately equal to 2:3, if we use stripe type<br>
> to combine these two devices, their layout could be showed below:<br>
> ------------------------------<wbr>--------------------------<br>
> |    A1    |    A2    |    B1    |    B2    |    B3    |<br>
> ------------------------------<wbr>--------------------------<br>
><br>
> If we seletect asymmetric stripe type, their layout could be illustrated<br>
<br>
        select<br>
<br>
> follow:<br>
> ------------------------------<wbr>--------------------------<br>
> |         A1          |               B1               |<br>
> ------------------------------<wbr>--------------------------<br>
><br>
> The former has 5 stripe devices and each stripe device has also equal<br>
> chunk size, e.g.: 256secs. If there is a data block which size is<br>
> 1280secs, so transfer the data to this stripe defvice will be split<br>
<br>
                                                device<br>
<br>
> to 5 ios which io size is 256secs. But if we use the asymmetric<br>
> stripe device, it only has two stripe devices and each one has be<br>
> setting in optimal chunk size, e.g.: ratio is 2:3, the first one<br>
> optimal chunk size is 512secs, the second is 768secs.  And same<br>
> 1280secs data block just only be splited two ios, this can be achieve<br>
<br>
                                   split into two ios,<br>
<br>
> perfect io performance.<br>
><br>
> Change-Id: Iebaee3480e27022e2b3a7edbfb654<wbr>25b1166274e<br>
> Signed-off-by: liuchaowei <<a href="mailto:tgvlcw@gmail.com">tgvlcw@gmail.com</a>><br>
> ---<br>
>  Documentation/device-mapper/<wbr>asymmetric-striped.txt |  85 ++++<br>
>  drivers/md/Kconfig                                 |  11 +<br>
>  drivers/md/Makefile                                |   1 +<br>
>  drivers/md/dm-asymmetric-<wbr>stripe.c                  | 523 +++++++++++++++++++++<br>
>  drivers/md/dm.c                                    |   5 +<br>
>  include/linux/device-mapper.h                      |  15 +<br>
>  6 files changed, 640 insertions(+)<br>
>  create mode 100644 Documentation/device-mapper/<wbr>asymmetric-striped.txt<br>
>  create mode 100644 drivers/md/dm-asymmetric-<wbr>stripe.c<br>
><br>
> diff --git a/Documentation/device-mapper/<wbr>asymmetric-striped.txt b/Documentation/device-mapper/<wbr>asymmetric-striped.txt<br>
> new file mode 100644<br>
> index 000000000000..0412a224a49e<br>
> --- /dev/null<br>
> +++ b/Documentation/device-mapper/<wbr>asymmetric-striped.txt<br>
> @@ -0,0 +1,85 @@<br>
> +dm-asymmetric-stripe<br>
> +=========<br>
> +<br>
> +Device-Mapper's "asm-striped" target is used to create a striped (i.e. RAID-0)<br>
> +device across one or more underlying devices. Data is written in "chunks",<br>
> +with consecutive chunks rotating among the underlying devices. This can<br>
> +potentially provide improved I/O throughput by utilizing several physical<br>
> +devices in parallel. However, in order to gain maximum I/O performance bewteen<br>
<br>
                                                                          between<br>
<br>
> +slow and fast device, there is a ratio to set up the chunk size among these<br>
> +device.<br>
> +<br>
> +Parameters: <num devs> <chunk size> <ratio> [<dev path> <offset>]+<br>
> +<num devs>: Number of underlying devices.<br>
> +<chunk size>: Size of each chunk of data. Must be at least as<br>
> +large as the system's PAGE_SIZE.<br>
> +<ratio>: The proportion of per io size, it is the times as much<br>
> +as 1 chunk size<br>
> +<dev path>: Full pathname to the underlying block-device, or a<br>
> +"major:minor" device-number.<br>
> +<offset>: Starting sector within the device.<br>
> +<br>
> +One or more underlying devices can be specified. The striped device<br>
> +size must be a multiple of the chunk size multiplied by the number of underlying<br>
> +devices. However, there is a ratio can be setting, e.g.: 2:3 means the first one<br>
<br>
                     there is a ratio that can be set,<br>
<br>
> +striped device optimal width size is 2 time as much as 1 chunk size, the second<br>
<br>
                                          times<br>
<br>
> +striped device is 3.<br>
> +<br>
> +<br>
> +Example scripts<br>
> +===============<br>
> +<br>
> +[[<br>
> +#!/usr/bin/perl -w<br>
> +# Create a striped device across any number of underlying devices. The device<br>
> +# will be called "stripe_dev" and have a chunk-size of 128k.<br>
> +<br>
> +my $chunk_size = 128 * 2;<br>
> +my $ratio = "2:3";<br>
> +my $dev_name = "stripe_dev";<br>
> +my $num_devs = @ARGV;<br>
> +my @devs = @ARGV;<br>
> +<br>
> +if ($num_devs < 2) {<br>
> +die("Specify at least two devices\n");<br>
> +}<br>
> +<br>
> +<br>
> +$stripe_average_size = 1073741824<br>
> +$stripe_dev_size = $stripe_average_size * 5;<br>
> +<br>
> +$table = "0 $stripe_dev_size asm-striped $num_devs $chunk_size $ratio";<br>
> +for ($i = 0; $i < $num_devs; $i++) {<br>
> +$table .= " $devs[$i] 0";<br>
> +}<br>
> +<br>
> +`echo $table | dmsetup create $dev_name`;<br>
> +]]<br>
> +<br>
> +<br>
> +Why asymmetric striped<br>
> +=======================<br>
> +Considering one case:<br>
> +There are 2 storage device or flash devices: A and B, their sequential<br>
> +read permance are 220M/s and 315M/s inspectively, so their sequential<br>
<br>
        performance                    respectively,<br>
<br>
> +read speed could be approximately equal to 2:3, if we use stripe type<br>
> +to combine these two devices, their layout could be showed below:<br>
> +-----------------------------<wbr>---------------------------<br>
> +|    A1    |    A2    |    B1    |    B2    |    B3    |<br>
> +-----------------------------<wbr>---------------------------<br>
> +<br>
> +If we seletect asymmetric stripe type, their layout could be illustrated<br>
<br>
         select<br>
<br>
> +follow:<br>
> +-----------------------------<wbr>---------------------------<br>
> +|         A1          |               B1               |<br>
> +-----------------------------<wbr>---------------------------<br>
> +<br>
> +The former has 5 stripe devices and each stripe device has also equal<br>
> +chunk size, e.g.: 256secs. If there is a data block which size is 1280secs,<br>
> +so transfer the data to this stripe defvice will be split to 5 ios which io<br>
<br>
                                       device<br>
<br>
> +size is 256secs. But if we use the asymmetric stripe device, it only has two<br>
> +stripe devices and each one has be setting in optimal chunk size, e.g.: ratio<br>
> +is 2:3, the first one optimal chunk size is 512secs, the second is 768secs.<br>
> +And same 1280secs data block just only be splited two ios, this can be achieve<br>
<br>
                                             split into two ios,<br>
<br>
> +perfect io performance.<br>
> +<br>
> diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig<br>
> index 7d5aa2c5c81d..4232b929c2f3 100644<br>
> --- a/drivers/md/Kconfig<br>
> +++ b/drivers/md/Kconfig<br>
> @@ -455,6 +455,17 @@ config DM_FLAKEY<br>
>         ---help---<br>
>           A target that intermittently fails I/O for debugging purposes.<br>
><br>
> +config DM_ASYMMETRIC_STRIPE<br>
> +     tristate "DM asymmetric stripe(asymmetric raid0)"<br>
> +     depends on BLK_DEV_DM<br>
> +     ---help---<br>
> +       This device-mapper target creates a asymmetric raid0/stripe device that<br>
> +          support asymmetric stripe chunk size and can gain same performance as<br>
> +          raid0 device<br>
<br>
Align "support" and "raid0" under "This".  And end the sentence with a period (".").<br>
<br>
> +<br>
> +          You must configure the accurate ratio between different physical storage<br>
> +          device respectively<br>
<br>
End sentence with a period.<br>
<br>
> +<br>
>  config DM_VERITY<br>
>       tristate "Verity target support"<br>
>       depends on BLK_DEV_DM<br>
<br>
> diff --git a/drivers/md/dm-asymmetric-<wbr>stripe.c b/drivers/md/dm-asymmetric-<wbr>stripe.c<br>
> new file mode 100644<br>
> index 000000000000..4ef3915b435a<br>
> --- /dev/null<br>
> +++ b/drivers/md/dm-asymmetric-<wbr>stripe.c<br>
> @@ -0,0 +1,523 @@<br>
> +/*<br>
> + * Copyright (C) 2018 Smartisan, Inc.<br>
> + *<br>
> + * This software is licensed under the terms of the GNU General Public<br>
> + * License version 2, as published by the Free Software Foundation, and<br>
> + * may be copied, distributed, and modified under those terms.<br>
> + *<br>
> + * This program is distributed in the hope that it will be useful,<br>
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the<br>
> + * GNU General Public License for more details.<br>
> + *<br>
> + * Author: <<a href="mailto:tgvlcw@gmail.com">tgvlcw@gmail.com</a>><br>
> + * Name: Henry Liu<br>
> + *<br>
> + */<br>
> +<br>
> +<br>
> +#include "dm.h"<br>
> +#include <linux/device-mapper.h><br>
> +<br>
<br>
#include <linux/atomic.h><br>
<br>
> +#include <linux/module.h><br>
> +#include <linux/init.h><br>
<br>
#include <linux/kernel.h><br>
<br>
> +#include <linux/blkdev.h><br>
> +#include <linux/bio.h><br>
<br>
#include <linux/bitops.h><br>
<br>
> +#include <linux/slab.h><br>
> +#include <linux/log2.h><br>
<br>
#include <linux/workqueue.h><br>
<br>
> +<br>
> +#define DM_MSG_PREFIX "asm-striped"<br>
> +#define DM_IO_ERROR_THRESHOLD 15<br>
<br>
> +/*<br>
> + * An event is triggered whenever a drive<br>
> + * drops out of a stripe volume.<br>
> + */<br>
> +static void trigger_event(struct work_struct *work)<br>
> +{<br>
> +     asm_stripe_c *sc = container_of(work, asm_stripe_c, trigger_event);<br>
> +<br>
> +     dm_table_event(sc->ti->table);<br>
> +}<br>
> +<br>
> +     static inline<br>
<br>
Above line should not be indented.<br>
Above and below should be on one line if <= 80 characters.<br>
<br>
> +asm_stripe_c *alloc_context(unsigned int stripes)<br>
> +{<br>
> +     size_t len;<br>
> +<br>
> +     if (dm_array_too_big(sizeof(asm_<wbr>stripe_c),<br>
> +                             sizeof(asm_stripe),<br>
> +                             stripes))<br>
> +             return NULL;<br>
> +<br>
> +     len = sizeof(asm_stripe_c) + (sizeof(asm_stripe) * stripes);<br>
> +<br>
> +     return kmalloc(len, GFP_KERNEL);<br>
> +}<br>
<br>
> +static int set_stripe_ratio(struct dm_target *ti,<br>
> +             asm_stripe_c *sc,<br>
> +             char *ratio_str)<br>
> +{<br>
> +     char *p;<br>
> +     unsigned int i;<br>
> +     uint32_t r = 0, ratio;<br>
> +     char *tmp_ratio = ratio_str;<br>
> +<br>
> +     if (sizeof(sc->ratio_str) < strlen(ratio_str)) {<br>
> +             ti->error = "Too big stripe ratio string";<br>
> +             return -ENOMEM;<br>
> +     }<br>
> +<br>
> +     strlcpy(sc->ratio_str, ratio_str, strlen(ratio_str) + 1);<br>
> +     for (i = 0; i < sc->stripes; i++) {<br>
> +             p  = strsep(&tmp_ratio, ":");<br>
> +             if (p == NULL)<br>
> +                     return -EINVAL;<br>
> +<br>
> +             if (kstrtouint(p, 10, &ratio) || !ratio)<br>
> +                     return -EINVAL;<br>
> +<br>
> +             sc->stripe[i].ratio = ratio;<br>
> +             r += ratio;<br>
> +     }<br>
> +<br>
> +     sc->total_ratio = r;<br>
> +     sc->avg_width = ti->len / r;<br>
> +     sc->stripe_size = r * sc->chunk_size;<br>
> +<br>
> +     return 0;<br>
> +}<br>
<br>
Insert blank line here.<br>
<br>
> +/*<br>
> + * Construct a striped mapping.<br>
> + * <number of stripes> <chunk size> <ratio> [<dev_path> <offset>]+<br>
> + */<br>
> +static int asymmetric_stripe_ctr(struct dm_target *ti,<br>
> +             unsigned int argc,<br>
> +             char **argv)<br>
> +{<br>
<br>
[snip]<br>
<br>
<br>
> +static void asymmetric_stripe_map_range_<wbr>sector(asm_stripe_c *sc,<br>
> +             sector_t sector,<br>
> +             uint32_t target_stripe,<br>
> +             sector_t *result)<br>
> +{<br>
> +     sector_t width_offset;<br>
> +     uint32_t stripe;<br>
> +<br>
> +     width_offset = stripe_index_fetch(sc, &sector, &stripe);<br>
> +<br>
> +     *result = sector * sc->stripe[target_stripe].opt_<wbr>io_size;<br>
> +<br>
> +     if (target_stripe < stripe)<br>
> +             *result += sc->stripe[target_stripe].opt_<wbr>io_size;<br>
> +     else if (target_stripe == stripe)<br>
> +             *result += width_offset;<br>
<br>
Here you don't expect target_stripe ever to be > stripe, right?<br>
Then the last "else if" can just be "else"...<br>
<br>
<br>
> +}<br>
> +<br>
<span class="HOEnZb"><font color="#888888"><br>
<br>
--<br>
~Randy<br>
</font></span></blockquote></div><br></div>