aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/md.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@cse.unsw.edu.au>2005-09-09 19:23:45 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-09 19:39:10 -0400
commit36fa30636fb84b209210299684e1be66d9e58217 (patch)
tree28a7473238932f1e7ade1a5a5ec67a113b6d6205 /drivers/md/md.c
parent6a07997fc34ac15a1c5dc650285d79b7604a2276 (diff)
[PATCH] md: all hot-add and hot-remove of md intent logging bitmaps
Both file-bitmaps and superblock bitmaps are supported. If you add a bitmap file on the array device, you lose. This introduces a 'default_bitmap_offset' field in mddev, as the ioctl used for adding a superblock bitmap doesn't have room for giving an offset. Later, this value will be setable via sysfs. Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r--drivers/md/md.c104
1 files changed, 87 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}