diff options
author | NeilBrown <neilb@cse.unsw.edu.au> | 2005-06-21 20:17:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-21 22:07:47 -0400 |
commit | a654b9d8f851f4ca02649d5825cbe6c608adb10c (patch) | |
tree | 747301647f619a9f1dd48f4d6be96b5e35d2484c /drivers/md/bitmap.c | |
parent | 3d310eb7b3df1252e8595d059d982b0a9825a137 (diff) |
[PATCH] md: allow md intent bitmap to be stored near the superblock.
This provides an alternate to storing the bitmap in a separate file. The
bitmap can be stored at a given offset from the superblock. Obviously the
creator of the array must make sure this doesn't intersect with data....
After is good for version-0.90 superblocks.
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 | 132 |
1 files changed, 106 insertions, 26 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 204564dc6a0d..030d6861051a 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c | |||
@@ -116,7 +116,7 @@ static unsigned char *bitmap_alloc_page(struct bitmap *bitmap) | |||
116 | if (!page) | 116 | if (!page) |
117 | printk("%s: bitmap_alloc_page FAILED\n", bmname(bitmap)); | 117 | printk("%s: bitmap_alloc_page FAILED\n", bmname(bitmap)); |
118 | else | 118 | else |
119 | printk("%s: bitmap_alloc_page: allocated page at %p\n", | 119 | PRINTK("%s: bitmap_alloc_page: allocated page at %p\n", |
120 | bmname(bitmap), page); | 120 | bmname(bitmap), page); |
121 | return page; | 121 | return page; |
122 | } | 122 | } |
@@ -258,13 +258,61 @@ char *file_path(struct file *file, char *buf, int count) | |||
258 | * basic page I/O operations | 258 | * basic page I/O operations |
259 | */ | 259 | */ |
260 | 260 | ||
261 | /* IO operations when bitmap is stored near all superblocks */ | ||
262 | static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long index) | ||
263 | { | ||
264 | /* choose a good rdev and read the page from there */ | ||
265 | |||
266 | mdk_rdev_t *rdev; | ||
267 | struct list_head *tmp; | ||
268 | struct page *page = alloc_page(GFP_KERNEL); | ||
269 | sector_t target; | ||
270 | |||
271 | if (!page) | ||
272 | return ERR_PTR(-ENOMEM); | ||
273 | do { | ||
274 | ITERATE_RDEV(mddev, rdev, tmp) | ||
275 | if (rdev->in_sync && !rdev->faulty) | ||
276 | goto found; | ||
277 | return ERR_PTR(-EIO); | ||
278 | |||
279 | found: | ||
280 | target = (rdev->sb_offset << 1) + offset + index * (PAGE_SIZE/512); | ||
281 | |||
282 | } while (!sync_page_io(rdev->bdev, target, PAGE_SIZE, page, READ)); | ||
283 | |||
284 | page->index = index; | ||
285 | return page; | ||
286 | } | ||
287 | |||
288 | static int write_sb_page(mddev_t *mddev, long offset, struct page *page, int wait) | ||
289 | { | ||
290 | mdk_rdev_t *rdev; | ||
291 | struct list_head *tmp; | ||
292 | |||
293 | ITERATE_RDEV(mddev, rdev, tmp) | ||
294 | if (rdev->in_sync && !rdev->faulty) | ||
295 | md_super_write(mddev, rdev, | ||
296 | (rdev->sb_offset<<1) + offset | ||
297 | + page->index * (PAGE_SIZE/512), | ||
298 | PAGE_SIZE, | ||
299 | page); | ||
300 | |||
301 | if (wait) | ||
302 | wait_event(mddev->sb_wait, atomic_read(&mddev->pending_writes)==0); | ||
303 | return 0; | ||
304 | } | ||
305 | |||
261 | /* | 306 | /* |
262 | * write out a page | 307 | * write out a page to a file |
263 | */ | 308 | */ |
264 | static int write_page(struct bitmap *bitmap, struct page *page, int wait) | 309 | static int write_page(struct bitmap *bitmap, struct page *page, int wait) |
265 | { | 310 | { |
266 | int ret = -ENOMEM; | 311 | int ret = -ENOMEM; |
267 | 312 | ||
313 | if (bitmap->file == NULL) | ||
314 | return write_sb_page(bitmap->mddev, bitmap->offset, page, wait); | ||
315 | |||
268 | lock_page(page); | 316 | lock_page(page); |
269 | 317 | ||
270 | ret = page->mapping->a_ops->prepare_write(NULL, page, 0, PAGE_SIZE); | 318 | ret = page->mapping->a_ops->prepare_write(NULL, page, 0, PAGE_SIZE); |
@@ -394,7 +442,12 @@ static int bitmap_read_sb(struct bitmap *bitmap) | |||
394 | int err = -EINVAL; | 442 | int err = -EINVAL; |
395 | 443 | ||
396 | /* page 0 is the superblock, read it... */ | 444 | /* page 0 is the superblock, read it... */ |
397 | bitmap->sb_page = read_page(bitmap->file, 0, &bytes_read); | 445 | if (bitmap->file) |
446 | bitmap->sb_page = read_page(bitmap->file, 0, &bytes_read); | ||
447 | else { | ||
448 | bitmap->sb_page = read_sb_page(bitmap->mddev, bitmap->offset, 0); | ||
449 | bytes_read = PAGE_SIZE; | ||
450 | } | ||
398 | if (IS_ERR(bitmap->sb_page)) { | 451 | if (IS_ERR(bitmap->sb_page)) { |
399 | err = PTR_ERR(bitmap->sb_page); | 452 | err = PTR_ERR(bitmap->sb_page); |
400 | bitmap->sb_page = NULL; | 453 | bitmap->sb_page = NULL; |
@@ -625,14 +678,16 @@ static void bitmap_file_kick(struct bitmap *bitmap) | |||
625 | bitmap_mask_state(bitmap, BITMAP_STALE, MASK_SET); | 678 | bitmap_mask_state(bitmap, BITMAP_STALE, MASK_SET); |
626 | bitmap_update_sb(bitmap); | 679 | bitmap_update_sb(bitmap); |
627 | 680 | ||
628 | path = kmalloc(PAGE_SIZE, GFP_KERNEL); | 681 | if (bitmap->file) { |
629 | if (path) | 682 | path = kmalloc(PAGE_SIZE, GFP_KERNEL); |
630 | ptr = file_path(bitmap->file, path, PAGE_SIZE); | 683 | if (path) |
684 | ptr = file_path(bitmap->file, path, PAGE_SIZE); | ||
631 | 685 | ||
632 | printk(KERN_ALERT "%s: kicking failed bitmap file %s from array!\n", | 686 | printk(KERN_ALERT "%s: kicking failed bitmap file %s from array!\n", |
633 | bmname(bitmap), ptr ? ptr : ""); | 687 | bmname(bitmap), ptr ? ptr : ""); |
634 | 688 | ||
635 | kfree(path); | 689 | kfree(path); |
690 | } | ||
636 | 691 | ||
637 | bitmap_file_put(bitmap); | 692 | bitmap_file_put(bitmap); |
638 | 693 | ||
@@ -676,7 +731,7 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block) | |||
676 | void *kaddr; | 731 | void *kaddr; |
677 | unsigned long chunk = block >> CHUNK_BLOCK_SHIFT(bitmap); | 732 | unsigned long chunk = block >> CHUNK_BLOCK_SHIFT(bitmap); |
678 | 733 | ||
679 | if (!bitmap->file || !bitmap->filemap) { | 734 | if (!bitmap->filemap) { |
680 | return; | 735 | return; |
681 | } | 736 | } |
682 | 737 | ||
@@ -715,7 +770,7 @@ int bitmap_unplug(struct bitmap *bitmap) | |||
715 | * flushed out to disk */ | 770 | * flushed out to disk */ |
716 | for (i = 0; i < bitmap->file_pages; i++) { | 771 | for (i = 0; i < bitmap->file_pages; i++) { |
717 | spin_lock_irqsave(&bitmap->lock, flags); | 772 | spin_lock_irqsave(&bitmap->lock, flags); |
718 | if (!bitmap->file || !bitmap->filemap) { | 773 | if (!bitmap->filemap) { |
719 | spin_unlock_irqrestore(&bitmap->lock, flags); | 774 | spin_unlock_irqrestore(&bitmap->lock, flags); |
720 | return 0; | 775 | return 0; |
721 | } | 776 | } |
@@ -732,11 +787,15 @@ int bitmap_unplug(struct bitmap *bitmap) | |||
732 | return 1; | 787 | return 1; |
733 | } | 788 | } |
734 | if (wait) { /* if any writes were performed, we need to wait on them */ | 789 | if (wait) { /* if any writes were performed, we need to wait on them */ |
735 | spin_lock_irq(&bitmap->write_lock); | 790 | if (bitmap->file) { |
736 | wait_event_lock_irq(bitmap->write_wait, | 791 | spin_lock_irq(&bitmap->write_lock); |
737 | list_empty(&bitmap->complete_pages), bitmap->write_lock, | 792 | wait_event_lock_irq(bitmap->write_wait, |
738 | wake_up_process(bitmap->writeback_daemon->tsk)); | 793 | list_empty(&bitmap->complete_pages), bitmap->write_lock, |
739 | spin_unlock_irq(&bitmap->write_lock); | 794 | wake_up_process(bitmap->writeback_daemon->tsk)); |
795 | spin_unlock_irq(&bitmap->write_lock); | ||
796 | } else | ||
797 | wait_event(bitmap->mddev->sb_wait, | ||
798 | atomic_read(&bitmap->mddev->pending_writes)==0); | ||
740 | } | 799 | } |
741 | return 0; | 800 | return 0; |
742 | } | 801 | } |
@@ -764,7 +823,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync) | |||
764 | chunks = bitmap->chunks; | 823 | chunks = bitmap->chunks; |
765 | file = bitmap->file; | 824 | file = bitmap->file; |
766 | 825 | ||
767 | BUG_ON(!file); | 826 | BUG_ON(!file && !bitmap->offset); |
768 | 827 | ||
769 | #if INJECT_FAULTS_3 | 828 | #if INJECT_FAULTS_3 |
770 | outofdate = 1; | 829 | outofdate = 1; |
@@ -779,7 +838,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync) | |||
779 | 838 | ||
780 | num_pages = (bytes + sizeof(bitmap_super_t) + PAGE_SIZE - 1) / PAGE_SIZE; | 839 | num_pages = (bytes + sizeof(bitmap_super_t) + PAGE_SIZE - 1) / PAGE_SIZE; |
781 | 840 | ||
782 | if (i_size_read(file->f_mapping->host) < bytes + sizeof(bitmap_super_t)) { | 841 | if (file && i_size_read(file->f_mapping->host) < bytes + sizeof(bitmap_super_t)) { |
783 | printk(KERN_INFO "%s: bitmap file too short %lu < %lu\n", | 842 | printk(KERN_INFO "%s: bitmap file too short %lu < %lu\n", |
784 | bmname(bitmap), | 843 | bmname(bitmap), |
785 | (unsigned long) i_size_read(file->f_mapping->host), | 844 | (unsigned long) i_size_read(file->f_mapping->host), |
@@ -816,14 +875,18 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync) | |||
816 | */ | 875 | */ |
817 | page = bitmap->sb_page; | 876 | page = bitmap->sb_page; |
818 | offset = sizeof(bitmap_super_t); | 877 | offset = sizeof(bitmap_super_t); |
819 | } else { | 878 | } else if (file) { |
820 | page = read_page(file, index, &dummy); | 879 | page = read_page(file, index, &dummy); |
821 | if (IS_ERR(page)) { /* read error */ | 880 | offset = 0; |
822 | ret = PTR_ERR(page); | 881 | } else { |
823 | goto out; | 882 | page = read_sb_page(bitmap->mddev, bitmap->offset, index); |
824 | } | ||
825 | offset = 0; | 883 | offset = 0; |
826 | } | 884 | } |
885 | if (IS_ERR(page)) { /* read error */ | ||
886 | ret = PTR_ERR(page); | ||
887 | goto out; | ||
888 | } | ||
889 | |||
827 | oldindex = index; | 890 | oldindex = index; |
828 | oldpage = page; | 891 | oldpage = page; |
829 | kmap(page); | 892 | kmap(page); |
@@ -874,6 +937,19 @@ out: | |||
874 | return ret; | 937 | return ret; |
875 | } | 938 | } |
876 | 939 | ||
940 | void bitmap_write_all(struct bitmap *bitmap) | ||
941 | { | ||
942 | /* We don't actually write all bitmap blocks here, | ||
943 | * just flag them as needing to be written | ||
944 | */ | ||
945 | |||
946 | unsigned long chunks = bitmap->chunks; | ||
947 | unsigned long bytes = (chunks+7)/8 + sizeof(bitmap_super_t); | ||
948 | unsigned long num_pages = (bytes + PAGE_SIZE-1) / PAGE_SIZE; | ||
949 | while (num_pages--) | ||
950 | bitmap->filemap_attr[num_pages] |= BITMAP_PAGE_NEEDWRITE; | ||
951 | } | ||
952 | |||
877 | 953 | ||
878 | static void bitmap_count_page(struct bitmap *bitmap, sector_t offset, int inc) | 954 | static void bitmap_count_page(struct bitmap *bitmap, sector_t offset, int inc) |
879 | { | 955 | { |
@@ -913,7 +989,7 @@ int bitmap_daemon_work(struct bitmap *bitmap) | |||
913 | for (j = 0; j < bitmap->chunks; j++) { | 989 | for (j = 0; j < bitmap->chunks; j++) { |
914 | bitmap_counter_t *bmc; | 990 | bitmap_counter_t *bmc; |
915 | spin_lock_irqsave(&bitmap->lock, flags); | 991 | spin_lock_irqsave(&bitmap->lock, flags); |
916 | if (!bitmap->file || !bitmap->filemap) { | 992 | if (!bitmap->filemap) { |
917 | /* error or shutdown */ | 993 | /* error or shutdown */ |
918 | spin_unlock_irqrestore(&bitmap->lock, flags); | 994 | spin_unlock_irqrestore(&bitmap->lock, flags); |
919 | break; | 995 | break; |
@@ -1072,6 +1148,7 @@ static int bitmap_start_daemon(struct bitmap *bitmap, mdk_thread_t **ptr, | |||
1072 | 1148 | ||
1073 | spin_lock_irqsave(&bitmap->lock, flags); | 1149 | spin_lock_irqsave(&bitmap->lock, flags); |
1074 | *ptr = NULL; | 1150 | *ptr = NULL; |
1151 | |||
1075 | if (!bitmap->file) /* no need for daemon if there's no backing file */ | 1152 | if (!bitmap->file) /* no need for daemon if there's no backing file */ |
1076 | goto out_unlock; | 1153 | goto out_unlock; |
1077 | 1154 | ||
@@ -1416,9 +1493,11 @@ int bitmap_create(mddev_t *mddev) | |||
1416 | 1493 | ||
1417 | BUG_ON(sizeof(bitmap_super_t) != 256); | 1494 | BUG_ON(sizeof(bitmap_super_t) != 256); |
1418 | 1495 | ||
1419 | if (!file) /* bitmap disabled, nothing to do */ | 1496 | if (!file && !mddev->bitmap_offset) /* bitmap disabled, nothing to do */ |
1420 | return 0; | 1497 | return 0; |
1421 | 1498 | ||
1499 | BUG_ON(file && mddev->bitmap_offset); | ||
1500 | |||
1422 | bitmap = kmalloc(sizeof(*bitmap), GFP_KERNEL); | 1501 | bitmap = kmalloc(sizeof(*bitmap), GFP_KERNEL); |
1423 | if (!bitmap) | 1502 | if (!bitmap) |
1424 | return -ENOMEM; | 1503 | return -ENOMEM; |
@@ -1438,7 +1517,8 @@ int bitmap_create(mddev_t *mddev) | |||
1438 | return -ENOMEM; | 1517 | return -ENOMEM; |
1439 | 1518 | ||
1440 | bitmap->file = file; | 1519 | bitmap->file = file; |
1441 | get_file(file); | 1520 | bitmap->offset = mddev->bitmap_offset; |
1521 | if (file) get_file(file); | ||
1442 | /* read superblock from bitmap file (this sets bitmap->chunksize) */ | 1522 | /* read superblock from bitmap file (this sets bitmap->chunksize) */ |
1443 | err = bitmap_read_sb(bitmap); | 1523 | err = bitmap_read_sb(bitmap); |
1444 | if (err) | 1524 | if (err) |