diff options
-rw-r--r-- | drivers/md/md.c | 65 | ||||
-rw-r--r-- | include/linux/raid/md_k.h | 1 |
2 files changed, 58 insertions, 8 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 6f97817d28b9..34b6902cda46 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -1558,15 +1558,30 @@ static void md_print_devices(void) | |||
1558 | } | 1558 | } |
1559 | 1559 | ||
1560 | 1560 | ||
1561 | static void sync_sbs(mddev_t * mddev) | 1561 | static void sync_sbs(mddev_t * mddev, int nospares) |
1562 | { | 1562 | { |
1563 | /* Update each superblock (in-memory image), but | ||
1564 | * if we are allowed to, skip spares which already | ||
1565 | * have the right event counter, or have one earlier | ||
1566 | * (which would mean they aren't being marked as dirty | ||
1567 | * with the rest of the array) | ||
1568 | */ | ||
1563 | mdk_rdev_t *rdev; | 1569 | mdk_rdev_t *rdev; |
1564 | struct list_head *tmp; | 1570 | struct list_head *tmp; |
1565 | 1571 | ||
1566 | ITERATE_RDEV(mddev,rdev,tmp) { | 1572 | ITERATE_RDEV(mddev,rdev,tmp) { |
1567 | super_types[mddev->major_version]. | 1573 | if (rdev->sb_events == mddev->events || |
1568 | sync_super(mddev, rdev); | 1574 | (nospares && |
1569 | rdev->sb_loaded = 1; | 1575 | rdev->raid_disk < 0 && |
1576 | (rdev->sb_events&1)==0 && | ||
1577 | rdev->sb_events+1 == mddev->events)) { | ||
1578 | /* Don't update this superblock */ | ||
1579 | rdev->sb_loaded = 2; | ||
1580 | } else { | ||
1581 | super_types[mddev->major_version]. | ||
1582 | sync_super(mddev, rdev); | ||
1583 | rdev->sb_loaded = 1; | ||
1584 | } | ||
1570 | } | 1585 | } |
1571 | } | 1586 | } |
1572 | 1587 | ||
@@ -1576,12 +1591,42 @@ void md_update_sb(mddev_t * mddev) | |||
1576 | struct list_head *tmp; | 1591 | struct list_head *tmp; |
1577 | mdk_rdev_t *rdev; | 1592 | mdk_rdev_t *rdev; |
1578 | int sync_req; | 1593 | int sync_req; |
1594 | int nospares = 0; | ||
1579 | 1595 | ||
1580 | repeat: | 1596 | repeat: |
1581 | spin_lock_irq(&mddev->write_lock); | 1597 | spin_lock_irq(&mddev->write_lock); |
1582 | sync_req = mddev->in_sync; | 1598 | sync_req = mddev->in_sync; |
1583 | mddev->utime = get_seconds(); | 1599 | mddev->utime = get_seconds(); |
1584 | mddev->events ++; | 1600 | if (mddev->sb_dirty == 3) |
1601 | /* just a clean<-> dirty transition, possibly leave spares alone, | ||
1602 | * though if events isn't the right even/odd, we will have to do | ||
1603 | * spares after all | ||
1604 | */ | ||
1605 | nospares = 1; | ||
1606 | |||
1607 | /* If this is just a dirty<->clean transition, and the array is clean | ||
1608 | * and 'events' is odd, we can roll back to the previous clean state */ | ||
1609 | if (mddev->sb_dirty == 3 | ||
1610 | && (mddev->in_sync && mddev->recovery_cp == MaxSector) | ||
1611 | && (mddev->events & 1)) | ||
1612 | mddev->events--; | ||
1613 | else { | ||
1614 | /* otherwise we have to go forward and ... */ | ||
1615 | mddev->events ++; | ||
1616 | if (!mddev->in_sync || mddev->recovery_cp != MaxSector) { /* not clean */ | ||
1617 | /* .. if the array isn't clean, insist on an odd 'events' */ | ||
1618 | if ((mddev->events&1)==0) { | ||
1619 | mddev->events++; | ||
1620 | nospares = 0; | ||
1621 | } | ||
1622 | } else { | ||
1623 | /* otherwise insist on an even 'events' (for clean states) */ | ||
1624 | if ((mddev->events&1)) { | ||
1625 | mddev->events++; | ||
1626 | nospares = 0; | ||
1627 | } | ||
1628 | } | ||
1629 | } | ||
1585 | 1630 | ||
1586 | if (!mddev->events) { | 1631 | if (!mddev->events) { |
1587 | /* | 1632 | /* |
@@ -1593,7 +1638,7 @@ repeat: | |||
1593 | mddev->events --; | 1638 | mddev->events --; |
1594 | } | 1639 | } |
1595 | mddev->sb_dirty = 2; | 1640 | mddev->sb_dirty = 2; |
1596 | sync_sbs(mddev); | 1641 | sync_sbs(mddev, nospares); |
1597 | 1642 | ||
1598 | /* | 1643 | /* |
1599 | * do not write anything to disk if using | 1644 | * do not write anything to disk if using |
@@ -1615,6 +1660,8 @@ repeat: | |||
1615 | ITERATE_RDEV(mddev,rdev,tmp) { | 1660 | ITERATE_RDEV(mddev,rdev,tmp) { |
1616 | char b[BDEVNAME_SIZE]; | 1661 | char b[BDEVNAME_SIZE]; |
1617 | dprintk(KERN_INFO "md: "); | 1662 | dprintk(KERN_INFO "md: "); |
1663 | if (rdev->sb_loaded != 1) | ||
1664 | continue; /* no noise on spare devices */ | ||
1618 | if (test_bit(Faulty, &rdev->flags)) | 1665 | if (test_bit(Faulty, &rdev->flags)) |
1619 | dprintk("(skipping faulty "); | 1666 | dprintk("(skipping faulty "); |
1620 | 1667 | ||
@@ -1626,6 +1673,7 @@ repeat: | |||
1626 | dprintk(KERN_INFO "(write) %s's sb offset: %llu\n", | 1673 | dprintk(KERN_INFO "(write) %s's sb offset: %llu\n", |
1627 | bdevname(rdev->bdev,b), | 1674 | bdevname(rdev->bdev,b), |
1628 | (unsigned long long)rdev->sb_offset); | 1675 | (unsigned long long)rdev->sb_offset); |
1676 | rdev->sb_events = mddev->events; | ||
1629 | 1677 | ||
1630 | } else | 1678 | } else |
1631 | dprintk(")\n"); | 1679 | dprintk(")\n"); |
@@ -1895,6 +1943,7 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi | |||
1895 | rdev->desc_nr = -1; | 1943 | rdev->desc_nr = -1; |
1896 | rdev->flags = 0; | 1944 | rdev->flags = 0; |
1897 | rdev->data_offset = 0; | 1945 | rdev->data_offset = 0; |
1946 | rdev->sb_events = 0; | ||
1898 | atomic_set(&rdev->nr_pending, 0); | 1947 | atomic_set(&rdev->nr_pending, 0); |
1899 | atomic_set(&rdev->read_errors, 0); | 1948 | atomic_set(&rdev->read_errors, 0); |
1900 | atomic_set(&rdev->corrected_errors, 0); | 1949 | atomic_set(&rdev->corrected_errors, 0); |
@@ -4708,7 +4757,7 @@ void md_write_start(mddev_t *mddev, struct bio *bi) | |||
4708 | spin_lock_irq(&mddev->write_lock); | 4757 | spin_lock_irq(&mddev->write_lock); |
4709 | if (mddev->in_sync) { | 4758 | if (mddev->in_sync) { |
4710 | mddev->in_sync = 0; | 4759 | mddev->in_sync = 0; |
4711 | mddev->sb_dirty = 1; | 4760 | mddev->sb_dirty = 3; |
4712 | md_wakeup_thread(mddev->thread); | 4761 | md_wakeup_thread(mddev->thread); |
4713 | } | 4762 | } |
4714 | spin_unlock_irq(&mddev->write_lock); | 4763 | spin_unlock_irq(&mddev->write_lock); |
@@ -5055,7 +5104,7 @@ void md_check_recovery(mddev_t *mddev) | |||
5055 | if (mddev->safemode && !atomic_read(&mddev->writes_pending) && | 5104 | if (mddev->safemode && !atomic_read(&mddev->writes_pending) && |
5056 | !mddev->in_sync && mddev->recovery_cp == MaxSector) { | 5105 | !mddev->in_sync && mddev->recovery_cp == MaxSector) { |
5057 | mddev->in_sync = 1; | 5106 | mddev->in_sync = 1; |
5058 | mddev->sb_dirty = 1; | 5107 | mddev->sb_dirty = 3; |
5059 | } | 5108 | } |
5060 | if (mddev->safemode == 1) | 5109 | if (mddev->safemode == 1) |
5061 | mddev->safemode = 0; | 5110 | mddev->safemode = 0; |
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index 682574f3bd36..c1e0ac55bab5 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h | |||
@@ -58,6 +58,7 @@ struct mdk_rdev_s | |||
58 | 58 | ||
59 | struct page *sb_page; | 59 | struct page *sb_page; |
60 | int sb_loaded; | 60 | int sb_loaded; |
61 | __u64 sb_events; | ||
61 | sector_t data_offset; /* start of data in array */ | 62 | sector_t data_offset; /* start of data in array */ |
62 | sector_t sb_offset; | 63 | sector_t sb_offset; |
63 | int sb_size; /* bytes in the superblock */ | 64 | int sb_size; /* bytes in the superblock */ |