Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 305938
b: refs/heads/master
c: ef99bf4
h: refs/heads/master
v: v3
  • Loading branch information
NeilBrown committed May 22, 2012
1 parent a41c6d3 commit ead30ee
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 63 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 6409bb05a9831f6af36a20b97cda13059c2ef1b6
refs/heads/master: ef99bf480de9bde9d3b2afdf05324670fab4e571
136 changes: 76 additions & 60 deletions trunk/drivers/md/bitmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,14 @@ static int bitmap_read_sb(struct bitmap *bitmap)
unsigned long long events;
int err = -EINVAL;

if (!bitmap->file && !bitmap->mddev->bitmap_info.offset) {
chunksize = 128 * 1024 * 1024;
daemon_sleep = 5 * HZ;
write_behind = 0;
bitmap->flags = BITMAP_STALE;
err = 0;
goto out_no_sb;
}
/* page 0 is the superblock, read it... */
if (bitmap->file) {
loff_t isize = i_size_read(bitmap->file->f_mapping->host);
Expand Down Expand Up @@ -623,18 +631,19 @@ static int bitmap_read_sb(struct bitmap *bitmap)
}

/* assign fields using values from superblock */
bitmap->mddev->bitmap_info.chunksize = chunksize;
bitmap->mddev->bitmap_info.daemon_sleep = daemon_sleep;
bitmap->mddev->bitmap_info.max_write_behind = write_behind;
bitmap->flags |= le32_to_cpu(sb->state);
if (le32_to_cpu(sb->version) == BITMAP_MAJOR_HOSTENDIAN)
bitmap->flags |= BITMAP_HOSTENDIAN;
bitmap->events_cleared = le64_to_cpu(sb->events_cleared);
if (bitmap->flags & BITMAP_STALE)
bitmap->events_cleared = bitmap->mddev->events;
err = 0;
out:
kunmap_atomic(sb);
out_no_sb:
if (bitmap->flags & BITMAP_STALE)
bitmap->events_cleared = bitmap->mddev->events;
bitmap->mddev->bitmap_info.chunksize = chunksize;
bitmap->mddev->bitmap_info.daemon_sleep = daemon_sleep;
bitmap->mddev->bitmap_info.max_write_behind = write_behind;
if (err)
bitmap_print_sb(bitmap);
return err;
Expand Down Expand Up @@ -837,9 +846,6 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
void *kaddr;
unsigned long chunk = block >> bitmap->chunkshift;

if (!bitmap->filemap)
return;

page = filemap_get_page(bitmap, chunk);
if (!page)
return;
Expand All @@ -857,6 +863,29 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
set_page_attr(bitmap, page, BITMAP_PAGE_DIRTY);
}

static void bitmap_file_clear_bit(struct bitmap *bitmap, sector_t block)
{
unsigned long bit;
struct page *page;
void *paddr;
unsigned long chunk = block >> bitmap->chunkshift;

page = filemap_get_page(bitmap, chunk);
if (!page)
return;
bit = file_page_offset(bitmap, chunk);
paddr = kmap_atomic(page);
if (bitmap->flags & BITMAP_HOSTENDIAN)
clear_bit(bit, paddr);
else
__clear_bit_le(bit, paddr);
kunmap_atomic(paddr);
if (!test_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE)) {
set_page_attr(bitmap, page, BITMAP_PAGE_PENDING);
bitmap->allclean = 0;
}
}

/* this gets called when the md device is ready to unplug its underlying
* (slave) device queues -- before we let any writes go down, we need to
* sync the dirty pages of the bitmap file to disk */
Expand All @@ -867,7 +896,7 @@ void bitmap_unplug(struct bitmap *bitmap)
struct page *page;
int wait = 0;

if (!bitmap)
if (!bitmap || !bitmap->filemap)
return;

