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);
}
/* 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;
void *kaddr;
unsigned long chunk = block >> bitmap->chunkshift;
- if (!bitmap->filemap)
- return;
-
page = filemap_get_page(bitmap, chunk);
if (!page)
return;
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 */
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
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)
}
}
- /* 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);
*/
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],
unsigned long nextpage;
unsigned long flags;
sector_t blocks;
- void *paddr;
/* Use a mutex to guard daemon_work against
* bitmap_destroy.
* 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)) {
* 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;
bitmap->bp[j >> PAGE_COUNTER_SHIFT].pending = 0;
}
bmc = bitmap_get_counter(bitmap,
- (sector_t)j << bitmap->chunkshift,
+ block,
&blocks, 0);
if (!bmc) {
}
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;
}
}
break;
}
}
-out:
spin_unlock_irqrestore(&bitmap->lock, flags);
done:
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
*/
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);
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);