mdadm: bad block support for external metadata - initialization
If metadata handler provides support for bad blocks, tell md by writing 'external_bbl' to rdev state file (both on create and assemble), followed by a list of known bad blocks written via sysfs 'bad_blocks' file. Signed-off-by: Tomasz Majchrzak <tomasz.majchrzak@intel.com> Reviewed-by: Artur Paszkiewicz <artur.paszkiewicz@intel.com> Signed-off-by: Jes Sorensen <Jes.Sorensen@redhat.com>
This commit is contained in:
parent
06fb291ac1
commit
bb758ccad0
13
mdadm.h
13
mdadm.h
|
@ -237,6 +237,17 @@ struct dlm_lksb {
|
||||||
|
|
||||||
extern const char Name[];
|
extern const char Name[];
|
||||||
|
|
||||||
|
struct md_bb_entry {
|
||||||
|
unsigned long long sector;
|
||||||
|
int length;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct md_bb {
|
||||||
|
int supported;
|
||||||
|
int count;
|
||||||
|
struct md_bb_entry *entries;
|
||||||
|
};
|
||||||
|
|
||||||
/* general information that might be extracted from a superblock */
|
/* general information that might be extracted from a superblock */
|
||||||
struct mdinfo {
|
struct mdinfo {
|
||||||
mdu_array_info_t array;
|
mdu_array_info_t array;
|
||||||
|
@ -311,6 +322,8 @@ struct mdinfo {
|
||||||
|
|
||||||
/* info read from sysfs */
|
/* info read from sysfs */
|
||||||
char sysfs_array_state[20];
|
char sysfs_array_state[20];
|
||||||
|
|
||||||
|
struct md_bb bb;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct createinfo {
|
struct createinfo {
|
||||||
|
|
27
sysfs.c
27
sysfs.c
|
@ -52,8 +52,10 @@ void sysfs_free(struct mdinfo *sra)
|
||||||
while (sra->devs) {
|
while (sra->devs) {
|
||||||
struct mdinfo *d = sra->devs;
|
struct mdinfo *d = sra->devs;
|
||||||
sra->devs = d->next;
|
sra->devs = d->next;
|
||||||
|
free(d->bb.entries);
|
||||||
free(d);
|
free(d);
|
||||||
}
|
}
|
||||||
|
free(sra->bb.entries);
|
||||||
free(sra);
|
free(sra);
|
||||||
sra = sra2;
|
sra = sra2;
|
||||||
}
|
}
|
||||||
|
@ -261,7 +263,7 @@ struct mdinfo *sysfs_read(int fd, char *devnm, unsigned long options)
|
||||||
dbase = base + strlen(base);
|
dbase = base + strlen(base);
|
||||||
*dbase++ = '/';
|
*dbase++ = '/';
|
||||||
|
|
||||||
dev = xmalloc(sizeof(*dev));
|
dev = xcalloc(1, sizeof(*dev));
|
||||||
|
|
||||||
/* Always get slot, major, minor */
|
/* Always get slot, major, minor */
|
||||||
strcpy(dbase, "slot");
|
strcpy(dbase, "slot");
|
||||||
|
@ -691,6 +693,7 @@ int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd, int resume)
|
||||||
char nm[PATH_MAX];
|
char nm[PATH_MAX];
|
||||||
char *dname;
|
char *dname;
|
||||||
int rv;
|
int rv;
|
||||||
|
int i;
|
||||||
|
|
||||||
sprintf(dv, "%d:%d", sd->disk.major, sd->disk.minor);
|
sprintf(dv, "%d:%d", sd->disk.major, sd->disk.minor);
|
||||||
rv = sysfs_set_str(sra, NULL, "new_dev", dv);
|
rv = sysfs_set_str(sra, NULL, "new_dev", dv);
|
||||||
|
@ -722,6 +725,28 @@ int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd, int resume)
|
||||||
if (resume)
|
if (resume)
|
||||||
sysfs_set_num(sra, sd, "recovery_start", sd->recovery_start);
|
sysfs_set_num(sra, sd, "recovery_start", sd->recovery_start);
|
||||||
}
|
}
|
||||||
|
if (sd->bb.supported) {
|
||||||
|
if (sysfs_set_str(sra, sd, "state", "external_bbl")) {
|
||||||
|
/*
|
||||||
|
* backward compatibility - if kernel doesn't support
|
||||||
|
* bad blocks for external metadata, let it continue
|
||||||
|
* as long as there are none known so far
|
||||||
|
*/
|
||||||
|
if (sd->bb.count) {
|
||||||
|
pr_err("The kernel has no support for bad blocks in external metadata\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < sd->bb.count; i++) {
|
||||||
|
char s[30];
|
||||||
|
const struct md_bb_entry *entry = &sd->bb.entries[i];
|
||||||
|
|
||||||
|
snprintf(s, sizeof(s) - 1, "%llu %d\n", entry->sector,
|
||||||
|
entry->length);
|
||||||
|
rv |= sysfs_set_str(sra, sd, "bad_blocks", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue