Commit 9b1d1dac181d8c1b9492e05cee660a985d035a06
Committed by
Linus Torvalds
1 parent
76186dd8b7
Exists in
master
and in
4 other branches
[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>
Showing 4 changed files with 56 additions and 0 deletions Side-by-side Diff
Documentation/md.txt
... | ... | @@ -410,6 +410,15 @@ |
410 | 410 | than sectors, this my be larger than the number of actual errors |
411 | 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 | + | |
413 | 422 | Each active md device may also have attributes specific to the |
414 | 423 | personality module that manages it. |
415 | 424 | These are specific to the implementation of the module and could |
drivers/md/bitmap.c
... | ... | @@ -613,6 +613,7 @@ |
613 | 613 | static inline struct page *filemap_get_page(struct bitmap *bitmap, |
614 | 614 | unsigned long chunk) |
615 | 615 | { |
616 | + if (file_page_index(chunk) >= bitmap->file_pages) return NULL; | |
616 | 617 | return bitmap->filemap[file_page_index(chunk) - file_page_index(0)]; |
617 | 618 | } |
618 | 619 | |
... | ... | @@ -739,6 +740,7 @@ |
739 | 740 | } |
740 | 741 | |
741 | 742 | page = filemap_get_page(bitmap, chunk); |
743 | + if (!page) return; | |
742 | 744 | bit = file_page_offset(chunk); |
743 | 745 | |
744 | 746 | /* set the bit */ |
... | ... | @@ -1320,6 +1322,18 @@ |
1320 | 1322 | } |
1321 | 1323 | spin_unlock_irq(&bitmap->lock); |
1322 | 1324 | |
1325 | +} | |
1326 | + | |
1327 | +/* dirty the memory and file bits for bitmap chunks "s" to "e" */ | |
1328 | +void 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 | + } | |
1323 | 1337 | } |
1324 | 1338 | |
1325 | 1339 | /* |
drivers/md/md.c
... | ... | @@ -2524,6 +2524,36 @@ |
2524 | 2524 | __ATTR(new_dev, S_IWUSR, null_show, new_dev_store); |
2525 | 2525 | |
2526 | 2526 | static ssize_t |
2527 | +bitmap_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 */ | |
2549 | +out: | |
2550 | + return len; | |
2551 | +} | |
2552 | + | |
2553 | +static struct md_sysfs_entry md_bitmap = | |
2554 | +__ATTR(bitmap_set_bits, S_IWUSR, null_show, bitmap_store); | |
2555 | + | |
2556 | +static ssize_t | |
2527 | 2557 | size_show(mddev_t *mddev, char *page) |
2528 | 2558 | { |
2529 | 2559 | return sprintf(page, "%llu\n", (unsigned long long)mddev->size); |
... | ... | @@ -2843,6 +2873,7 @@ |
2843 | 2873 | &md_sync_completed.attr, |
2844 | 2874 | &md_suspend_lo.attr, |
2845 | 2875 | &md_suspend_hi.attr, |
2876 | + &md_bitmap.attr, | |
2846 | 2877 | NULL, |
2847 | 2878 | }; |
2848 | 2879 | static struct attribute_group md_redundancy_group = { |
include/linux/raid/bitmap.h
... | ... | @@ -265,6 +265,8 @@ |
265 | 265 | int bitmap_setallbits(struct bitmap *bitmap); |
266 | 266 | void bitmap_write_all(struct bitmap *bitmap); |
267 | 267 | |
268 | +void bitmap_dirty_bits(struct bitmap *bitmap, unsigned long s, unsigned long e); | |
269 | + | |
268 | 270 | /* these are exported */ |
269 | 271 | int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, |
270 | 272 | unsigned long sectors, int behind); |