/* look at each page to see if there are any set bits that need to be
Expand Down Expand Up @@ -930,7 +959,20 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
chunks = bitmap->chunks;
file = bitmap->file;

BUG_ON(!file && !bitmap->mddev->bitmap_info.offset);
if (!file && !bitmap->mddev->bitmap_info.offset) {
/* No permanent bitmap - fill with '1s'. */
bitmap->filemap = NULL;
bitmap->file_pages = 0;
for (i = 0; i < chunks ; i++) {
/* if the disk bit is set, set the memory bit */
int needed = ((sector_t)(i+1) << (bitmap->chunkshift)
>= start);
bitmap_set_memory_bits(bitmap,
(sector_t)i << bitmap->chunkshift,
needed);
}
return 0;
}

outofdate = bitmap->flags & BITMAP_STALE;
if (outofdate)
Expand Down Expand Up @@ -1045,15 +1087,6 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
}
}

/* everything went OK */
ret = 0;
bitmap_mask_state(bitmap, BITMAP_STALE, MASK_UNSET);

if (bit_cnt) { /* Kick recovery if any bits were set */
set_bit(MD_RECOVERY_NEEDED, &bitmap->mddev->recovery);
md_wakeup_thread(bitmap->mddev->thread);
}

printk(KERN_INFO "%s: bitmap initialized from disk: "
"read %lu/%lu pages, set %lu of %lu bits\n",
bmname(bitmap), bitmap->file_pages, num_pages, bit_cnt, chunks);
Expand All @@ -1073,6 +1106,12 @@ void bitmap_write_all(struct bitmap *bitmap)
*/
int i;

if (!bitmap || !bitmap->filemap)
return;
if (bitmap->file)
/* Only one copy, so nothing needed */
return;

spin_lock_irq(&bitmap->lock);
for (i = 0; i < bitmap->file_pages; i++)
set_page_attr(bitmap, bitmap->filemap[i],
Expand Down Expand Up @@ -1115,7 +1154,6 @@ void bitmap_daemon_work(struct mddev *mddev)
unsigned long nextpage;
unsigned long flags;
sector_t blocks;
void *paddr;

/* Use a mutex to guard daemon_work against
* bitmap_destroy.
Expand All @@ -1142,10 +1180,6 @@ void bitmap_daemon_work(struct mddev *mddev)
* we will write it.
*/
spin_lock_irqsave(&bitmap->lock, flags);
if (!bitmap->filemap)
/* error or shutdown */
goto out;

for (j = 0; j < bitmap->file_pages; j++)
if (test_page_attr(bitmap, bitmap->filemap[j],
BITMAP_PAGE_PENDING)) {
Expand All @@ -1161,18 +1195,22 @@ void bitmap_daemon_work(struct mddev *mddev)
* other changes */
bitmap_super_t *sb;
bitmap->need_sync = 0;
sb = kmap_atomic(bitmap->sb_page);
sb->events_cleared =
cpu_to_le64(bitmap->events_cleared);
kunmap_atomic(sb);
set_page_attr(bitmap, bitmap->sb_page, BITMAP_PAGE_NEEDWRITE);
if (bitmap->filemap) {
sb = kmap_atomic(bitmap->sb_page);
sb->events_cleared =
cpu_to_le64(bitmap->events_cleared);
kunmap_atomic(sb);
set_page_attr(bitmap, bitmap->sb_page,
BITMAP_PAGE_NEEDWRITE);
}
}
/* Now look at the bitmap counters and if any are '2' or '1',
* decrement and handle accordingly.
*/
nextpage = 0;
for (j = 0; j < bitmap->chunks; j++) {
bitmap_counter_t *bmc;
sector_t block = (sector_t)j << bitmap->chunkshift;

if (j == nextpage) {
nextpage += PAGE_COUNTER_RATIO;
Expand All @@ -1183,7 +1221,7 @@ void bitmap_daemon_work(struct mddev *mddev)
bitmap->bp[j >> PAGE_COUNTER_SHIFT].pending = 0;
}
bmc = bitmap_get_counter(bitmap,
(sector_t)j << bitmap->chunkshift,
block,
&blocks, 0);

if (!bmc) {
Expand All @@ -1192,33 +1230,12 @@ void bitmap_daemon_work(struct mddev *mddev)
}
if (*bmc == 1 && !bitmap->need_sync) {
/* We can clear the bit */
struct page *page;
*bmc = 0;
bitmap_count_page(
bitmap,
(sector_t)j << bitmap->chunkshift,
-1);

page = filemap_get_page(bitmap, j);
paddr = kmap_atomic(page);
if (bitmap->flags & BITMAP_HOSTENDIAN)
clear_bit(file_page_offset(bitmap, j),
paddr);
else
__clear_bit_le(file_page_offset(bitmap, j),
paddr);
kunmap_atomic(paddr);
if (!test_page_attr(bitmap, page,
BITMAP_PAGE_NEEDWRITE)) {
set_page_attr(bitmap, page,
BITMAP_PAGE_PENDING);
bitmap->allclean = 0;
}
bitmap_count_page(bitmap, block, -1);
bitmap_file_clear_bit(bitmap, block);
} else if (*bmc && *bmc <= 2) {
*bmc = 1;
bitmap_set_pending(
bitmap,
(sector_t)j << bitmap->chunkshift);
bitmap_set_pending(bitmap, block);
bitmap->allclean = 0;
}
}
Expand Down Expand Up @@ -1249,7 +1266,6 @@ void bitmap_daemon_work(struct mddev *mddev)
break;
}
}
out:
spin_unlock_irqrestore(&bitmap->lock, flags);

