|
@@ -96,6 +96,13 @@ struct drbd_bitmap {
|
|
struct page **bm_pages;
|
|
struct page **bm_pages;
|
|
spinlock_t bm_lock;
|
|
spinlock_t bm_lock;
|
|
|
|
|
|
|
|
+ /* exclusively to be used by __al_write_transaction(),
|
|
|
|
+ * drbd_bm_mark_for_writeout() and
|
|
|
|
+ * and drbd_bm_write_hinted() -> bm_rw() called from there.
|
|
|
|
+ */
|
|
|
|
+ unsigned int n_bitmap_hints;
|
|
|
|
+ unsigned int al_bitmap_hints[AL_UPDATES_PER_TRANSACTION];
|
|
|
|
+
|
|
/* see LIMITATIONS: above */
|
|
/* see LIMITATIONS: above */
|
|
|
|
|
|
unsigned long bm_set; /* nr of set bits; THINK maybe atomic_t? */
|
|
unsigned long bm_set; /* nr of set bits; THINK maybe atomic_t? */
|
|
@@ -242,6 +249,11 @@ static void bm_set_page_need_writeout(struct page *page)
|
|
set_bit(BM_PAGE_NEED_WRITEOUT, &page_private(page));
|
|
set_bit(BM_PAGE_NEED_WRITEOUT, &page_private(page));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void drbd_bm_reset_al_hints(struct drbd_device *device)
|
|
|
|
+{
|
|
|
|
+ device->bitmap->n_bitmap_hints = 0;
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* drbd_bm_mark_for_writeout() - mark a page with a "hint" to be considered for writeout
|
|
* drbd_bm_mark_for_writeout() - mark a page with a "hint" to be considered for writeout
|
|
* @device: DRBD device.
|
|
* @device: DRBD device.
|
|
@@ -253,6 +265,7 @@ static void bm_set_page_need_writeout(struct page *page)
|
|
*/
|
|
*/
|
|
void drbd_bm_mark_for_writeout(struct drbd_device *device, int page_nr)
|
|
void drbd_bm_mark_for_writeout(struct drbd_device *device, int page_nr)
|
|
{
|
|
{
|
|
|
|
+ struct drbd_bitmap *b = device->bitmap;
|
|
struct page *page;
|
|
struct page *page;
|
|
if (page_nr >= device->bitmap->bm_number_of_pages) {
|
|
if (page_nr >= device->bitmap->bm_number_of_pages) {
|
|
drbd_warn(device, "BAD: page_nr: %u, number_of_pages: %u\n",
|
|
drbd_warn(device, "BAD: page_nr: %u, number_of_pages: %u\n",
|
|
@@ -260,7 +273,9 @@ void drbd_bm_mark_for_writeout(struct drbd_device *device, int page_nr)
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
page = device->bitmap->bm_pages[page_nr];
|
|
page = device->bitmap->bm_pages[page_nr];
|
|
- set_bit(BM_PAGE_HINT_WRITEOUT, &page_private(page));
|
|
|
|
|
|
+ BUG_ON(b->n_bitmap_hints >= ARRAY_SIZE(b->al_bitmap_hints));
|
|
|
|
+ if (!test_and_set_bit(BM_PAGE_HINT_WRITEOUT, &page_private(page)))
|
|
|
|
+ b->al_bitmap_hints[b->n_bitmap_hints++] = page_nr;
|
|
}
|
|
}
|
|
|
|
|
|
static int bm_test_page_unchanged(struct page *page)
|
|
static int bm_test_page_unchanged(struct page *page)
|
|
@@ -1030,7 +1045,7 @@ static int bm_rw(struct drbd_device *device, const unsigned int flags, unsigned
|
|
{
|
|
{
|
|
struct drbd_bm_aio_ctx *ctx;
|
|
struct drbd_bm_aio_ctx *ctx;
|
|
struct drbd_bitmap *b = device->bitmap;
|
|
struct drbd_bitmap *b = device->bitmap;
|
|
- int num_pages, i, count = 0;
|
|
|
|
|
|
+ unsigned int num_pages, i, count = 0;
|
|
unsigned long now;
|
|
unsigned long now;
|
|
char ppb[10];
|
|
char ppb[10];
|
|
int err = 0;
|
|
int err = 0;
|
|
@@ -1078,16 +1093,37 @@ static int bm_rw(struct drbd_device *device, const unsigned int flags, unsigned
|
|
now = jiffies;
|
|
now = jiffies;
|
|
|
|
|
|
/* let the layers below us try to merge these bios... */
|
|
/* let the layers below us try to merge these bios... */
|
|
- for (i = 0; i < num_pages; i++) {
|
|
|
|
- /* ignore completely unchanged pages */
|
|
|
|
- if (lazy_writeout_upper_idx && i == lazy_writeout_upper_idx)
|
|
|
|
- break;
|
|
|
|
- if (!(flags & BM_AIO_READ)) {
|
|
|
|
- if ((flags & BM_AIO_WRITE_HINTED) &&
|
|
|
|
- !test_and_clear_bit(BM_PAGE_HINT_WRITEOUT,
|
|
|
|
- &page_private(b->bm_pages[i])))
|
|
|
|
- continue;
|
|
|
|
|
|
|
|
|
|
+ if (flags & BM_AIO_READ) {
|
|
|
|
+ for (i = 0; i < num_pages; i++) {
|
|
|
|
+ atomic_inc(&ctx->in_flight);
|
|
|
|
+ bm_page_io_async(ctx, i);
|
|
|
|
+ ++count;
|
|
|
|
+ cond_resched();
|
|
|
|
+ }
|
|
|
|
+ } else if (flags & BM_AIO_WRITE_HINTED) {
|
|
|
|
+ /* ASSERT: BM_AIO_WRITE_ALL_PAGES is not set. */
|
|
|
|
+ unsigned int hint;
|
|
|
|
+ for (hint = 0; hint < b->n_bitmap_hints; hint++) {
|
|
|
|
+ i = b->al_bitmap_hints[hint];
|
|
|
|
+ if (i >= num_pages) /* == -1U: no hint here. */
|
|
|
|
+ continue;
|
|
|
|
+ /* Several AL-extents may point to the same page. */
|
|
|
|
+ if (!test_and_clear_bit(BM_PAGE_HINT_WRITEOUT,
|
|
|
|
+ &page_private(b->bm_pages[i])))
|
|
|
|
+ continue;
|
|
|
|
+ /* Has it even changed? */
|
|
|
|
+ if (bm_test_page_unchanged(b->bm_pages[i]))
|
|
|
|
+ continue;
|
|
|
|
+ atomic_inc(&ctx->in_flight);
|
|
|
|
+ bm_page_io_async(ctx, i);
|
|
|
|
+ ++count;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ for (i = 0; i < num_pages; i++) {
|
|
|
|
+ /* ignore completely unchanged pages */
|
|
|
|
+ if (lazy_writeout_upper_idx && i == lazy_writeout_upper_idx)
|
|
|
|
+ break;
|
|
if (!(flags & BM_AIO_WRITE_ALL_PAGES) &&
|
|
if (!(flags & BM_AIO_WRITE_ALL_PAGES) &&
|
|
bm_test_page_unchanged(b->bm_pages[i])) {
|
|
bm_test_page_unchanged(b->bm_pages[i])) {
|
|
dynamic_drbd_dbg(device, "skipped bm write for idx %u\n", i);
|
|
dynamic_drbd_dbg(device, "skipped bm write for idx %u\n", i);
|
|
@@ -1100,11 +1136,11 @@ static int bm_rw(struct drbd_device *device, const unsigned int flags, unsigned
|
|
dynamic_drbd_dbg(device, "skipped bm lazy write for idx %u\n", i);
|
|
dynamic_drbd_dbg(device, "skipped bm lazy write for idx %u\n", i);
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
+ atomic_inc(&ctx->in_flight);
|
|
|
|
+ bm_page_io_async(ctx, i);
|
|
|
|
+ ++count;
|
|
|
|
+ cond_resched();
|
|
}
|
|
}
|
|
- atomic_inc(&ctx->in_flight);
|
|
|
|
- bm_page_io_async(ctx, i);
|
|
|
|
- ++count;
|
|
|
|
- cond_resched();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|