recreate journal in mdadm

This patch tries recreates missing/faulty journal in mdadm.

Example:

./mdadm --fail /dev/md1 /dev/sdb2
mdadm: set /dev/sdb2 faulty in /dev/md1

./mdadm --stop /dev/md1
mdadm: stopped /dev/md1

./mdadm -A --scan --force
mdadm: Journal is missing or stale, starting array read only.
mdadm: /dev/md/1 has been started with 15 drives.

./mdadm --add-journal /dev/md1 /dev/sdb2
mdadm: added /dev/sdb2

Signed-off-by: Song Liu <songliubraving@fb.com>
Signed-off-by: Shaohua Li <shli@fb.com>
Signed-off-by: NeilBrown <neilb@suse.com>
This commit is contained in:
Song Liu 2015-12-14 17:43:43 -08:00 committed by NeilBrown
parent 5aa644c68a
commit 01290056d0
5 changed files with 51 additions and 4 deletions

View File

@ -825,7 +825,8 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
}
/* Make sure device is large enough */
if (tst->sb &&
if (dv->disposition != 'j' && /* skip size check for Journal */
tst->sb &&
tst->ss->avail_size(tst, ldsize/512, INVALID_SECTORS) <
array_size) {
if (dv->disposition == 'M')
@ -929,8 +930,31 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
else
disc.number = raid_slot;
disc.state = 0;
/* only add journal to array that supports journaling */
if (dv->disposition == 'j') {
struct mdinfo mdi;
struct mdinfo *mdp;
mdp = sysfs_read(fd, NULL, GET_ARRAY_STATE);
if (strncmp(mdp->sysfs_array_state, "readonly", 8) != 0) {
pr_err("%s is not readonly, cannot add journal.\n", devname);
return -1;
}
tst->ss->getinfo_super(tst, &mdi, NULL);
if (mdi.journal_device_required == 0) {
pr_err("%s does not support journal device.\n", devname);
return -1;
}
disc.raid_disk = array->raid_disks;
}
if (array->not_persistent==0) {
int dfd;
if (dv->disposition == 'j')
disc.state |= (1 << MD_DISK_JOURNAL) | (1 << MD_DISK_SYNC);
if (dv->writemostly == 1)
disc.state |= 1 << MD_DISK_WRITEMOSTLY;
dfd = dev_open(dv->devname, O_RDWR | O_EXCL|O_DIRECT);
@ -1041,10 +1065,20 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
} else {
tst->ss->free_super(tst);
if (ioctl(fd, ADD_NEW_DISK, &disc)) {
pr_err("add new device failed for %s as %d: %s\n",
dv->devname, j, strerror(errno));
if (dv->disposition == 'j')
pr_err("Failed to hot add %s as journal, "
"please try restart %s.\n", dv->devname, devname);
else
pr_err("add new device failed for %s as %d: %s\n",
dv->devname, j, strerror(errno));
return -1;
}
if (dv->disposition == 'j') {
pr_err("Journal added successfully, making %s read-write\n", devname);
if (Manage_ro(devname, fd, -1))
pr_err("Failed to make %s read-write\n", devname);
}
}
if (verbose >= 0)
pr_err("added %s\n", dv->devname);
@ -1277,6 +1311,7 @@ int Manage_subdevs(char *devname, int fd,
* try HOT_ADD_DISK
* If that fails EINVAL, try ADD_NEW_DISK
* 'S' - add the device as a spare - don't try re-add
* 'j' - add the device as a journal device
* 'A' - re-add the device
* 'r' - remove the device: HOT_REMOVE_DISK
* device can be 'faulty' or 'detached' in which case all
@ -1509,6 +1544,7 @@ int Manage_subdevs(char *devname, int fd,
goto abort;
case 'a':
case 'S': /* --add-spare */
case 'j': /* --add-journal */
case 'A':
case 'M': /* --re-add missing */
case 'F': /* --re-add faulty */

View File

@ -157,6 +157,7 @@ struct option long_options[] = {
/* Management */
{"add", 0, 0, Add},
{"add-spare", 0, 0, AddSpare},
{"add-journal", 0, 0, AddJournal},
{"remove", 0, 0, Remove},
{"fail", 0, 0, Fail},
{"set-faulty",0, 0, Fail},

View File

@ -190,6 +190,7 @@ int main(int argc, char *argv[])
case 'a':
case Add:
case AddSpare:
case AddJournal:
case 'r':
case Remove:
case Replace:
@ -925,6 +926,13 @@ int main(int argc, char *argv[])
case O(MANAGE,AddSpare): /* add drive - never re-add */
devmode = 'S';
continue;
case O(MANAGE,AddJournal): /* add journal */
if (s.journaldisks && (s.level < 4 || s.level > 6)) {
pr_err("--add-journal is only supported for RAID level 4/5/6.\n");
exit(2);
}
devmode = 'j';
continue;
case O(MANAGE,ReAdd):
devmode = 'A';
continue;

View File

@ -370,6 +370,7 @@ enum special_options {
ManageOpt,
Add,
AddSpare,
AddJournal,
Remove,
Fail,
Replace,

View File

@ -1713,7 +1713,8 @@ static int write_init_super1(struct supertype *st)
if (rfd >= 0)
close(rfd);
sb->events = 0;
if (!(di->disk.state & (1<<MD_DISK_JOURNAL)))
sb->events = 0;
refst = dup_super(st);
if (load_super1(refst, di->fd, NULL)==0) {