diff options
author | NeilBrown <neilb@cse.unsw.edu.au> | 2005-09-09 19:23:50 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-09 19:39:11 -0400 |
commit | 3178b0dbdf67322f6506582e494bdf553cc85c32 (patch) | |
tree | a1169a85a0b3a54f1368dcdd86f656cfe4edd89e /drivers/md/bitmap.c | |
parent | 585f0dd5a955c420ff3af5193aa07d6f789bf81a (diff) |
[PATCH] md: do not set mddev->bitmap until bitmap is fully initialised
When hot-adding a bitmap, bitmap_daemon_work could get called while the bitmap
is being created, so don't set mddev->bitmap until the bitmap is ready.
This requires freeing the bitmap inside bitmap_create if creation failed
part-way through.
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/bitmap.c')
-rw-r--r-- | drivers/md/bitmap.c | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index f0f510c13410..c971d38f3a05 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c | |||
@@ -1503,17 +1503,14 @@ void bitmap_flush(mddev_t *mddev) | |||
1503 | /* | 1503 | /* |
1504 | * free memory that was allocated | 1504 | * free memory that was allocated |
1505 | */ | 1505 | */ |
1506 | void bitmap_destroy(mddev_t *mddev) | 1506 | static void bitmap_free(struct bitmap *bitmap) |
1507 | { | 1507 | { |
1508 | unsigned long k, pages; | 1508 | unsigned long k, pages; |
1509 | struct bitmap_page *bp; | 1509 | struct bitmap_page *bp; |
1510 | struct bitmap *bitmap = mddev->bitmap; | ||
1511 | 1510 | ||
1512 | if (!bitmap) /* there was no bitmap */ | 1511 | if (!bitmap) /* there was no bitmap */ |
1513 | return; | 1512 | return; |
1514 | 1513 | ||
1515 | mddev->bitmap = NULL; /* disconnect from the md device */ | ||
1516 | |||
1517 | /* release the bitmap file and kill the daemon */ | 1514 | /* release the bitmap file and kill the daemon */ |
1518 | bitmap_file_put(bitmap); | 1515 | bitmap_file_put(bitmap); |
1519 | 1516 | ||
@@ -1531,6 +1528,17 @@ void bitmap_destroy(mddev_t *mddev) | |||
1531 | kfree(bp); | 1528 | kfree(bp); |
1532 | kfree(bitmap); | 1529 | kfree(bitmap); |
1533 | } | 1530 | } |
1531 | void bitmap_destroy(mddev_t *mddev) | ||
1532 | { | ||
1533 | struct bitmap *bitmap = mddev->bitmap; | ||
1534 | |||
1535 | if (!bitmap) /* there was no bitmap */ | ||
1536 | return; | ||
1537 | |||
1538 | mddev->bitmap = NULL; /* disconnect from the md device */ | ||
1539 | |||
1540 | bitmap_free(bitmap); | ||
1541 | } | ||
1534 | 1542 | ||
1535 | /* | 1543 | /* |
1536 | * initialize the bitmap structure | 1544 | * initialize the bitmap structure |
@@ -1561,15 +1569,15 @@ int bitmap_create(mddev_t *mddev) | |||
1561 | 1569 | ||
1562 | spin_lock_init(&bitmap->lock); | 1570 | spin_lock_init(&bitmap->lock); |
1563 | bitmap->mddev = mddev; | 1571 | bitmap->mddev = mddev; |
1564 | mddev->bitmap = bitmap; | ||
1565 | 1572 | ||
1566 | spin_lock_init(&bitmap->write_lock); | 1573 | spin_lock_init(&bitmap->write_lock); |
1567 | INIT_LIST_HEAD(&bitmap->complete_pages); | 1574 | INIT_LIST_HEAD(&bitmap->complete_pages); |
1568 | init_waitqueue_head(&bitmap->write_wait); | 1575 | init_waitqueue_head(&bitmap->write_wait); |
1569 | bitmap->write_pool = mempool_create(WRITE_POOL_SIZE, write_pool_alloc, | 1576 | bitmap->write_pool = mempool_create(WRITE_POOL_SIZE, write_pool_alloc, |
1570 | write_pool_free, NULL); | 1577 | write_pool_free, NULL); |
1578 | err = -ENOMEM; | ||
1571 | if (!bitmap->write_pool) | 1579 | if (!bitmap->write_pool) |
1572 | return -ENOMEM; | 1580 | goto error; |
1573 | 1581 | ||
1574 | bitmap->file = file; | 1582 | bitmap->file = file; |
1575 | bitmap->offset = mddev->bitmap_offset; | 1583 | bitmap->offset = mddev->bitmap_offset; |
@@ -1577,7 +1585,7 @@ int bitmap_create(mddev_t *mddev) | |||
1577 | /* read superblock from bitmap file (this sets bitmap->chunksize) */ | 1585 | /* read superblock from bitmap file (this sets bitmap->chunksize) */ |
1578 | err = bitmap_read_sb(bitmap); | 1586 | err = bitmap_read_sb(bitmap); |
1579 | if (err) | 1587 | if (err) |
1580 | return err; | 1588 | goto error; |
1581 | 1589 | ||
1582 | bitmap->chunkshift = find_first_bit(&bitmap->chunksize, | 1590 | bitmap->chunkshift = find_first_bit(&bitmap->chunksize, |
1583 | sizeof(bitmap->chunksize)); | 1591 | sizeof(bitmap->chunksize)); |
@@ -1601,8 +1609,9 @@ int bitmap_create(mddev_t *mddev) | |||
1601 | #else | 1609 | #else |
1602 | bitmap->bp = kmalloc(pages * sizeof(*bitmap->bp), GFP_KERNEL); | 1610 | bitmap->bp = kmalloc(pages * sizeof(*bitmap->bp), GFP_KERNEL); |
1603 | #endif | 1611 | #endif |
1612 | err = -ENOMEM; | ||
1604 | if (!bitmap->bp) | 1613 | if (!bitmap->bp) |
1605 | return -ENOMEM; | 1614 | goto error; |
1606 | memset(bitmap->bp, 0, pages * sizeof(*bitmap->bp)); | 1615 | memset(bitmap->bp, 0, pages * sizeof(*bitmap->bp)); |
1607 | 1616 | ||
1608 | bitmap->flags |= BITMAP_ACTIVE; | 1617 | bitmap->flags |= BITMAP_ACTIVE; |
@@ -1617,16 +1626,22 @@ int bitmap_create(mddev_t *mddev) | |||
1617 | err = bitmap_init_from_disk(bitmap, start); | 1626 | err = bitmap_init_from_disk(bitmap, start); |
1618 | 1627 | ||
1619 | if (err) | 1628 | if (err) |
1620 | return err; | 1629 | goto error; |
1621 | 1630 | ||
1622 | printk(KERN_INFO "created bitmap (%lu pages) for device %s\n", | 1631 | printk(KERN_INFO "created bitmap (%lu pages) for device %s\n", |
1623 | pages, bmname(bitmap)); | 1632 | pages, bmname(bitmap)); |
1624 | 1633 | ||
1634 | mddev->bitmap = bitmap; | ||
1635 | |||
1625 | /* kick off the bitmap daemons */ | 1636 | /* kick off the bitmap daemons */ |
1626 | err = bitmap_start_daemons(bitmap); | 1637 | err = bitmap_start_daemons(bitmap); |
1627 | if (err) | 1638 | if (err) |
1628 | return err; | 1639 | return err; |
1629 | return bitmap_update_sb(bitmap); | 1640 | return bitmap_update_sb(bitmap); |
1641 | |||
1642 | error: | ||
1643 | bitmap_free(bitmap); | ||
1644 | return err; | ||
1630 | } | 1645 | } |
1631 | 1646 | ||
1632 | /* the bitmap API -- for raid personalities */ | 1647 | /* the bitmap API -- for raid personalities */ |