MISC: Add --examine-badblocks option
This will list the contents of the bad-blocks log, if one is present. Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
parent
8cf2eb96b2
commit
6d388a8816
36
Examine.c
36
Examine.c
|
@ -187,3 +187,39 @@ int Examine(struct mddev_dev *devlist,
|
|||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
int ExamineBadblocks(char *devname, int brief, struct supertype *forcest)
|
||||
{
|
||||
int fd = dev_open(devname, O_RDONLY);
|
||||
struct supertype *st = forcest;
|
||||
int err = 1;
|
||||
|
||||
if (fd < 0) {
|
||||
pr_err("cannot open %s: %s\n", devname, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
if (!st)
|
||||
st = guess_super(fd);
|
||||
if (!st) {
|
||||
if (!brief)
|
||||
pr_err("No md superblock detected on %s\n", devname);
|
||||
goto out;
|
||||
}
|
||||
if (!st->ss->examine_badblocks) {
|
||||
pr_err("%s metadata does not support badblocks\n", st->ss->name);
|
||||
goto out;
|
||||
}
|
||||
err = st->ss->load_super(st, fd, brief ? NULL : devname);
|
||||
if (err)
|
||||
goto out;
|
||||
err = st->ss->examine_badblocks(st, fd, devname);
|
||||
|
||||
out:
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
if (st) {
|
||||
st->ss->free_super(st);
|
||||
free(st);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
|
3
ReadMe.c
3
ReadMe.c
|
@ -95,6 +95,7 @@ struct option long_options[] = {
|
|||
{"update-subarray", 1, 0, UpdateSubarray},
|
||||
{"udev-rules", 2, 0, UdevRules},
|
||||
{"offroot", 0, 0, OffRootOpt},
|
||||
{"examine-badblocks", 0, 0, ExamineBB},
|
||||
|
||||
/* synonyms */
|
||||
{"monitor", 0, 0, 'F'},
|
||||
|
@ -251,6 +252,7 @@ char OptionHelp[] =
|
|||
" --detail -D : Display details of an array\n"
|
||||
" --examine -E : Examine superblock on an array component\n"
|
||||
" --examine-bitmap -X: Display the detail of a bitmap file\n"
|
||||
" --examine-badblocks: Display list of known bad blocks on device\n"
|
||||
" --monitor -F : monitor (follow) some arrays\n"
|
||||
" --grow -G : resize/ reshape and array\n"
|
||||
" --incremental -I : add/remove a single device to/from an array as appropriate\n"
|
||||
|
@ -490,6 +492,7 @@ char Help_misc[] =
|
|||
" --detail-platform : Display hardware/firmware details\n"
|
||||
" --examine -E : Examine superblock on an array component\n"
|
||||
" --examine-bitmap -X: Display contents of a bitmap file\n"
|
||||
" --examine-badblocks: Display list of known bad blocks on device\n"
|
||||
" --zero-superblock : erase the MD superblock from a device.\n"
|
||||
" --run -R : start a partially built array\n"
|
||||
" --stop -S : deactivate array, releasing all resources\n"
|
||||
|
|
|
@ -1426,6 +1426,13 @@ device (e.g.
|
|||
.BR /dev/md0 )
|
||||
does not report the bitmap for that array.
|
||||
|
||||
.TP
|
||||
.B \-\-examine\-badblocks
|
||||
List the bad-blocks recorded for the device, if a bad-blocks list has
|
||||
been configured. Currently only
|
||||
.B 1.x
|
||||
metadata supports bad-blocks lists.
|
||||
|
||||
.TP
|
||||
.BR \-R ", " \-\-run
|
||||
start a partially assembled array. If
|
||||
|
|
4
mdadm.c
4
mdadm.c
|
@ -232,6 +232,7 @@ int main(int argc, char *argv[])
|
|||
case 'E':
|
||||
case 'X':
|
||||
case 'Q':
|
||||
case ExamineBB:
|
||||
newmode = MISC;
|
||||
break;
|
||||
|
||||
|
@ -971,6 +972,7 @@ int main(int argc, char *argv[])
|
|||
case O(MISC,'R'):
|
||||
case O(MISC,'S'):
|
||||
case O(MISC,'X'):
|
||||
case O(MISC, ExamineBB):
|
||||
case O(MISC,'o'):
|
||||
case O(MISC,'w'):
|
||||
case O(MISC,'W'):
|
||||
|
@ -1750,6 +1752,8 @@ static int misc_list(struct mddev_dev *devlist,
|
|||
rv |= Query(dv->devname); continue;
|
||||
case 'X':
|
||||
rv |= ExamineBitmap(dv->devname, c->brief, ss); continue;
|
||||
case ExamineBB:
|
||||
rv |= ExamineBadblocks(dv->devname, c->brief, ss); continue;
|
||||
case 'W':
|
||||
case WaitOpt:
|
||||
rv |= Wait(dv->devname); continue;
|
||||
|
|
3
mdadm.h
3
mdadm.h
|
@ -337,6 +337,7 @@ enum special_options {
|
|||
Prefer,
|
||||
KillOpt,
|
||||
DataOffset,
|
||||
ExamineBB,
|
||||
};
|
||||
|
||||
enum prefix_standard {
|
||||
|
@ -662,6 +663,7 @@ extern struct superswitch {
|
|||
void (*brief_examine_super)(struct supertype *st, int verbose);
|
||||
void (*brief_examine_subarrays)(struct supertype *st, int verbose);
|
||||
void (*export_examine_super)(struct supertype *st);
|
||||
int (*examine_badblocks)(struct supertype *st, int fd, char *devname);
|
||||
|
||||
/* Used to report details of an active array.
|
||||
* ->load_super was possibly given a 'component' string.
|
||||
|
@ -1145,6 +1147,7 @@ extern int Create(struct supertype *st, char *mddev,
|
|||
extern int Detail(char *dev, struct context *c);
|
||||
extern int Detail_Platform(struct superswitch *ss, int scan, int verbose, int export, char *controller_path);
|
||||
extern int Query(char *dev);
|
||||
extern int ExamineBadblocks(char *devname, int brief, struct supertype *forcest);
|
||||
extern int Examine(struct mddev_dev *devlist, struct context *c,
|
||||
struct supertype *forcest);
|
||||
extern int Monitor(struct mddev_dev *devlist,
|
||||
|
|
54
super1.c
54
super1.c
|
@ -648,6 +648,59 @@ static void export_detail_super1(struct supertype *st)
|
|||
printf("MD_NAME=%.*s\n", len, sb->set_name);
|
||||
}
|
||||
|
||||
static int examine_badblocks_super1(struct supertype *st, int fd, char *devname)
|
||||
{
|
||||
struct mdp_superblock_1 *sb = st->sb;
|
||||
unsigned long long offset;
|
||||
int size;
|
||||
__u64 *bbl, *bbp;
|
||||
int i;
|
||||
|
||||
if (!sb->bblog_size || __le32_to_cpu(sb->bblog_size) > 100
|
||||
|| !sb->bblog_offset){
|
||||
printf("No bad-blocks list configured on %s\n", devname);
|
||||
return 0;
|
||||
}
|
||||
if ((sb->feature_map & __cpu_to_le32(MD_FEATURE_BAD_BLOCKS))
|
||||
== 0) {
|
||||
printf("Bad-blocks list is empty in %s\n", devname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size = __le32_to_cpu(sb->bblog_size)* 512;
|
||||
posix_memalign((void**)&bbl, 4096, size);
|
||||
offset = __le64_to_cpu(sb->super_offset) +
|
||||
(int)__le32_to_cpu(sb->bblog_offset);
|
||||
offset <<= 9;
|
||||
if (lseek64(fd, offset, 0) < 0) {
|
||||
pr_err("Cannot seek to bad-blocks list\n");
|
||||
return 1;
|
||||
}
|
||||
if (read(fd, bbl, size) != size) {
|
||||
pr_err("Cannot read bad-blocks list\n");
|
||||
return 1;
|
||||
}
|
||||
/* 64bits per entry. 10 bits is block-count, 54 bits is block
|
||||
* offset. Blocks are sectors unless bblog->shift makes them bigger
|
||||
*/
|
||||
bbp = (__u64*)bbl;
|
||||
printf("Bad-blocks on %s:\n", devname);
|
||||
for (i = 0; i < size/8; i++, bbp++) {
|
||||
__u64 bb = __le64_to_cpu(*bbp);
|
||||
int count = bb & 0x3ff;
|
||||
unsigned long long sector = bb >> 10;
|
||||
|
||||
if (bb + 1 == 0)
|
||||
break;
|
||||
|
||||
sector <<= sb->bblog_shift;
|
||||
count <<= sb->bblog_shift;
|
||||
|
||||
printf("%20llu for %d sectors\n", sector, count);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int match_home1(struct supertype *st, char *homehost)
|
||||
|
@ -2049,6 +2102,7 @@ struct superswitch super1 = {
|
|||
.write_init_super = write_init_super1,
|
||||
.validate_geometry = validate_geometry1,
|
||||
.add_to_super = add_to_super1,
|
||||
.examine_badblocks = examine_badblocks_super1,
|
||||
#endif
|
||||
.match_home = match_home1,
|
||||
.uuid_from_super = uuid_from_super1,
|
||||
|
|
Loading…
Reference in New Issue