aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Clements <paul.clements@steeleye.com>2006-10-03 04:15:49 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-03 11:04:17 -0400
commit9b1d1dac181d8c1b9492e05cee660a985d035a06 (patch)
treeaf12b1eaac4e0f7f3528ec26a223faeabed35845
parent76186dd8b73d2b7b9b4c8629b89c845e97009801 (diff)
[PATCH] md: new sysfs interface for setting bits in the write-intent-bitmap
Add a new sysfs interface that allows the bitmap of an array to be dirtied. The interface is write-only, and is used as follows: echo "1000" > /sys/block/md2/md/bitmap (dirty the bit for chunk 1000 [offset 0] in the in-memory and on-disk bitmaps of array md2) echo "1000-2000" > /sys/block/md1/md/bitmap (dirty the bits for chunks 1000-2000 in md1's bitmap) This is useful, for example, in cluster environments where you may need to combine two disjoint bitmaps into one (following a server failure, after a secondary server has taken over the array). By combining the bitmaps on the two servers, a full resync can be avoided (This was discussed on the list back on March 18, 2005, "[PATCH 1/2] md bitmap bug fixes" thread). Signed-off-by: Neil Brown <neilb@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--Documentation/md.txt9
-rw-r--r--drivers/md/bitmap.c14
-rw-r--r--drivers/md/md.c31
-rw-r--r--include/linux/raid/bitmap.h2
4 files changed, 56 insertions, 0 deletions
diff --git a/Documentation/md.txt b/Documentation/md.txt
index 0668f9dc9d29..084ecf4eb2f8 100644
--- a/Documentation/md.txt
+++ b/Documentation/md.txt
@@ -410,6 +410,15 @@ also have
410 than sectors, this my be larger than the number of actual errors 410 than sectors, this my be larger than the number of actual errors
411 by a factor of the number of sectors in a page. 411 by a factor of the number of sectors in a page.
412 412
413 bitmap_set_bits
414 If the array has a write-intent bitmap, then writing to this
415 attribute can set bits in the bitmap, indicating that a resync
416 would need to check the corresponding blocks. Either individual
417 numbers or start-end pairs can be written. Multiple numbers
418 can be separated by a space.
419 Note that the numbers are 'bit' numbers, not 'block' numbers.
420 They should be scaled by the bitmap_chunksize.
421
413Each active md device may also have attributes specific to the 422Each active md device may also have attributes specific to the
414personality module that manages it. 423personality module that manages it.
415These are specific to the implementation of the module and could 424These are specific to the implementation of the module and could
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index ecc56765d949..0a44298fb353 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -613,6 +613,7 @@ static inline unsigned long file_page_offset(unsigned long chunk)
613static inline struct page *filemap_get_page(struct bitmap *bitmap, 613static inline struct page *filemap_get_page(struct bitmap *bitmap,
614 unsigned long chunk) 614 unsigned long chunk)
615{ 615{
616 if (file_page_index(chunk) >= bitmap->file_pages) return NULL;
616 return bitmap->filemap[file_page_index(chunk) - file_page_index(0)]; 617 return bitmap->filemap[file_page_index(chunk) - file_page_index(0)];
617} 618}
618 619
@@ -739,6 +740,7 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
739 } 740 }
740 741
741 page = filemap_get_page(bitmap, chunk); 742 page = filemap_get_page(bitmap, chunk);
743 if (!page) return;
742 bit = file_page_offset(chunk); 744 bit = file_page_offset(chunk);
743 745
744 /* set the bit */ 746 /* set the bit */
@@ -1322,6 +1324,18 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int n
1322 1324
1323} 1325}
1324 1326
1327/* dirty the memory and file bits for bitmap chunks "s" to "e" */
1328void bitmap_dirty_bits(struct bitmap *bitmap, unsigned long s, unsigned long e)
1329{
1330 unsigned long chunk;
1331
1332 for (chunk = s; chunk <= e; chunk++) {
1333 sector_t sec = chunk << CHUNK_BLOCK_SHIFT(bitmap);
1334 bitmap_set_memory_bits(bitmap, sec, 1);
1335 bitmap_file_set_bit(bitmap, sec);
1336 }
1337}
1338
1325/* 1339/*
1326 * flush out any pending updates 1340 * flush out any pending updates
1327 */ 1341 */
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 8b08043f07ef..b95dd8a183ec 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2524,6 +2524,36 @@ static struct md_sysfs_entry md_new_device =
2524__ATTR(new_dev, S_IWUSR, null_show, new_dev_store); 2524__ATTR(new_dev, S_IWUSR, null_show, new_dev_store);
2525 2525
2526static ssize_t 2526static ssize_t
2527bitmap_store(mddev_t *mddev, const char *buf, size_t len)
2528{
2529 char *end;
2530 unsigned long chunk, end_chunk;
2531
2532 if (!mddev->bitmap)
2533 goto out;
2534 /* buf should be <chunk> <chunk> ... or <chunk>-<chunk> ... (range) */
2535 while (*buf) {
2536 chunk = end_chunk = simple_strtoul(buf, &end, 0);
2537 if (buf == end) break;
2538 if (*end == '-') { /* range */
2539 buf = end + 1;
2540 end_chunk = simple_strtoul(buf, &end, 0);
2541 if (buf == end) break;
2542 }
2543 if (*end && !isspace(*end)) break;
2544 bitmap_dirty_bits(mddev->bitmap, chunk, end_chunk);
2545 buf = end;
2546 while (isspace(*buf)) buf++;
2547 }
2548 bitmap_unplug(mddev->bitmap); /* flush the bits to disk */
2549out:
2550 return len;
2551}
2552
2553static struct md_sysfs_entry md_bitmap =
2554__ATTR(bitmap_set_bits, S_IWUSR, null_show, bitmap_store);
2555
2556static ssize_t
2527size_show(mddev_t *mddev, char *page) 2557size_show(mddev_t *mddev, char *page)
2528{ 2558{
2529 return sprintf(page, "%llu\n", (unsigned long long)mddev->size); 2559 return sprintf(page, "%llu\n", (unsigned long long)mddev->size);
@@ -2843,6 +2873,7 @@ static struct attribute *md_redundancy_attrs[] = {
2843 &md_sync_completed.attr, 2873 &md_sync_completed.attr,
2844 &md_suspend_lo.attr, 2874 &md_suspend_lo.attr,
2845 &md_suspend_hi.attr, 2875 &md_suspend_hi.attr,
2876 &md_bitmap.attr,
2846 NULL, 2877 NULL,
2847}; 2878};
2848static struct attribute_group md_redundancy_group = { 2879static struct attribute_group md_redundancy_group = {
diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h
index 63df898fe2e9..84d887751855 100644
--- a/include/linux/raid/bitmap.h
+++ b/include/linux/raid/bitmap.h
@@ -265,6 +265,8 @@ int bitmap_update_sb(struct bitmap *bitmap);
265int bitmap_setallbits(struct bitmap *bitmap); 265int bitmap_setallbits(struct bitmap *bitmap);
266void bitmap_write_all(struct bitmap *bitmap); 266void bitmap_write_all(struct bitmap *bitmap);
267 267
268void bitmap_dirty_bits(struct bitmap *bitmap, unsigned long s, unsigned long e);
269
268/* these are exported */ 270/* these are exported */
269int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, 271int bitmap_startwrite(struct bitmap *bitmap, sector_t offset,
270 unsigned long sectors, int behind); 272 unsigned long sectors, int behind);