aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2010-06-01 05:37:34 -0400
committerNeilBrown <neilb@suse.de>2010-07-25 23:21:34 -0400
commite384e58549a2e9a83071ad80280c1a9053cfd84c (patch)
tree805619143612ddc8cc71a45dd4522393c23a576f /drivers/md
parentef4256733506f2459a0c436b62267d22a3f0cec6 (diff)
md/bitmap: prepare for storing write-intent-bitmap via dm-dirty-log.
This allows md/raid5 to fully work as a dm target. Normally md uses a 'filemap' which contains a list of pages of bits each of which may be written separately. dm-log uses and all-or-nothing approach to writing the log, so when using a dm-log, ->filemap is NULL and the flags normally stored in filemap_attr are stored in ->logattrs instead. Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/bitmap.c128
-rw-r--r--drivers/md/bitmap.h5
-rw-r--r--drivers/md/md.h5
3 files changed, 99 insertions, 39 deletions
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 29a3c864e6b0..93765261c363 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -29,6 +29,7 @@
29#include "md.h" 29#include "md.h"
30#include "bitmap.h" 30#include "bitmap.h"
31 31
32#include <linux/dm-dirty-log.h>
32/* debug macros */ 33/* debug macros */
33 34
34#define DEBUG 0 35#define DEBUG 0
@@ -694,6 +695,8 @@ static inline unsigned long file_page_offset(struct bitmap *bitmap, unsigned lon
694static inline struct page *filemap_get_page(struct bitmap *bitmap, 695static inline struct page *filemap_get_page(struct bitmap *bitmap,
695 unsigned long chunk) 696 unsigned long chunk)
696{ 697{
698 if (bitmap->filemap == NULL)
699 return NULL;
697 if (file_page_index(bitmap, chunk) >= bitmap->file_pages) 700 if (file_page_index(bitmap, chunk) >= bitmap->file_pages)
698 return NULL; 701 return NULL;
699 return bitmap->filemap[file_page_index(bitmap, chunk) 702 return bitmap->filemap[file_page_index(bitmap, chunk)
@@ -793,19 +796,28 @@ enum bitmap_page_attr {
793static inline void set_page_attr(struct bitmap *bitmap, struct page *page, 796static inline void set_page_attr(struct bitmap *bitmap, struct page *page,
794 enum bitmap_page_attr attr) 797 enum bitmap_page_attr attr)
795{ 798{
796 __set_bit((page->index<<2) + attr, bitmap->filemap_attr); 799 if (page)
800 __set_bit((page->index<<2) + attr, bitmap->filemap_attr);
801 else
802 __set_bit(attr, &bitmap->logattrs);
797} 803}
798 804
799static inline void clear_page_attr(struct bitmap *bitmap, struct page *page, 805static inline void clear_page_attr(struct bitmap *bitmap, struct page *page,
800 enum bitmap_page_attr attr) 806 enum bitmap_page_attr attr)
801{ 807{
802 __clear_bit((page->index<<2) + attr, bitmap->filemap_attr); 808 if (page)
809 __clear_bit((page->index<<2) + attr, bitmap->filemap_attr);
810 else
811 __clear_bit(attr, &bitmap->logattrs);
803} 812}
804 813
805static inline unsigned long test_page_attr(struct bitmap *bitmap, struct page *page, 814static inline unsigned long test_page_attr(struct bitmap *bitmap, struct page *page,
806 enum bitmap_page_attr attr) 815 enum bitmap_page_attr attr)
807{ 816{
808 return test_bit((page->index<<2) + attr, bitmap->filemap_attr); 817 if (page)
818 return test_bit((page->index<<2) + attr, bitmap->filemap_attr);
819 else
820 return test_bit(attr, &bitmap->logattrs);
809} 821}
810 822
811/* 823/*
@@ -818,27 +830,30 @@ static inline unsigned long test_page_attr(struct bitmap *bitmap, struct page *p
818static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block) 830static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
819{ 831{
820 unsigned long bit; 832 unsigned long bit;
821 struct page *page; 833 struct page *page = NULL;
822 void *kaddr; 834 void *kaddr;
823 unsigned long chunk = block >> CHUNK_BLOCK_SHIFT(bitmap); 835 unsigned long chunk = block >> CHUNK_BLOCK_SHIFT(bitmap);
824 836
825 if (!bitmap->filemap) 837 if (!bitmap->filemap) {
826 return; 838 struct dm_dirty_log *log = bitmap->mddev->bitmap_info.log;
827 839 if (log)
828 page = filemap_get_page(bitmap, chunk); 840 log->type->mark_region(log, chunk);
829 if (!page) 841 } else {
830 return;
831 bit = file_page_offset(bitmap, chunk);
832 842
833 /* set the bit */ 843 page = filemap_get_page(bitmap, chunk);
834 kaddr = kmap_atomic(page, KM_USER0); 844 if (!page)
835 if (bitmap->flags & BITMAP_HOSTENDIAN) 845 return;
836 set_bit(bit, kaddr); 846 bit = file_page_offset(bitmap, chunk);
837 else
838 ext2_set_bit(bit, kaddr);
839 kunmap_atomic(kaddr, KM_USER0);
840 PRINTK("set file bit %lu page %lu\n", bit, page->index);
841 847
848 /* set the bit */
849 kaddr = kmap_atomic(page, KM_USER0);
850 if (bitmap->flags & BITMAP_HOSTENDIAN)
851 set_bit(bit, kaddr);
852 else
853 ext2_set_bit(bit, kaddr);
854 kunmap_atomic(kaddr, KM_USER0);
855 PRINTK("set file bit %lu page %lu\n", bit, page->index);
856 }
842 /* record page number so it gets flushed to disk when unplug occurs */ 857 /* record page number so it gets flushed to disk when unplug occurs */
843 set_page_attr(bitmap, page, BITMAP_PAGE_DIRTY); 858 set_page_attr(bitmap, page, BITMAP_PAGE_DIRTY);
844} 859}
@@ -855,6 +870,16 @@ void bitmap_unplug(struct bitmap *bitmap)
855 870
856 if (!bitmap) 871 if (!bitmap)
857 return; 872 return;
873 if (!bitmap->filemap) {
874 /* Must be using a dirty_log */
875 struct dm_dirty_log *log = bitmap->mddev->bitmap_info.log;
876 dirty = test_and_clear_bit(BITMAP_PAGE_DIRTY, &bitmap->logattrs);
877 need_write = test_and_clear_bit(BITMAP_PAGE_NEEDWRITE, &bitmap->logattrs);
878 if (dirty || need_write)
879 if (log->type->flush(log))
880 bitmap->flags |= BITMAP_WRITE_ERROR;
881 goto out;
882 }
858 883
859 /* look at each page to see if there are any set bits that need to be 884 /* look at each page to see if there are any set bits that need to be
860 * flushed out to disk */ 885 * flushed out to disk */
@@ -883,6 +908,7 @@ void bitmap_unplug(struct bitmap *bitmap)
883 else 908 else
884 md_super_wait(bitmap->mddev); 909 md_super_wait(bitmap->mddev);
885 } 910 }
911out:
886 if (bitmap->flags & BITMAP_WRITE_ERROR) 912 if (bitmap->flags & BITMAP_WRITE_ERROR)
887 bitmap_file_kick(bitmap); 913 bitmap_file_kick(bitmap);
888} 914}
@@ -925,11 +951,11 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
925 printk(KERN_INFO "%s: bitmap file is out of date, doing full " 951 printk(KERN_INFO "%s: bitmap file is out of date, doing full "
926 "recovery\n", bmname(bitmap)); 952 "recovery\n", bmname(bitmap));
927 953
928 bytes = (chunks + 7) / 8; 954 bytes = DIV_ROUND_UP(bitmap->chunks, 8);
929 if (!bitmap->mddev->bitmap_info.external) 955 if (!bitmap->mddev->bitmap_info.external)
930 bytes += sizeof(bitmap_super_t); 956 bytes += sizeof(bitmap_super_t);
931 957
932 num_pages = (bytes + PAGE_SIZE - 1) / PAGE_SIZE; 958 num_pages = DIV_ROUND_UP(bytes, PAGE_SIZE);
933 959
934 if (file && i_size_read(file->f_mapping->host) < bytes) { 960 if (file && i_size_read(file->f_mapping->host) < bytes) {
935 printk(KERN_INFO "%s: bitmap file too short %lu < %lu\n", 961 printk(KERN_INFO "%s: bitmap file too short %lu < %lu\n",
@@ -1090,6 +1116,7 @@ void bitmap_daemon_work(mddev_t *mddev)
1090 struct page *page = NULL, *lastpage = NULL; 1116 struct page *page = NULL, *lastpage = NULL;
1091 int blocks; 1117 int blocks;
1092 void *paddr; 1118 void *paddr;
1119 struct dm_dirty_log *log = mddev->bitmap_info.log;
1093 1120
1094 /* Use a mutex to guard daemon_work against 1121 /* Use a mutex to guard daemon_work against
1095 * bitmap_destroy. 1122 * bitmap_destroy.
@@ -1114,11 +1141,12 @@ void bitmap_daemon_work(mddev_t *mddev)
1114 spin_lock_irqsave(&bitmap->lock, flags); 1141 spin_lock_irqsave(&bitmap->lock, flags);
1115 for (j = 0; j < bitmap->chunks; j++) { 1142 for (j = 0; j < bitmap->chunks; j++) {
1116 bitmap_counter_t *bmc; 1143 bitmap_counter_t *bmc;
1117 if (!bitmap->filemap) 1144 if (!bitmap->filemap) {
1118 /* error or shutdown */ 1145 if (!log)
1119 break; 1146 /* error or shutdown */
1120 1147 break;
1121 page = filemap_get_page(bitmap, j); 1148 } else
1149 page = filemap_get_page(bitmap, j);
1122 1150
1123 if (page != lastpage) { 1151 if (page != lastpage) {
1124 /* skip this page unless it's marked as needing cleaning */ 1152 /* skip this page unless it's marked as needing cleaning */
@@ -1187,14 +1215,17 @@ void bitmap_daemon_work(mddev_t *mddev)
1187 -1); 1215 -1);
1188 1216
1189 /* clear the bit */ 1217 /* clear the bit */
1190 paddr = kmap_atomic(page, KM_USER0); 1218 if (page) {
1191 if (bitmap->flags & BITMAP_HOSTENDIAN) 1219 paddr = kmap_atomic(page, KM_USER0);
1192 clear_bit(file_page_offset(bitmap, j), 1220 if (bitmap->flags & BITMAP_HOSTENDIAN)
1193 paddr); 1221 clear_bit(file_page_offset(bitmap, j),
1194 else 1222 paddr);
1195 ext2_clear_bit(file_page_offset(bitmap, j), 1223 else
1196 paddr); 1224 ext2_clear_bit(file_page_offset(bitmap, j),
1197 kunmap_atomic(paddr, KM_USER0); 1225 paddr);
1226 kunmap_atomic(paddr, KM_USER0);
1227 } else
1228 log->type->clear_region(log, j);
1198 } 1229 }
1199 } else 1230 } else
1200 j |= PAGE_COUNTER_MASK; 1231 j |= PAGE_COUNTER_MASK;
@@ -1202,12 +1233,16 @@ void bitmap_daemon_work(mddev_t *mddev)
1202 spin_unlock_irqrestore(&bitmap->lock, flags); 1233 spin_unlock_irqrestore(&bitmap->lock, flags);
1203 1234
1204 /* now sync the final page */ 1235 /* now sync the final page */
1205 if (lastpage != NULL) { 1236 if (lastpage != NULL || log != NULL) {
1206 spin_lock_irqsave(&bitmap->lock, flags); 1237 spin_lock_irqsave(&bitmap->lock, flags);
1207 if (test_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE)) { 1238 if (test_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE)) {
1208 clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE); 1239 clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
1209 spin_unlock_irqrestore(&bitmap->lock, flags); 1240 spin_unlock_irqrestore(&bitmap->lock, flags);
1210 write_page(bitmap, lastpage, 0); 1241 if (lastpage)
1242 write_page(bitmap, lastpage, 0);
1243 else
1244 if (log->type->flush(log))
1245 bitmap->flags |= BITMAP_WRITE_ERROR;
1211 } else { 1246 } else {
1212 set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE); 1247 set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
1213 spin_unlock_irqrestore(&bitmap->lock, flags); 1248 spin_unlock_irqrestore(&bitmap->lock, flags);
@@ -1372,7 +1407,9 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto
1372 (*bmc)--; 1407 (*bmc)--;
1373 if (*bmc <= 2) 1408 if (*bmc <= 2)
1374 set_page_attr(bitmap, 1409 set_page_attr(bitmap,
1375 filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)), 1410 filemap_get_page(
1411 bitmap,
1412 offset >> CHUNK_BLOCK_SHIFT(bitmap)),
1376 BITMAP_PAGE_CLEAN); 1413 BITMAP_PAGE_CLEAN);
1377 1414
1378 spin_unlock_irqrestore(&bitmap->lock, flags); 1415 spin_unlock_irqrestore(&bitmap->lock, flags);
@@ -1649,10 +1686,13 @@ int bitmap_create(mddev_t *mddev)
1649 1686
1650 BUILD_BUG_ON(sizeof(bitmap_super_t) != 256); 1687 BUILD_BUG_ON(sizeof(bitmap_super_t) != 256);
1651 1688
1652 if (!file && !mddev->bitmap_info.offset) /* bitmap disabled, nothing to do */ 1689 if (!file
1690 && !mddev->bitmap_info.offset
1691 && !mddev->bitmap_info.log) /* bitmap disabled, nothing to do */
1653 return 0; 1692 return 0;
1654 1693
1655 BUG_ON(file && mddev->bitmap_info.offset); 1694 BUG_ON(file && mddev->bitmap_info.offset);
1695 BUG_ON(mddev->bitmap_info.offset && mddev->bitmap_info.log);
1656 1696
1657 bitmap = kzalloc(sizeof(*bitmap), GFP_KERNEL); 1697 bitmap = kzalloc(sizeof(*bitmap), GFP_KERNEL);
1658 if (!bitmap) 1698 if (!bitmap)
@@ -1730,7 +1770,17 @@ int bitmap_create(mddev_t *mddev)
1730 || bitmap->events_cleared == mddev->events) 1770 || bitmap->events_cleared == mddev->events)
1731 /* no need to keep dirty bits to optimise a re-add of a missing device */ 1771 /* no need to keep dirty bits to optimise a re-add of a missing device */
1732 start = mddev->recovery_cp; 1772 start = mddev->recovery_cp;
1733 err = bitmap_init_from_disk(bitmap, start); 1773 if (mddev->bitmap_info.log) {
1774 unsigned long i;
1775 struct dm_dirty_log *log = mddev->bitmap_info.log;
1776 for (i = 0; i < bitmap->chunks; i++)
1777 if (!log->type->in_sync(log, i, 1))
1778 bitmap_set_memory_bits(bitmap,
1779 (sector_t)i << CHUNK_BLOCK_SHIFT(bitmap),
1780 1);
1781 err = 0;
1782 } else
1783 err = bitmap_init_from_disk(bitmap, start);
1734 1784
1735 if (err) 1785 if (err)
1736 goto error; 1786 goto error;
diff --git a/drivers/md/bitmap.h b/drivers/md/bitmap.h
index 3797dea4723a..a7a11134268d 100644
--- a/drivers/md/bitmap.h
+++ b/drivers/md/bitmap.h
@@ -222,6 +222,10 @@ struct bitmap {
222 unsigned long file_pages; /* number of pages in the file */ 222 unsigned long file_pages; /* number of pages in the file */
223 int last_page_size; /* bytes in the last page */ 223 int last_page_size; /* bytes in the last page */
224 224
225 unsigned long logattrs; /* used when filemap_attr doesn't exist
226 * because we are working with a dirty_log
227 */
228
225 unsigned long flags; 229 unsigned long flags;
226 230
227 int allclean; 231 int allclean;
@@ -243,6 +247,7 @@ struct bitmap {
243 wait_queue_head_t behind_wait; 247 wait_queue_head_t behind_wait;
244 248
245 struct sysfs_dirent *sysfs_can_clear; 249 struct sysfs_dirent *sysfs_can_clear;
250
246}; 251};
247 252
248/* the bitmap API */ 253/* the bitmap API */
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 0a850780b5d1..cccbadb31bae 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -317,6 +317,11 @@ struct mddev_s
317 * hot-adding a bitmap. It should 317 * hot-adding a bitmap. It should
318 * eventually be settable by sysfs. 318 * eventually be settable by sysfs.
319 */ 319 */
320 /* When md is serving under dm, it might use a
321 * dirty_log to store the bits.
322 */
323 struct dm_dirty_log *log;
324
320 struct mutex mutex; 325 struct mutex mutex;
321 unsigned long chunksize; 326 unsigned long chunksize;
322 unsigned long daemon_sleep; /* how many jiffies between updates? */ 327 unsigned long daemon_sleep; /* how many jiffies between updates? */