md: separate meta and data devs
Allow the metadata to be on a separate device from the data. This doesn't mean the data and metadata will by on separate physical devices - it simply gives device-mapper and userspace tools more flexibility. Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
committed by
NeilBrown
parent
ccebd4c415
commit
a6ff7e089c
@@ -264,14 +264,18 @@ static mdk_rdev_t *next_active_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
|
|||||||
static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
|
static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
|
||||||
{
|
{
|
||||||
mdk_rdev_t *rdev = NULL;
|
mdk_rdev_t *rdev = NULL;
|
||||||
|
struct block_device *bdev;
|
||||||
mddev_t *mddev = bitmap->mddev;
|
mddev_t *mddev = bitmap->mddev;
|
||||||
|
|
||||||
while ((rdev = next_active_rdev(rdev, mddev)) != NULL) {
|
while ((rdev = next_active_rdev(rdev, mddev)) != NULL) {
|
||||||
int size = PAGE_SIZE;
|
int size = PAGE_SIZE;
|
||||||
loff_t offset = mddev->bitmap_info.offset;
|
loff_t offset = mddev->bitmap_info.offset;
|
||||||
|
|
||||||
|
bdev = (rdev->meta_bdev) ? rdev->meta_bdev : rdev->bdev;
|
||||||
|
|
||||||
if (page->index == bitmap->file_pages-1)
|
if (page->index == bitmap->file_pages-1)
|
||||||
size = roundup(bitmap->last_page_size,
|
size = roundup(bitmap->last_page_size,
|
||||||
bdev_logical_block_size(rdev->bdev));
|
bdev_logical_block_size(bdev));
|
||||||
/* Just make sure we aren't corrupting data or
|
/* Just make sure we aren't corrupting data or
|
||||||
* metadata
|
* metadata
|
||||||
*/
|
*/
|
||||||
|
@@ -765,7 +765,7 @@ void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
|
|||||||
*/
|
*/
|
||||||
struct bio *bio = bio_alloc_mddev(GFP_NOIO, 1, mddev);
|
struct bio *bio = bio_alloc_mddev(GFP_NOIO, 1, mddev);
|
||||||
|
|
||||||
bio->bi_bdev = rdev->bdev;
|
bio->bi_bdev = rdev->meta_bdev ? rdev->meta_bdev : rdev->bdev;
|
||||||
bio->bi_sector = sector;
|
bio->bi_sector = sector;
|
||||||
bio_add_page(bio, page, size, 0);
|
bio_add_page(bio, page, size, 0);
|
||||||
bio->bi_private = rdev;
|
bio->bi_private = rdev;
|
||||||
@@ -803,7 +803,8 @@ int sync_page_io(mdk_rdev_t *rdev, sector_t sector, int size,
|
|||||||
|
|
||||||
rw |= REQ_SYNC | REQ_UNPLUG;
|
rw |= REQ_SYNC | REQ_UNPLUG;
|
||||||
|
|
||||||
bio->bi_bdev = rdev->bdev;
|
bio->bi_bdev = (metadata_op && rdev->meta_bdev) ?
|
||||||
|
rdev->meta_bdev : rdev->bdev;
|
||||||
if (metadata_op)
|
if (metadata_op)
|
||||||
bio->bi_sector = sector + rdev->sb_start;
|
bio->bi_sector = sector + rdev->sb_start;
|
||||||
else
|
else
|
||||||
@@ -4435,7 +4436,9 @@ int md_run(mddev_t *mddev)
|
|||||||
* We don't want the data to overlap the metadata,
|
* We don't want the data to overlap the metadata,
|
||||||
* Internal Bitmap issues have been handled elsewhere.
|
* Internal Bitmap issues have been handled elsewhere.
|
||||||
*/
|
*/
|
||||||
if (rdev->data_offset < rdev->sb_start) {
|
if (rdev->meta_bdev) {
|
||||||
|
/* Nothing to check */;
|
||||||
|
} else if (rdev->data_offset < rdev->sb_start) {
|
||||||
if (mddev->dev_sectors &&
|
if (mddev->dev_sectors &&
|
||||||
rdev->data_offset + mddev->dev_sectors
|
rdev->data_offset + mddev->dev_sectors
|
||||||
> rdev->sb_start) {
|
> rdev->sb_start) {
|
||||||
@@ -5532,7 +5535,6 @@ static int update_size(mddev_t *mddev, sector_t num_sectors)
|
|||||||
* sb_start or, if that is <data_offset, it must fit before the size
|
* sb_start or, if that is <data_offset, it must fit before the size
|
||||||
* of each device. If num_sectors is zero, we find the largest size
|
* of each device. If num_sectors is zero, we find the largest size
|
||||||
* that fits.
|
* that fits.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
if (mddev->sync_thread)
|
if (mddev->sync_thread)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
@@ -60,6 +60,12 @@ struct mdk_rdev_s
|
|||||||
mddev_t *mddev; /* RAID array if running */
|
mddev_t *mddev; /* RAID array if running */
|
||||||
int last_events; /* IO event timestamp */
|
int last_events; /* IO event timestamp */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If meta_bdev is non-NULL, it means that a separate device is
|
||||||
|
* being used to store the metadata (superblock/bitmap) which
|
||||||
|
* would otherwise be contained on the same device as the data (bdev).
|
||||||
|
*/
|
||||||
|
struct block_device *meta_bdev;
|
||||||
struct block_device *bdev; /* block device handle */
|
struct block_device *bdev; /* block device handle */
|
||||||
|
|
||||||
struct page *sb_page;
|
struct page *sb_page;
|
||||||
|
Reference in New Issue
Block a user