aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorJonathan Brassow <jbrassow@redhat.com>2011-08-02 07:32:07 -0400
committerAlasdair G Kergon <agk@redhat.com>2011-08-02 07:32:07 -0400
commitc1084561bb85da3630540ebe951749a8cd8fc714 (patch)
treeecdefcf24dd88f4c19a873fa5d26039a0edf03a7 /drivers/md
parentc0a2fa1ef1057a1e9450d6f055f1cde2ad4f85a2 (diff)
dm raid: add region_size parameter
Allow the user to specify the region_size. Ensures that the supplied value meets md's constraints, viz. the number of regions does not exceed 2^21. Signed-off-by: Jonathan Brassow <jbrassow@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/dm-raid.c82
1 files changed, 79 insertions, 3 deletions
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index d4e95b2e39f6..a8a1915a450d 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -52,7 +52,7 @@ struct raid_dev {
52#define DMPF_MAX_RECOVERY_RATE 0x20 52#define DMPF_MAX_RECOVERY_RATE 0x20
53#define DMPF_MAX_WRITE_BEHIND 0x40 53#define DMPF_MAX_WRITE_BEHIND 0x40
54#define DMPF_STRIPE_CACHE 0x80 54#define DMPF_STRIPE_CACHE 0x80
55 55#define DMPF_REGION_SIZE 0X100
56struct raid_set { 56struct raid_set {
57 struct dm_target *ti; 57 struct dm_target *ti;
58 58
@@ -237,6 +237,67 @@ static int dev_parms(struct raid_set *rs, char **argv)
237} 237}
238 238
239/* 239/*
240 * validate_region_size
241 * @rs
242 * @region_size: region size in sectors. If 0, pick a size (4MiB default).
243 *
244 * Set rs->md.bitmap_info.chunksize (which really refers to 'region size').
245 * Ensure that (ti->len/region_size < 2^21) - required by MD bitmap.
246 *
247 * Returns: 0 on success, -EINVAL on failure.
248 */
249static int validate_region_size(struct raid_set *rs, unsigned long region_size)
250{
251 unsigned long min_region_size = rs->ti->len / (1 << 21);
252
253 if (!region_size) {
254 /*
255 * Choose a reasonable default. All figures in sectors.
256 */
257 if (min_region_size > (1 << 13)) {
258 DMINFO("Choosing default region size of %lu sectors",
259 region_size);
260 region_size = min_region_size;
261 } else {
262 DMINFO("Choosing default region size of 4MiB");
263 region_size = 1 << 13; /* sectors */
264 }
265 } else {
266 /*
267 * Validate user-supplied value.
268 */
269 if (region_size > rs->ti->len) {
270 rs->ti->error = "Supplied region size is too large";
271 return -EINVAL;
272 }
273
274 if (region_size < min_region_size) {
275 DMERR("Supplied region_size (%lu sectors) below minimum (%lu)",
276 region_size, min_region_size);
277 rs->ti->error = "Supplied region size is too small";
278 return -EINVAL;
279 }
280
281 if (!is_power_of_2(region_size)) {
282 rs->ti->error = "Region size is not a power of 2";
283 return -EINVAL;
284 }
285
286 if (region_size < rs->md.chunk_sectors) {
287 rs->ti->error = "Region size is smaller than the chunk size";
288 return -EINVAL;
289 }
290 }
291
292 /*
293 * Convert sectors to bytes.
294 */
295 rs->md.bitmap_info.chunksize = (region_size << 9);
296
297 return 0;
298}
299
300/*
240 * Possible arguments are... 301 * Possible arguments are...
241 * RAID456: 302 * RAID456:
242 * <chunk_size> [optional_args] 303 * <chunk_size> [optional_args]
@@ -249,12 +310,13 @@ static int dev_parms(struct raid_set *rs, char **argv)
249 * [max_recovery_rate <kB/sec/disk>] Throttle RAID initialization 310 * [max_recovery_rate <kB/sec/disk>] Throttle RAID initialization
250 * [max_write_behind <sectors>] See '-write-behind=' (man mdadm) 311 * [max_write_behind <sectors>] See '-write-behind=' (man mdadm)
251 * [stripe_cache <sectors>] Stripe cache size for higher RAIDs 312 * [stripe_cache <sectors>] Stripe cache size for higher RAIDs
313 * [region_size <sectors>] Defines granularity of bitmap
252 */ 314 */
253static int parse_raid_params(struct raid_set *rs, char **argv, 315static int parse_raid_params(struct raid_set *rs, char **argv,
254 unsigned num_raid_params) 316 unsigned num_raid_params)
255{ 317{
256 unsigned i, rebuild_cnt = 0; 318 unsigned i, rebuild_cnt = 0;
257 unsigned long value; 319 unsigned long value, region_size = 0;
258 char *key; 320 char *key;
259 321
260 /* 322 /*
@@ -365,6 +427,9 @@ static int parse_raid_params(struct raid_set *rs, char **argv,
365 return -EINVAL; 427 return -EINVAL;
366 } 428 }
367 rs->md.sync_speed_max = (int)value; 429 rs->md.sync_speed_max = (int)value;
430 } else if (!strcasecmp(key, "region_size")) {
431 rs->print_flags |= DMPF_REGION_SIZE;
432 region_size = value;
368 } else { 433 } else {
369 DMERR("Unable to parse RAID parameter: %s", key); 434 DMERR("Unable to parse RAID parameter: %s", key);
370 rs->ti->error = "Unable to parse RAID parameters"; 435 rs->ti->error = "Unable to parse RAID parameters";
@@ -372,6 +437,14 @@ static int parse_raid_params(struct raid_set *rs, char **argv,
372 } 437 }
373 } 438 }
374 439
440 if (validate_region_size(rs, region_size))
441 return -EINVAL;
442
443 if (rs->md.chunk_sectors)
444 rs->ti->split_io = rs->md.chunk_sectors;
445 else
446 rs->ti->split_io = region_size;
447
375 /* Assume there are no metadata devices until the drives are parsed */ 448 /* Assume there are no metadata devices until the drives are parsed */
376 rs->md.persistent = 0; 449 rs->md.persistent = 0;
377 rs->md.external = 1; 450 rs->md.external = 1;
@@ -469,7 +542,6 @@ static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv)
469 goto bad; 542 goto bad;
470 543
471 INIT_WORK(&rs->md.event_work, do_table_event); 544 INIT_WORK(&rs->md.event_work, do_table_event);
472 ti->split_io = rs->md.chunk_sectors;
473 ti->private = rs; 545 ti->private = rs;
474 546
475 mutex_lock(&rs->md.reconfig_mutex); 547 mutex_lock(&rs->md.reconfig_mutex);
@@ -596,6 +668,10 @@ static int raid_status(struct dm_target *ti, status_type_t type,
596 conf ? conf->max_nr_stripes * 2 : 0); 668 conf ? conf->max_nr_stripes * 2 : 0);
597 } 669 }
598 670
671 if (rs->print_flags & DMPF_REGION_SIZE)
672 DMEMIT(" region_size %lu",
673 rs->md.bitmap_info.chunksize >> 9);
674
599 DMEMIT(" %d", rs->md.raid_disks); 675 DMEMIT(" %d", rs->md.raid_disks);
600 for (i = 0; i < rs->md.raid_disks; i++) { 676 for (i = 0; i < rs->md.raid_disks; i++) {
601 DMEMIT(" -"); /* metadata device */ 677 DMEMIT(" -"); /* metadata device */