* [PATCH v2] imsm: Remove possibility for get_imsm_dev to return NULL
@ 2021-11-25 11:30 Mateusz Grzonka
2022-01-03 14:08 ` Grzonka, Mateusz
0 siblings, 1 reply; 2+ messages in thread
From: Mateusz Grzonka @ 2021-11-25 11:30 UTC (permalink / raw)
To: linux-raid; +Cc: jes
Returning NULL from get_imsm_dev or __get_imsm_dev will cause segfault.
Guarantee that it never happens.
Signed-off-by: Mateusz Grzonka <mateusz.grzonka@intel.com>
---
super-intel.c | 153 +++++++++++++++++++++++++-------------------------
1 file changed, 78 insertions(+), 75 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 28472a1a..b7441716 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -851,6 +851,21 @@ static struct disk_info *get_disk_info(struct imsm_update_create_array *update)
return inf;
}
+/**
+ * __get_imsm_dev() - Get device with index from imsm_super.
+ * @mpb: &imsm_super pointer, not NULL.
+ * @index: Device index.
+ *
+ * Function works as non-NULL, aborting in such a case,
+ * when NULL would be returned.
+ *
+ * Device index should be in range 0 up to num_raid_devs.
+ * Function assumes the index was already verified.
+ * Index must be valid, otherwise abort() is called.
+ *
+ * Return: Pointer to corresponding imsm_dev.
+ *
+ */
static struct imsm_dev *__get_imsm_dev(struct imsm_super *mpb, __u8 index)
{
int offset;
@@ -858,30 +873,47 @@ static struct imsm_dev *__get_imsm_dev(struct imsm_super *mpb, __u8 index)
void *_mpb = mpb;
if (index >= mpb->num_raid_devs)
- return NULL;
+ goto error;
/* devices start after all disks */
offset = ((void *) &mpb->disk[mpb->num_disks]) - _mpb;
- for (i = 0; i <= index; i++)
+ for (i = 0; i <= index; i++, offset += sizeof_imsm_dev(_mpb + offset, 0))
if (i == index)
return _mpb + offset;
- else
- offset += sizeof_imsm_dev(_mpb + offset, 0);
-
- return NULL;
+error:
+ pr_err("cannot find imsm_dev with index %u in imsm_super\n", index);
+ abort();
}
+/**
+ * get_imsm_dev() - Get device with index from intel_super.
+ * @super: &intel_super pointer, not NULL.
+ * @index: Device index.
+ *
+ * Function works as non-NULL, aborting in such a case,
+ * when NULL would be returned.
+ *
+ * Device index should be in range 0 up to num_raid_devs.
+ * Function assumes the index was already verified.
+ * Index must be valid, otherwise abort() is called.
+ *
+ * Return: Pointer to corresponding imsm_dev.
+ *
+ */
static struct imsm_dev *get_imsm_dev(struct intel_super *super, __u8 index)
{
struct intel_dev *dv;
if (index >= super->anchor->num_raid_devs)
- return NULL;
+ goto error;
+
for (dv = super->devlist; dv; dv = dv->next)
if (dv->index == index)
return dv->dev;
- return NULL;
+error:
+ pr_err("cannot find imsm_dev with index %u in intel_super\n", index);
+ abort();
}
static inline unsigned long long __le48_to_cpu(const struct bbm_log_block_addr
@@ -4358,8 +4390,7 @@ int check_mpb_migr_compatibility(struct intel_super *super)
for (i = 0; i < super->anchor->num_raid_devs; i++) {
struct imsm_dev *dev_iter = __get_imsm_dev(super->anchor, i);
- if (dev_iter &&
- dev_iter->vol.migr_state == 1 &&
+ if (dev_iter->vol.migr_state == 1 &&
dev_iter->vol.migr_type == MIGR_GEN_MIGR) {
/* This device is migrating */
map0 = get_imsm_map(dev_iter, MAP_0);
@@ -4508,8 +4539,6 @@ static void clear_hi(struct intel_super *super)
}
for (i = 0; i < mpb->num_raid_devs; ++i) {
struct imsm_dev *dev = get_imsm_dev(super, i);
- if (!dev)
- return;
for (n = 0; n < 2; ++n) {
struct imsm_map *map = get_imsm_map(dev, n);
if (!map)
@@ -5830,7 +5859,7 @@ static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk,
struct imsm_dev *_dev = __get_imsm_dev(mpb, 0);
_disk = __get_imsm_disk(mpb, dl->index);
- if (!_dev || !_disk) {
+ if (!_disk) {
pr_err("BUG mpb setup error\n");
return 1;
}
@@ -6165,10 +6194,10 @@ static int write_super_imsm(struct supertype *st, int doclose)
for (i = 0; i < mpb->num_raid_devs; i++) {
struct imsm_dev *dev = __get_imsm_dev(mpb, i);
struct imsm_dev *dev2 = get_imsm_dev(super, i);
- if (dev && dev2) {
- imsm_copy_dev(dev, dev2);
- mpb_size += sizeof_imsm_dev(dev, 0);
- }
+
+ imsm_copy_dev(dev, dev2);
+ mpb_size += sizeof_imsm_dev(dev, 0);
+
if (is_gen_migration(dev2))
clear_migration_record = 0;
}
@@ -9032,29 +9061,26 @@ static int imsm_rebuild_allowed(struct supertype *cont, int dev_idx, int failed)
__u8 state;
dev2 = get_imsm_dev(cont->sb, dev_idx);
- if (dev2) {
- state = imsm_check_degraded(cont->sb, dev2, failed, MAP_0);
- if (state == IMSM_T_STATE_FAILED) {
- map = get_imsm_map(dev2, MAP_0);
- if (!map)
- return 1;
- for (slot = 0; slot < map->num_members; slot++) {
- /*
- * Check if failed disks are deleted from intel
- * disk list or are marked to be deleted
- */
- idx = get_imsm_disk_idx(dev2, slot, MAP_X);
- idisk = get_imsm_dl_disk(cont->sb, idx);
- /*
- * Do not rebuild the array if failed disks
- * from failed sub-array are not removed from
- * container.
- */
- if (idisk &&
- is_failed(&idisk->disk) &&
- (idisk->action != DISK_REMOVE))
- return 0;
- }
+
+ state = imsm_check_degraded(cont->sb, dev2, failed, MAP_0);
+ if (state == IMSM_T_STATE_FAILED) {
+ map = get_imsm_map(dev2, MAP_0);
+ for (slot = 0; slot < map->num_members; slot++) {
+ /*
+ * Check if failed disks are deleted from intel
+ * disk list or are marked to be deleted
+ */
+ idx = get_imsm_disk_idx(dev2, slot, MAP_X);
+ idisk = get_imsm_dl_disk(cont->sb, idx);
+ /*
+ * Do not rebuild the array if failed disks
+ * from failed sub-array are not removed from
+ * container.
+ */
+ if (idisk &&
+ is_failed(&idisk->disk) &&
+ (idisk->action != DISK_REMOVE))
+ return 0;
}
}
return 1;
@@ -10088,7 +10114,6 @@ static void imsm_process_update(struct supertype *st,
int victim = u->dev_idx;
struct active_array *a;
struct intel_dev **dp;
- struct imsm_dev *dev;
/* sanity check that we are not affecting the uuid of
* active arrays, or deleting an active array
@@ -10104,8 +10129,7 @@ static void imsm_process_update(struct supertype *st,
* is active in the container, so checking
* mpb->num_raid_devs is just extra paranoia
*/
- dev = get_imsm_dev(super, victim);
- if (a || !dev || mpb->num_raid_devs == 1) {
+ if (a || mpb->num_raid_devs == 1 || victim >= super->anchor->num_raid_devs) {
dprintf("failed to delete subarray-%d\n", victim);
break;
}
@@ -10139,7 +10163,7 @@ static void imsm_process_update(struct supertype *st,
if (a->info.container_member == target)
break;
dev = get_imsm_dev(super, u->dev_idx);
- if (a || !dev || !check_name(super, name, 1)) {
+ if (a || !check_name(super, name, 1)) {
dprintf("failed to rename subarray-%d\n", target);
break;
}
@@ -10168,10 +10192,6 @@ static void imsm_process_update(struct supertype *st,
struct imsm_update_rwh_policy *u = (void *)update->buf;
int target = u->dev_idx;
struct imsm_dev *dev = get_imsm_dev(super, target);
- if (!dev) {
- dprintf("could not find subarray-%d\n", target);
- break;
- }
if (dev->rwh_policy != u->new_policy) {
dev->rwh_policy = u->new_policy;
@@ -11396,8 +11416,10 @@ static int imsm_create_metadata_update_for_migration(
{
struct intel_super *super = st->sb;
int update_memory_size;
+ int current_chunk_size;
struct imsm_update_reshape_migration *u;
- struct imsm_dev *dev;
+ struct imsm_dev *dev = get_imsm_dev(super, super->current_vol);
+ struct imsm_map *map = get_imsm_map(dev, MAP_0);
int previous_level = -1;
dprintf("(enter) New Level = %i\n", geo->level);
@@ -11414,23 +11436,15 @@ static int imsm_create_metadata_update_for_migration(
u->new_disks[0] = -1;
u->new_chunksize = -1;
- dev = get_imsm_dev(super, u->subdev);
- if (dev) {
- struct imsm_map *map;
+ current_chunk_size = __le16_to_cpu(map->blocks_per_strip) / 2;
- map = get_imsm_map(dev, MAP_0);
- if (map) {
- int current_chunk_size =
- __le16_to_cpu(map->blocks_per_strip) / 2;
-
- if (geo->chunksize != current_chunk_size) {
- u->new_chunksize = geo->chunksize / 1024;
- dprintf("imsm: chunk size change from %i to %i\n",
- current_chunk_size, u->new_chunksize);
- }
- previous_level = map->raid_level;
- }
+ if (geo->chunksize != current_chunk_size) {
+ u->new_chunksize = geo->chunksize / 1024;
+ dprintf("imsm: chunk size change from %i to %i\n",
+ current_chunk_size, u->new_chunksize);
}
+ previous_level = map->raid_level;
+
if (geo->level == 5 && previous_level == 0) {
struct mdinfo *spares = NULL;
@@ -12517,9 +12531,6 @@ static int validate_internal_bitmap_imsm(struct supertype *st)
unsigned long long offset;
struct dl *d;
- if (!dev)
- return -1;
-
if (dev->rwh_policy != RWH_BITMAP)
return 0;
@@ -12565,16 +12576,8 @@ static int add_internal_bitmap_imsm(struct supertype *st, int *chunkp,
return -1;
dev = get_imsm_dev(super, vol_idx);
-
- if (!dev) {
- dprintf("cannot find the device for volume index %d\n",
- vol_idx);
- return -1;
- }
dev->rwh_policy = RWH_BITMAP;
-
*chunkp = calculate_bitmap_chunksize(st, dev);
-
return 0;
}
--
2.26.2
^ permalink raw reply related [flat|nested] 2+ messages in thread
* RE: [PATCH v2] imsm: Remove possibility for get_imsm_dev to return NULL
2021-11-25 11:30 [PATCH v2] imsm: Remove possibility for get_imsm_dev to return NULL Mateusz Grzonka
@ 2022-01-03 14:08 ` Grzonka, Mateusz
0 siblings, 0 replies; 2+ messages in thread
From: Grzonka, Mateusz @ 2022-01-03 14:08 UTC (permalink / raw)
To: jes, linux-raid
Hi Jes,
Any updates?
On 11/25/21 12:30 PM, Mateusz Grzonka wrote:
> Returning NULL from get_imsm_dev or __get_imsm_dev will cause segfault.
> Guarantee that it never happens.
>
> Signed-off-by: Mateusz Grzonka <mateusz.grzonka@intel.com>
> ---
> super-intel.c | 153 +++++++++++++++++++++++++-------------------------
> 1 file changed, 78 insertions(+), 75 deletions(-)
>
> diff --git a/super-intel.c b/super-intel.c index 28472a1a..b7441716 100644
> --- a/super-intel.c
> +++ b/super-intel.c
> @@ -851,6 +851,21 @@ static struct disk_info *get_disk_info(struct imsm_update_create_array *update)
> return inf;
> }
>
> +/**
> + * __get_imsm_dev() - Get device with index from imsm_super.
> + * @mpb: &imsm_super pointer, not NULL.
> + * @index: Device index.
> + *
> + * Function works as non-NULL, aborting in such a case,
> + * when NULL would be returned.
> + *
> + * Device index should be in range 0 up to num_raid_devs.
> + * Function assumes the index was already verified.
> + * Index must be valid, otherwise abort() is called.
> + *
> + * Return: Pointer to corresponding imsm_dev.
> + *
> + */
> static struct imsm_dev *__get_imsm_dev(struct imsm_super *mpb, __u8 index) {
> int offset;
> @@ -858,30 +873,47 @@ static struct imsm_dev *__get_imsm_dev(struct imsm_super *mpb, __u8 index)
> void *_mpb = mpb;
>
> if (index >= mpb->num_raid_devs)
> - return NULL;
> + goto error;
>
> /* devices start after all disks */
> offset = ((void *) &mpb->disk[mpb->num_disks]) - _mpb;
>
> - for (i = 0; i <= index; i++)
> + for (i = 0; i <= index; i++, offset += sizeof_imsm_dev(_mpb + offset,
> +0))
> if (i == index)
> return _mpb + offset;
> - else
> - offset += sizeof_imsm_dev(_mpb + offset, 0);
> -
> - return NULL;
> +error:
> + pr_err("cannot find imsm_dev with index %u in imsm_super\n", index);
> + abort();
> }
>
> +/**
> + * get_imsm_dev() - Get device with index from intel_super.
> + * @super: &intel_super pointer, not NULL.
> + * @index: Device index.
> + *
> + * Function works as non-NULL, aborting in such a case,
> + * when NULL would be returned.
> + *
> + * Device index should be in range 0 up to num_raid_devs.
> + * Function assumes the index was already verified.
> + * Index must be valid, otherwise abort() is called.
> + *
> + * Return: Pointer to corresponding imsm_dev.
> + *
> + */
> static struct imsm_dev *get_imsm_dev(struct intel_super *super, __u8 index) {
> struct intel_dev *dv;
>
> if (index >= super->anchor->num_raid_devs)
> - return NULL;
> + goto error;
> +
> for (dv = super->devlist; dv; dv = dv->next)
> if (dv->index == index)
> return dv->dev;
> - return NULL;
> +error:
> + pr_err("cannot find imsm_dev with index %u in intel_super\n", index);
> + abort();
> }
>
> static inline unsigned long long __le48_to_cpu(const struct bbm_log_block_addr @@ -4358,8 +4390,7 @@ int check_mpb_migr_compatibility(struct intel_super *super)
> for (i = 0; i < super->anchor->num_raid_devs; i++) {
> struct imsm_dev *dev_iter = __get_imsm_dev(super->anchor, i);
>
> - if (dev_iter &&
> - dev_iter->vol.migr_state == 1 &&
> + if (dev_iter->vol.migr_state == 1 &&
> dev_iter->vol.migr_type == MIGR_GEN_MIGR) {
> /* This device is migrating */
> map0 = get_imsm_map(dev_iter, MAP_0); @@ -4508,8 +4539,6 @@ static void clear_hi(struct intel_super *super)
> }
> for (i = 0; i < mpb->num_raid_devs; ++i) {
> struct imsm_dev *dev = get_imsm_dev(super, i);
> - if (!dev)
> - return;
> for (n = 0; n < 2; ++n) {
> struct imsm_map *map = get_imsm_map(dev, n);
> if (!map)
> @@ -5830,7 +5859,7 @@ static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk,
> struct imsm_dev *_dev = __get_imsm_dev(mpb, 0);
>
> _disk = __get_imsm_disk(mpb, dl->index);
> - if (!_dev || !_disk) {
> + if (!_disk) {
> pr_err("BUG mpb setup error\n");
> return 1;
> }
> @@ -6165,10 +6194,10 @@ static int write_super_imsm(struct supertype *st, int doclose)
> for (i = 0; i < mpb->num_raid_devs; i++) {
> struct imsm_dev *dev = __get_imsm_dev(mpb, i);
> struct imsm_dev *dev2 = get_imsm_dev(super, i);
> - if (dev && dev2) {
> - imsm_copy_dev(dev, dev2);
> - mpb_size += sizeof_imsm_dev(dev, 0);
> - }
> +
> + imsm_copy_dev(dev, dev2);
> + mpb_size += sizeof_imsm_dev(dev, 0);
> +
> if (is_gen_migration(dev2))
> clear_migration_record = 0;
> }
> @@ -9032,29 +9061,26 @@ static int imsm_rebuild_allowed(struct supertype *cont, int dev_idx, int failed)
> __u8 state;
>
> dev2 = get_imsm_dev(cont->sb, dev_idx);
> - if (dev2) {
> - state = imsm_check_degraded(cont->sb, dev2, failed, MAP_0);
> - if (state == IMSM_T_STATE_FAILED) {
> - map = get_imsm_map(dev2, MAP_0);
> - if (!map)
> - return 1;
> - for (slot = 0; slot < map->num_members; slot++) {
> - /*
> - * Check if failed disks are deleted from intel
> - * disk list or are marked to be deleted
> - */
> - idx = get_imsm_disk_idx(dev2, slot, MAP_X);
> - idisk = get_imsm_dl_disk(cont->sb, idx);
> - /*
> - * Do not rebuild the array if failed disks
> - * from failed sub-array are not removed from
> - * container.
> - */
> - if (idisk &&
> - is_failed(&idisk->disk) &&
> - (idisk->action != DISK_REMOVE))
> - return 0;
> - }
> +
> + state = imsm_check_degraded(cont->sb, dev2, failed, MAP_0);
> + if (state == IMSM_T_STATE_FAILED) {
> + map = get_imsm_map(dev2, MAP_0);
> + for (slot = 0; slot < map->num_members; slot++) {
> + /*
> + * Check if failed disks are deleted from intel
> + * disk list or are marked to be deleted
> + */
> + idx = get_imsm_disk_idx(dev2, slot, MAP_X);
> + idisk = get_imsm_dl_disk(cont->sb, idx);
> + /*
> + * Do not rebuild the array if failed disks
> + * from failed sub-array are not removed from
> + * container.
> + */
> + if (idisk &&
> + is_failed(&idisk->disk) &&
> + (idisk->action != DISK_REMOVE))
> + return 0;
> }
> }
> return 1;
> @@ -10088,7 +10114,6 @@ static void imsm_process_update(struct supertype *st,
> int victim = u->dev_idx;
> struct active_array *a;
> struct intel_dev **dp;
> - struct imsm_dev *dev;
>
> /* sanity check that we are not affecting the uuid of
> * active arrays, or deleting an active array @@ -10104,8 +10129,7 @@ static void imsm_process_update(struct supertype *st,
> * is active in the container, so checking
> * mpb->num_raid_devs is just extra paranoia
> */
> - dev = get_imsm_dev(super, victim);
> - if (a || !dev || mpb->num_raid_devs == 1) {
> + if (a || mpb->num_raid_devs == 1 || victim >=
> +super->anchor->num_raid_devs) {
> dprintf("failed to delete subarray-%d\n", victim);
> break;
> }
> @@ -10139,7 +10163,7 @@ static void imsm_process_update(struct supertype *st,
> if (a->info.container_member == target)
> break;
> dev = get_imsm_dev(super, u->dev_idx);
> - if (a || !dev || !check_name(super, name, 1)) {
> + if (a || !check_name(super, name, 1)) {
> dprintf("failed to rename subarray-%d\n", target);
> break;
> }
> @@ -10168,10 +10192,6 @@ static void imsm_process_update(struct supertype *st,
> struct imsm_update_rwh_policy *u = (void *)update->buf;
> int target = u->dev_idx;
> struct imsm_dev *dev = get_imsm_dev(super, target);
> - if (!dev) {
> - dprintf("could not find subarray-%d\n", target);
> - break;
> - }
>
> if (dev->rwh_policy != u->new_policy) {
> dev->rwh_policy = u->new_policy;
> @@ -11396,8 +11416,10 @@ static int imsm_create_metadata_update_for_migration(
> {
> struct intel_super *super = st->sb;
> int update_memory_size;
> + int current_chunk_size;
> struct imsm_update_reshape_migration *u;
> - struct imsm_dev *dev;
> + struct imsm_dev *dev = get_imsm_dev(super, super->current_vol);
> + struct imsm_map *map = get_imsm_map(dev, MAP_0);
> int previous_level = -1;
>
> dprintf("(enter) New Level = %i\n", geo->level); @@ -11414,23 +11436,15 @@ static int imsm_create_metadata_update_for_migration(
> u->new_disks[0] = -1;
> u->new_chunksize = -1;
>
> - dev = get_imsm_dev(super, u->subdev);
> - if (dev) {
> - struct imsm_map *map;
> + current_chunk_size = __le16_to_cpu(map->blocks_per_strip) / 2;
>
> - map = get_imsm_map(dev, MAP_0);
> - if (map) {
> - int current_chunk_size =
> - __le16_to_cpu(map->blocks_per_strip) / 2;
> -
> - if (geo->chunksize != current_chunk_size) {
> - u->new_chunksize = geo->chunksize / 1024;
> - dprintf("imsm: chunk size change from %i to %i\n",
> - current_chunk_size, u->new_chunksize);
> - }
> - previous_level = map->raid_level;
> - }
> + if (geo->chunksize != current_chunk_size) {
> + u->new_chunksize = geo->chunksize / 1024;
> + dprintf("imsm: chunk size change from %i to %i\n",
> + current_chunk_size, u->new_chunksize);
> }
> + previous_level = map->raid_level;
> +
> if (geo->level == 5 && previous_level == 0) {
> struct mdinfo *spares = NULL;
>
> @@ -12517,9 +12531,6 @@ static int validate_internal_bitmap_imsm(struct supertype *st)
> unsigned long long offset;
> struct dl *d;
>
> - if (!dev)
> - return -1;
> -
> if (dev->rwh_policy != RWH_BITMAP)
> return 0;
>
> @@ -12565,16 +12576,8 @@ static int add_internal_bitmap_imsm(struct supertype *st, int *chunkp,
> return -1;
>
> dev = get_imsm_dev(super, vol_idx);
> -
> - if (!dev) {
> - dprintf("cannot find the device for volume index %d\n",
> - vol_idx);
> - return -1;
> - }
> dev->rwh_policy = RWH_BITMAP;
> -
> *chunkp = calculate_bitmap_chunksize(st, dev);
> -
> return 0;
> }
>
> --
> 2.26.2
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2022-01-03 14:10 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-25 11:30 [PATCH v2] imsm: Remove possibility for get_imsm_dev to return NULL Mateusz Grzonka
2022-01-03 14:08 ` Grzonka, Mateusz
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.