aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/md.c104
-rw-r--r--drivers/md/raid1.c30
-rw-r--r--include/linux/raid/md_k.h10
3 files changed, 127 insertions, 17 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 63c566165189..ae654466dc23 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -623,6 +623,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
623 mddev->size = sb->size; 623 mddev->size = sb->size;
624 mddev->events = md_event(sb); 624 mddev->events = md_event(sb);
625 mddev->bitmap_offset = 0; 625 mddev->bitmap_offset = 0;
626 mddev->default_bitmap_offset = MD_SB_BYTES >> 9;
626 627
627 if (sb->state & (1<<MD_SB_CLEAN)) 628 if (sb->state & (1<<MD_SB_CLEAN))
628 mddev->recovery_cp = MaxSector; 629 mddev->recovery_cp = MaxSector;
@@ -648,7 +649,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
648 printk(KERN_WARNING "md: bitmaps only support for raid1\n"); 649 printk(KERN_WARNING "md: bitmaps only support for raid1\n");
649 return -EINVAL; 650 return -EINVAL;
650 } 651 }
651 mddev->bitmap_offset = (MD_SB_BYTES >> 9); 652 mddev->bitmap_offset = mddev->default_bitmap_offset;
652 } 653 }
653 654
654 } else if (mddev->pers == NULL) { 655 } else if (mddev->pers == NULL) {
@@ -939,6 +940,9 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
939 mddev->size = le64_to_cpu(sb->size)/2; 940 mddev->size = le64_to_cpu(sb->size)/2;
940 mddev->events = le64_to_cpu(sb->events); 941 mddev->events = le64_to_cpu(sb->events);
941 mddev->bitmap_offset = 0; 942 mddev->bitmap_offset = 0;
943 mddev->default_bitmap_offset = 0;
944 if (mddev->minor_version == 0)
945 mddev->default_bitmap_offset = -(64*1024)/512;
942 946
943 mddev->recovery_cp = le64_to_cpu(sb->resync_offset); 947 mddev->recovery_cp = le64_to_cpu(sb->resync_offset);
944 memcpy(mddev->uuid, sb->set_uuid, 16); 948 memcpy(mddev->uuid, sb->set_uuid, 16);
@@ -2073,6 +2077,8 @@ static int get_array_info(mddev_t * mddev, void __user * arg)
2073 info.state = 0; 2077 info.state = 0;
2074 if (mddev->in_sync) 2078 if (mddev->in_sync)
2075 info.state = (1<<MD_SB_CLEAN); 2079 info.state = (1<<MD_SB_CLEAN);
2080 if (mddev->bitmap && mddev->bitmap_offset)
2081 info.state = (1<<MD_SB_BITMAP_PRESENT);
2076 info.active_disks = active; 2082 info.active_disks = active;
2077 info.working_disks = working; 2083 info.working_disks = working;
2078 info.failed_disks = failed; 2084 info.failed_disks = failed;
@@ -2430,25 +2436,51 @@ static int set_bitmap_file(mddev_t *mddev, int fd)
2430{ 2436{
2431 int err; 2437 int err;
2432 2438
2433 if (mddev->pers || mddev->bitmap_file) 2439 if (mddev->pers) {
2434 return -EBUSY; 2440 if (!mddev->pers->quiesce)
2441 return -EBUSY;
2442 if (mddev->recovery || mddev->sync_thread)
2443 return -EBUSY;
2444 /* we should be able to change the bitmap.. */
2445 }
2435 2446
2436 mddev->bitmap_file = fget(fd);
2437 2447
2438 if (mddev->bitmap_file == NULL) { 2448 if (fd >= 0) {
2439 printk(KERN_ERR "%s: error: failed to get bitmap file\n", 2449 if (mddev->bitmap)
2440 mdname(mddev)); 2450 return -EEXIST; /* cannot add when bitmap is present */
2441 return -EBADF; 2451 mddev->bitmap_file = fget(fd);
2442 }
2443 2452
2444 err = deny_bitmap_write_access(mddev->bitmap_file); 2453 if (mddev->bitmap_file == NULL) {
2445 if (err) { 2454 printk(KERN_ERR "%s: error: failed to get bitmap file\n",
2446 printk(KERN_ERR "%s: error: bitmap file is already in use\n", 2455 mdname(mddev));
2447 mdname(mddev)); 2456 return -EBADF;
2448 fput(mddev->bitmap_file); 2457 }
2449 mddev->bitmap_file = NULL; 2458
2450 } else 2459 err = deny_bitmap_write_access(mddev->bitmap_file);
2460 if (err) {
2461 printk(KERN_ERR "%s: error: bitmap file is already in use\n",
2462 mdname(mddev));
2463 fput(mddev->bitmap_file);
2464 mddev->bitmap_file = NULL;
2465 return err;
2466 }
2451 mddev->bitmap_offset = 0; /* file overrides offset */ 2467 mddev->bitmap_offset = 0; /* file overrides offset */
2468 } else if (mddev->bitmap == NULL)
2469 return -ENOENT; /* cannot remove what isn't there */
2470 err = 0;
2471 if (mddev->pers) {
2472 mddev->pers->quiesce(mddev, 1);
2473 if (fd >= 0)
2474 err = bitmap_create(mddev);
2475 if (fd < 0 || err)
2476 bitmap_destroy(mddev);
2477 mddev->pers->quiesce(mddev, 0);
2478 } else if (fd < 0) {
2479 if (mddev->bitmap_file)
2480 fput(mddev->bitmap_file);
2481 mddev->bitmap_file = NULL;
2482 }
2483
2452 return err; 2484 return err;
2453} 2485}
2454 2486
@@ -2528,6 +2560,11 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
2528{ 2560{
2529 int rv = 0; 2561 int rv = 0;
2530 int cnt = 0; 2562 int cnt = 0;
2563 int state = 0;
2564
2565 /* calculate expected state,ignoring low bits */
2566 if (mddev->bitmap && mddev->bitmap_offset)
2567 state |= (1 << MD_SB_BITMAP_PRESENT);
2531 2568
2532 if (mddev->major_version != info->major_version || 2569 if (mddev->major_version != info->major_version ||
2533 mddev->minor_version != info->minor_version || 2570 mddev->minor_version != info->minor_version ||
@@ -2536,12 +2573,16 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
2536 mddev->level != info->level || 2573 mddev->level != info->level ||
2537/* mddev->layout != info->layout || */ 2574/* mddev->layout != info->layout || */
2538 !mddev->persistent != info->not_persistent|| 2575 !mddev->persistent != info->not_persistent||
2539 mddev->chunk_size != info->chunk_size ) 2576 mddev->chunk_size != info->chunk_size ||
2577 /* ignore bottom 8 bits of state, and allow SB_BITMAP_PRESENT to change */
2578 ((state^info->state) & 0xfffffe00)
2579 )
2540 return -EINVAL; 2580 return -EINVAL;
2541 /* Check there is only one change */ 2581 /* Check there is only one change */
2542 if (mddev->size != info->size) cnt++; 2582 if (mddev->size != info->size) cnt++;
2543 if (mddev->raid_disks != info->raid_disks) cnt++; 2583 if (mddev->raid_disks != info->raid_disks) cnt++;
2544 if (mddev->layout != info->layout) cnt++; 2584 if (mddev->layout != info->layout) cnt++;
2585 if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) cnt++;
2545 if (cnt == 0) return 0; 2586 if (cnt == 0) return 0;
2546 if (cnt > 1) return -EINVAL; 2587 if (cnt > 1) return -EINVAL;
2547 2588
@@ -2620,6 +2661,35 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
2620 } 2661 }
2621 } 2662 }
2622 } 2663 }
2664 if ((state ^ info->state) & (1<<MD_SB_BITMAP_PRESENT)) {
2665 if (mddev->pers->quiesce == NULL)
2666 return -EINVAL;
2667 if (mddev->recovery || mddev->sync_thread)
2668 return -EBUSY;
2669 if (info->state & (1<<MD_SB_BITMAP_PRESENT)) {
2670 /* add the bitmap */
2671 if (mddev->bitmap)
2672 return -EEXIST;
2673 if (mddev->default_bitmap_offset == 0)
2674 return -EINVAL;
2675 mddev->bitmap_offset = mddev->default_bitmap_offset;
2676 mddev->pers->quiesce(mddev, 1);
2677 rv = bitmap_create(mddev);
2678 if (rv)
2679 bitmap_destroy(mddev);
2680 mddev->pers->quiesce(mddev, 0);
2681 } else {
2682 /* remove the bitmap */
2683 if (!mddev->bitmap)
2684 return -ENOENT;
2685 if (mddev->bitmap->file)
2686 return -EINVAL;
2687 mddev->pers->quiesce(mddev, 1);
2688 bitmap_destroy(mddev);
2689 mddev->pers->quiesce(mddev, 0);
2690 mddev->bitmap_offset = 0;
2691 }
2692 }
2623 md_update_sb(mddev); 2693 md_update_sb(mddev);
2624 return rv; 2694 return rv;
2625} 2695}
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index ace41c571aeb..ba643e4bfac9 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1565,6 +1565,35 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
1565 return 0; 1565 return 0;
1566} 1566}
1567 1567
1568void raid1_quiesce(mddev_t *mddev, int state)
1569{
1570 conf_t *conf = mddev_to_conf(mddev);
1571
1572 switch(state) {
1573 case 0:
1574 spin_lock_irq(&conf->resync_lock);
1575 conf->barrier++;
1576 wait_event_lock_irq(conf->wait_idle, !conf->nr_pending,
1577 conf->resync_lock, raid1_unplug(mddev->queue));
1578 spin_unlock_irq(&conf->resync_lock);
1579 break;
1580 case 1:
1581 spin_lock_irq(&conf->resync_lock);
1582 conf->barrier--;
1583 spin_unlock_irq(&conf->resync_lock);
1584 wake_up(&conf->wait_resume);
1585 wake_up(&conf->wait_idle);
1586 break;
1587 }
1588 if (mddev->thread) {
1589 if (mddev->bitmap)
1590 mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
1591 else
1592 mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
1593 md_wakeup_thread(mddev->thread);
1594 }
1595}
1596
1568 1597
1569static mdk_personality_t raid1_personality = 1598static mdk_personality_t raid1_personality =
1570{ 1599{
@@ -1581,6 +1610,7 @@ static mdk_personality_t raid1_personality =
1581 .sync_request = sync_request, 1610 .sync_request = sync_request,
1582 .resize = raid1_resize, 1611 .resize = raid1_resize,
1583 .reshape = raid1_reshape, 1612 .reshape = raid1_reshape,
1613 .quiesce = raid1_quiesce,
1584}; 1614};
1585 1615
1586static int __init raid_init(void) 1616static int __init raid_init(void)
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
index 8c14ba565a45..817062bf7352 100644
--- a/include/linux/raid/md_k.h
+++ b/include/linux/raid/md_k.h
@@ -278,6 +278,10 @@ struct mddev_s
278 * start of bitmap. May be 278 * start of bitmap. May be
279 * negative, but not '0' 279 * negative, but not '0'
280 */ 280 */
281 long default_bitmap_offset; /* this is the offset to use when
282 * hot-adding a bitmap. It should
283 * eventually be settable by sysfs.
284 */
281 285
282 struct list_head all_mddevs; 286 struct list_head all_mddevs;
283}; 287};
@@ -314,6 +318,12 @@ struct mdk_personality_s
314 int (*resize) (mddev_t *mddev, sector_t sectors); 318 int (*resize) (mddev_t *mddev, sector_t sectors);
315 int (*reshape) (mddev_t *mddev, int raid_disks); 319 int (*reshape) (mddev_t *mddev, int raid_disks);
316 int (*reconfig) (mddev_t *mddev, int layout, int chunk_size); 320 int (*reconfig) (mddev_t *mddev, int layout, int chunk_size);
321 /* quiesce moves between quiescence states
322 * 0 - fully active
323 * 1 - no new requests allowed
324 * others - reserved
325 */
326 void (*quiesce) (mddev_t *mddev, int state);
317}; 327};
318 328
319 329