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:
Tomasz Majchrzak 2016-11-28 15:07:05 +01:00 committed by Jes Sorensen
parent 06fb291ac1
commit bb758ccad0
2 changed files with 39 additions and 1 deletions

13
mdadm.h
View File

@ -237,6 +237,17 @@ struct dlm_lksb {
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 */
struct mdinfo {
mdu_array_info_t array;
@ -311,6 +322,8 @@ struct mdinfo {
/* info read from sysfs */
char sysfs_array_state[20];
struct md_bb bb;
};
struct createinfo {

27
sysfs.c
View File

@ -52,8 +52,10 @@ void sysfs_free(struct mdinfo *sra)
while (sra->devs) {
struct mdinfo *d = sra->devs;
sra->devs = d->next;
free(d->bb.entries);
free(d);
}
free(sra->bb.entries);
free(sra);
sra = sra2;
}
@ -261,7 +263,7 @@ struct mdinfo *sysfs_read(int fd, char *devnm, unsigned long options)
dbase = base + strlen(base);
*dbase++ = '/';
dev = xmalloc(sizeof(*dev));
dev = xcalloc(1, sizeof(*dev));
/* Always get slot, major, minor */
strcpy(dbase, "slot");
@ -691,6 +693,7 @@ int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd, int resume)
char nm[PATH_MAX];
char *dname;
int rv;
int i;
sprintf(dv, "%d:%d", sd->disk.major, sd->disk.minor);
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)
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;
}