root/drivers/md/dm-unstripe.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cleanup_unstripe
  2. unstripe_ctr
  3. unstripe_dtr
  4. map_to_core
  5. unstripe_map
  6. unstripe_status
  7. unstripe_iterate_devices
  8. unstripe_io_hints
  9. dm_unstripe_init
  10. dm_unstripe_exit

   1 /*
   2  * Copyright (C) 2017 Intel Corporation.
   3  *
   4  * This file is released under the GPL.
   5  */
   6 
   7 #include "dm.h"
   8 
   9 #include <linux/module.h>
  10 
  11 struct unstripe_c {
  12         struct dm_dev *dev;
  13         sector_t physical_start;
  14 
  15         uint32_t stripes;
  16 
  17         uint32_t unstripe;
  18         sector_t unstripe_width;
  19         sector_t unstripe_offset;
  20 
  21         uint32_t chunk_size;
  22         u8 chunk_shift;
  23 };
  24 
  25 #define DM_MSG_PREFIX "unstriped"
  26 
  27 static void cleanup_unstripe(struct unstripe_c *uc, struct dm_target *ti)
  28 {
  29         if (uc->dev)
  30                 dm_put_device(ti, uc->dev);
  31         kfree(uc);
  32 }
  33 
  34 /*
  35  * Contruct an unstriped mapping.
  36  * <number of stripes> <chunk size> <stripe #> <dev_path> <offset>
  37  */
  38 static int unstripe_ctr(struct dm_target *ti, unsigned int argc, char **argv)
  39 {
  40         struct unstripe_c *uc;
  41         sector_t tmp_len;
  42         unsigned long long start;
  43         char dummy;
  44 
  45         if (argc != 5) {
  46                 ti->error = "Invalid number of arguments";
  47                 return -EINVAL;
  48         }
  49 
  50         uc = kzalloc(sizeof(*uc), GFP_KERNEL);
  51         if (!uc) {
  52                 ti->error = "Memory allocation for unstriped context failed";
  53                 return -ENOMEM;
  54         }
  55 
  56         if (kstrtouint(argv[0], 10, &uc->stripes) || !uc->stripes) {
  57                 ti->error = "Invalid stripe count";
  58                 goto err;
  59         }
  60 
  61         if (kstrtouint(argv[1], 10, &uc->chunk_size) || !uc->chunk_size) {
  62                 ti->error = "Invalid chunk_size";
  63                 goto err;
  64         }
  65 
  66         if (kstrtouint(argv[2], 10, &uc->unstripe)) {
  67                 ti->error = "Invalid stripe number";
  68                 goto err;
  69         }
  70 
  71         if (uc->unstripe > uc->stripes && uc->stripes > 1) {
  72                 ti->error = "Please provide stripe between [0, # of stripes]";
  73                 goto err;
  74         }
  75 
  76         if (dm_get_device(ti, argv[3], dm_table_get_mode(ti->table), &uc->dev)) {
  77                 ti->error = "Couldn't get striped device";
  78                 goto err;
  79         }
  80 
  81         if (sscanf(argv[4], "%llu%c", &start, &dummy) != 1 || start != (sector_t)start) {
  82                 ti->error = "Invalid striped device offset";
  83                 goto err;
  84         }
  85         uc->physical_start = start;
  86 
  87         uc->unstripe_offset = uc->unstripe * uc->chunk_size;
  88         uc->unstripe_width = (uc->stripes - 1) * uc->chunk_size;
  89         uc->chunk_shift = is_power_of_2(uc->chunk_size) ? fls(uc->chunk_size) - 1 : 0;
  90 
  91         tmp_len = ti->len;
  92         if (sector_div(tmp_len, uc->chunk_size)) {
  93                 ti->error = "Target length not divisible by chunk size";
  94                 goto err;
  95         }
  96 
  97         if (dm_set_target_max_io_len(ti, uc->chunk_size)) {
  98                 ti->error = "Failed to set max io len";
  99                 goto err;
 100         }
 101 
 102         ti->private = uc;
 103         return 0;
 104 err:
 105         cleanup_unstripe(uc, ti);
 106         return -EINVAL;
 107 }
 108 
 109 static void unstripe_dtr(struct dm_target *ti)
 110 {
 111         struct unstripe_c *uc = ti->private;
 112 
 113         cleanup_unstripe(uc, ti);
 114 }
 115 
 116 static sector_t map_to_core(struct dm_target *ti, struct bio *bio)
 117 {
 118         struct unstripe_c *uc = ti->private;
 119         sector_t sector = bio->bi_iter.bi_sector;
 120         sector_t tmp_sector = sector;
 121 
 122         /* Shift us up to the right "row" on the stripe */
 123         if (uc->chunk_shift)
 124                 tmp_sector >>= uc->chunk_shift;
 125         else
 126                 sector_div(tmp_sector, uc->chunk_size);
 127 
 128         sector += uc->unstripe_width * tmp_sector;
 129 
 130         /* Account for what stripe we're operating on */
 131         return sector + uc->unstripe_offset;
 132 }
 133 
 134 static int unstripe_map(struct dm_target *ti, struct bio *bio)
 135 {
 136         struct unstripe_c *uc = ti->private;
 137 
 138         bio_set_dev(bio, uc->dev->bdev);
 139         bio->bi_iter.bi_sector = map_to_core(ti, bio) + uc->physical_start;
 140 
 141         return DM_MAPIO_REMAPPED;
 142 }
 143 
 144 static void unstripe_status(struct dm_target *ti, status_type_t type,
 145                             unsigned int status_flags, char *result, unsigned int maxlen)
 146 {
 147         struct unstripe_c *uc = ti->private;
 148         unsigned int sz = 0;
 149 
 150         switch (type) {
 151         case STATUSTYPE_INFO:
 152                 break;
 153 
 154         case STATUSTYPE_TABLE:
 155                 DMEMIT("%d %llu %d %s %llu",
 156                        uc->stripes, (unsigned long long)uc->chunk_size, uc->unstripe,
 157                        uc->dev->name, (unsigned long long)uc->physical_start);
 158                 break;
 159         }
 160 }
 161 
 162 static int unstripe_iterate_devices(struct dm_target *ti,
 163                                     iterate_devices_callout_fn fn, void *data)
 164 {
 165         struct unstripe_c *uc = ti->private;
 166 
 167         return fn(ti, uc->dev, uc->physical_start, ti->len, data);
 168 }
 169 
 170 static void unstripe_io_hints(struct dm_target *ti,
 171                                struct queue_limits *limits)
 172 {
 173         struct unstripe_c *uc = ti->private;
 174 
 175         limits->chunk_sectors = uc->chunk_size;
 176 }
 177 
 178 static struct target_type unstripe_target = {
 179         .name = "unstriped",
 180         .version = {1, 1, 0},
 181         .module = THIS_MODULE,
 182         .ctr = unstripe_ctr,
 183         .dtr = unstripe_dtr,
 184         .map = unstripe_map,
 185         .status = unstripe_status,
 186         .iterate_devices = unstripe_iterate_devices,
 187         .io_hints = unstripe_io_hints,
 188 };
 189 
 190 static int __init dm_unstripe_init(void)
 191 {
 192         return dm_register_target(&unstripe_target);
 193 }
 194 
 195 static void __exit dm_unstripe_exit(void)
 196 {
 197         dm_unregister_target(&unstripe_target);
 198 }
 199 
 200 module_init(dm_unstripe_init);
 201 module_exit(dm_unstripe_exit);
 202 
 203 MODULE_DESCRIPTION(DM_NAME " unstriped target");
 204 MODULE_ALIAS("dm-unstriped");
 205 MODULE_AUTHOR("Scott Bauer <scott.bauer@intel.com>");
 206 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */