imsm: clear bad blocks if disk becomes unavailable

If a disk fails or goes missing, clear the bad blocks associated with it
from metadata. If necessary, update disk ordinals.

Signed-off-by: Tomasz Majchrzak <tomasz.majchrzak@intel.com>
Signed-off-by: Jes Sorensen <Jes.Sorensen@redhat.com>
This commit is contained in:
Tomasz Majchrzak 2016-11-29 14:02:32 +01:00 committed by Jes Sorensen
parent c07a5a4f41
commit 4c9e8c1ea6
1 changed files with 39 additions and 7 deletions

View File

@ -905,6 +905,24 @@ static int record_new_badblock(struct bbm_log *log, const __u8 idx, unsigned
return new_bb;
}
/* clear all bad blocks for given disk */
static void clear_disk_badblocks(struct bbm_log *log, const __u8 idx)
{
__u32 i = 0;
while (i < log->entry_count) {
struct bbm_log_entry *entries = log->marked_block_entries;
if (entries[i].disk_ordinal == idx) {
if (i < log->entry_count - 1)
entries[i] = entries[log->entry_count - 1];
log->entry_count--;
} else {
i++;
}
}
}
/* clear given bad block */
static int clear_badblock(struct bbm_log *log, const __u8 idx, const unsigned
long long sector, const int length) {
@ -7497,7 +7515,8 @@ static int is_resyncing(struct imsm_dev *dev)
}
/* return true if we recorded new information */
static int mark_failure(struct imsm_dev *dev, struct imsm_disk *disk, int idx)
static int mark_failure(struct intel_super *super,
struct imsm_dev *dev, struct imsm_disk *disk, int idx)
{
__u32 ord;
int slot;
@ -7539,12 +7558,16 @@ static int mark_failure(struct imsm_dev *dev, struct imsm_disk *disk, int idx)
}
if (map->failed_disk_num == 0xff)
map->failed_disk_num = slot;
clear_disk_badblocks(super->bbm_log, ord_to_idx(ord));
return 1;
}
static void mark_missing(struct imsm_dev *dev, struct imsm_disk *disk, int idx)
static void mark_missing(struct intel_super *super,
struct imsm_dev *dev, struct imsm_disk *disk, int idx)
{
mark_failure(dev, disk, idx);
mark_failure(super, dev, disk, idx);
if (disk->scsi_id == __cpu_to_le32(~(__u32)0))
return;
@ -7580,7 +7603,7 @@ static void handle_missing(struct intel_super *super, struct imsm_dev *dev)
end_migration(dev, super, map_state);
}
for (dl = super->missing; dl; dl = dl->next)
mark_missing(dev, &dl->disk, dl->index);
mark_missing(super, dev, &dl->disk, dl->index);
super->updates_pending++;
}
@ -7869,7 +7892,7 @@ static void imsm_set_disk(struct active_array *a, int n, int state)
/* check for new failures */
if (state & DS_FAULTY) {
if (mark_failure(dev, disk, ord_to_idx(ord)))
if (mark_failure(super, dev, disk, ord_to_idx(ord)))
super->updates_pending++;
}
@ -8967,7 +8990,7 @@ static int apply_takeover_update(struct imsm_update_takeover *u,
for (du = super->missing; du; du = du->next)
if (du->index >= 0) {
set_imsm_ord_tbl_ent(map, du->index, du->index);
mark_missing(dv->dev, &du->disk, du->index);
mark_missing(super, dv->dev, &du->disk, du->index);
}
return 1;
@ -9541,8 +9564,9 @@ static void imsm_delete(struct intel_super *super, struct dl **dlp, unsigned ind
struct dl *iter;
struct imsm_dev *dev;
struct imsm_map *map;
int i, j, num_members;
unsigned int i, j, num_members;
__u32 ord;
struct bbm_log *log = super->bbm_log;
dprintf("deleting device[%d] from imsm_super\n", index);
@ -9575,6 +9599,14 @@ static void imsm_delete(struct intel_super *super, struct dl **dlp, unsigned ind
}
}
for (i = 0; i < log->entry_count; i++) {
struct bbm_log_entry *entry = &log->marked_block_entries[i];
if (entry->disk_ordinal <= index)
continue;
entry->disk_ordinal--;
}
mpb->num_disks--;
super->updates_pending++;
if (*dlp) {