done:
Expand Down Expand Up @@ -1551,7 +1567,7 @@ EXPORT_SYMBOL(bitmap_cond_end_sync);
static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed)
{
/* For each chunk covered by any of these sectors, set the
* counter to 1 and set resync_needed. They should all
* counter to 2 and possibly set resync_needed. They should all
* be 0 at this point
*/

Expand Down Expand Up @@ -1678,10 +1694,6 @@ int bitmap_create(struct mddev *mddev)

BUILD_BUG_ON(sizeof(bitmap_super_t) != 256);

if (!file
&& !mddev->bitmap_info.offset) /* bitmap disabled, nothing to do */
return 0;

BUG_ON(file && mddev->bitmap_info.offset);

bitmap = kzalloc(sizeof(*bitmap), GFP_KERNEL);
Expand Down Expand Up @@ -1801,6 +1813,10 @@ int bitmap_load(struct mddev *mddev)

if (err)
goto out;
bitmap_mask_state(bitmap, BITMAP_STALE, MASK_UNSET);

/* Kick recovery in case any bits were set */
set_bit(MD_RECOVERY_NEEDED, &bitmap->mddev->recovery);

mddev->thread->timeout = mddev->bitmap_info.daemon_sleep;
md_wakeup_thread(mddev->thread);
Expand Down
5 changes: 3 additions & 2 deletions trunk/drivers/md/md.c
Original file line number Diff line number Diff line change
Expand Up @@ -5139,7 +5139,8 @@ int md_run(struct mddev *mddev)
err = -EINVAL;
mddev->pers->stop(mddev);
}
if (err == 0 && mddev->pers->sync_request) {
if (err == 0 && mddev->pers->sync_request &&
(mddev->bitmap_info.file || mddev->bitmap_info.offset)) {
err = bitmap_create(mddev);
if (err) {
printk(KERN_ERR "%s: failed to create bitmap (%d)\n",
Expand Down Expand Up @@ -7847,7 +7848,7 @@ void md_check_recovery(struct mddev *mddev)
goto unlock;

if (mddev->pers->sync_request) {
if (spares && mddev->bitmap && ! mddev->bitmap->file) {
if (spares) {
/* We are adding a device or devices to an array
* which has the bitmap stored on all devices.
* So make sure all bitmap pages get written
Expand Down

0 comments on commit ead30ee

Please sign in to comment.