diff options
Diffstat (limited to 'drivers/block/drbd/drbd_bitmap.c')
-rw-r--r-- | drivers/block/drbd/drbd_bitmap.c | 84 |
1 files changed, 62 insertions, 22 deletions
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index e5d89f623b90..ab62b81c2ca7 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c | |||
@@ -96,6 +96,13 @@ struct drbd_bitmap { | |||
96 | struct page **bm_pages; | 96 | struct page **bm_pages; |
97 | spinlock_t bm_lock; | 97 | spinlock_t bm_lock; |
98 | 98 | ||
99 | /* exclusively to be used by __al_write_transaction(), | ||
100 | * drbd_bm_mark_for_writeout() and | ||
101 | * and drbd_bm_write_hinted() -> bm_rw() called from there. | ||
102 | */ | ||
103 | unsigned int n_bitmap_hints; | ||
104 | unsigned int al_bitmap_hints[AL_UPDATES_PER_TRANSACTION]; | ||
105 | |||
99 | /* see LIMITATIONS: above */ | 106 | /* see LIMITATIONS: above */ |
100 | 107 | ||
101 | unsigned long bm_set; /* nr of set bits; THINK maybe atomic_t? */ | 108 | 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) | |||
242 | set_bit(BM_PAGE_NEED_WRITEOUT, &page_private(page)); | 249 | set_bit(BM_PAGE_NEED_WRITEOUT, &page_private(page)); |
243 | } | 250 | } |
244 | 251 | ||
252 | void drbd_bm_reset_al_hints(struct drbd_device *device) | ||
253 | { | ||
254 | device->bitmap->n_bitmap_hints = 0; | ||
255 | } | ||
256 | |||
245 | /** | 257 | /** |
246 | * drbd_bm_mark_for_writeout() - mark a page with a "hint" to be considered for writeout | 258 | * drbd_bm_mark_for_writeout() - mark a page with a "hint" to be considered for writeout |
247 | * @device: DRBD device. | 259 | * @device: DRBD device. |
@@ -253,6 +265,7 @@ static void bm_set_page_need_writeout(struct page *page) | |||
253 | */ | 265 | */ |
254 | void drbd_bm_mark_for_writeout(struct drbd_device *device, int page_nr) | 266 | void drbd_bm_mark_for_writeout(struct drbd_device *device, int page_nr) |
255 | { | 267 | { |
268 | struct drbd_bitmap *b = device->bitmap; | ||
256 | struct page *page; | 269 | struct page *page; |
257 | if (page_nr >= device->bitmap->bm_number_of_pages) { | 270 | if (page_nr >= device->bitmap->bm_number_of_pages) { |
258 | drbd_warn(device, "BAD: page_nr: %u, number_of_pages: %u\n", | 271 | 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) | |||
260 | return; | 273 | return; |
261 | } | 274 | } |
262 | page = device->bitmap->bm_pages[page_nr]; | 275 | page = device->bitmap->bm_pages[page_nr]; |
263 | set_bit(BM_PAGE_HINT_WRITEOUT, &page_private(page)); | 276 | BUG_ON(b->n_bitmap_hints >= ARRAY_SIZE(b->al_bitmap_hints)); |
277 | if (!test_and_set_bit(BM_PAGE_HINT_WRITEOUT, &page_private(page))) | ||
278 | b->al_bitmap_hints[b->n_bitmap_hints++] = page_nr; | ||
264 | } | 279 | } |
265 | 280 | ||
266 | static int bm_test_page_unchanged(struct page *page) | 281 | static int bm_test_page_unchanged(struct page *page) |
@@ -427,8 +442,7 @@ static struct page **bm_realloc_pages(struct drbd_bitmap *b, unsigned long want) | |||
427 | } | 442 | } |
428 | 443 | ||
429 | /* | 444 | /* |
430 | * called on driver init only. TODO call when a device is created. | 445 | * allocates the drbd_bitmap and stores it in device->bitmap. |
431 | * allocates the drbd_bitmap, and stores it in device->bitmap. | ||
432 | */ | 446 | */ |
433 | int drbd_bm_init(struct drbd_device *device) | 447 | int drbd_bm_init(struct drbd_device *device) |
434 | { | 448 | { |
@@ -633,7 +647,8 @@ int drbd_bm_resize(struct drbd_device *device, sector_t capacity, int set_new_bi | |||
633 | unsigned long bits, words, owords, obits; | 647 | unsigned long bits, words, owords, obits; |
634 | unsigned long want, have, onpages; /* number of pages */ | 648 | unsigned long want, have, onpages; /* number of pages */ |
635 | struct page **npages, **opages = NULL; | 649 | struct page **npages, **opages = NULL; |
636 | int err = 0, growing; | 650 | int err = 0; |
651 | bool growing; | ||
637 | 652 | ||
638 | if (!expect(b)) | 653 | if (!expect(b)) |
639 | return -ENOMEM; | 654 | return -ENOMEM; |
@@ -1030,7 +1045,7 @@ static int bm_rw(struct drbd_device *device, const unsigned int flags, unsigned | |||
1030 | { | 1045 | { |
1031 | struct drbd_bm_aio_ctx *ctx; | 1046 | struct drbd_bm_aio_ctx *ctx; |
1032 | struct drbd_bitmap *b = device->bitmap; | 1047 | struct drbd_bitmap *b = device->bitmap; |
1033 | int num_pages, i, count = 0; | 1048 | unsigned int num_pages, i, count = 0; |
1034 | unsigned long now; | 1049 | unsigned long now; |
1035 | char ppb[10]; | 1050 | char ppb[10]; |
1036 | int err = 0; | 1051 | int err = 0; |
@@ -1078,16 +1093,37 @@ static int bm_rw(struct drbd_device *device, const unsigned int flags, unsigned | |||
1078 | now = jiffies; | 1093 | now = jiffies; |
1079 | 1094 | ||
1080 | /* let the layers below us try to merge these bios... */ | 1095 | /* let the layers below us try to merge these bios... */ |
1081 | for (i = 0; i < num_pages; i++) { | ||
1082 | /* ignore completely unchanged pages */ | ||
1083 | if (lazy_writeout_upper_idx && i == lazy_writeout_upper_idx) | ||
1084 | break; | ||
1085 | if (!(flags & BM_AIO_READ)) { | ||
1086 | if ((flags & BM_AIO_WRITE_HINTED) && | ||
1087 | !test_and_clear_bit(BM_PAGE_HINT_WRITEOUT, | ||
1088 | &page_private(b->bm_pages[i]))) | ||
1089 | continue; | ||
1090 | 1096 | ||
1097 | if (flags & BM_AIO_READ) { | ||
1098 | for (i = 0; i < num_pages; i++) { | ||
1099 | atomic_inc(&ctx->in_flight); | ||
1100 | bm_page_io_async(ctx, i); | ||
1101 | ++count; | ||
1102 | cond_resched(); | ||
1103 | } | ||
1104 | } else if (flags & BM_AIO_WRITE_HINTED) { | ||
1105 | /* ASSERT: BM_AIO_WRITE_ALL_PAGES is not set. */ | ||
1106 | unsigned int hint; | ||
1107 | for (hint = 0; hint < b->n_bitmap_hints; hint++) { | ||
1108 | i = b->al_bitmap_hints[hint]; | ||
1109 | if (i >= num_pages) /* == -1U: no hint here. */ | ||
1110 | continue; | ||
1111 | /* Several AL-extents may point to the same page. */ | ||
1112 | if (!test_and_clear_bit(BM_PAGE_HINT_WRITEOUT, | ||
1113 | &page_private(b->bm_pages[i]))) | ||
1114 | continue; | ||
1115 | /* Has it even changed? */ | ||
1116 | if (bm_test_page_unchanged(b->bm_pages[i])) | ||
1117 | continue; | ||
1118 | atomic_inc(&ctx->in_flight); | ||
1119 | bm_page_io_async(ctx, i); | ||
1120 | ++count; | ||
1121 | } | ||
1122 | } else { | ||
1123 | for (i = 0; i < num_pages; i++) { | ||
1124 | /* ignore completely unchanged pages */ | ||
1125 | if (lazy_writeout_upper_idx && i == lazy_writeout_upper_idx) | ||
1126 | break; | ||
1091 | if (!(flags & BM_AIO_WRITE_ALL_PAGES) && | 1127 | if (!(flags & BM_AIO_WRITE_ALL_PAGES) && |
1092 | bm_test_page_unchanged(b->bm_pages[i])) { | 1128 | bm_test_page_unchanged(b->bm_pages[i])) { |
1093 | dynamic_drbd_dbg(device, "skipped bm write for idx %u\n", i); | 1129 | 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 | |||
1100 | dynamic_drbd_dbg(device, "skipped bm lazy write for idx %u\n", i); | 1136 | dynamic_drbd_dbg(device, "skipped bm lazy write for idx %u\n", i); |
1101 | continue; | 1137 | continue; |
1102 | } | 1138 | } |
1139 | atomic_inc(&ctx->in_flight); | ||
1140 | bm_page_io_async(ctx, i); | ||
1141 | ++count; | ||
1142 | cond_resched(); | ||
1103 | } | 1143 | } |
1104 | atomic_inc(&ctx->in_flight); | ||
1105 | bm_page_io_async(ctx, i); | ||
1106 | ++count; | ||
1107 | cond_resched(); | ||
1108 | } | 1144 | } |
1109 | 1145 | ||
1110 | /* | 1146 | /* |
@@ -1121,10 +1157,14 @@ static int bm_rw(struct drbd_device *device, const unsigned int flags, unsigned | |||
1121 | kref_put(&ctx->kref, &drbd_bm_aio_ctx_destroy); | 1157 | kref_put(&ctx->kref, &drbd_bm_aio_ctx_destroy); |
1122 | 1158 | ||
1123 | /* summary for global bitmap IO */ | 1159 | /* summary for global bitmap IO */ |
1124 | if (flags == 0) | 1160 | if (flags == 0) { |
1125 | drbd_info(device, "bitmap %s of %u pages took %lu jiffies\n", | 1161 | unsigned int ms = jiffies_to_msecs(jiffies - now); |
1126 | (flags & BM_AIO_READ) ? "READ" : "WRITE", | 1162 | if (ms > 5) { |
1127 | count, jiffies - now); | 1163 | drbd_info(device, "bitmap %s of %u pages took %u ms\n", |
1164 | (flags & BM_AIO_READ) ? "READ" : "WRITE", | ||
1165 | count, ms); | ||
1166 | } | ||
1167 | } | ||
1128 | 1168 | ||
1129 | if (ctx->error) { | 1169 | if (ctx->error) { |
1130 | drbd_alert(device, "we had at least one MD IO ERROR during bitmap IO\n"); | 1170 | drbd_alert(device, "we had at least one MD IO ERROR during bitmap IO\n"); |