diff options
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/drbd/drbd_bitmap.c | 49 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_int.h | 13 |
2 files changed, 52 insertions, 10 deletions
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index 4be737055718..bc89c4a30cbc 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c | |||
@@ -188,6 +188,9 @@ void drbd_bm_unlock(struct drbd_conf *mdev) | |||
188 | /* to mark for lazy writeout once syncer cleared all clearable bits, | 188 | /* to mark for lazy writeout once syncer cleared all clearable bits, |
189 | * we if bits have been cleared since last IO. */ | 189 | * we if bits have been cleared since last IO. */ |
190 | #define BM_PAGE_LAZY_WRITEOUT 28 | 190 | #define BM_PAGE_LAZY_WRITEOUT 28 |
191 | /* pages marked with this "HINT" will be considered for writeout | ||
192 | * on activity log transactions */ | ||
193 | #define BM_PAGE_HINT_WRITEOUT 27 | ||
191 | 194 | ||
192 | /* store_page_idx uses non-atomic assignment. It is only used directly after | 195 | /* store_page_idx uses non-atomic assignment. It is only used directly after |
193 | * allocating the page. All other bm_set_page_* and bm_clear_page_* need to | 196 | * allocating the page. All other bm_set_page_* and bm_clear_page_* need to |
@@ -237,6 +240,27 @@ static void bm_set_page_need_writeout(struct page *page) | |||
237 | set_bit(BM_PAGE_NEED_WRITEOUT, &page_private(page)); | 240 | set_bit(BM_PAGE_NEED_WRITEOUT, &page_private(page)); |
238 | } | 241 | } |
239 | 242 | ||
243 | /** | ||
244 | * drbd_bm_mark_for_writeout() - mark a page with a "hint" to be considered for writeout | ||
245 | * @mdev: DRBD device. | ||
246 | * @page_nr: the bitmap page to mark with the "hint" flag | ||
247 | * | ||
248 | * From within an activity log transaction, we mark a few pages with these | ||
249 | * hints, then call drbd_bm_write_hinted(), which will only write out changed | ||
250 | * pages which are flagged with this mark. | ||
251 | */ | ||
252 | void drbd_bm_mark_for_writeout(struct drbd_conf *mdev, int page_nr) | ||
253 | { | ||
254 | struct page *page; | ||
255 | if (page_nr >= mdev->bitmap->bm_number_of_pages) { | ||
256 | dev_warn(DEV, "BAD: page_nr: %u, number_of_pages: %u\n", | ||
257 | page_nr, (int)mdev->bitmap->bm_number_of_pages); | ||
258 | return; | ||
259 | } | ||
260 | page = mdev->bitmap->bm_pages[page_nr]; | ||
261 | set_bit(BM_PAGE_HINT_WRITEOUT, &page_private(page)); | ||
262 | } | ||
263 | |||
240 | static int bm_test_page_unchanged(struct page *page) | 264 | static int bm_test_page_unchanged(struct page *page) |
241 | { | 265 | { |
242 | volatile const unsigned long *addr = &page_private(page); | 266 | volatile const unsigned long *addr = &page_private(page); |
@@ -897,6 +921,7 @@ struct bm_aio_ctx { | |||
897 | struct completion done; | 921 | struct completion done; |
898 | unsigned flags; | 922 | unsigned flags; |
899 | #define BM_AIO_COPY_PAGES 1 | 923 | #define BM_AIO_COPY_PAGES 1 |
924 | #define BM_AIO_WRITE_HINTED 2 | ||
900 | int error; | 925 | int error; |
901 | }; | 926 | }; |
902 | 927 | ||
@@ -1007,13 +1032,13 @@ static void bm_page_io_async(struct bm_aio_ctx *ctx, int page_nr, int rw) __must | |||
1007 | /* | 1032 | /* |
1008 | * bm_rw: read/write the whole bitmap from/to its on disk location. | 1033 | * bm_rw: read/write the whole bitmap from/to its on disk location. |
1009 | */ | 1034 | */ |
1010 | static int bm_rw(struct drbd_conf *mdev, int rw, unsigned lazy_writeout_upper_idx) __must_hold(local) | 1035 | static int bm_rw(struct drbd_conf *mdev, int rw, unsigned flags, unsigned lazy_writeout_upper_idx) __must_hold(local) |
1011 | { | 1036 | { |
1012 | struct bm_aio_ctx ctx = { | 1037 | struct bm_aio_ctx ctx = { |
1013 | .mdev = mdev, | 1038 | .mdev = mdev, |
1014 | .in_flight = ATOMIC_INIT(1), | 1039 | .in_flight = ATOMIC_INIT(1), |
1015 | .done = COMPLETION_INITIALIZER_ONSTACK(ctx.done), | 1040 | .done = COMPLETION_INITIALIZER_ONSTACK(ctx.done), |
1016 | .flags = lazy_writeout_upper_idx ? BM_AIO_COPY_PAGES : 0, | 1041 | .flags = flags, |
1017 | }; | 1042 | }; |
1018 | struct drbd_bitmap *b = mdev->bitmap; | 1043 | struct drbd_bitmap *b = mdev->bitmap; |
1019 | int num_pages, i, count = 0; | 1044 | int num_pages, i, count = 0; |
@@ -1042,6 +1067,10 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned lazy_writeout_upper_id | |||
1042 | if (lazy_writeout_upper_idx && i == lazy_writeout_upper_idx) | 1067 | if (lazy_writeout_upper_idx && i == lazy_writeout_upper_idx) |
1043 | break; | 1068 | break; |
1044 | if (rw & WRITE) { | 1069 | if (rw & WRITE) { |
1070 | if ((flags & BM_AIO_WRITE_HINTED) && | ||
1071 | !test_and_clear_bit(BM_PAGE_HINT_WRITEOUT, | ||
1072 | &page_private(b->bm_pages[i]))) | ||
1073 | continue; | ||
1045 | if (bm_test_page_unchanged(b->bm_pages[i])) { | 1074 | if (bm_test_page_unchanged(b->bm_pages[i])) { |
1046 | dynamic_dev_dbg(DEV, "skipped bm write for idx %u\n", i); | 1075 | dynamic_dev_dbg(DEV, "skipped bm write for idx %u\n", i); |
1047 | continue; | 1076 | continue; |
@@ -1099,7 +1128,7 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned lazy_writeout_upper_id | |||
1099 | */ | 1128 | */ |
1100 | int drbd_bm_read(struct drbd_conf *mdev) __must_hold(local) | 1129 | int drbd_bm_read(struct drbd_conf *mdev) __must_hold(local) |
1101 | { | 1130 | { |
1102 | return bm_rw(mdev, READ, 0); | 1131 | return bm_rw(mdev, READ, 0, 0); |
1103 | } | 1132 | } |
1104 | 1133 | ||
1105 | /** | 1134 | /** |
@@ -1110,7 +1139,7 @@ int drbd_bm_read(struct drbd_conf *mdev) __must_hold(local) | |||
1110 | */ | 1139 | */ |
1111 | int drbd_bm_write(struct drbd_conf *mdev) __must_hold(local) | 1140 | int drbd_bm_write(struct drbd_conf *mdev) __must_hold(local) |
1112 | { | 1141 | { |
1113 | return bm_rw(mdev, WRITE, 0); | 1142 | return bm_rw(mdev, WRITE, 0, 0); |
1114 | } | 1143 | } |
1115 | 1144 | ||
1116 | /** | 1145 | /** |
@@ -1120,12 +1149,20 @@ int drbd_bm_write(struct drbd_conf *mdev) __must_hold(local) | |||
1120 | */ | 1149 | */ |
1121 | int drbd_bm_write_lazy(struct drbd_conf *mdev, unsigned upper_idx) __must_hold(local) | 1150 | int drbd_bm_write_lazy(struct drbd_conf *mdev, unsigned upper_idx) __must_hold(local) |
1122 | { | 1151 | { |
1123 | return bm_rw(mdev, WRITE, upper_idx); | 1152 | return bm_rw(mdev, WRITE, BM_AIO_COPY_PAGES, upper_idx); |
1124 | } | 1153 | } |
1125 | 1154 | ||
1155 | /** | ||
1156 | * drbd_bm_write_hinted() - Write bitmap pages with "hint" marks, if they have changed. | ||
1157 | * @mdev: DRBD device. | ||
1158 | */ | ||
1159 | int drbd_bm_write_hinted(struct drbd_conf *mdev) __must_hold(local) | ||
1160 | { | ||
1161 | return bm_rw(mdev, WRITE, BM_AIO_WRITE_HINTED | BM_AIO_COPY_PAGES, 0); | ||
1162 | } | ||
1126 | 1163 | ||
1127 | /** | 1164 | /** |
1128 | * drbd_bm_write_page: Writes a PAGE_SIZE aligned piece of bitmap | 1165 | * drbd_bm_write_page() - Writes a PAGE_SIZE aligned piece of bitmap |
1129 | * @mdev: DRBD device. | 1166 | * @mdev: DRBD device. |
1130 | * @idx: bitmap page index | 1167 | * @idx: bitmap page index |
1131 | * | 1168 | * |
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 93eb3a7ac711..edfdeb62c18f 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h | |||
@@ -1310,11 +1310,14 @@ struct bm_extent { | |||
1310 | 1310 | ||
1311 | #define SLEEP_TIME (HZ/10) | 1311 | #define SLEEP_TIME (HZ/10) |
1312 | 1312 | ||
1313 | #define BM_BLOCK_SHIFT 12 /* 4k per bit */ | 1313 | /* We do bitmap IO in units of 4k blocks. |
1314 | * We also still have a hardcoded 4k per bit relation. */ | ||
1315 | #define BM_BLOCK_SHIFT 12 /* 4k per bit */ | ||
1314 | #define BM_BLOCK_SIZE (1<<BM_BLOCK_SHIFT) | 1316 | #define BM_BLOCK_SIZE (1<<BM_BLOCK_SHIFT) |
1315 | /* (9+3) : 512 bytes @ 8 bits; representing 16M storage | 1317 | /* mostly arbitrarily set the represented size of one bitmap extent, |
1316 | * per sector of on disk bitmap */ | 1318 | * aka resync extent, to 16 MiB (which is also 512 Byte worth of bitmap |
1317 | #define BM_EXT_SHIFT (BM_BLOCK_SHIFT + MD_SECTOR_SHIFT + 3) /* = 24 */ | 1319 | * at 4k per bit resolution) */ |
1320 | #define BM_EXT_SHIFT 24 /* 16 MiB per resync extent */ | ||
1318 | #define BM_EXT_SIZE (1<<BM_EXT_SHIFT) | 1321 | #define BM_EXT_SIZE (1<<BM_EXT_SHIFT) |
1319 | 1322 | ||
1320 | #if (BM_EXT_SHIFT != 24) || (BM_BLOCK_SHIFT != 12) | 1323 | #if (BM_EXT_SHIFT != 24) || (BM_BLOCK_SHIFT != 12) |
@@ -1408,7 +1411,9 @@ extern int drbd_bm_test_bit(struct drbd_conf *mdev, unsigned long bitnr); | |||
1408 | extern int drbd_bm_e_weight(struct drbd_conf *mdev, unsigned long enr); | 1411 | extern int drbd_bm_e_weight(struct drbd_conf *mdev, unsigned long enr); |
1409 | extern int drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(local); | 1412 | extern int drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(local); |
1410 | extern int drbd_bm_read(struct drbd_conf *mdev) __must_hold(local); | 1413 | extern int drbd_bm_read(struct drbd_conf *mdev) __must_hold(local); |
1414 | extern void drbd_bm_mark_for_writeout(struct drbd_conf *mdev, int page_nr); | ||
1411 | extern int drbd_bm_write(struct drbd_conf *mdev) __must_hold(local); | 1415 | extern int drbd_bm_write(struct drbd_conf *mdev) __must_hold(local); |
1416 | extern int drbd_bm_write_hinted(struct drbd_conf *mdev) __must_hold(local); | ||
1412 | extern unsigned long drbd_bm_ALe_set_all(struct drbd_conf *mdev, | 1417 | extern unsigned long drbd_bm_ALe_set_all(struct drbd_conf *mdev, |
1413 | unsigned long al_enr); | 1418 | unsigned long al_enr); |
1414 | extern size_t drbd_bm_words(struct drbd_conf *mdev); | 1419 | extern size_t drbd_bm_words(struct drbd_conf *mdev); |