diff options
author | mwilck@arcor.de <mwilck@arcor.de> | 2013-09-24 19:18:52 +0200 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2013-10-16 15:31:30 +1100 |
commit | 105e6e93a2b556560d0275bd5ceb29751de28469 (patch) | |
tree | 15abb8f617cfdd2fc6aaa1c717ef567a7f6a05bf /super-ddf.c | |
parent | f502b11c743d9fb27615776d42c2daea4edb0f97 (diff) | |
download | mdadm-105e6e93a2b556560d0275bd5ceb29751de28469.tar.gz |
DDF: add_to_super_ddf: be careful with workspace_lba
Some vendor DDF structures interpret workspace_lba
very differently then us. Make a sanity check on the value
before using it for config_size.
Signed-off-by: Martin Wilck <mwilck@arcor.de>
Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'super-ddf.c')
-rw-r--r-- | super-ddf.c | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/super-ddf.c b/super-ddf.c index 002b271..400088e 100644 --- a/super-ddf.c +++ b/super-ddf.c @@ -2703,6 +2703,31 @@ static unsigned int find_unused_pde(const struct ddf_super *ddf) return DDF_NOTFOUND; } +static void _set_config_size(struct phys_disk_entry *pde, const struct dl *dl) +{ + __u64 cfs, t; + cfs = min(dl->size - 32*1024*2ULL, be64_to_cpu(dl->primary_lba)); + t = be64_to_cpu(dl->secondary_lba); + if (t != ~(__u64)0) + cfs = min(cfs, t); + /* + * Some vendor DDF structures interpret workspace_lba + * very differently then us. Make a sanity check on the value. + */ + t = be64_to_cpu(dl->workspace_lba); + if (t < cfs) { + __u64 wsp = cfs - t; + if (wsp > 1024*1024*2ULL && wsp > dl->size / 16) { + pr_err("%s: %x:%x: workspace size 0x%llx too big, ignoring\n", + __func__, dl->major, dl->minor, wsp); + } else + cfs = t; + } + pde->config_size = cpu_to_be64(cfs); + dprintf("%s: %x:%x config_size %llx, DDF structure is %llx blocks\n", + __func__, dl->major, dl->minor, cfs, dl->size-cfs); +} + /* add a device to a container, either while creating it or while * expanding a pre-existing container */ @@ -2825,7 +2850,7 @@ static int add_to_super_ddf(struct supertype *st, if (ddf->dlist == NULL || be64_to_cpu(ddf->dlist->secondary_lba) != ~(__u64)0) __calc_lba(dd, ddf->dlist, secondary_lba, 32); - pde->config_size = dd->workspace_lba; + _set_config_size(pde, dd); sprintf(pde->path, "%17.17s","Information: nil") ; memset(pde->pad, 0xff, 6); |