aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);