forked from Minki/linux
md updates for 3.14
All bug fixes, two tagged for -stable. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIVAwUAUuG8WTnsnt1WYoG5AQKW7A//V93TYUiUAG6zNUFrNZjuoXP0ym3jlpkH eIIFdcV7rr0Irgtd8+s9cW8Cjsbq3d/vMbFlwP1Co32mnCnFFojeKtCvM9GqkYrH o4Zr1nVAVYzKO4awByK3wBT9WbzEc/XlDgYQIpZExIYeZdzLOm6HyvlRbcE86Ug5 QoGYOUlLu4LUZmFgB9zQ7JM0GACV5pS1afSObtACj2t2x5GVHNU84u+M+D8urPXO wnf+AIAzquh5F+8MX+DxmMEUaSzUHf8fXOM3jYVbzPI71SpaHssL4SwBn+j4I/8/ SCSqeIh7qMSuqUy63/iHKCy5qAgNuRdL9fYlOTkpxzHm81Ddj8u7fySsApggVOa2 yeKTkSRlsMFeu+LiGKNi/fINVxboaoYJVZ2DTNtKxSuW2VL2aPNz1Qjq4QnR3nSI LpaB3VeVKdMsH8Em1a8cgZWcjo5YFAcNtUnJq2fvj9VZ3SJNw4ZoKDL+l718iGao xIwAXMSafAHQVAAaNVFkwrea13TeOyxikY5Ra4vWfm+Fw8TzmYq5DqO0zaILwdAJ 2FnNj2/2y3hk2K7qBcEvjjEakxPlTwzrzxZMfJDRMuQLqvrjbXiMGOnWzgl1D/9x 4/uPjeFZLG7byxmIyg4Y83NkPgkWnRPpGK98r26pUH1UgnRF0a5aUFXQk7rsQrU6 noRkZ9EPD8s= =d81E -----END PGP SIGNATURE----- Merge tag 'md/3.14' of git://neil.brown.name/md Pull md updates from Neil Brown: "All bug fixes, two tagged for -stable" * tag 'md/3.14' of git://neil.brown.name/md: md/raid5: close recently introduced race in stripe_head management. md/raid5: fix long-standing problem with bitmap handling on write failure. md: check command validity early in md_ioctl(). md: ensure metadata is writen after raid level change. md/raid10: avoid fullsync when not necessary. md: allow a partially recovered device to be hot-added to an array. md: Change handling of save_raid_disk and metadata update during recovery.
This commit is contained in:
commit
5c85121bf6
@ -1173,6 +1173,7 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev)
|
|||||||
desc->raid_disk < mddev->raid_disks */) {
|
desc->raid_disk < mddev->raid_disks */) {
|
||||||
set_bit(In_sync, &rdev->flags);
|
set_bit(In_sync, &rdev->flags);
|
||||||
rdev->raid_disk = desc->raid_disk;
|
rdev->raid_disk = desc->raid_disk;
|
||||||
|
rdev->saved_raid_disk = desc->raid_disk;
|
||||||
} else if (desc->state & (1<<MD_DISK_ACTIVE)) {
|
} else if (desc->state & (1<<MD_DISK_ACTIVE)) {
|
||||||
/* active but not in sync implies recovery up to
|
/* active but not in sync implies recovery up to
|
||||||
* reshape position. We don't know exactly where
|
* reshape position. We don't know exactly where
|
||||||
@ -1671,10 +1672,14 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
|
|||||||
set_bit(Faulty, &rdev->flags);
|
set_bit(Faulty, &rdev->flags);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
rdev->saved_raid_disk = role;
|
||||||
if ((le32_to_cpu(sb->feature_map) &
|
if ((le32_to_cpu(sb->feature_map) &
|
||||||
MD_FEATURE_RECOVERY_OFFSET))
|
MD_FEATURE_RECOVERY_OFFSET)) {
|
||||||
rdev->recovery_offset = le64_to_cpu(sb->recovery_offset);
|
rdev->recovery_offset = le64_to_cpu(sb->recovery_offset);
|
||||||
else
|
if (!(le32_to_cpu(sb->feature_map) &
|
||||||
|
MD_FEATURE_RECOVERY_BITMAP))
|
||||||
|
rdev->saved_raid_disk = -1;
|
||||||
|
} else
|
||||||
set_bit(In_sync, &rdev->flags);
|
set_bit(In_sync, &rdev->flags);
|
||||||
rdev->raid_disk = role;
|
rdev->raid_disk = role;
|
||||||
break;
|
break;
|
||||||
@ -1736,6 +1741,9 @@ static void super_1_sync(struct mddev *mddev, struct md_rdev *rdev)
|
|||||||
cpu_to_le32(MD_FEATURE_RECOVERY_OFFSET);
|
cpu_to_le32(MD_FEATURE_RECOVERY_OFFSET);
|
||||||
sb->recovery_offset =
|
sb->recovery_offset =
|
||||||
cpu_to_le64(rdev->recovery_offset);
|
cpu_to_le64(rdev->recovery_offset);
|
||||||
|
if (rdev->saved_raid_disk >= 0 && mddev->bitmap)
|
||||||
|
sb->feature_map |=
|
||||||
|
cpu_to_le32(MD_FEATURE_RECOVERY_BITMAP);
|
||||||
}
|
}
|
||||||
if (test_bit(Replacement, &rdev->flags))
|
if (test_bit(Replacement, &rdev->flags))
|
||||||
sb->feature_map |=
|
sb->feature_map |=
|
||||||
@ -2477,8 +2485,7 @@ repeat:
|
|||||||
if (rdev->sb_loaded != 1)
|
if (rdev->sb_loaded != 1)
|
||||||
continue; /* no noise on spare devices */
|
continue; /* no noise on spare devices */
|
||||||
|
|
||||||
if (!test_bit(Faulty, &rdev->flags) &&
|
if (!test_bit(Faulty, &rdev->flags)) {
|
||||||
rdev->saved_raid_disk == -1) {
|
|
||||||
md_super_write(mddev,rdev,
|
md_super_write(mddev,rdev,
|
||||||
rdev->sb_start, rdev->sb_size,
|
rdev->sb_start, rdev->sb_size,
|
||||||
rdev->sb_page);
|
rdev->sb_page);
|
||||||
@ -2494,11 +2501,9 @@ repeat:
|
|||||||
rdev->badblocks.size = 0;
|
rdev->badblocks.size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (test_bit(Faulty, &rdev->flags))
|
} else
|
||||||
pr_debug("md: %s (skipping faulty)\n",
|
pr_debug("md: %s (skipping faulty)\n",
|
||||||
bdevname(rdev->bdev, b));
|
bdevname(rdev->bdev, b));
|
||||||
else
|
|
||||||
pr_debug("(skipping incremental s/r ");
|
|
||||||
|
|
||||||
if (mddev->level == LEVEL_MULTIPATH)
|
if (mddev->level == LEVEL_MULTIPATH)
|
||||||
/* only need to write one superblock... */
|
/* only need to write one superblock... */
|
||||||
@ -2614,6 +2619,8 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len)
|
|||||||
* blocked - sets the Blocked flags
|
* blocked - sets the Blocked flags
|
||||||
* -blocked - clears the Blocked and possibly simulates an error
|
* -blocked - clears the Blocked and possibly simulates an error
|
||||||
* insync - sets Insync providing device isn't active
|
* insync - sets Insync providing device isn't active
|
||||||
|
* -insync - clear Insync for a device with a slot assigned,
|
||||||
|
* so that it gets rebuilt based on bitmap
|
||||||
* write_error - sets WriteErrorSeen
|
* write_error - sets WriteErrorSeen
|
||||||
* -write_error - clears WriteErrorSeen
|
* -write_error - clears WriteErrorSeen
|
||||||
*/
|
*/
|
||||||
@ -2662,6 +2669,11 @@ state_store(struct md_rdev *rdev, const char *buf, size_t len)
|
|||||||
} else if (cmd_match(buf, "insync") && rdev->raid_disk == -1) {
|
} else if (cmd_match(buf, "insync") && rdev->raid_disk == -1) {
|
||||||
set_bit(In_sync, &rdev->flags);
|
set_bit(In_sync, &rdev->flags);
|
||||||
err = 0;
|
err = 0;
|
||||||
|
} else if (cmd_match(buf, "-insync") && rdev->raid_disk >= 0) {
|
||||||
|
clear_bit(In_sync, &rdev->flags);
|
||||||
|
rdev->saved_raid_disk = rdev->raid_disk;
|
||||||
|
rdev->raid_disk = -1;
|
||||||
|
err = 0;
|
||||||
} else if (cmd_match(buf, "write_error")) {
|
} else if (cmd_match(buf, "write_error")) {
|
||||||
set_bit(WriteErrorSeen, &rdev->flags);
|
set_bit(WriteErrorSeen, &rdev->flags);
|
||||||
err = 0;
|
err = 0;
|
||||||
@ -3589,6 +3601,8 @@ level_store(struct mddev *mddev, const char *buf, size_t len)
|
|||||||
pers->run(mddev);
|
pers->run(mddev);
|
||||||
set_bit(MD_CHANGE_DEVS, &mddev->flags);
|
set_bit(MD_CHANGE_DEVS, &mddev->flags);
|
||||||
mddev_resume(mddev);
|
mddev_resume(mddev);
|
||||||
|
if (!mddev->thread)
|
||||||
|
md_update_sb(mddev, 1);
|
||||||
sysfs_notify(&mddev->kobj, NULL, "level");
|
sysfs_notify(&mddev->kobj, NULL, "level");
|
||||||
md_new_event(mddev);
|
md_new_event(mddev);
|
||||||
return rv;
|
return rv;
|
||||||
@ -5770,6 +5784,7 @@ static int add_new_disk(struct mddev * mddev, mdu_disk_info_t *info)
|
|||||||
clear_bit(Bitmap_sync, &rdev->flags);
|
clear_bit(Bitmap_sync, &rdev->flags);
|
||||||
} else
|
} else
|
||||||
rdev->raid_disk = -1;
|
rdev->raid_disk = -1;
|
||||||
|
rdev->saved_raid_disk = rdev->raid_disk;
|
||||||
} else
|
} else
|
||||||
super_types[mddev->major_version].
|
super_types[mddev->major_version].
|
||||||
validate_super(mddev, rdev);
|
validate_super(mddev, rdev);
|
||||||
@ -5782,11 +5797,6 @@ static int add_new_disk(struct mddev * mddev, mdu_disk_info_t *info)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_bit(In_sync, &rdev->flags))
|
|
||||||
rdev->saved_raid_disk = rdev->raid_disk;
|
|
||||||
else
|
|
||||||
rdev->saved_raid_disk = -1;
|
|
||||||
|
|
||||||
clear_bit(In_sync, &rdev->flags); /* just to be sure */
|
clear_bit(In_sync, &rdev->flags); /* just to be sure */
|
||||||
if (info->state & (1<<MD_DISK_WRITEMOSTLY))
|
if (info->state & (1<<MD_DISK_WRITEMOSTLY))
|
||||||
set_bit(WriteMostly, &rdev->flags);
|
set_bit(WriteMostly, &rdev->flags);
|
||||||
@ -6336,6 +6346,32 @@ static int md_getgeo(struct block_device *bdev, struct hd_geometry *geo)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool md_ioctl_valid(unsigned int cmd)
|
||||||
|
{
|
||||||
|
switch (cmd) {
|
||||||
|
case ADD_NEW_DISK:
|
||||||
|
case BLKROSET:
|
||||||
|
case GET_ARRAY_INFO:
|
||||||
|
case GET_BITMAP_FILE:
|
||||||
|
case GET_DISK_INFO:
|
||||||
|
case HOT_ADD_DISK:
|
||||||
|
case HOT_REMOVE_DISK:
|
||||||
|
case PRINT_RAID_DEBUG:
|
||||||
|
case RAID_AUTORUN:
|
||||||
|
case RAID_VERSION:
|
||||||
|
case RESTART_ARRAY_RW:
|
||||||
|
case RUN_ARRAY:
|
||||||
|
case SET_ARRAY_INFO:
|
||||||
|
case SET_BITMAP_FILE:
|
||||||
|
case SET_DISK_FAULTY:
|
||||||
|
case STOP_ARRAY:
|
||||||
|
case STOP_ARRAY_RO:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int md_ioctl(struct block_device *bdev, fmode_t mode,
|
static int md_ioctl(struct block_device *bdev, fmode_t mode,
|
||||||
unsigned int cmd, unsigned long arg)
|
unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
@ -6344,6 +6380,9 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
|
|||||||
struct mddev *mddev = NULL;
|
struct mddev *mddev = NULL;
|
||||||
int ro;
|
int ro;
|
||||||
|
|
||||||
|
if (!md_ioctl_valid(cmd))
|
||||||
|
return -ENOTTY;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case RAID_VERSION:
|
case RAID_VERSION:
|
||||||
case GET_ARRAY_INFO:
|
case GET_ARRAY_INFO:
|
||||||
@ -7718,7 +7757,8 @@ static int remove_and_add_spares(struct mddev *mddev,
|
|||||||
!test_bit(Bitmap_sync, &rdev->flags)))
|
!test_bit(Bitmap_sync, &rdev->flags)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
rdev->recovery_offset = 0;
|
if (rdev->saved_raid_disk < 0)
|
||||||
|
rdev->recovery_offset = 0;
|
||||||
if (mddev->pers->
|
if (mddev->pers->
|
||||||
hot_add_disk(mddev, rdev) == 0) {
|
hot_add_disk(mddev, rdev) == 0) {
|
||||||
if (sysfs_link_rdev(mddev, rdev))
|
if (sysfs_link_rdev(mddev, rdev))
|
||||||
@ -7938,14 +7978,10 @@ void md_reap_sync_thread(struct mddev *mddev)
|
|||||||
mddev->pers->finish_reshape(mddev);
|
mddev->pers->finish_reshape(mddev);
|
||||||
|
|
||||||
/* If array is no-longer degraded, then any saved_raid_disk
|
/* If array is no-longer degraded, then any saved_raid_disk
|
||||||
* information must be scrapped. Also if any device is now
|
* information must be scrapped.
|
||||||
* In_sync we must scrape the saved_raid_disk for that device
|
|
||||||
* do the superblock for an incrementally recovered device
|
|
||||||
* written out.
|
|
||||||
*/
|
*/
|
||||||
rdev_for_each(rdev, mddev)
|
if (!mddev->degraded)
|
||||||
if (!mddev->degraded ||
|
rdev_for_each(rdev, mddev)
|
||||||
test_bit(In_sync, &rdev->flags))
|
|
||||||
rdev->saved_raid_disk = -1;
|
rdev->saved_raid_disk = -1;
|
||||||
|
|
||||||
md_update_sb(mddev, 1);
|
md_update_sb(mddev, 1);
|
||||||
|
@ -3747,7 +3747,8 @@ static int run(struct mddev *mddev)
|
|||||||
!test_bit(In_sync, &disk->rdev->flags)) {
|
!test_bit(In_sync, &disk->rdev->flags)) {
|
||||||
disk->head_position = 0;
|
disk->head_position = 0;
|
||||||
mddev->degraded++;
|
mddev->degraded++;
|
||||||
if (disk->rdev)
|
if (disk->rdev &&
|
||||||
|
disk->rdev->saved_raid_disk < 0)
|
||||||
conf->fullsync = 1;
|
conf->fullsync = 1;
|
||||||
}
|
}
|
||||||
disk->recovery_disabled = mddev->recovery_disabled - 1;
|
disk->recovery_disabled = mddev->recovery_disabled - 1;
|
||||||
|
@ -675,8 +675,10 @@ get_active_stripe(struct r5conf *conf, sector_t sector,
|
|||||||
|| !conf->inactive_blocked),
|
|| !conf->inactive_blocked),
|
||||||
*(conf->hash_locks + hash));
|
*(conf->hash_locks + hash));
|
||||||
conf->inactive_blocked = 0;
|
conf->inactive_blocked = 0;
|
||||||
} else
|
} else {
|
||||||
init_stripe(sh, sector, previous);
|
init_stripe(sh, sector, previous);
|
||||||
|
atomic_inc(&sh->count);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
spin_lock(&conf->device_lock);
|
spin_lock(&conf->device_lock);
|
||||||
if (atomic_read(&sh->count)) {
|
if (atomic_read(&sh->count)) {
|
||||||
@ -695,13 +697,11 @@ get_active_stripe(struct r5conf *conf, sector_t sector,
|
|||||||
sh->group = NULL;
|
sh->group = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
atomic_inc(&sh->count);
|
||||||
spin_unlock(&conf->device_lock);
|
spin_unlock(&conf->device_lock);
|
||||||
}
|
}
|
||||||
} while (sh == NULL);
|
} while (sh == NULL);
|
||||||
|
|
||||||
if (sh)
|
|
||||||
atomic_inc(&sh->count);
|
|
||||||
|
|
||||||
spin_unlock_irq(conf->hash_locks + hash);
|
spin_unlock_irq(conf->hash_locks + hash);
|
||||||
return sh;
|
return sh;
|
||||||
}
|
}
|
||||||
@ -2111,6 +2111,7 @@ static void raid5_end_write_request(struct bio *bi, int error)
|
|||||||
set_bit(R5_MadeGoodRepl, &sh->dev[i].flags);
|
set_bit(R5_MadeGoodRepl, &sh->dev[i].flags);
|
||||||
} else {
|
} else {
|
||||||
if (!uptodate) {
|
if (!uptodate) {
|
||||||
|
set_bit(STRIPE_DEGRADED, &sh->state);
|
||||||
set_bit(WriteErrorSeen, &rdev->flags);
|
set_bit(WriteErrorSeen, &rdev->flags);
|
||||||
set_bit(R5_WriteError, &sh->dev[i].flags);
|
set_bit(R5_WriteError, &sh->dev[i].flags);
|
||||||
if (!test_and_set_bit(WantReplacement, &rdev->flags))
|
if (!test_and_set_bit(WantReplacement, &rdev->flags))
|
||||||
|
@ -292,6 +292,9 @@ struct mdp_superblock_1 {
|
|||||||
* backwards anyway.
|
* backwards anyway.
|
||||||
*/
|
*/
|
||||||
#define MD_FEATURE_NEW_OFFSET 64 /* new_offset must be honoured */
|
#define MD_FEATURE_NEW_OFFSET 64 /* new_offset must be honoured */
|
||||||
|
#define MD_FEATURE_RECOVERY_BITMAP 128 /* recovery that is happening
|
||||||
|
* is guided by bitmap.
|
||||||
|
*/
|
||||||
#define MD_FEATURE_ALL (MD_FEATURE_BITMAP_OFFSET \
|
#define MD_FEATURE_ALL (MD_FEATURE_BITMAP_OFFSET \
|
||||||
|MD_FEATURE_RECOVERY_OFFSET \
|
|MD_FEATURE_RECOVERY_OFFSET \
|
||||||
|MD_FEATURE_RESHAPE_ACTIVE \
|
|MD_FEATURE_RESHAPE_ACTIVE \
|
||||||
@ -299,6 +302,7 @@ struct mdp_superblock_1 {
|
|||||||
|MD_FEATURE_REPLACEMENT \
|
|MD_FEATURE_REPLACEMENT \
|
||||||
|MD_FEATURE_RESHAPE_BACKWARDS \
|
|MD_FEATURE_RESHAPE_BACKWARDS \
|
||||||
|MD_FEATURE_NEW_OFFSET \
|
|MD_FEATURE_NEW_OFFSET \
|
||||||
|
|MD_FEATURE_RECOVERY_BITMAP \
|
||||||
)
|
)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user