NeilBrown <neilb@xxxxxxx> writes: > This the first step in allowing md to track bad-blocks per-device so > that we can fail individual blocks rather than the whole device. > > This patch just adds a data structure for recording bad blocks, with > routines to add, remove, search the list. > > Signed-off-by: NeilBrown <neilb@xxxxxxx> > --- > > drivers/md/md.c | 457 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > drivers/md/md.h | 49 ++++++ > 2 files changed, 502 insertions(+), 4 deletions(-) > > diff --git a/drivers/md/md.c b/drivers/md/md.c > index 2a32050..220fadb 100644 > --- a/drivers/md/md.c > +++ b/drivers/md/md.c > @@ -1952,6 +1952,10 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev) > sysfs_remove_link(&rdev->kobj, "block"); > sysfs_put(rdev->sysfs_state); > rdev->sysfs_state = NULL; > + kfree(rdev->badblocks.page); > + rdev->badblocks.count = 0; > + rdev->badblocks.page = NULL; > + rdev->badblocks.active_page = NULL; > /* We need to delay this, otherwise we can deadlock when > * writing to 'remove' to "dev/state". We also need > * to delay it due to rcu usage. > @@ -2778,7 +2782,7 @@ static struct kobj_type rdev_ktype = { > .default_attrs = rdev_default_attrs, > }; > > -void md_rdev_init(mdk_rdev_t *rdev) > +int md_rdev_init(mdk_rdev_t *rdev) > { > rdev->desc_nr = -1; > rdev->saved_raid_disk = -1; > @@ -2794,6 +2798,20 @@ void md_rdev_init(mdk_rdev_t *rdev) > > INIT_LIST_HEAD(&rdev->same_set); > init_waitqueue_head(&rdev->blocked_wait); > + > + /* Add space to store bad block list. > + * This reserves the space even on arrays where it cannot > + * be used - I wonder if that matters > + */ > + rdev->badblocks.count = 0; > + rdev->badblocks.shift = 0; > + rdev->badblocks.page = kmalloc(PAGE_SIZE, GFP_KERNEL); > + rdev->badblocks.active_page = rdev->badblocks.page; > + spin_lock_init(&rdev->badblocks.lock); > + if (rdev->badblocks.page == NULL) > + return -ENOMEM; > + > + return 0; > } > EXPORT_SYMBOL_GPL(md_rdev_init); > /* > @@ -2819,8 +2837,11 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi > return ERR_PTR(-ENOMEM); > } > > - md_rdev_init(rdev); > - if ((err = alloc_disk_sb(rdev))) > + err = md_rdev_init(rdev); > + if (err) > + goto abort_free; > + err = alloc_disk_sb(rdev); > + if (err) > goto abort_free; > > err = lock_rdev(rdev, newdev, super_format == -2); Now error path at abort_free needs to free rdev->badblocks.page otherwise there will be memory leaks. -- To unsubscribe from this list: send the line "unsubscribe linux-raid" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html