aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/drbd
diff options
context:
space:
mode:
authorLars Ellenberg <lars.ellenberg@linbit.com>2012-04-25 17:06:45 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2012-05-09 09:17:00 -0400
commit0e8488ade26b4b16a9745aa15ecb88c3fb1cb953 (patch)
tree368b5bf6ddf7a687303a6e01ce33460dbc096287 /drivers/block/drbd
parenta574daf5d722f4ca8cc18509f30b804c4d519962 (diff)
drbd: allow bitmap to change during writeout from resync_finished
Symptom: messages similar to "FIXME asender in bm_change_bits_to, bitmap locked for 'write from resync_finished' by worker" If a resync or verify is finished (or aborted), a full bitmap writeout is triggered. If we have ongoing local IO, the bitmap may still change during that writeout, pending and not yet processed acks may cause bits to be cleared, while new writes may cause bits to be to be set. To fix this, introduce the drbd_bm_write_copy_pages() variant. Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block/drbd')
-rw-r--r--drivers/block/drbd/drbd_bitmap.c26
-rw-r--r--drivers/block/drbd/drbd_int.h15
-rw-r--r--drivers/block/drbd/drbd_main.c4
3 files changed, 34 insertions, 11 deletions
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
index 49603bc67fe..9dab3700ca2 100644
--- a/drivers/block/drbd/drbd_bitmap.c
+++ b/drivers/block/drbd/drbd_bitmap.c
@@ -1011,7 +1011,7 @@ static void bm_page_io_async(struct bm_aio_ctx *ctx, int page_nr, int rw) __must
1011/* 1011/*
1012 * bm_rw: read/write the whole bitmap from/to its on disk location. 1012 * bm_rw: read/write the whole bitmap from/to its on disk location.
1013 */ 1013 */
1014static int bm_rw(struct drbd_conf *mdev, int rw, unsigned lazy_writeout_upper_idx) __must_hold(local) 1014static int bm_rw(struct drbd_conf *mdev, int rw, unsigned flags, unsigned lazy_writeout_upper_idx) __must_hold(local)
1015{ 1015{
1016 struct bm_aio_ctx *ctx; 1016 struct bm_aio_ctx *ctx;
1017 struct drbd_bitmap *b = mdev->bitmap; 1017 struct drbd_bitmap *b = mdev->bitmap;
@@ -1037,7 +1037,7 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned lazy_writeout_upper_id
1037 .mdev = mdev, 1037 .mdev = mdev,
1038 .in_flight = ATOMIC_INIT(1), 1038 .in_flight = ATOMIC_INIT(1),
1039 .done = 0, 1039 .done = 0,
1040 .flags = lazy_writeout_upper_idx ? BM_AIO_COPY_PAGES : 0, 1040 .flags = flags,
1041 .error = 0, 1041 .error = 0,
1042 .kref = { ATOMIC_INIT(2) }, 1042 .kref = { ATOMIC_INIT(2) },
1043 }; 1043 };
@@ -1128,7 +1128,7 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned lazy_writeout_upper_id
1128 */ 1128 */
1129int drbd_bm_read(struct drbd_conf *mdev) __must_hold(local) 1129int drbd_bm_read(struct drbd_conf *mdev) __must_hold(local)
1130{ 1130{
1131 return bm_rw(mdev, READ, 0); 1131 return bm_rw(mdev, READ, 0, 0);
1132} 1132}
1133 1133
1134/** 1134/**
@@ -1139,7 +1139,7 @@ int drbd_bm_read(struct drbd_conf *mdev) __must_hold(local)
1139 */ 1139 */
1140int drbd_bm_write(struct drbd_conf *mdev) __must_hold(local) 1140int drbd_bm_write(struct drbd_conf *mdev) __must_hold(local)
1141{ 1141{
1142 return bm_rw(mdev, WRITE, 0); 1142 return bm_rw(mdev, WRITE, 0, 0);
1143} 1143}
1144 1144
1145/** 1145/**
@@ -1149,7 +1149,23 @@ int drbd_bm_write(struct drbd_conf *mdev) __must_hold(local)
1149 */ 1149 */
1150int drbd_bm_write_lazy(struct drbd_conf *mdev, unsigned upper_idx) __must_hold(local) 1150int drbd_bm_write_lazy(struct drbd_conf *mdev, unsigned upper_idx) __must_hold(local)
1151{ 1151{
1152 return bm_rw(mdev, WRITE, upper_idx); 1152 return bm_rw(mdev, WRITE, BM_AIO_COPY_PAGES, upper_idx);
1153}
1154
1155/**
1156 * drbd_bm_write_copy_pages() - Write the whole bitmap to its on disk location.
1157 * @mdev: DRBD device.
1158 *
1159 * Will only write pages that have changed since last IO.
1160 * In contrast to drbd_bm_write(), this will copy the bitmap pages
1161 * to temporary writeout pages. It is intended to trigger a full write-out
1162 * while still allowing the bitmap to change, for example if a resync or online
1163 * verify is aborted due to a failed peer disk, while local IO continues, or
1164 * pending resync acks are still being processed.
1165 */
1166int drbd_bm_write_copy_pages(struct drbd_conf *mdev) __must_hold(local)
1167{
1168 return bm_rw(mdev, WRITE, BM_AIO_COPY_PAGES, 0);
1153} 1169}
1154 1170
1155 1171
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 302a6e786f7..6586053429b 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -862,22 +862,28 @@ enum bm_flag {
862 BM_P_VMALLOCED = 0x10000, /* internal use only, will be masked out */ 862 BM_P_VMALLOCED = 0x10000, /* internal use only, will be masked out */
863 863
864 /* currently locked for bulk operation */ 864 /* currently locked for bulk operation */
865 BM_LOCKED_MASK = 0x7, 865 BM_LOCKED_MASK = 0xf,
866 866
867 /* in detail, that is: */ 867 /* in detail, that is: */
868 BM_DONT_CLEAR = 0x1, 868 BM_DONT_CLEAR = 0x1,
869 BM_DONT_SET = 0x2, 869 BM_DONT_SET = 0x2,
870 BM_DONT_TEST = 0x4, 870 BM_DONT_TEST = 0x4,
871 871
872 /* so we can mark it locked for bulk operation,
873 * and still allow all non-bulk operations */
874 BM_IS_LOCKED = 0x8,
875
872 /* (test bit, count bit) allowed (common case) */ 876 /* (test bit, count bit) allowed (common case) */
873 BM_LOCKED_TEST_ALLOWED = 0x3, 877 BM_LOCKED_TEST_ALLOWED = BM_DONT_CLEAR | BM_DONT_SET | BM_IS_LOCKED,
874 878
875 /* testing bits, as well as setting new bits allowed, but clearing bits 879 /* testing bits, as well as setting new bits allowed, but clearing bits
876 * would be unexpected. Used during bitmap receive. Setting new bits 880 * would be unexpected. Used during bitmap receive. Setting new bits
877 * requires sending of "out-of-sync" information, though. */ 881 * requires sending of "out-of-sync" information, though. */
878 BM_LOCKED_SET_ALLOWED = 0x1, 882 BM_LOCKED_SET_ALLOWED = BM_DONT_CLEAR | BM_IS_LOCKED,
879 883
880 /* clear is not expected while bitmap is locked for bulk operation */ 884 /* for drbd_bm_write_copy_pages, everything is allowed,
885 * only concurrent bulk operations are locked out. */
886 BM_LOCKED_CHANGE_ALLOWED = BM_IS_LOCKED,
881}; 887};
882 888
883struct drbd_work_queue { 889struct drbd_work_queue {
@@ -1457,6 +1463,7 @@ extern int drbd_bm_e_weight(struct drbd_conf *mdev, unsigned long enr);
1457extern int drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(local); 1463extern int drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(local);
1458extern int drbd_bm_read(struct drbd_conf *mdev) __must_hold(local); 1464extern int drbd_bm_read(struct drbd_conf *mdev) __must_hold(local);
1459extern int drbd_bm_write(struct drbd_conf *mdev) __must_hold(local); 1465extern int drbd_bm_write(struct drbd_conf *mdev) __must_hold(local);
1466extern int drbd_bm_write_copy_pages(struct drbd_conf *mdev) __must_hold(local);
1460extern unsigned long drbd_bm_ALe_set_all(struct drbd_conf *mdev, 1467extern unsigned long drbd_bm_ALe_set_all(struct drbd_conf *mdev,
1461 unsigned long al_enr); 1468 unsigned long al_enr);
1462extern size_t drbd_bm_words(struct drbd_conf *mdev); 1469extern size_t drbd_bm_words(struct drbd_conf *mdev);
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index ab501b23b50..d830116781f 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -1698,8 +1698,8 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
1698 * No harm done if some bits change during this phase. 1698 * No harm done if some bits change during this phase.
1699 */ 1699 */
1700 if (os.conn > C_CONNECTED && ns.conn <= C_CONNECTED && get_ldev(mdev)) { 1700 if (os.conn > C_CONNECTED && ns.conn <= C_CONNECTED && get_ldev(mdev)) {
1701 drbd_queue_bitmap_io(mdev, &drbd_bm_write, NULL, 1701 drbd_queue_bitmap_io(mdev, &drbd_bm_write_copy_pages, NULL,
1702 "write from resync_finished", BM_LOCKED_SET_ALLOWED); 1702 "write from resync_finished", BM_LOCKED_CHANGE_ALLOWED);
1703 put_ldev(mdev); 1703 put_ldev(mdev);
1704 } 1704 }
1705 1705