Skip to content

Commit

Permalink
md/bitmap: improve handling of 'allclean'.
Browse files Browse the repository at this point in the history
The 'allclean' flag is used to cache the fact that there is nothing to
do, so we can avoid waking up and scanning the bitmap regularly.

The two sorts of pages that might need the attention of the bitmap
daemon are BITMAP_PAGE_PENDING and BITMAP_PAGE_NEEDWRITE pages.

So make sure allclean reflects exactly when there are none of those.
So:
  set it before scanning all pages with either bit set.
  clear it whenever these bits are set
  clear it when we desire not to clear one of these bits.
  don't clear it any other time.

Signed-off-by: NeilBrown <neilb@suse.de>
  • Loading branch information
NeilBrown committed Sep 21, 2011
1 parent 5a537df commit 2585f3e
Showing 1 changed file with 20 additions and 15 deletions.
35 changes: 20 additions & 15 deletions drivers/md/bitmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1146,6 +1146,7 @@ void bitmap_write_all(struct bitmap *bitmap)
for (i = 0; i < bitmap->file_pages; i++)
set_page_attr(bitmap, bitmap->filemap[i],
BITMAP_PAGE_NEEDWRITE);
bitmap->allclean = 0;
}

static void bitmap_count_page(struct bitmap *bitmap, sector_t offset, int inc)
Expand Down Expand Up @@ -1211,23 +1212,25 @@ void bitmap_daemon_work(mddev_t *mddev)
clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);

spin_unlock_irqrestore(&bitmap->lock, flags);
if (need_write) {
if (need_write)
write_page(bitmap, page, 0);
bitmap->allclean = 0;
}
spin_lock_irqsave(&bitmap->lock, flags);
j |= (PAGE_BITS - 1);
continue;
}

/* grab the new page, sync and release the old */
if (lastpage != NULL) {
if (test_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE)) {
clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
if (test_page_attr(bitmap, lastpage,
BITMAP_PAGE_NEEDWRITE)) {
clear_page_attr(bitmap, lastpage,
BITMAP_PAGE_NEEDWRITE);
spin_unlock_irqrestore(&bitmap->lock, flags);
write_page(bitmap, lastpage, 0);
} else {
set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
set_page_attr(bitmap, lastpage,
BITMAP_PAGE_NEEDWRITE);
bitmap->allclean = 0;
spin_unlock_irqrestore(&bitmap->lock, flags);
}
} else
Expand All @@ -1250,15 +1253,15 @@ void bitmap_daemon_work(mddev_t *mddev)
spin_lock_irqsave(&bitmap->lock, flags);
if (!bitmap->need_sync)
clear_page_attr(bitmap, page, BITMAP_PAGE_PENDING);
else
bitmap->allclean = 0;
}
bmc = bitmap_get_counter(bitmap,
(sector_t)j << CHUNK_BLOCK_SHIFT(bitmap),
&blocks, 0);
if (!bmc)
j |= PAGE_COUNTER_MASK;
else if (*bmc) {
bitmap->allclean = 0;

if (*bmc == 1 && !bitmap->need_sync) {
/* we can clear the bit */
*bmc = 0;
Expand All @@ -1280,6 +1283,7 @@ void bitmap_daemon_work(mddev_t *mddev)
} else if (*bmc <= 2) {
*bmc = 1; /* maybe clear the bit next time */
set_page_attr(bitmap, page, BITMAP_PAGE_PENDING);
bitmap->allclean = 0;
}
}
}
Expand All @@ -1294,6 +1298,7 @@ void bitmap_daemon_work(mddev_t *mddev)
write_page(bitmap, lastpage, 0);
} else {
set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
bitmap->allclean = 0;
spin_unlock_irqrestore(&bitmap->lock, flags);
}
}
Expand Down Expand Up @@ -1407,7 +1412,6 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
else
sectors = 0;
}
bitmap->allclean = 0;
return 0;
}
EXPORT_SYMBOL(bitmap_startwrite);
Expand Down Expand Up @@ -1453,13 +1457,14 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto
wake_up(&bitmap->overflow_wait);

(*bmc)--;
if (*bmc <= 2)
if (*bmc <= 2) {
set_page_attr(bitmap,
filemap_get_page(
bitmap,
offset >> CHUNK_BLOCK_SHIFT(bitmap)),
BITMAP_PAGE_PENDING);

bitmap->allclean = 0;
}
spin_unlock_irqrestore(&bitmap->lock, flags);
offset += blocks;
if (sectors > blocks)
Expand Down Expand Up @@ -1495,7 +1500,6 @@ static int __bitmap_start_sync(struct bitmap *bitmap, sector_t offset, sector_t
}
}
spin_unlock_irq(&bitmap->lock);
bitmap->allclean = 0;
return rv;
}

Expand Down Expand Up @@ -1543,15 +1547,16 @@ void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, sector_t *blocks, i
if (!NEEDED(*bmc) && aborted)
*bmc |= NEEDED_MASK;
else {
if (*bmc <= 2)
if (*bmc <= 2) {
set_page_attr(bitmap,
filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)),
BITMAP_PAGE_PENDING);
bitmap->allclean = 0;
}
}
}
unlock:
spin_unlock_irqrestore(&bitmap->lock, flags);
bitmap->allclean = 0;
}
EXPORT_SYMBOL(bitmap_end_sync);

Expand Down Expand Up @@ -1623,9 +1628,9 @@ static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int n
bitmap_count_page(bitmap, offset, 1);
page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
set_page_attr(bitmap, page, BITMAP_PAGE_PENDING);
bitmap->allclean = 0;
}
spin_unlock_irq(&bitmap->lock);
bitmap->allclean = 0;
}

/* dirty the memory and file bits for bitmap chunks "s" to "e" */
Expand Down

0 comments on commit 2585f3e

Please sign in to comment.