Merge tag 'md/4.5' of git://neil.brown.name/md
Pull md updates from Neil Brown: "Mostly clustered-raid1 and raid5 journal updates. one Y2038 fix and other minor stuff. One patch removes me from the MAINTAINERS file and adds a record of my md maintainership to Credits" Many thanks to Neil, who has been around for a _looong_ time. * tag 'md/4.5' of git://neil.brown.name/md: (26 commits) md/raid: only permit hot-add of compatible integrity profiles Remove myself as MD Maintainer, and add to Credits. raid5-cache: handle journal hotadd in quiesce MD: add journal with array suspended md: set MD_HAS_JOURNAL in correct places md: Remove 'ready' field from mddev. md: remove unnecesary md_new_event_inintr raid5: allow r5l_io_unit allocations to fail raid5-cache: use a mempool for the metadata block raid5-cache: use a bio_set raid5-cache: add journal hot add/remove support drivers: md: use ktime_get_real_seconds() md: avoid warning for 32-bit sector_t raid5-cache: free meta_page earlier raid5-cache: simplify r5l_move_io_unit_list md: update comment for md_allow_write md-cluster: update comments for MD_CLUSTER_SEND_LOCKED_ALREADY md-cluster: Protect communication with mutexes md-cluster: Defer MD reloading to mddev->thread md-cluster: update the documentation ...
此提交包含在:
171
drivers/md/md.c
171
drivers/md/md.c
@@ -206,15 +206,6 @@ void md_new_event(struct mddev *mddev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(md_new_event);
|
||||
|
||||
/* Alternate version that can be called from interrupts
|
||||
* when calling sysfs_notify isn't needed.
|
||||
*/
|
||||
static void md_new_event_inintr(struct mddev *mddev)
|
||||
{
|
||||
atomic_inc(&md_event_count);
|
||||
wake_up(&md_event_waiters);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enables to iterate over all existing md arrays
|
||||
* all_mddevs_lock protects this list.
|
||||
@@ -260,8 +251,7 @@ static blk_qc_t md_make_request(struct request_queue *q, struct bio *bio)
|
||||
|
||||
blk_queue_split(q, &bio, q->bio_split);
|
||||
|
||||
if (mddev == NULL || mddev->pers == NULL
|
||||
|| !mddev->ready) {
|
||||
if (mddev == NULL || mddev->pers == NULL) {
|
||||
bio_io_error(bio);
|
||||
return BLK_QC_T_NONE;
|
||||
}
|
||||
@@ -1026,8 +1016,9 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor
|
||||
* (not needed for Linear and RAID0 as metadata doesn't
|
||||
* record this size)
|
||||
*/
|
||||
if (rdev->sectors >= (2ULL << 32) && sb->level >= 1)
|
||||
rdev->sectors = (2ULL << 32) - 2;
|
||||
if (IS_ENABLED(CONFIG_LBDAF) && (u64)rdev->sectors >= (2ULL << 32) &&
|
||||
sb->level >= 1)
|
||||
rdev->sectors = (sector_t)(2ULL << 32) - 2;
|
||||
|
||||
if (rdev->sectors < ((sector_t)sb->size) * 2 && sb->level >= 1)
|
||||
/* "this cannot possibly happen" ... */
|
||||
@@ -1199,13 +1190,13 @@ static void super_90_sync(struct mddev *mddev, struct md_rdev *rdev)
|
||||
memcpy(&sb->set_uuid2, mddev->uuid+8, 4);
|
||||
memcpy(&sb->set_uuid3, mddev->uuid+12,4);
|
||||
|
||||
sb->ctime = mddev->ctime;
|
||||
sb->ctime = clamp_t(time64_t, mddev->ctime, 0, U32_MAX);
|
||||
sb->level = mddev->level;
|
||||
sb->size = mddev->dev_sectors / 2;
|
||||
sb->raid_disks = mddev->raid_disks;
|
||||
sb->md_minor = mddev->md_minor;
|
||||
sb->not_persistent = 0;
|
||||
sb->utime = mddev->utime;
|
||||
sb->utime = clamp_t(time64_t, mddev->utime, 0, U32_MAX);
|
||||
sb->state = 0;
|
||||
sb->events_hi = (mddev->events>>32);
|
||||
sb->events_lo = (u32)mddev->events;
|
||||
@@ -1320,8 +1311,9 @@ super_90_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors)
|
||||
/* Limit to 4TB as metadata cannot record more than that.
|
||||
* 4TB == 2^32 KB, or 2*2^32 sectors.
|
||||
*/
|
||||
if (num_sectors >= (2ULL << 32) && rdev->mddev->level >= 1)
|
||||
num_sectors = (2ULL << 32) - 2;
|
||||
if (IS_ENABLED(CONFIG_LBDAF) && (u64)num_sectors >= (2ULL << 32) &&
|
||||
rdev->mddev->level >= 1)
|
||||
num_sectors = (sector_t)(2ULL << 32) - 2;
|
||||
md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size,
|
||||
rdev->sb_page);
|
||||
md_super_wait(rdev->mddev);
|
||||
@@ -1542,8 +1534,8 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
|
||||
mddev->patch_version = 0;
|
||||
mddev->external = 0;
|
||||
mddev->chunk_sectors = le32_to_cpu(sb->chunksize);
|
||||
mddev->ctime = le64_to_cpu(sb->ctime) & ((1ULL << 32)-1);
|
||||
mddev->utime = le64_to_cpu(sb->utime) & ((1ULL << 32)-1);
|
||||
mddev->ctime = le64_to_cpu(sb->ctime);
|
||||
mddev->utime = le64_to_cpu(sb->utime);
|
||||
mddev->level = le32_to_cpu(sb->level);
|
||||
mddev->clevel[0] = 0;
|
||||
mddev->layout = le32_to_cpu(sb->layout);
|
||||
@@ -1602,6 +1594,11 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
|
||||
mddev->new_chunk_sectors = mddev->chunk_sectors;
|
||||
}
|
||||
|
||||
if (le32_to_cpu(sb->feature_map) & MD_FEATURE_JOURNAL) {
|
||||
set_bit(MD_HAS_JOURNAL, &mddev->flags);
|
||||
if (mddev->recovery_cp == MaxSector)
|
||||
set_bit(MD_JOURNAL_CLEAN, &mddev->flags);
|
||||
}
|
||||
} else if (mddev->pers == NULL) {
|
||||
/* Insist of good event counter while assembling, except for
|
||||
* spares (which don't need an event count) */
|
||||
@@ -1648,8 +1645,6 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
|
||||
}
|
||||
set_bit(Journal, &rdev->flags);
|
||||
rdev->journal_tail = le64_to_cpu(sb->journal_tail);
|
||||
if (mddev->recovery_cp == MaxSector)
|
||||
set_bit(MD_JOURNAL_CLEAN, &mddev->flags);
|
||||
rdev->raid_disk = 0;
|
||||
break;
|
||||
default:
|
||||
@@ -1669,8 +1664,6 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
|
||||
set_bit(WriteMostly, &rdev->flags);
|
||||
if (le32_to_cpu(sb->feature_map) & MD_FEATURE_REPLACEMENT)
|
||||
set_bit(Replacement, &rdev->flags);
|
||||
if (le32_to_cpu(sb->feature_map) & MD_FEATURE_JOURNAL)
|
||||
set_bit(MD_HAS_JOURNAL, &mddev->flags);
|
||||
} else /* MULTIPATH are always insync */
|
||||
set_bit(In_sync, &rdev->flags);
|
||||
|
||||
@@ -2014,28 +2007,32 @@ int md_integrity_register(struct mddev *mddev)
|
||||
}
|
||||
EXPORT_SYMBOL(md_integrity_register);
|
||||
|
||||
/* Disable data integrity if non-capable/non-matching disk is being added */
|
||||
void md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev)
|
||||
/*
|
||||
* Attempt to add an rdev, but only if it is consistent with the current
|
||||
* integrity profile
|
||||
*/
|
||||
int md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev)
|
||||
{
|
||||
struct blk_integrity *bi_rdev;
|
||||
struct blk_integrity *bi_mddev;
|
||||
char name[BDEVNAME_SIZE];
|
||||
|
||||
if (!mddev->gendisk)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
bi_rdev = bdev_get_integrity(rdev->bdev);
|
||||
bi_mddev = blk_get_integrity(mddev->gendisk);
|
||||
|
||||
if (!bi_mddev) /* nothing to do */
|
||||
return;
|
||||
if (rdev->raid_disk < 0) /* skip spares */
|
||||
return;
|
||||
if (bi_rdev && blk_integrity_compare(mddev->gendisk,
|
||||
rdev->bdev->bd_disk) >= 0)
|
||||
return;
|
||||
WARN_ON_ONCE(!mddev->suspended);
|
||||
printk(KERN_NOTICE "disabling data integrity on %s\n", mdname(mddev));
|
||||
blk_integrity_unregister(mddev->gendisk);
|
||||
return 0;
|
||||
|
||||
if (blk_integrity_compare(mddev->gendisk, rdev->bdev->bd_disk) != 0) {
|
||||
printk(KERN_NOTICE "%s: incompatible integrity profile for %s\n",
|
||||
mdname(mddev), bdevname(rdev->bdev, name));
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(md_integrity_add_rdev);
|
||||
|
||||
@@ -2050,8 +2047,9 @@ static int bind_rdev_to_array(struct md_rdev *rdev, struct mddev *mddev)
|
||||
return -EEXIST;
|
||||
|
||||
/* make sure rdev->sectors exceeds mddev->dev_sectors */
|
||||
if (rdev->sectors && (mddev->dev_sectors == 0 ||
|
||||
rdev->sectors < mddev->dev_sectors)) {
|
||||
if (!test_bit(Journal, &rdev->flags) &&
|
||||
rdev->sectors &&
|
||||
(mddev->dev_sectors == 0 || rdev->sectors < mddev->dev_sectors)) {
|
||||
if (mddev->pers) {
|
||||
/* Cannot change size, so fail
|
||||
* If mddev->level <= 0, then we don't care
|
||||
@@ -2082,7 +2080,8 @@ static int bind_rdev_to_array(struct md_rdev *rdev, struct mddev *mddev)
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
if (mddev->max_disks && rdev->desc_nr >= mddev->max_disks) {
|
||||
if (!test_bit(Journal, &rdev->flags) &&
|
||||
mddev->max_disks && rdev->desc_nr >= mddev->max_disks) {
|
||||
printk(KERN_WARNING "md: %s: array is limited to %d devices\n",
|
||||
mdname(mddev), mddev->max_disks);
|
||||
return -EBUSY;
|
||||
@@ -2331,7 +2330,7 @@ repeat:
|
||||
|
||||
spin_lock(&mddev->lock);
|
||||
|
||||
mddev->utime = get_seconds();
|
||||
mddev->utime = ktime_get_real_seconds();
|
||||
|
||||
if (test_and_clear_bit(MD_CHANGE_DEVS, &mddev->flags))
|
||||
force_change = 1;
|
||||
@@ -2457,15 +2456,20 @@ static int add_bound_rdev(struct md_rdev *rdev)
|
||||
{
|
||||
struct mddev *mddev = rdev->mddev;
|
||||
int err = 0;
|
||||
bool add_journal = test_bit(Journal, &rdev->flags);
|
||||
|
||||
if (!mddev->pers->hot_remove_disk) {
|
||||
if (!mddev->pers->hot_remove_disk || add_journal) {
|
||||
/* If there is hot_add_disk but no hot_remove_disk
|
||||
* then added disks for geometry changes,
|
||||
* and should be added immediately.
|
||||
*/
|
||||
super_types[mddev->major_version].
|
||||
validate_super(mddev, rdev);
|
||||
if (add_journal)
|
||||
mddev_suspend(mddev);
|
||||
err = mddev->pers->hot_add_disk(mddev, rdev);
|
||||
if (add_journal)
|
||||
mddev_resume(mddev);
|
||||
if (err) {
|
||||
unbind_rdev_from_array(rdev);
|
||||
export_rdev(rdev);
|
||||
@@ -5299,7 +5303,6 @@ int md_run(struct mddev *mddev)
|
||||
smp_wmb();
|
||||
spin_lock(&mddev->lock);
|
||||
mddev->pers = pers;
|
||||
mddev->ready = 1;
|
||||
spin_unlock(&mddev->lock);
|
||||
rdev_for_each(rdev, mddev)
|
||||
if (rdev->raid_disk >= 0)
|
||||
@@ -5499,7 +5502,6 @@ static void __md_stop(struct mddev *mddev)
|
||||
/* Ensure ->event_work is done */
|
||||
flush_workqueue(md_misc_wq);
|
||||
spin_lock(&mddev->lock);
|
||||
mddev->ready = 0;
|
||||
mddev->pers = NULL;
|
||||
spin_unlock(&mddev->lock);
|
||||
pers->free(mddev, mddev->private);
|
||||
@@ -5837,7 +5839,7 @@ static int get_array_info(struct mddev *mddev, void __user *arg)
|
||||
info.major_version = mddev->major_version;
|
||||
info.minor_version = mddev->minor_version;
|
||||
info.patch_version = MD_PATCHLEVEL_VERSION;
|
||||
info.ctime = mddev->ctime;
|
||||
info.ctime = clamp_t(time64_t, mddev->ctime, 0, U32_MAX);
|
||||
info.level = mddev->level;
|
||||
info.size = mddev->dev_sectors / 2;
|
||||
if (info.size != mddev->dev_sectors / 2) /* overflow */
|
||||
@@ -5847,7 +5849,7 @@ static int get_array_info(struct mddev *mddev, void __user *arg)
|
||||
info.md_minor = mddev->md_minor;
|
||||
info.not_persistent= !mddev->persistent;
|
||||
|
||||
info.utime = mddev->utime;
|
||||
info.utime = clamp_t(time64_t, mddev->utime, 0, U32_MAX);
|
||||
info.state = 0;
|
||||
if (mddev->in_sync)
|
||||
info.state = (1<<MD_SB_CLEAN);
|
||||
@@ -6038,8 +6040,23 @@ static int add_new_disk(struct mddev *mddev, mdu_disk_info_t *info)
|
||||
else
|
||||
clear_bit(WriteMostly, &rdev->flags);
|
||||
|
||||
if (info->state & (1<<MD_DISK_JOURNAL))
|
||||
if (info->state & (1<<MD_DISK_JOURNAL)) {
|
||||
struct md_rdev *rdev2;
|
||||
bool has_journal = false;
|
||||
|
||||
/* make sure no existing journal disk */
|
||||
rdev_for_each(rdev2, mddev) {
|
||||
if (test_bit(Journal, &rdev2->flags)) {
|
||||
has_journal = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (has_journal) {
|
||||
export_rdev(rdev);
|
||||
return -EBUSY;
|
||||
}
|
||||
set_bit(Journal, &rdev->flags);
|
||||
}
|
||||
/*
|
||||
* check whether the device shows up in other nodes
|
||||
*/
|
||||
@@ -6130,15 +6147,11 @@ static int hot_remove_disk(struct mddev *mddev, dev_t dev)
|
||||
{
|
||||
char b[BDEVNAME_SIZE];
|
||||
struct md_rdev *rdev;
|
||||
int ret = -1;
|
||||
|
||||
rdev = find_rdev(mddev, dev);
|
||||
if (!rdev)
|
||||
return -ENXIO;
|
||||
|
||||
if (mddev_is_clustered(mddev))
|
||||
ret = md_cluster_ops->metadata_update_start(mddev);
|
||||
|
||||
if (rdev->raid_disk < 0)
|
||||
goto kick_rdev;
|
||||
|
||||
@@ -6149,7 +6162,7 @@ static int hot_remove_disk(struct mddev *mddev, dev_t dev)
|
||||
goto busy;
|
||||
|
||||
kick_rdev:
|
||||
if (mddev_is_clustered(mddev) && ret == 0)
|
||||
if (mddev_is_clustered(mddev))
|
||||
md_cluster_ops->remove_disk(mddev, rdev);
|
||||
|
||||
md_kick_rdev_from_array(rdev);
|
||||
@@ -6158,9 +6171,6 @@ kick_rdev:
|
||||
|
||||
return 0;
|
||||
busy:
|
||||
if (mddev_is_clustered(mddev) && ret == 0)
|
||||
md_cluster_ops->metadata_update_cancel(mddev);
|
||||
|
||||
printk(KERN_WARNING "md: cannot remove active disk %s from %s ...\n",
|
||||
bdevname(rdev->bdev,b), mdname(mddev));
|
||||
return -EBUSY;
|
||||
@@ -6354,13 +6364,13 @@ static int set_array_info(struct mddev *mddev, mdu_array_info_t *info)
|
||||
/* ensure mddev_put doesn't delete this now that there
|
||||
* is some minimal configuration.
|
||||
*/
|
||||
mddev->ctime = get_seconds();
|
||||
mddev->ctime = ktime_get_real_seconds();
|
||||
return 0;
|
||||
}
|
||||
mddev->major_version = MD_MAJOR_VERSION;
|
||||
mddev->minor_version = MD_MINOR_VERSION;
|
||||
mddev->patch_version = MD_PATCHLEVEL_VERSION;
|
||||
mddev->ctime = get_seconds();
|
||||
mddev->ctime = ktime_get_real_seconds();
|
||||
|
||||
mddev->level = info->level;
|
||||
mddev->clevel[0] = 0;
|
||||
@@ -6602,6 +6612,19 @@ static int update_array_info(struct mddev *mddev, mdu_array_info_t *info)
|
||||
rv = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
if (mddev->bitmap_info.nodes) {
|
||||
/* hold PW on all the bitmap lock */
|
||||
if (md_cluster_ops->lock_all_bitmaps(mddev) <= 0) {
|
||||
printk("md: can't change bitmap to none since the"
|
||||
" array is in use by more than one node\n");
|
||||
rv = -EPERM;
|
||||
md_cluster_ops->unlock_all_bitmaps(mddev);
|
||||
goto err;
|
||||
}
|
||||
|
||||
mddev->bitmap_info.nodes = 0;
|
||||
md_cluster_ops->leave(mddev);
|
||||
}
|
||||
mddev->pers->quiesce(mddev, 1);
|
||||
bitmap_destroy(mddev);
|
||||
mddev->pers->quiesce(mddev, 0);
|
||||
@@ -7180,7 +7203,7 @@ void md_error(struct mddev *mddev, struct md_rdev *rdev)
|
||||
md_wakeup_thread(mddev->thread);
|
||||
if (mddev->event_work.func)
|
||||
queue_work(md_misc_wq, &mddev->event_work);
|
||||
md_new_event_inintr(mddev);
|
||||
md_new_event(mddev);
|
||||
}
|
||||
EXPORT_SYMBOL(md_error);
|
||||
|
||||
@@ -7704,7 +7727,7 @@ EXPORT_SYMBOL(md_write_end);
|
||||
* attempting a GFP_KERNEL allocation while holding the mddev lock.
|
||||
* Must be called with mddev_lock held.
|
||||
*
|
||||
* In the ->external case MD_CHANGE_CLEAN can not be cleared until mddev->lock
|
||||
* In the ->external case MD_CHANGE_PENDING can not be cleared until mddev->lock
|
||||
* is dropped, so return -EAGAIN after notifying userspace.
|
||||
*/
|
||||
int md_allow_write(struct mddev *mddev)
|
||||
@@ -8169,19 +8192,20 @@ static int remove_and_add_spares(struct mddev *mddev,
|
||||
continue;
|
||||
if (test_bit(Faulty, &rdev->flags))
|
||||
continue;
|
||||
if (test_bit(Journal, &rdev->flags))
|
||||
continue;
|
||||
if (mddev->ro &&
|
||||
! (rdev->saved_raid_disk >= 0 &&
|
||||
!test_bit(Bitmap_sync, &rdev->flags)))
|
||||
continue;
|
||||
if (!test_bit(Journal, &rdev->flags)) {
|
||||
if (mddev->ro &&
|
||||
! (rdev->saved_raid_disk >= 0 &&
|
||||
!test_bit(Bitmap_sync, &rdev->flags)))
|
||||
continue;
|
||||
|
||||
rdev->recovery_offset = 0;
|
||||
rdev->recovery_offset = 0;
|
||||
}
|
||||
if (mddev->pers->
|
||||
hot_add_disk(mddev, rdev) == 0) {
|
||||
if (sysfs_link_rdev(mddev, rdev))
|
||||
/* failure here is OK */;
|
||||
spares++;
|
||||
if (!test_bit(Journal, &rdev->flags))
|
||||
spares++;
|
||||
md_new_event(mddev);
|
||||
set_bit(MD_CHANGE_DEVS, &mddev->flags);
|
||||
}
|
||||
@@ -8276,6 +8300,7 @@ void md_check_recovery(struct mddev *mddev)
|
||||
(mddev->flags & MD_UPDATE_SB_FLAGS & ~ (1<<MD_CHANGE_PENDING)) ||
|
||||
test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) ||
|
||||
test_bit(MD_RECOVERY_DONE, &mddev->recovery) ||
|
||||
test_bit(MD_RELOAD_SB, &mddev->flags) ||
|
||||
(mddev->external == 0 && mddev->safemode == 1) ||
|
||||
(mddev->safemode == 2 && ! atomic_read(&mddev->writes_pending)
|
||||
&& !mddev->in_sync && mddev->recovery_cp == MaxSector)
|
||||
@@ -8314,6 +8339,21 @@ void md_check_recovery(struct mddev *mddev)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (mddev_is_clustered(mddev)) {
|
||||
struct md_rdev *rdev;
|
||||
/* kick the device if another node issued a
|
||||
* remove disk.
|
||||
*/
|
||||
rdev_for_each(rdev, mddev) {
|
||||
if (test_and_clear_bit(ClusterRemove, &rdev->flags) &&
|
||||
rdev->raid_disk < 0)
|
||||
md_kick_rdev_from_array(rdev);
|
||||
}
|
||||
|
||||
if (test_and_clear_bit(MD_RELOAD_SB, &mddev->flags))
|
||||
md_reload_sb(mddev, mddev->good_device_nr);
|
||||
}
|
||||
|
||||
if (!mddev->external) {
|
||||
int did_change = 0;
|
||||
spin_lock(&mddev->lock);
|
||||
@@ -8635,7 +8675,6 @@ static void check_sb_changes(struct mddev *mddev, struct md_rdev *rdev)
|
||||
ret = remove_and_add_spares(mddev, rdev2);
|
||||
pr_info("Activated spare: %s\n",
|
||||
bdevname(rdev2->bdev,b));
|
||||
continue;
|
||||
}
|
||||
/* device faulty
|
||||
* We just want to do the minimum to mark the disk
|
||||
|
新增問題並參考
封鎖使用者