From f9dc362b8eacd7d967b89a7d8375035cacac7a82ddbd358ed211e41f6316dcf2 Mon Sep 17 00:00:00 2001 From: nick wang Date: Wed, 13 Apr 2016 12:42:42 +0000 Subject: [PATCH] Accepting request 389406 from home:wanghaisu:branches:network:ha-clustering:Factory Update to drbd9. OBS-URL: https://build.opensuse.org/request/show/389406 OBS-URL: https://build.opensuse.org/package/show/network:ha-clustering:Factory/drbd?expand=0&rev=31 --- ...pport-zeroout-device-in-initial-sync.patch | 529 ------- Module.supported | 1 + _service | 24 + ...ess:tar_scm:drbd-9.0.1+git.86e4439.tar.bz2 | 3 + _service:set_version:drbd.spec | 113 ++ drbd-8.4.6.tar.gz | 3 - drbd-buildcompare.patch | 15 - drbd.changes | 21 +- drbd.spec | 61 +- drbd_git_revision | 1 + kernel-4.5-compat.patch | 35 + new-bio-struct.patch | 391 ------ preamble | 3 +- rename-GFP_WAIT-to-GFP_RECLAIM.patch | 32 - update-to-8.4.6-5.patch | 1241 ----------------- 15 files changed, 224 insertions(+), 2249 deletions(-) delete mode 100644 0001-Support-zeroout-device-in-initial-sync.patch create mode 100644 _service create mode 100644 _service:recompress:tar_scm:drbd-9.0.1+git.86e4439.tar.bz2 create mode 100644 _service:set_version:drbd.spec delete mode 100644 drbd-8.4.6.tar.gz delete mode 100644 drbd-buildcompare.patch create mode 100644 drbd_git_revision create mode 100644 kernel-4.5-compat.patch delete mode 100644 new-bio-struct.patch delete mode 100644 rename-GFP_WAIT-to-GFP_RECLAIM.patch delete mode 100644 update-to-8.4.6-5.patch diff --git a/0001-Support-zeroout-device-in-initial-sync.patch b/0001-Support-zeroout-device-in-initial-sync.patch deleted file mode 100644 index f419ed4..0000000 --- a/0001-Support-zeroout-device-in-initial-sync.patch +++ /dev/null @@ -1,529 +0,0 @@ -From e15ba3799caf4cdcdf151078efe01e9a3f3ab206 Mon Sep 17 00:00:00 2001 -From: Nick Wang -Date: Fri, 10 Jul 2015 17:28:18 +0800 -Subject: [PATCH] drbd: Support zeroout device instead of initial full sync - -Patch set for zeroing out device on both side -instead of initial full sync. Useful for high -latency network environment. - -Implement --zeroout-devices and --discard-devices -for new-current-uuid ---- - drbd/drbd_int.h | 15 +++++++ - drbd/drbd_main.c | 60 +++++++++++++++++++++++++++- - drbd/drbd_nl.c | 41 +++++++++++++++++-- - drbd/drbd_protocol.h | 2 + - drbd/drbd_receiver.c | 86 +++++++++++++++++++++++++++++++++++++++- - drbd/drbd_worker.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++ - drbd/linux/drbd_genl.h | 2 + - 7 files changed, 305 insertions(+), 6 deletions(-) - -diff --git a/drbd/drbd_int.h b/drbd/drbd_int.h -index d1e2bc0..555b24c 100644 ---- a/drbd/drbd_int.h -+++ b/drbd/drbd_int.h -@@ -621,6 +621,13 @@ enum { - RS_START, /* tell worker to start resync/OV */ - RS_PROGRESS, /* tell worker that resync made significant progress */ - RS_DONE, /* tell worker that resync is done */ -+ P_ZERO_START, /* tell worker to zero out device */ -+ S_ZERO_START, /* tell worker to zero out device as requested*/ -+ -+ /* used for zero out/discard device */ -+ DISCARD_DISK, /* flag to discard device */ -+ ZERO_DONE, /* succeed on zero out a device */ -+ ZERO_FAIL, /* fail to zero out a device */ - }; - - struct drbd_bitmap; /* opaque for drbd_device */ -@@ -1204,6 +1211,11 @@ extern int __drbd_send_protocol(struct drbd_connection *connection, enum drbd_pa - extern int drbd_send_protocol(struct drbd_connection *connection); - extern int drbd_send_uuids(struct drbd_peer_device *); - extern int drbd_send_uuids_skip_initial_sync(struct drbd_peer_device *); -+extern int drbd_send_zeroout_start(struct drbd_peer_device *); -+extern int drbd_send_discard_start(struct drbd_peer_device *); -+extern int drbd_send_zeroout_finish(struct drbd_peer_device *); -+extern int drbd_send_zeroout_ok(struct drbd_peer_device *); -+extern int drbd_send_zeroout_fail(struct drbd_peer_device *); - extern void drbd_gen_and_send_sync_uuid(struct drbd_peer_device *); - extern int drbd_send_sizes(struct drbd_peer_device *peer_device, int trigger_reply, enum dds_flags flags); - extern int drbd_send_state(struct drbd_peer_device *, union drbd_state); -@@ -1661,6 +1673,9 @@ extern void drbd_send_acks_wf(struct work_struct *ws); - extern bool drbd_rs_c_min_rate_throttle(struct drbd_device *device); - extern bool drbd_rs_should_slow_down(struct drbd_device *device, sector_t sector, - bool throttle_if_app_is_waiting); -+extern int zeroout_local_device(struct drbd_device *device, bool discard); -+extern void require_zeroout_local_device(struct drbd_device *device); -+extern void receive_zeroout_local_device(struct drbd_device *device); - extern int drbd_submit_peer_request(struct drbd_device *, - struct drbd_peer_request *, const unsigned, - const int); -diff --git a/drbd/drbd_main.c b/drbd/drbd_main.c -index 31bf43f..badc719 100644 ---- a/drbd/drbd_main.c -+++ b/drbd/drbd_main.c -@@ -908,6 +908,62 @@ int drbd_send_uuids_skip_initial_sync(struct drbd_peer_device *peer_device) - return _drbd_send_uuids(peer_device, 8); - } - -+ -+/** -+ * drbd_send_zeroout_start() - Notify peer node to zeroout device -+ * @peer_device: DRBD peer device. -+ */ -+int drbd_send_zeroout_start(struct drbd_peer_device *peer_device) -+{ -+ return _drbd_send_uuids(peer_device, 16); -+} -+ -+/** -+ * drbd_send_discard_start() - Notify peer node to discard device -+ * @peer_device: DRBD peer device. -+ */ -+int drbd_send_discard_start(struct drbd_peer_device *peer_device) -+{ -+ return _drbd_send_uuids(peer_device, 32); -+} -+ -+/** -+ * drbd_send_zeroout_finish() - Notify both node finished zeroing out -+ * @peer_device: DRBD peer device. -+ */ -+int drbd_send_zeroout_finish(struct drbd_peer_device *peer_device) -+{ -+ return _drbd_send_uuids(peer_device, 64); -+} -+ -+/** -+ * _drbd_send_zeroout_state() - Sends the drbd state to the peer -+ * @peer_device: DRBD peer device. -+ * @state: Device zero out status. -+ */ -+static int _drbd_send_zeroout_state(struct drbd_peer_device *peer_device, unsigned int status) -+{ -+ struct drbd_socket *sock; -+ struct p_state *p; -+ -+ sock = &peer_device->connection->data; -+ p = drbd_prepare_command(peer_device, sock); -+ if (!p) -+ return -EIO; -+ p->state = cpu_to_be32(status); -+ return drbd_send_command(peer_device, sock, P_ZERO_OUT, sizeof(*p), NULL, 0); -+} -+ -+int drbd_send_zeroout_ok(struct drbd_peer_device *peer_device) -+{ -+ return _drbd_send_zeroout_state(peer_device, 0); -+} -+ -+int drbd_send_zeroout_fail(struct drbd_peer_device *peer_device) -+{ -+ return _drbd_send_zeroout_state(peer_device, 1); -+} -+ - void drbd_print_uuids(struct drbd_device *device, const char *text) - { - if (get_ldev_if_state(device, D_NEGOTIATING)) { -@@ -3466,8 +3522,8 @@ void drbd_uuid_move_history(struct drbd_device *device) __must_hold(local) - { - int i; - -- for (i = UI_HISTORY_START; i < UI_HISTORY_END; i++) -- device->ldev->md.uuid[i+1] = device->ldev->md.uuid[i]; -+ for (i = UI_HISTORY_END; i > UI_HISTORY_START; i--) -+ device->ldev->md.uuid[i] = device->ldev->md.uuid[i-1]; - } - - void __drbd_uuid_set(struct drbd_device *device, int idx, u64 val) __must_hold(local) -diff --git a/drbd/drbd_nl.c b/drbd/drbd_nl.c -index bb7e1b0..dc2bfec 100644 ---- a/drbd/drbd_nl.c -+++ b/drbd/drbd_nl.c -@@ -4015,8 +4015,11 @@ int drbd_adm_new_c_uuid(struct sk_buff *skb, struct genl_info *info) - { - struct drbd_config_context adm_ctx; - struct drbd_device *device; -+ struct drbd_peer_device *peer_device = NULL; - enum drbd_ret_code retcode; - int skip_initial_sync = 0; -+ int zeroout_devices = 0; -+ int discard_devices = 0; - int err; - struct new_c_uuid_parms args; - -@@ -4045,12 +4048,28 @@ int drbd_adm_new_c_uuid(struct sk_buff *skb, struct genl_info *info) - goto out; - } - -+ peer_device = first_peer_device(device); -+ - /* this is "skip initial sync", assume to be clean */ - if (device->state.conn == C_CONNECTED && -- first_peer_device(device)->connection->agreed_pro_version >= 90 && -+ peer_device->connection->agreed_pro_version >= 90 && - device->ldev->md.uuid[UI_CURRENT] == UUID_JUST_CREATED && args.clear_bm) { - drbd_info(device, "Preparing to skip initial sync\n"); - skip_initial_sync = 1; -+ /* this is "zero out/discard" devices to make it all zero. -+ * ignore "zero out" if both "clear_bm" and "zeroout_devices/discard_devices" set. */ -+ } else if (device->state.conn == C_CONNECTED && -+ peer_device->connection->agreed_features & FF_DISCARD && -+ device->ldev->md.uuid[UI_CURRENT] == UUID_JUST_CREATED && -+ args.zeroout_devices) { -+ drbd_info(device, "Preparing to zero out devices, will take a long time\n"); -+ zeroout_devices = 1; -+ } else if (device->state.conn == C_CONNECTED && -+ peer_device->connection->agreed_features & FF_DISCARD && -+ device->ldev->md.uuid[UI_CURRENT] == UUID_JUST_CREATED && -+ args.discard_devices) { -+ drbd_info(device, "Preparing to discard devices, will take a long time\n"); -+ discard_devices = 1; - } else if (device->state.conn != C_STANDALONE) { - retcode = ERR_CONNECTED; - goto out_dec; -@@ -4059,7 +4078,7 @@ int drbd_adm_new_c_uuid(struct sk_buff *skb, struct genl_info *info) - drbd_uuid_set(device, UI_BITMAP, 0); /* Rotate UI_BITMAP to History 1, etc... */ - drbd_uuid_new_current(device); /* New current, previous to UI_BITMAP */ - -- if (args.clear_bm) { -+ if (args.clear_bm || args.zeroout_devices || args.discard_devices) { - err = drbd_bitmap_io(device, &drbd_bmio_clear_n_write, - "clear_n_write from new_c_uuid", BM_LOCKED_MASK); - if (err) { -@@ -4067,7 +4086,7 @@ int drbd_adm_new_c_uuid(struct sk_buff *skb, struct genl_info *info) - retcode = ERR_IO_MD_DISK; - } - if (skip_initial_sync) { -- drbd_send_uuids_skip_initial_sync(first_peer_device(device)); -+ drbd_send_uuids_skip_initial_sync(peer_device); - _drbd_uuid_set(device, UI_BITMAP, 0); - drbd_print_uuids(device, "cleared bitmap UUID"); - spin_lock_irq(&device->resource->req_lock); -@@ -4075,6 +4094,22 @@ int drbd_adm_new_c_uuid(struct sk_buff *skb, struct genl_info *info) - CS_VERBOSE, NULL); - spin_unlock_irq(&device->resource->req_lock); - } -+ if (zeroout_devices || discard_devices) { -+ if (discard_devices) { -+ drbd_send_discard_start(peer_device); -+ set_bit(DISCARD_DISK, &device->flags); -+ } else { -+ drbd_send_zeroout_start(peer_device); -+ clear_bit(DISCARD_DISK, &device->flags); -+ } -+ _drbd_uuid_set(device, UI_BITMAP, 0); -+ drbd_print_uuids(device, "cleared bitmap UUID for zeroing device"); -+ -+ /* CLear bit flag of zero out */ -+ clear_bit(ZERO_DONE, &device->flags); -+ clear_bit(ZERO_FAIL, &device->flags); -+ drbd_device_post_work(device, P_ZERO_START); -+ } - } - - drbd_md_sync(device); -diff --git a/drbd/drbd_protocol.h b/drbd/drbd_protocol.h -index 405b181..d9db0ce 100644 ---- a/drbd/drbd_protocol.h -+++ b/drbd/drbd_protocol.h -@@ -59,6 +59,7 @@ enum drbd_packet { - /* REQ_DISCARD. We used "discard" in different contexts before, - * which is why I chose TRIM here, to disambiguate. */ - P_TRIM = 0x31, -+ P_ZERO_OUT = 0x32, - - P_MAY_IGNORE = 0x100, /* Flag to test if (cmd > P_MAY_IGNORE) ... */ - P_MAX_OPT_CMD = 0x101, -@@ -161,6 +162,7 @@ struct p_block_req { - */ - - #define FF_TRIM 1 -+#define FF_DISCARD 4 - - struct p_connection_features { - u32 protocol_min; -diff --git a/drbd/drbd_receiver.c b/drbd/drbd_receiver.c -index 06e5667..ec324ef 100644 ---- a/drbd/drbd_receiver.c -+++ b/drbd/drbd_receiver.c -@@ -47,7 +47,7 @@ - #include "drbd_vli.h" - #include - --#define PRO_FEATURES (FF_TRIM) -+#define PRO_FEATURES (FF_TRIM | FF_DISCARD) - - struct flush_work { - struct drbd_work w; -@@ -4317,6 +4317,20 @@ static int receive_uuids(struct drbd_connection *connection, struct packet_info - peer_device->connection->agreed_pro_version >= 90 && - device->ldev->md.uuid[UI_CURRENT] == UUID_JUST_CREATED && - (p_uuid[UI_FLAGS] & 8); -+ int zeroout_devices = -+ device->state.conn == C_CONNECTED && -+ peer_device->connection->agreed_pro_version >= 90 && -+ device->ldev->md.uuid[UI_CURRENT] == UUID_JUST_CREATED && -+ (p_uuid[UI_FLAGS] & 16); -+ int discard_devices = -+ device->state.conn == C_CONNECTED && -+ peer_device->connection->agreed_pro_version >= 90 && -+ device->ldev->md.uuid[UI_CURRENT] == UUID_JUST_CREATED && -+ (p_uuid[UI_FLAGS] & 32); -+ int zeroout_finish = -+ device->state.conn == C_CONNECTED && -+ peer_device->connection->agreed_pro_version >= 90 && -+ (p_uuid[UI_FLAGS] & 64); - if (skip_initial_sync) { - drbd_info(device, "Accepted new current UUID, preparing to skip initial sync\n"); - drbd_bitmap_io(device, &drbd_bmio_clear_n_write, -@@ -4324,11 +4338,42 @@ static int receive_uuids(struct drbd_connection *connection, struct packet_info - BM_LOCKED_TEST_ALLOWED); - _drbd_uuid_set(device, UI_CURRENT, p_uuid[UI_CURRENT]); - _drbd_uuid_set(device, UI_BITMAP, 0); -+ spin_lock_irq(&device->resource->req_lock); - _drbd_set_state(_NS2(device, disk, D_UP_TO_DATE, pdsk, D_UP_TO_DATE), - CS_VERBOSE, NULL); -+ spin_unlock_irq(&device->resource->req_lock); - drbd_md_sync(device); - updated_uuids = 1; - } -+ -+ if (zeroout_devices || discard_devices) { -+ if (discard_devices) { -+ drbd_info(device, "Accepted to discard devices, will take a long time\n"); -+ set_bit(DISCARD_DISK, &device->flags); -+ } else { -+ drbd_info(device, "Accepted to zeroout devices, will take a long time\n"); -+ clear_bit(DISCARD_DISK, &device->flags); -+ } -+ -+ drbd_bitmap_io(device, &drbd_bmio_clear_n_write, -+ "clear_n_write from receive_uuids", -+ BM_LOCKED_TEST_ALLOWED); -+ _drbd_uuid_set(device, UI_CURRENT, p_uuid[UI_CURRENT]); -+ _drbd_uuid_set(device, UI_BITMAP, 0); -+ drbd_print_uuids(device, "cleared bitmap UUID for zeroing device"); -+ -+ drbd_device_post_work(device, S_ZERO_START); -+ updated_uuids = 1; -+ } -+ -+ if (zeroout_finish) { -+ drbd_info(device, "Both side finished zero out devices.\n"); -+ spin_lock_irq(&device->resource->req_lock); -+ _drbd_set_state(_NS2(device, disk, D_UP_TO_DATE, pdsk, D_UP_TO_DATE), -+ CS_VERBOSE, NULL); -+ spin_unlock_irq(&device->resource->req_lock); -+ } -+ - put_ldev(device); - } else if (device->state.disk < D_INCONSISTENT && - device->state.role == R_PRIMARY) { -@@ -4383,6 +4428,41 @@ static union drbd_state convert_state(union drbd_state ps) - return ms; - } - -+static int receive_zeroout_state(struct drbd_connection *connection, struct packet_info *pi) -+{ -+ struct drbd_peer_device *peer_device; -+ struct drbd_device *device; -+ struct p_state *p = pi->data; -+ unsigned int isfail; -+ -+ peer_device = conn_peer_device(connection, pi->vnr); -+ if (!peer_device) -+ return -EIO; -+ device = peer_device->device; -+ -+ isfail = be32_to_cpu(p->state); -+ -+ if (isfail) { -+ drbd_info(device, "Failed to zero out peer device\n"); -+ set_bit(ZERO_FAIL, &device->flags); -+ } else { -+ drbd_info(device, "Finished zero out peer device\n"); -+ if (test_and_clear_bit(ZERO_DONE, &device->flags)) { -+ drbd_info(device, "Both side finished zeroing.\n"); -+ spin_lock_irq(&device->resource->req_lock); -+ _drbd_set_state(_NS2(device, disk, D_UP_TO_DATE, -+ pdsk, D_UP_TO_DATE), CS_VERBOSE, NULL); -+ spin_unlock_irq(&device->resource->req_lock); -+ drbd_send_zeroout_finish(peer_device); -+ } else { -+ /* waiting for local device finished */ -+ set_bit(ZERO_DONE, &device->flags); -+ } -+ } -+ -+ return 0; -+} -+ - static int receive_req_state(struct drbd_connection *connection, struct packet_info *pi) - { - struct drbd_peer_device *peer_device; -@@ -5008,6 +5088,7 @@ static struct data_cmd drbd_cmd_handler[] = { - [P_CONN_ST_CHG_REQ] = { 0, sizeof(struct p_req_state), receive_req_conn_state }, - [P_PROTOCOL_UPDATE] = { 1, sizeof(struct p_protocol), receive_protocol }, - [P_TRIM] = { 0, sizeof(struct p_trim), receive_Data }, -+ [P_ZERO_OUT] = { 0, sizeof(struct p_state), receive_zeroout_state }, - }; - - static void drbdd(struct drbd_connection *connection) -@@ -5287,6 +5368,9 @@ static int drbd_do_features(struct drbd_connection *connection) - drbd_info(connection, "Agreed to%ssupport TRIM on protocol level\n", - connection->agreed_features & FF_TRIM ? " " : " not "); - -+ drbd_info(connection, "Agreed to%ssupport DISCARD DEVICE on protocol level\n", -+ connection->agreed_features & FF_DISCARD ? " " : " not "); -+ - return 1; - - incompat: -diff --git a/drbd/drbd_worker.c b/drbd/drbd_worker.c -index 2a15aeb..a8e231f 100644 ---- a/drbd/drbd_worker.c -+++ b/drbd/drbd_worker.c -@@ -1653,6 +1653,105 @@ void drbd_rs_controller_reset(struct drbd_device *device) - rcu_read_unlock(); - } - -+/** -+ * zeroout_local_device() -+ * @device: DRBD device. -+ * @discard: whether to discard the block range. -+ * -+ * Description: -+ * Zero out drbd backing device when creating new uuid. -+ * -+**/ -+int zeroout_local_device(struct drbd_device *device, bool discard) -+{ -+ struct block_device *bdev; -+ -+ bdev = device->ldev->backing_bdev; -+ if (device->ldev->known_size != drbd_get_capacity(bdev)) -+ device->ldev->known_size = drbd_get_capacity(bdev); -+ -+ if (discard){ -+ /* zero out the backing device by discarding blocks */ -+ return blkdev_issue_zeroout(bdev, 0, -+ device->ldev->known_size, GFP_NOIO, true); -+ } else { -+ /* zero out the backing device with WRITE call*/ -+ return blkdev_issue_zeroout(bdev, 0, -+ device->ldev->known_size, GFP_NOIO, false); -+ } -+} -+ -+/** -+ * require_zeroout_local_device() -+ * @device: DRBD device. -+ * -+ * Description: -+ * Start to zero out local device. Update -+ * status if peer node (secondary) finished -+ * zeroing. -+ * -+**/ -+void require_zeroout_local_device(struct drbd_device *device) -+{ -+ int zeroout_err = 0; -+ -+ if (test_and_clear_bit(DISCARD_DISK, &device->flags)) { -+ zeroout_err = zeroout_local_device(device, true); -+ } else { -+ zeroout_err = zeroout_local_device(device, false); -+ } -+ -+ if (zeroout_err) { -+ drbd_err(device, "Failed to zero out local device\n"); -+ set_bit(ZERO_FAIL, &device->flags); -+ drbd_chk_io_error(device, 1, DRBD_WRITE_ERROR); -+ } else { -+ drbd_info(device, "Finished zero out local device.\n"); -+ -+ if (test_and_clear_bit(ZERO_DONE, &device->flags)) { -+ spin_lock_irq(&device->resource->req_lock); -+ _drbd_set_state(_NS2(device, disk, D_UP_TO_DATE, -+ pdsk, D_UP_TO_DATE), CS_VERBOSE, NULL); -+ spin_unlock_irq(&device->resource->req_lock); -+ drbd_send_zeroout_finish(first_peer_device(device)); -+ } else if (test_and_clear_bit(ZERO_FAIL, &device->flags)) { -+ drbd_info(device, "Peer device has already failed on zero out\n"); -+ } else { -+ /* waiting for peer device finished */ -+ set_bit(ZERO_DONE, &device->flags); -+ } -+ } -+} -+ -+/** -+ * receive_zeroout_local_device() -+ * @device: DRBD device. -+ * -+ * Description: -+ * Start to zero out local device. -+ * Notify peer node the zeroing result. -+ * -+**/ -+void receive_zeroout_local_device(struct drbd_device *device) -+{ -+ int zeroout_err = 0; -+ struct drbd_peer_device *const peer_device = first_peer_device(device); -+ -+ if (test_and_clear_bit(DISCARD_DISK, &device->flags)) { -+ zeroout_err = zeroout_local_device(device, true); -+ } else { -+ zeroout_err = zeroout_local_device(device, false); -+ } -+ if (zeroout_err) { -+ drbd_err(device, "Failed to zero out local device\n"); -+ drbd_send_zeroout_fail(peer_device); -+ drbd_chk_io_error(device, 1, DRBD_WRITE_ERROR); -+ } else { -+ drbd_info(device, "Finished zero out local device.\n"); -+ drbd_send_zeroout_ok(peer_device); -+ } -+} -+ - void start_resync_timer_fn(unsigned long data) - { - struct drbd_device *device = (struct drbd_device *) data; -@@ -1986,6 +2085,10 @@ static void do_device_work(struct drbd_device *device, const unsigned long todo) - drbd_ldev_destroy(device); - if (test_bit(RS_START, &todo)) - do_start_resync(device); -+ if (test_bit(P_ZERO_START, &todo)) -+ require_zeroout_local_device(device); -+ if (test_bit(S_ZERO_START, &todo)) -+ receive_zeroout_local_device(device); - } - - #define DRBD_DEVICE_WORK_MASK \ -@@ -1995,6 +2098,8 @@ static void do_device_work(struct drbd_device *device, const unsigned long todo) - |(1UL << RS_START) \ - |(1UL << RS_PROGRESS) \ - |(1UL << RS_DONE) \ -+ |(1UL << P_ZERO_START) \ -+ |(1UL << S_ZERO_START) \ - ) - - static unsigned long get_work_bits(unsigned long *flags) -diff --git a/drbd/linux/drbd_genl.h b/drbd/linux/drbd_genl.h -index 5db53f5..5a31a5c 100644 ---- a/drbd/linux/drbd_genl.h -+++ b/drbd/linux/drbd_genl.h -@@ -240,6 +240,8 @@ GENL_struct(DRBD_NLA_START_OV_PARMS, 9, start_ov_parms, - - GENL_struct(DRBD_NLA_NEW_C_UUID_PARMS, 10, new_c_uuid_parms, - __flg_field(1, DRBD_GENLA_F_MANDATORY, clear_bm) -+ __flg_field(2, 0, zeroout_devices) -+ __flg_field(3, 0, discard_devices) - ) - - GENL_struct(DRBD_NLA_TIMEOUT_PARMS, 11, timeout_parms, --- -2.1.4 - diff --git a/Module.supported b/Module.supported index 44986e3..36f0225 100644 --- a/Module.supported +++ b/Module.supported @@ -1 +1,2 @@ updates/drbd.ko +updates/drbd_transport_tcp.ko diff --git a/_service b/_service new file mode 100644 index 0000000..83d9461 --- /dev/null +++ b/_service @@ -0,0 +1,24 @@ + + + git://git.linbit.com/drbd-9.0.git + git + drbd + + 9.0.1+git.%h + 86e443973082570aeb651848db89e0c7b995c306 + + + + *drbd*.tar + bz2 + + + + drbd + + diff --git a/_service:recompress:tar_scm:drbd-9.0.1+git.86e4439.tar.bz2 b/_service:recompress:tar_scm:drbd-9.0.1+git.86e4439.tar.bz2 new file mode 100644 index 0000000..fc2dfcb --- /dev/null +++ b/_service:recompress:tar_scm:drbd-9.0.1+git.86e4439.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:35e160ffffed266f54e50db947cf103a544261b7a416cb1b55aa346ea04bf90b +size 282912 diff --git a/_service:set_version:drbd.spec b/_service:set_version:drbd.spec new file mode 100644 index 0000000..c0560cf --- /dev/null +++ b/_service:set_version:drbd.spec @@ -0,0 +1,113 @@ +# +# spec file for package drbd +# +# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany. +# +# All modifications and additions to the file contributed by third parties +# remain the property of their copyright owners, unless otherwise agreed +# upon. The license for this file, and modifications and additions to the +# file, is the same license as for the pristine package itself (unless the +# license for the pristine package is not an Open Source License, in which +# case the license is the MIT License). An "Open Source License" is a +# license that conforms to the Open Source Definition (Version 1.9) +# published by the Open Source Initiative. + +# Please submit bugfixes or comments via http://bugs.opensuse.org/ +# + + +# needssslcertforbuild + +%ifarch x86_64 +%define buildrt 0 +%endif + +Name: drbd +Version: 9.0.1+git.86e4439 +Release: 0 +Summary: DRBD driver for Linux +License: GPL-2.0 +Group: Productivity/Clustering/HA +Url: http://drbd.linbit.com/ +Source: %{name}-%{version}.tar.bz2 +Source1: preamble +#In kernel is: kernel/drivers/block/drbd/drbd.ko +Source2: Module.supported +Source3: drbd_git_revision +Patch0: kernel-4.5-compat.patch +BuildRequires: kernel-source +BuildRequires: kernel-syms +BuildRequires: module-init-tools + +%if 0%{?buildrt} == 1 +BuildRequires: kernel-source-rt +BuildRequires: kernel-syms-rt +%endif + +Requires: drbd-utils >= 8.9.6 +Supplements: drbd-utils >= 8.9.6 +Obsoletes: drbd-kmp < %{version} +BuildRoot: %{_tmppath}/%{name}-%{version}-build +ExcludeArch: i586 s390 + +%kernel_module_package -n drbd -p %_sourcedir/preamble + +%description +Drbd is a distributed replicated block device. It mirrors a block +device over the network to another machine. Think of it as networked +raid 1. It is a building block for setting up clusters. + +%package KMP +Summary: Kernel driver for DRBD +Group: Productivity/Clustering/HA + +%description KMP +This module is the kernel-dependent driver for DRBD. This is split out so +that multiple kernel driver versions can be installed, one for each +installed kernel. + +%prep +%setup -q -n drbd-%{version} +%patch0 -p1 + +mkdir source +cp -a drbd/. source/. || : +cp $RPM_SOURCE_DIR/drbd_git_revision source/.drbd_git_revision + +%build +rm -rf obj +mkdir obj +ln -s ../scripts obj/ + +export CONFIG_BLK_DEV_DRBD=m +export EXTRA_CFLAGS='-DVERSION=\"%{version}\"' + +for flavor in %flavors_to_build; do + rm -rf $flavor + cp -r source $flavor + cp %_sourcedir/Module.supported $flavor + export DRBDSRC="$PWD/obj/$flavor" + make -C %{kernel_source $flavor} modules M=$PWD/$flavor +done + +%install +export INSTALL_MOD_PATH=%{buildroot} +export INSTALL_MOD_DIR=updates +for flavor in %{flavors_to_build}; do + make -C %{kernel_source $flavor} modules_install M=$PWD/$flavor +done + +mkdir -p %{buildroot}/%{_sbindir} +%{__ln_s} -f %{_sbindir}/service %{buildroot}/%{_sbindir}/rc%{name} +rm -f drbd.conf + +%clean +rm -rf %{buildroot} + +%files +%defattr(-,root,root) +%doc COPYING +%doc ChangeLog +%{_sbindir}/rc%{name} + +%changelog diff --git a/drbd-8.4.6.tar.gz b/drbd-8.4.6.tar.gz deleted file mode 100644 index adc8e69..0000000 --- a/drbd-8.4.6.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c10c4d7a5389a9194eb2f7c094a3c1685b87f52513ae0af15fdc1df6a091d014 -size 321974 diff --git a/drbd-buildcompare.patch b/drbd-buildcompare.patch deleted file mode 100644 index fbd81ae..0000000 --- a/drbd-buildcompare.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- - drbd/Kbuild | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -Index: drbd-8.4.6/drbd/Kbuild -=================================================================== ---- drbd-8.4.6.orig/drbd/Kbuild -+++ drbd-8.4.6/drbd/Kbuild -@@ -134,5 +134,5 @@ $(obj)/drbd_buildtag.c: $(filter-out drb - echo >&2 "Your DRBD source tree is broken. Unpack again."; \ - exit 1; \ - fi ; \ -- echo -e "\t\t\" build by $$USER@$$HOSTNAME, `date "+%F %T"`\";\n}"; \ -+ echo -e "\t\t\" build by $$USER\";\n}"; \ - mv --force $@.new $@ diff --git a/drbd.changes b/drbd.changes index d709a78..32bc7f3 100644 --- a/drbd.changes +++ b/drbd.changes @@ -1,8 +1,23 @@ ------------------------------------------------------------------- -Mon Mar 7 14:23:53 UTC 2016 - olaf@aepfle.de +Fri Apr 8 14:44:21 UTC 2016 - nwang@suse.com -- Remove timstamp from binaries - Add patch drbd-buildcompare.patch +- Compat with kernel 4.5 +- Add patch kernel-4.5-compat.patch + +------------------------------------------------------------------- +Mon Mar 7 08:42:41 UTC 2016 - nwang@suse.com + +- Update to release drbd-9.0.1 +- Depend on drbd-utils >= 8.9.6 + +------------------------------------------------------------------- +Mon Nov 30 14:31:22 UTC 2015 - nwang@suse.com + +- Update to released drbd-9.0.0 +- Remove patch 0001-Support-zeroout-device-in-initial-sync.patch +- Remove patch update-to-8.4.6-5.patch +- Remove patch rename-GFP_WAIT-to-GFP_RECLAIM.patch +- Remove patch new-bio-struct.patch ------------------------------------------------------------------- Fri Nov 20 06:50:29 UTC 2015 - nwang@suse.com diff --git a/drbd.spec b/drbd.spec index b9c517b..82042ce 100644 --- a/drbd.spec +++ b/drbd.spec @@ -21,38 +21,31 @@ %ifarch x86_64 %define buildrt 0 %endif + Name: drbd -Version: 8.4.6 +Version: @VERSION@ Release: 0 -Summary: Distributed Replicated Block Device -License: GPL-2.0+ +Summary: DRBD driver for Linux +License: GPL-2.0 Group: Productivity/Clustering/HA -Url: http://www.drbd.org/ -Source: http://oss.linbit.com/drbd/8.4/%{name}-%{version}.tar.gz +Url: http://drbd.linbit.com/ +Source: %{name}-%{version}.tar.bz2 Source1: preamble #In kernel is: kernel/drivers/block/drbd/drbd.ko Source2: Module.supported - -Patch1: update-to-8.4.6-5.patch -#Patch for supporting drbd KMP after kernel4.3 -#This patch can be removed when using in-tree 4.3 -Patch2: new-bio-struct.patch -#Patch for fate: https://fate.suse.com/317940 -#Whether can merge into linbit is under discussion -Patch3: 0001-Support-zeroout-device-in-initial-sync.patch -Patch4: rename-GFP_WAIT-to-GFP_RECLAIM.patch -Patch5: drbd-buildcompare.patch - +Source3: drbd_git_revision +Patch0: kernel-4.5-compat.patch BuildRequires: kernel-source BuildRequires: kernel-syms BuildRequires: module-init-tools + %if 0%{?buildrt} == 1 BuildRequires: kernel-source-rt BuildRequires: kernel-syms-rt %endif -Requires: drbd-utils >= 8.9.0 -Supplements: drbd-utils >= 8.9.0 +Requires: drbd-utils >= 8.9.6 +Supplements: drbd-utils >= 8.9.6 Obsoletes: drbd-kmp < %{version} BuildRoot: %{_tmppath}/%{name}-%{version}-build ExcludeArch: i586 s390 @@ -75,33 +68,33 @@ installed kernel. %prep %setup -q -n drbd-%{version} -%patch1 -p1 -%patch2 -p1 -%patch3 -p1 -%patch4 -p1 -%patch5 -p1 +%patch0 -p1 + +mkdir source +cp -a drbd/. source/. || : +cp $RPM_SOURCE_DIR/drbd_git_revision source/.drbd_git_revision %build rm -rf obj mkdir obj ln -s ../scripts obj/ -for flavor in %{flavors_to_build}; do - cp -r drbd obj/$flavor - cp %_sourcedir/Module.supported obj/$flavor - #make -C %{kernel_source $flavor} modules M=$PWD/obj/$flavor - make -C obj/$flavor %{_smp_mflags} all KDIR=%{kernel_source $flavor} +export CONFIG_BLK_DEV_DRBD=m +export EXTRA_CFLAGS='-DVERSION=\"%{version}\"' + +for flavor in %flavors_to_build; do + rm -rf $flavor + cp -r source $flavor + cp %_sourcedir/Module.supported $flavor + export DRBDSRC="$PWD/obj/$flavor" + make -C %{kernel_source $flavor} modules M=$PWD/$flavor done %install export INSTALL_MOD_PATH=%{buildroot} export INSTALL_MOD_DIR=updates - -for flavor in %{flavors_to_build} ; do - make -C %{kernel_source $flavor} modules_install M=$PWD/obj/$flavor - #From upstream file: drbd-kernel.spec - #kernelrelease=$(cat %{kernel_source $flavor}/include/config/kernel.release || make -s -C %{kernel_source $flavor} kernelrelease) - #mv obj/$flavor/.kernel.config.gz obj/k-config-$kernelrelease.gz +for flavor in %{flavors_to_build}; do + make -C %{kernel_source $flavor} modules_install M=$PWD/$flavor done mkdir -p %{buildroot}/%{_sbindir} diff --git a/drbd_git_revision b/drbd_git_revision new file mode 100644 index 0000000..0776ea3 --- /dev/null +++ b/drbd_git_revision @@ -0,0 +1 @@ +GIT-hash: 86e443973082570aeb651848db89e0c7b995c306 diff --git a/kernel-4.5-compat.patch b/kernel-4.5-compat.patch new file mode 100644 index 0000000..bc8f785 --- /dev/null +++ b/kernel-4.5-compat.patch @@ -0,0 +1,35 @@ +diff -Naur drbd-9.0.1+git.86e4439.orig/drbd/drbd-kernel-compat/drbd_wrappers.h drbd-9.0.1+git.86e4439/drbd/drbd-kernel-compat/drbd_wrappers.h +--- drbd-9.0.1+git.86e4439.orig/drbd/drbd-kernel-compat/drbd_wrappers.h 2016-04-08 21:56:02.872683041 +0800 ++++ drbd-9.0.1+git.86e4439/drbd/drbd-kernel-compat/drbd_wrappers.h 2016-04-08 22:03:05.732665258 +0800 +@@ -1529,31 +1529,6 @@ + } + #endif + +-#ifndef COMPAT_HAVE_IB_CQ_INIT_ATTR +-#include +- +-struct ib_cq_init_attr { +- unsigned int cqe; +- int comp_vector; +- u32 flags; +-}; +- +-static inline struct ib_cq * +-drbd_ib_create_cq(struct ib_device *device, +- ib_comp_handler comp_handler, +- void (*event_handler)(struct ib_event *, void *), +- void *cq_context, +- const struct ib_cq_init_attr *cq_attr) +-{ +- return ib_create_cq(device, comp_handler, event_handler, cq_context, +- cq_attr->cqe, cq_attr->comp_vector); +-} +- +-#define ib_create_cq(DEV, COMP_H, EVENT_H, CTX, ATTR) \ +- drbd_ib_create_cq(DEV, COMP_H, EVENT_H, CTX, ATTR) +-#endif +- +- + #ifndef COMPAT_RDMA_CREATE_ID_HAS_NET_NS + /* Since linux v4.4 it has a network namespace as first argument */ + #define rdma_create_id(NS, H, C, P, T) rdma_create_id(H, C, P, T) diff --git a/new-bio-struct.patch b/new-bio-struct.patch deleted file mode 100644 index 9e97173..0000000 --- a/new-bio-struct.patch +++ /dev/null @@ -1,391 +0,0 @@ -From 641de14e15547788055e15b1db4601a436f048bb Mon Sep 17 00:00:00 2001 -From: Nick Wang -Date: Fri, 16 Oct 2015 10:16:47 +0800 -Subject: [PATCH] fix failure with new bi_error field of bio - -drbd fail to build with new bio structure and interface -after 4.3.0, see 4246a0b63bd8f56a1469b12eafeb875b1041a451 -A new bi_error field to store an errno value directly in -struct bio and remove the existing mechanisms to clean -all this up. - -With 8ae126660fddbeebb9251a174e6fa45b6ad8f932, -generic_make_request() is now able to handle arbitrarily -sized bios,it's no longer need to define its merge_bvec_fn. - -This patch delete merge_bvec_fn and support new bio struct. ---- - drbd/drbd_actlog.c | 4 ++ - drbd/drbd_bitmap.c | 46 +++++++++++++++++++++ - drbd/drbd_int.h | 2 + - drbd/drbd_main.c | 2 + - drbd/drbd_req.c | 4 +- - drbd/drbd_worker.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++ - drbd/drbd_wrappers.h | 31 +++++++++++++- - 7 files changed, 201 insertions(+), 2 deletions(-) - -diff --git a/drbd/drbd_actlog.c b/drbd/drbd_actlog.c -index 1a274c5..c73bb32 100644 ---- a/drbd/drbd_actlog.c -+++ b/drbd/drbd_actlog.c -@@ -184,7 +184,11 @@ static int _drbd_md_sync_page_io(struct drbd_device *device, - else - submit_bio(rw, bio); - wait_until_done_or_force_detached(device, bdev, &device->md_io.done); -+#ifdef NO_ERROR_BIO_END_IO -+ if (bio->bi_error) -+#else - if (bio_flagged(bio, BIO_UPTODATE)) -+#endif - err = device->md_io.error; - - #ifndef REQ_FLUSH -diff --git a/drbd/drbd_bitmap.c b/drbd/drbd_bitmap.c -index abf1bc1..2e16bc8 100644 ---- a/drbd/drbd_bitmap.c -+++ b/drbd/drbd_bitmap.c -@@ -960,6 +960,51 @@ static void drbd_bm_aio_ctx_destroy(struct kref *kref) - } - - /* bv_page may be a copy, or may be the original */ -+#ifdef NO_ERROR_BIO_END_IO -+static BIO_ENDIO_TYPE drbd_bm_endio BIO_ENDIO_ARGS(struct bio *bio) -+{ -+ struct drbd_bm_aio_ctx *ctx = bio->bi_private; -+ struct drbd_device *device = ctx->device; -+ struct drbd_bitmap *b = device->bitmap; -+ unsigned int idx = bm_page_to_idx(bio->bi_io_vec[0].bv_page); -+ -+ BIO_ENDIO_FN_START; -+ -+ if ((ctx->flags & BM_AIO_COPY_PAGES) == 0 && -+ !bm_test_page_unchanged(b->bm_pages[idx])) -+ drbd_warn(device, "bitmap page idx %u changed during IO!\n", idx); -+ -+ if (bio->bi_error) { -+ /* ctx error will hold the completed-last non-zero error code, -+ * in case error codes differ. */ -+ ctx->error = bio->bi_error; -+ bm_set_page_io_err(b->bm_pages[idx]); -+ /* Not identical to on disk version of it. -+ * Is BM_PAGE_IO_ERROR enough? */ -+ if (DRBD_ratelimit(5*HZ, 5)) -+ drbd_err(device, "IO ERROR %d on bitmap page idx %u\n", -+ bio->bi_error, idx); -+ } else { -+ bm_clear_page_io_err(b->bm_pages[idx]); -+ dynamic_drbd_dbg(device, "bitmap page idx %u completed\n", idx); -+ } -+ -+ bm_page_unlock_io(device, idx); -+ -+ if (ctx->flags & BM_AIO_COPY_PAGES) -+ mempool_free(bio->bi_io_vec[0].bv_page, drbd_md_io_page_pool); -+ -+ bio_put(bio); -+ -+ if (atomic_dec_and_test(&ctx->in_flight)) { -+ ctx->done = 1; -+ wake_up(&device->misc_wait); -+ kref_put(&ctx->kref, &drbd_bm_aio_ctx_destroy); -+ } -+ -+ BIO_ENDIO_FN_RETURN; -+} -+#else - static BIO_ENDIO_TYPE drbd_bm_endio BIO_ENDIO_ARGS(struct bio *bio, int error) - { - struct drbd_bm_aio_ctx *ctx = bio->bi_private; -@@ -1011,6 +1056,7 @@ static BIO_ENDIO_TYPE drbd_bm_endio BIO_ENDIO_ARGS(struct bio *bio, int error) - - BIO_ENDIO_FN_RETURN; - } -+#endif - - static void bm_page_io_async(struct drbd_bm_aio_ctx *ctx, int page_nr) __must_hold(local) - { -diff --git a/drbd/drbd_int.h b/drbd/drbd_int.h -index d1e2bc0..bed73cc 100644 ---- a/drbd/drbd_int.h -+++ b/drbd/drbd_int.h -@@ -1563,6 +1563,7 @@ extern void do_submit(struct work_struct *ws); - extern void __drbd_make_request(struct drbd_device *, struct bio *, unsigned long); - extern MAKE_REQUEST_TYPE drbd_make_request(struct request_queue *q, struct bio *bio); - extern int drbd_read_remote(struct drbd_device *device, struct drbd_request *req); -+#ifndef NO_ERROR_BIO_END_IO - extern int drbd_merge_bvec(struct request_queue *q, - #ifdef HAVE_bvec_merge_data - struct bvec_merge_data *bvm, -@@ -1570,6 +1571,7 @@ extern int drbd_merge_bvec(struct request_queue *q, - struct bio *bvm, - #endif - struct bio_vec *bvec); -+#endif - extern int is_valid_ar_handle(struct drbd_request *, sector_t); - - -diff --git a/drbd/drbd_main.c b/drbd/drbd_main.c -index 31bf43f..6171714 100644 ---- a/drbd/drbd_main.c -+++ b/drbd/drbd_main.c -@@ -2855,7 +2855,9 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig - This triggers a max_bio_size message upon first attach or connect */ - blk_queue_max_hw_sectors(q, DRBD_MAX_BIO_SIZE_SAFE >> 8); - blk_queue_bounce_limit(q, BLK_BOUNCE_ANY); -+#ifndef NO_ERROR_BIO_END_IO - blk_queue_merge_bvec(q, drbd_merge_bvec); -+#endif - q->queue_lock = &resource->req_lock; - #ifdef blk_queue_plugged - /* plugging on a queue, that actually has no requests! */ -diff --git a/drbd/drbd_req.c b/drbd/drbd_req.c -index 305fe71..e7b1b14 100644 ---- a/drbd/drbd_req.c -+++ b/drbd/drbd_req.c -@@ -1573,6 +1573,7 @@ MAKE_REQUEST_TYPE drbd_make_request(struct request_queue *q, struct bio *bio) - * As long as the BIO is empty we have to allow at least one bvec, - * regardless of size and offset, so no need to ask lower levels. - */ -+#ifndef NO_ERROR_BIO_END_IO - #ifdef HAVE_bvec_merge_data - int drbd_merge_bvec(struct request_queue *q, - struct bvec_merge_data *bvm, -@@ -1604,7 +1605,7 @@ int drbd_merge_bvec(struct request_queue *q, - struct bio_vec *bvec) - { - struct drbd_device *device = (struct drbd_device *) q->queuedata; -- unsigned int bio_size = bvm->bi_size; -+ unsigned int bio_size = bvm->bi_iter.bi_size; - int limit = DRBD_MAX_BIO_SIZE; - int backing_limit; - -@@ -1626,6 +1627,7 @@ int drbd_merge_bvec(struct request_queue *q, - return limit; - } - #endif -+#endif /* END NO_ERROR_BIO_END_IO*/ - - static bool net_timeout_reached(struct drbd_request *net_req, - struct drbd_connection *connection, -diff --git a/drbd/drbd_worker.c b/drbd/drbd_worker.c -index 2a15aeb..391237e 100644 ---- a/drbd/drbd_worker.c -+++ b/drbd/drbd_worker.c -@@ -58,14 +58,22 @@ static int make_resync_request(struct drbd_device *, int); - /* used for synchronous meta data and bitmap IO - * submitted by drbd_md_sync_page_io() - */ -+#ifdef NO_ERROR_BIO_END_IO -+BIO_ENDIO_TYPE drbd_md_endio BIO_ENDIO_ARGS(struct bio *bio) -+#else - BIO_ENDIO_TYPE drbd_md_endio BIO_ENDIO_ARGS(struct bio *bio, int error) -+#endif - { - struct drbd_device *device; - - BIO_ENDIO_FN_START; - - device = bio->bi_private; -+#ifdef NO_ERROR_BIO_END_IO -+ device->md_io.error = bio->bi_error; -+#else - device->md_io.error = error; -+#endif - - /* We grabbed an extra reference in _drbd_md_sync_page_io() to be able - * to timeout on the lower level device, and eventually detach from it. -@@ -194,6 +202,34 @@ void drbd_endio_write_sec_final(struct drbd_peer_request *peer_req) __releases(l - /* writes on behalf of the partner, or resync writes, - * "submitted" by the receiver. - */ -+#ifdef NO_ERROR_BIO_END_IO -+BIO_ENDIO_TYPE drbd_peer_request_endio BIO_ENDIO_ARGS(struct bio *bio) -+{ -+ struct drbd_peer_request *peer_req = bio->bi_private; -+ struct drbd_device *device = peer_req->peer_device->device; -+ int is_write = bio_data_dir(bio) == WRITE; -+ int is_discard = !!(bio->bi_rw & DRBD_REQ_DISCARD); -+ -+ BIO_ENDIO_FN_START; -+ if (bio->bi_error && DRBD_ratelimit(5*HZ, 5)) -+ drbd_warn(device, "%s: error=%d s=%llus\n", -+ is_write ? (is_discard ? "discard" : "write") -+ : "read", bio->bi_error, -+ (unsigned long long)peer_req->i.sector); -+ -+ if (bio->bi_error) -+ set_bit(__EE_WAS_ERROR, &peer_req->flags); -+ -+ bio_put(bio); /* no need for the bio anymore */ -+ if (atomic_dec_and_test(&peer_req->pending_bios)) { -+ if (is_write) -+ drbd_endio_write_sec_final(peer_req); -+ else -+ drbd_endio_read_sec_final(peer_req); -+ } -+ BIO_ENDIO_FN_RETURN; -+} -+#else - BIO_ENDIO_TYPE drbd_peer_request_endio BIO_ENDIO_ARGS(struct bio *bio, int error) - { - struct drbd_peer_request *peer_req = bio->bi_private; -@@ -231,6 +267,7 @@ BIO_ENDIO_TYPE drbd_peer_request_endio BIO_ENDIO_ARGS(struct bio *bio, int error - } - BIO_ENDIO_FN_RETURN; - } -+#endif - - void drbd_panic_after_delayed_completion_of_aborted_request(struct drbd_device *device) - { -@@ -240,6 +277,82 @@ void drbd_panic_after_delayed_completion_of_aborted_request(struct drbd_device * - - /* read, readA or write requests on R_PRIMARY coming from drbd_make_request - */ -+#ifdef NO_ERROR_BIO_END_IO -+BIO_ENDIO_TYPE drbd_request_endio BIO_ENDIO_ARGS(struct bio *bio) -+{ -+ unsigned long flags; -+ struct drbd_request *req = bio->bi_private; -+ struct drbd_device *device = req->device; -+ struct bio_and_error m; -+ enum drbd_req_event what; -+ -+ BIO_ENDIO_FN_START; -+ -+ /* If this request was aborted locally before, -+ * but now was completed "successfully", -+ * chances are that this caused arbitrary data corruption. -+ * -+ * "aborting" requests, or force-detaching the disk, is intended for -+ * completely blocked/hung local backing devices which do no longer -+ * complete requests at all, not even do error completions. In this -+ * situation, usually a hard-reset and failover is the only way out. -+ * -+ * By "aborting", basically faking a local error-completion, -+ * we allow for a more graceful swichover by cleanly migrating services. -+ * Still the affected node has to be rebooted "soon". -+ * -+ * By completing these requests, we allow the upper layers to re-use -+ * the associated data pages. -+ * -+ * If later the local backing device "recovers", and now DMAs some data -+ * from disk into the original request pages, in the best case it will -+ * just put random data into unused pages; but typically it will corrupt -+ * meanwhile completely unrelated data, causing all sorts of damage. -+ * -+ * Which means delayed successful completion, -+ * especially for READ requests, -+ * is a reason to panic(). -+ * -+ * We assume that a delayed *error* completion is OK, -+ * though we still will complain noisily about it. -+ */ -+ if (unlikely(req->rq_state & RQ_LOCAL_ABORTED)) { -+ if (DRBD_ratelimit(5*HZ, 5)) -+ drbd_emerg(device, "delayed completion of aborted local request; disk-timeout may be too aggressive\n"); -+ -+ if (!bio->bi_error) -+ drbd_panic_after_delayed_completion_of_aborted_request(device); -+ } -+ -+ /* to avoid recursion in __req_mod */ -+ if (unlikely(bio->bi_error)) { -+ if (bio->bi_rw & DRBD_REQ_DISCARD) -+ what = (bio->bi_error == -EOPNOTSUPP) -+ ? DISCARD_COMPLETED_NOTSUPP -+ : DISCARD_COMPLETED_WITH_ERROR; -+ else -+ what = (bio_data_dir(bio) == WRITE) -+ ? WRITE_COMPLETED_WITH_ERROR -+ : (bio_rw(bio) == READ) -+ ? READ_COMPLETED_WITH_ERROR -+ : READ_AHEAD_COMPLETED_WITH_ERROR; -+ } else -+ what = COMPLETED_OK; -+ -+ bio_put(req->private_bio); -+ req->private_bio = ERR_PTR(bio->bi_error); -+ -+ /* not req_mod(), we need irqsave here! */ -+ spin_lock_irqsave(&device->resource->req_lock, flags); -+ __req_mod(req, what, &m); -+ spin_unlock_irqrestore(&device->resource->req_lock, flags); -+ put_ldev(device); -+ -+ if (m.bio) -+ complete_master_bio(device, &m); -+ BIO_ENDIO_FN_RETURN; -+} -+#else - BIO_ENDIO_TYPE drbd_request_endio BIO_ENDIO_ARGS(struct bio *bio, int error) - { - unsigned long flags; -@@ -324,6 +437,7 @@ BIO_ENDIO_TYPE drbd_request_endio BIO_ENDIO_ARGS(struct bio *bio, int error) - complete_master_bio(device, &m); - BIO_ENDIO_FN_RETURN; - } -+#endif - - void drbd_csum_ee(struct crypto_hash *tfm, struct drbd_peer_request *peer_req, void *digest) - { -diff --git a/drbd/drbd_wrappers.h b/drbd/drbd_wrappers.h -index d7a4138..c9ccb93 100644 ---- a/drbd/drbd_wrappers.h -+++ b/drbd/drbd_wrappers.h -@@ -195,16 +195,38 @@ static inline int drbd_blkdev_put(struct block_device *bdev, fmode_t mode) - #define BIO_ENDIO_FN_START if (bio->bi_size) return 1 - #define BIO_ENDIO_FN_RETURN return 0 - #else -+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,3,0) -+ /* After Linux-4.3 a new bi_error field to store an errno value in struct bio. -+ See 4246a0b63bd8f56a1469b12eafeb875b1041a451 */ -+ #define bio_endio(B,E) \ -+ do { \ -+ (B)->bi_error = (E); \ -+ bio_endio(B); \ -+ } while (0) -+ #define BIO_ENDIO_ARGS(b) (b) -+ #else -+ #define BIO_ENDIO_ARGS(b,e) (b,e) -+ #endif - #define BIO_ENDIO_TYPE void --#define BIO_ENDIO_ARGS(b,e) (b,e) - #define BIO_ENDIO_FN_START do {} while (0) - #define BIO_ENDIO_FN_RETURN return - #endif - - /* bi_end_io handlers */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,3,0) -+#undef NO_ERROR_BIO_END_IO -+#define NO_ERROR_BIO_END_IO 1 -+#endif -+ -+#ifdef NO_ERROR_BIO_END_IO -+extern BIO_ENDIO_TYPE drbd_md_endio BIO_ENDIO_ARGS(struct bio *bio); -+extern BIO_ENDIO_TYPE drbd_peer_request_endio BIO_ENDIO_ARGS(struct bio *bio); -+extern BIO_ENDIO_TYPE drbd_request_endio BIO_ENDIO_ARGS(struct bio *bio); -+#else - extern BIO_ENDIO_TYPE drbd_md_endio BIO_ENDIO_ARGS(struct bio *bio, int error); - extern BIO_ENDIO_TYPE drbd_peer_request_endio BIO_ENDIO_ARGS(struct bio *bio, int error); - extern BIO_ENDIO_TYPE drbd_request_endio BIO_ENDIO_ARGS(struct bio *bio, int error); -+#endif - - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) - #define part_inc_in_flight(A, B) part_inc_in_flight(A) -@@ -222,6 +244,13 @@ extern BIO_ENDIO_TYPE drbd_request_endio BIO_ENDIO_ARGS(struct bio *bio, int err - # define HAVE_bvec_merge_data 1 - #endif - -+/* After 4.3.0 (with 8ae126660fddbeebb9251a174e6fa45b6ad8f932) -+ bvec_merge_data was killed. */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,3,0) -+# undef HAVE_bvec_merge_data -+#endif -+ -+ - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - static inline void sg_set_page(struct scatterlist *sg, struct page *page, - unsigned int len, unsigned int offset) --- -2.1.4 - diff --git a/preamble b/preamble index a1043de..58d7ac7 100644 --- a/preamble +++ b/preamble @@ -1,3 +1,4 @@ -Requires: kernel-%1 +Requires: kernel-%1 +Supplements: packageand(kernel-%1:%name) Recommends: drbd Recommends: drbd-utils diff --git a/rename-GFP_WAIT-to-GFP_RECLAIM.patch b/rename-GFP_WAIT-to-GFP_RECLAIM.patch deleted file mode 100644 index a13eb38..0000000 --- a/rename-GFP_WAIT-to-GFP_RECLAIM.patch +++ /dev/null @@ -1,32 +0,0 @@ -Index: drbd-8.4.6/drbd/drbd_bitmap.c -=================================================================== ---- drbd-8.4.6.orig/drbd/drbd_bitmap.c -+++ drbd-8.4.6/drbd/drbd_bitmap.c -@@ -1084,7 +1084,11 @@ static void bm_page_io_async(struct drbd - bm_set_page_unchanged(b->bm_pages[page_nr]); - - if (ctx->flags & BM_AIO_COPY_PAGES) { -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0) -+ page = mempool_alloc(drbd_md_io_page_pool, __GFP_HIGHMEM|__GFP_RECLAIM); -+#else - page = mempool_alloc(drbd_md_io_page_pool, __GFP_HIGHMEM|__GFP_WAIT); -+#endif - copy_highpage(page, b->bm_pages[page_nr]); - bm_store_page_idx(page, page_nr); - } else -Index: drbd-8.4.6/drbd/drbd_receiver.c -=================================================================== ---- drbd-8.4.6.orig/drbd/drbd_receiver.c -+++ drbd-8.4.6/drbd/drbd_receiver.c -@@ -421,7 +421,11 @@ drbd_alloc_peer_req(struct drbd_peer_dev - } - - if (has_payload && data_size) { -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0) -+ page = drbd_alloc_pages(peer_device, nr_pages, (gfp_mask & __GFP_RECLAIM)); -+#else - page = drbd_alloc_pages(peer_device, nr_pages, (gfp_mask & __GFP_WAIT)); -+#endif - if (!page) - goto fail; - } diff --git a/update-to-8.4.6-5.patch b/update-to-8.4.6-5.patch deleted file mode 100644 index 4400989..0000000 --- a/update-to-8.4.6-5.patch +++ /dev/null @@ -1,1241 +0,0 @@ -diff --git a/ChangeLog b/ChangeLog -index 47d535d..eddc3a7 100644 ---- a/ChangeLog -+++ b/ChangeLog -@@ -1,6 +1,14 @@ - Latest: - ------ -- For even more detail, use "git log" or visit http://git.drbd.org/. -+ For even more detail, visit http://git.linbit.com/drbd-8.4.git -+ -+ * fix latency regression introduced with 8.4.5 -+ protocol A was sometimes synchronous, C sometimes double-latency -+ * avoid potential deadlock during handshake -+ * avoid potential deadlock in disconnect during resync -+ with fencing resource-and-stonith -+ * allow IO during some bitmap bulk IO operations -+ * fix "endless" transfer log walk in protocol A - - 8.4.6 (api:genl1/proto:86-101) - ------- -diff --git a/drbd-kernel.spec b/drbd-kernel.spec -index 489b09f..9b70767 100644 ---- a/drbd-kernel.spec -+++ b/drbd-kernel.spec -@@ -1,7 +1,7 @@ - Name: drbd-kernel - Summary: Kernel driver for DRBD - Version: 8.4.6 --Release: 1%{?dist} -+Release: 5%{?dist} - Source: http://oss.linbit.com/drbd/drbd-%{version}.tar.gz - License: GPLv2+ - Group: System Environment/Kernel -@@ -97,6 +97,12 @@ echo "override drbd * weak-updates" \ - rm -rf %{buildroot} - - %changelog -+* Wed Sep 16 2015 Lars Ellenberg - 8.4.6-5 -+- New upstream release. -+ -+* Thu Jul 30 2015 Lars Ellenberg - 8.4.6-4 -+- New upstream release. -+ - * Fri Apr 3 2015 Philipp Reisner - 8.4.6-1 - - New upstream release. - -diff --git a/drbd-km.spec b/drbd-km.spec -index 859aa51..0cb976d 100644 ---- a/drbd-km.spec -+++ b/drbd-km.spec -@@ -10,7 +10,7 @@ - Name: drbd-km - Summary: DRBD driver for Linux - Version: 8.4.6 --Release: 1 -+Release: 5 - Source: http://oss.linbit.com/%{name}/8.4/drbd-%{version}.tar.gz - License: GPLv2+ - ExclusiveOS: linux -@@ -32,7 +32,7 @@ setting up high availability (HA) clusters. - Summary: Kernel driver for DRBD. - Group: System Environment/Kernel - # always require a suitable userland and depmod. --Requires: drbd-utils = %{version}, /sbin/depmod -+Requires: drbd-utils >= 8.9.2, /sbin/depmod - # to be able to override from build scripts which flavor of kernel we are building against. - Requires: %{expand: %(echo ${DRBD_KMOD_REQUIRES:-kernel})} - # TODO: break up this generic .spec file into per distribution ones, -@@ -92,6 +92,12 @@ uname -r | grep BOOT || - - - %changelog -+* Wed Sep 16 2015 Lars Ellenberg - 8.4.6-5 -+- New upstream release. -+ -+* Thu Jul 30 2015 Lars Ellenberg - 8.4.6-4 -+- New upstream release. -+ - * Fri Apr 3 2015 Philipp Reisner - 8.4.6-1 - - New upstream release. - -diff --git a/drbd/compat/tests/have_WB_congested_enum.c b/drbd/compat/tests/have_WB_congested_enum.c -new file mode 100644 -index 0000000..37fb32d ---- /dev/null -+++ b/drbd/compat/tests/have_WB_congested_enum.c -@@ -0,0 +1,13 @@ -+#include -+ -+ -+/* With commit 4452226 (linux v4.2) -+ BDI_async_congested was renamed to WB_async_congested and -+ BDI_sync_congested was renamed to WB_sync_congested. -+ */ -+ -+void foo(void) -+{ -+ int a = WB_async_congested; -+ int b = WB_sync_congested; -+} -diff --git a/drbd/compat/tests/have_generic_start_io_acct.c b/drbd/compat/tests/have_generic_start_io_acct.c -new file mode 100644 -index 0000000..14a18d1 ---- /dev/null -+++ b/drbd/compat/tests/have_generic_start_io_acct.c -@@ -0,0 +1,8 @@ -+#include -+ -+/* Introduced by mainline commit 394ffa503b, available since v3.19 */ -+ -+void foo(void) -+{ -+ generic_start_io_acct(WRITE, 0, (struct hd_struct *) NULL); -+} -diff --git a/drbd/compat/tests/have_simple_positive.c b/drbd/compat/tests/have_simple_positive.c -new file mode 100644 -index 0000000..410f157 ---- /dev/null -+++ b/drbd/compat/tests/have_simple_positive.c -@@ -0,0 +1,8 @@ -+#include -+ -+/* Since dc3f4198e (linux v4.2) simple_positive is accessible for modules */ -+ -+void foo(void) -+{ -+ int r = simple_positive((struct dentry *)NULL); -+} -diff --git a/drbd/compat/tests/sock_create_kern_has_five_parameters.c b/drbd/compat/tests/sock_create_kern_has_five_parameters.c -new file mode 100644 -index 0000000..342af09 ---- /dev/null -+++ b/drbd/compat/tests/sock_create_kern_has_five_parameters.c -@@ -0,0 +1,11 @@ -+#include -+ -+ -+/* With commit eeb1bd5 (linux v4.2) a new parameter was inserted in -+ first position */ -+ -+void foo(void) -+{ -+ int err; -+ err = sock_create_kern((struct net *)NULL, 0, 0, 0, (struct socket **)NULL); -+} -diff --git a/drbd/drbd_actlog.c b/drbd/drbd_actlog.c -index 00c7956..1a274c5 100644 ---- a/drbd/drbd_actlog.c -+++ b/drbd/drbd_actlog.c -@@ -312,7 +312,162 @@ bool drbd_al_begin_io_prepare(struct drbd_device *device, struct drbd_interval * - return need_transaction; - } - --static int al_write_transaction(struct drbd_device *device); -+#if (PAGE_SHIFT + 3) < (AL_EXTENT_SHIFT - BM_BLOCK_SHIFT) -+/* Currently BM_BLOCK_SHIFT, BM_EXT_SHIFT and AL_EXTENT_SHIFT -+ * are still coupled, or assume too much about their relation. -+ * Code below will not work if this is violated. -+ * Will be cleaned up with some followup patch. -+ */ -+# error FIXME -+#endif -+ -+static unsigned int al_extent_to_bm_page(unsigned int al_enr) -+{ -+ return al_enr >> -+ /* bit to page */ -+ ((PAGE_SHIFT + 3) - -+ /* al extent number to bit */ -+ (AL_EXTENT_SHIFT - BM_BLOCK_SHIFT)); -+} -+ -+static sector_t al_tr_number_to_on_disk_sector(struct drbd_device *device) -+{ -+ const unsigned int stripes = device->ldev->md.al_stripes; -+ const unsigned int stripe_size_4kB = device->ldev->md.al_stripe_size_4k; -+ -+ /* transaction number, modulo on-disk ring buffer wrap around */ -+ unsigned int t = device->al_tr_number % (device->ldev->md.al_size_4k); -+ -+ /* ... to aligned 4k on disk block */ -+ t = ((t % stripes) * stripe_size_4kB) + t/stripes; -+ -+ /* ... to 512 byte sector in activity log */ -+ t *= 8; -+ -+ /* ... plus offset to the on disk position */ -+ return device->ldev->md.md_offset + device->ldev->md.al_offset + t; -+} -+ -+static int __al_write_transaction(struct drbd_device *device, struct al_transaction_on_disk *buffer) -+{ -+ struct lc_element *e; -+ sector_t sector; -+ int i, mx; -+ unsigned extent_nr; -+ unsigned crc = 0; -+ int err = 0; -+ -+ memset(buffer, 0, sizeof(*buffer)); -+ buffer->magic = cpu_to_be32(DRBD_AL_MAGIC); -+ buffer->tr_number = cpu_to_be32(device->al_tr_number); -+ -+ i = 0; -+ -+ /* Even though no one can start to change this list -+ * once we set the LC_LOCKED -- from drbd_al_begin_io(), -+ * lc_try_lock_for_transaction() --, someone may still -+ * be in the process of changing it. */ -+ spin_lock_irq(&device->al_lock); -+ list_for_each_entry(e, &device->act_log->to_be_changed, list) { -+ if (i == AL_UPDATES_PER_TRANSACTION) { -+ i++; -+ break; -+ } -+ buffer->update_slot_nr[i] = cpu_to_be16(e->lc_index); -+ buffer->update_extent_nr[i] = cpu_to_be32(e->lc_new_number); -+ if (e->lc_number != LC_FREE) -+ drbd_bm_mark_for_writeout(device, -+ al_extent_to_bm_page(e->lc_number)); -+ i++; -+ } -+ spin_unlock_irq(&device->al_lock); -+ BUG_ON(i > AL_UPDATES_PER_TRANSACTION); -+ -+ buffer->n_updates = cpu_to_be16(i); -+ for ( ; i < AL_UPDATES_PER_TRANSACTION; i++) { -+ buffer->update_slot_nr[i] = cpu_to_be16(-1); -+ buffer->update_extent_nr[i] = cpu_to_be32(LC_FREE); -+ } -+ -+ buffer->context_size = cpu_to_be16(device->act_log->nr_elements); -+ buffer->context_start_slot_nr = cpu_to_be16(device->al_tr_cycle); -+ -+ mx = min_t(int, AL_CONTEXT_PER_TRANSACTION, -+ device->act_log->nr_elements - device->al_tr_cycle); -+ for (i = 0; i < mx; i++) { -+ unsigned idx = device->al_tr_cycle + i; -+ extent_nr = lc_element_by_index(device->act_log, idx)->lc_number; -+ buffer->context[i] = cpu_to_be32(extent_nr); -+ } -+ for (; i < AL_CONTEXT_PER_TRANSACTION; i++) -+ buffer->context[i] = cpu_to_be32(LC_FREE); -+ -+ device->al_tr_cycle += AL_CONTEXT_PER_TRANSACTION; -+ if (device->al_tr_cycle >= device->act_log->nr_elements) -+ device->al_tr_cycle = 0; -+ -+ sector = al_tr_number_to_on_disk_sector(device); -+ -+ crc = crc32c(0, buffer, 4096); -+ buffer->crc32c = cpu_to_be32(crc); -+ -+ if (drbd_bm_write_hinted(device)) -+ err = -EIO; -+ else { -+ bool write_al_updates; -+ rcu_read_lock(); -+ write_al_updates = rcu_dereference(device->ldev->disk_conf)->al_updates; -+ rcu_read_unlock(); -+ if (write_al_updates) { -+ if (drbd_md_sync_page_io(device, device->ldev, sector, WRITE)) { -+ err = -EIO; -+ drbd_chk_io_error(device, 1, DRBD_META_IO_ERROR); -+ } else { -+ device->al_tr_number++; -+ device->al_writ_cnt++; -+ } -+ } -+ } -+ -+ return err; -+} -+ -+static int al_write_transaction(struct drbd_device *device) -+{ -+ struct al_transaction_on_disk *buffer; -+ int err; -+ -+ if (!get_ldev(device)) { -+ drbd_err(device, "disk is %s, cannot start al transaction\n", -+ drbd_disk_str(device->state.disk)); -+ return -EIO; -+ } -+ -+ /* The bitmap write may have failed, causing a state change. */ -+ if (device->state.disk < D_INCONSISTENT) { -+ drbd_err(device, -+ "disk is %s, cannot write al transaction\n", -+ drbd_disk_str(device->state.disk)); -+ put_ldev(device); -+ return -EIO; -+ } -+ -+ /* protects md_io_buffer, al_tr_cycle, ... */ -+ buffer = drbd_md_get_buffer(device, __func__); -+ if (!buffer) { -+ drbd_err(device, "disk failed while waiting for md_io buffer\n"); -+ put_ldev(device); -+ return -ENODEV; -+ } -+ -+ err = __al_write_transaction(device, buffer); -+ -+ drbd_md_put_buffer(device); -+ put_ldev(device); -+ -+ return err; -+} -+ - - void drbd_al_begin_io_commit(struct drbd_device *device) - { -@@ -444,153 +599,6 @@ void drbd_al_complete_io(struct drbd_device *device, struct drbd_interval *i) - wake_up(&device->al_wait); - } - --#if (PAGE_SHIFT + 3) < (AL_EXTENT_SHIFT - BM_BLOCK_SHIFT) --/* Currently BM_BLOCK_SHIFT, BM_EXT_SHIFT and AL_EXTENT_SHIFT -- * are still coupled, or assume too much about their relation. -- * Code below will not work if this is violated. -- * Will be cleaned up with some followup patch. -- */ --# error FIXME --#endif -- --static unsigned int al_extent_to_bm_page(unsigned int al_enr) --{ -- return al_enr >> -- /* bit to page */ -- ((PAGE_SHIFT + 3) - -- /* al extent number to bit */ -- (AL_EXTENT_SHIFT - BM_BLOCK_SHIFT)); --} -- --static sector_t al_tr_number_to_on_disk_sector(struct drbd_device *device) --{ -- const unsigned int stripes = device->ldev->md.al_stripes; -- const unsigned int stripe_size_4kB = device->ldev->md.al_stripe_size_4k; -- -- /* transaction number, modulo on-disk ring buffer wrap around */ -- unsigned int t = device->al_tr_number % (device->ldev->md.al_size_4k); -- -- /* ... to aligned 4k on disk block */ -- t = ((t % stripes) * stripe_size_4kB) + t/stripes; -- -- /* ... to 512 byte sector in activity log */ -- t *= 8; -- -- /* ... plus offset to the on disk position */ -- return device->ldev->md.md_offset + device->ldev->md.al_offset + t; --} -- --int al_write_transaction(struct drbd_device *device) --{ -- struct al_transaction_on_disk *buffer; -- struct lc_element *e; -- sector_t sector; -- int i, mx; -- unsigned extent_nr; -- unsigned crc = 0; -- int err = 0; -- -- if (!get_ldev(device)) { -- drbd_err(device, "disk is %s, cannot start al transaction\n", -- drbd_disk_str(device->state.disk)); -- return -EIO; -- } -- -- /* The bitmap write may have failed, causing a state change. */ -- if (device->state.disk < D_INCONSISTENT) { -- drbd_err(device, -- "disk is %s, cannot write al transaction\n", -- drbd_disk_str(device->state.disk)); -- put_ldev(device); -- return -EIO; -- } -- -- /* protects md_io_buffer, al_tr_cycle, ... */ -- buffer = drbd_md_get_buffer(device, __func__); -- if (!buffer) { -- drbd_err(device, "disk failed while waiting for md_io buffer\n"); -- put_ldev(device); -- return -ENODEV; -- } -- -- memset(buffer, 0, sizeof(*buffer)); -- buffer->magic = cpu_to_be32(DRBD_AL_MAGIC); -- buffer->tr_number = cpu_to_be32(device->al_tr_number); -- -- i = 0; -- -- /* Even though no one can start to change this list -- * once we set the LC_LOCKED -- from drbd_al_begin_io(), -- * lc_try_lock_for_transaction() --, someone may still -- * be in the process of changing it. */ -- spin_lock_irq(&device->al_lock); -- list_for_each_entry(e, &device->act_log->to_be_changed, list) { -- if (i == AL_UPDATES_PER_TRANSACTION) { -- i++; -- break; -- } -- buffer->update_slot_nr[i] = cpu_to_be16(e->lc_index); -- buffer->update_extent_nr[i] = cpu_to_be32(e->lc_new_number); -- if (e->lc_number != LC_FREE) -- drbd_bm_mark_for_writeout(device, -- al_extent_to_bm_page(e->lc_number)); -- i++; -- } -- spin_unlock_irq(&device->al_lock); -- BUG_ON(i > AL_UPDATES_PER_TRANSACTION); -- -- buffer->n_updates = cpu_to_be16(i); -- for ( ; i < AL_UPDATES_PER_TRANSACTION; i++) { -- buffer->update_slot_nr[i] = cpu_to_be16(-1); -- buffer->update_extent_nr[i] = cpu_to_be32(LC_FREE); -- } -- -- buffer->context_size = cpu_to_be16(device->act_log->nr_elements); -- buffer->context_start_slot_nr = cpu_to_be16(device->al_tr_cycle); -- -- mx = min_t(int, AL_CONTEXT_PER_TRANSACTION, -- device->act_log->nr_elements - device->al_tr_cycle); -- for (i = 0; i < mx; i++) { -- unsigned idx = device->al_tr_cycle + i; -- extent_nr = lc_element_by_index(device->act_log, idx)->lc_number; -- buffer->context[i] = cpu_to_be32(extent_nr); -- } -- for (; i < AL_CONTEXT_PER_TRANSACTION; i++) -- buffer->context[i] = cpu_to_be32(LC_FREE); -- -- device->al_tr_cycle += AL_CONTEXT_PER_TRANSACTION; -- if (device->al_tr_cycle >= device->act_log->nr_elements) -- device->al_tr_cycle = 0; -- -- sector = al_tr_number_to_on_disk_sector(device); -- -- crc = crc32c(0, buffer, 4096); -- buffer->crc32c = cpu_to_be32(crc); -- -- if (drbd_bm_write_hinted(device)) -- err = -EIO; -- else { -- bool write_al_updates; -- rcu_read_lock(); -- write_al_updates = rcu_dereference(device->ldev->disk_conf)->al_updates; -- rcu_read_unlock(); -- if (write_al_updates) { -- if (drbd_md_sync_page_io(device, device->ldev, sector, WRITE)) { -- err = -EIO; -- drbd_chk_io_error(device, 1, DRBD_META_IO_ERROR); -- } else { -- device->al_tr_number++; -- device->al_writ_cnt++; -- } -- } -- } -- -- drbd_md_put_buffer(device); -- put_ldev(device); -- -- return err; --} -- - static int _try_lc_del(struct drbd_device *device, struct lc_element *al_ext) - { - int rv; -@@ -630,21 +638,24 @@ void drbd_al_shrink(struct drbd_device *device) - wake_up(&device->al_wait); - } - --int drbd_initialize_al(struct drbd_device *device, void *buffer) -+int drbd_al_initialize(struct drbd_device *device, void *buffer) - { - struct al_transaction_on_disk *al = buffer; - struct drbd_md *md = &device->ldev->md; -- sector_t al_base = md->md_offset + md->al_offset; - int al_size_4k = md->al_stripes * md->al_stripe_size_4k; - int i; - -- memset(al, 0, 4096); -- al->magic = cpu_to_be32(DRBD_AL_MAGIC); -- al->transaction_type = cpu_to_be16(AL_TR_INITIALIZED); -- al->crc32c = cpu_to_be32(crc32c(0, al, 4096)); -+ __al_write_transaction(device, al); -+ /* There may or may not have been a pending transaction. */ -+ spin_lock_irq(&device->al_lock); -+ lc_committed(device->act_log); -+ spin_unlock_irq(&device->al_lock); - -- for (i = 0; i < al_size_4k; i++) { -- int err = drbd_md_sync_page_io(device, device->ldev, al_base + i * 8, WRITE); -+ /* The rest of the transactions will have an empty "updates" list, and -+ * are written out only to provide the context, and to initialize the -+ * on-disk ring buffer. */ -+ for (i = 1; i < al_size_4k; i++) { -+ int err = __al_write_transaction(device, al); - if (err) - return err; - } -diff --git a/drbd/drbd_debugfs.c b/drbd/drbd_debugfs.c -index da50b19..df9b4a8 100644 ---- a/drbd/drbd_debugfs.c -+++ b/drbd/drbd_debugfs.c -@@ -429,14 +429,6 @@ static int in_flight_summary_show(struct seq_file *m, void *pos) - #endif - - --/* simple_positive(file->f_path.dentry) respectively debugfs_positive(), -- * but neither is "reachable" from here. -- * So we have our own inline version of it above. :-( */ --static inline int debugfs_positive(struct dentry *dentry) --{ -- return dentry->d_inode && !d_unhashed(dentry); --} -- - /* make sure at *open* time that the respective object won't go away. */ - static int drbd_single_open(struct file *file, int (*show)(struct seq_file *, void *), - void *data, struct kref *kref, -@@ -454,7 +446,7 @@ static int drbd_single_open(struct file *file, int (*show)(struct seq_file *, vo - /* serialize with d_delete() */ - mutex_lock(&parent->d_inode->i_mutex); - /* Make sure the object is still alive */ -- if (debugfs_positive(file->f_dentry) -+ if (simple_positive(file->f_dentry) - && kref_get_unless_zero(kref)) - ret = 0; - mutex_unlock(&parent->d_inode->i_mutex); -diff --git a/drbd/drbd_int.h b/drbd/drbd_int.h -index 08d6648..d1e2bc0 100644 ---- a/drbd/drbd_int.h -+++ b/drbd/drbd_int.h -@@ -36,6 +36,9 @@ - #include - #include - #include -+#include -+#include -+#include - #include - #include - #include -@@ -98,14 +101,10 @@ extern int fault_devs; - - extern char usermode_helper[]; - --#include - #ifndef DRBD_MAJOR - # define DRBD_MAJOR 147 - #endif - --#include --#include -- - /* This is used to stop/restart our threads. - * Cannot use SIGTERM nor SIGKILL, since these - * are sent out by init on runlevel changes -@@ -593,7 +592,6 @@ enum { - - MD_NO_BARRIER, /* meta data device does not support barriers, - so don't even try */ -- SUSPEND_IO, /* suspend application io */ - BITMAP_IO, /* suspend application io; - once no more io in flight, start bitmap io */ - BITMAP_IO_QUEUED, /* Started bitmap IO */ -@@ -986,6 +984,7 @@ struct drbd_device { - atomic_t rs_pending_cnt; /* RS request/data packets on the wire */ - atomic_t unacked_cnt; /* Need to send replies for */ - atomic_t local_cnt; /* Waiting for local completion */ -+ atomic_t suspend_cnt; - - /* Interval tree of pending local write requests */ - struct rb_root read_requests; -@@ -1785,7 +1784,7 @@ extern int __drbd_change_sync(struct drbd_device *device, sector_t sector, int s - #define drbd_rs_failed_io(device, sector, size) \ - __drbd_change_sync(device, sector, size, RECORD_RS_FAILED) - extern void drbd_al_shrink(struct drbd_device *device); --extern int drbd_initialize_al(struct drbd_device *, void *); -+extern int drbd_al_initialize(struct drbd_device *, void *); - - /* drbd_nl.c */ - /* state info broadcast */ -@@ -2376,7 +2375,7 @@ static inline bool may_inc_ap_bio(struct drbd_device *device) - - if (drbd_suspended(device)) - return false; -- if (test_bit(SUSPEND_IO, &device->flags)) -+ if (atomic_read(&device->suspend_cnt)) - return false; - - /* to avoid potential deadlock or bitmap corruption, -diff --git a/drbd/drbd_main.c b/drbd/drbd_main.c -index f41aa8a..31bf43f 100644 ---- a/drbd/drbd_main.c -+++ b/drbd/drbd_main.c -@@ -2435,7 +2435,7 @@ static void drbd_cleanup(void) - * @congested_data: User data - * @bdi_bits: Bits the BDI flusher thread is currently interested in - * -- * Returns 1<connection->flags)) { -- r |= (1 << BDI_async_congested); -+ r |= (1 << WB_async_congested); - /* Without good local data, we would need to read from remote, - * and that would need the worker thread as well, which is - * currently blocked waiting for that usermode helper to - * finish. - */ - if (!get_ldev_if_state(device, D_UP_TO_DATE)) -- r |= (1 << BDI_sync_congested); -+ r |= (1 << WB_sync_congested); - else - put_ldev(device); - r &= bdi_bits; -@@ -2475,9 +2475,9 @@ static int drbd_congested(void *congested_data, int bdi_bits) - reason = 'b'; - } - -- if (bdi_bits & (1 << BDI_async_congested) && -+ if (bdi_bits & (1 << WB_async_congested) && - test_bit(NET_CONGESTED, &first_peer_device(device)->connection->flags)) { -- r |= (1 << BDI_async_congested); -+ r |= (1 << WB_async_congested); - reason = reason == 'b' ? 'a' : 'n'; - } - -@@ -3601,7 +3601,12 @@ static int w_bitmap_io(struct drbd_work *w, int unused) - struct bm_io_work *work = &device->bm_io_work; - int rv = -EIO; - -- D_ASSERT(device, atomic_read(&device->ap_bio_cnt) == 0); -+ if (work->flags != BM_LOCKED_CHANGE_ALLOWED) { -+ int cnt = atomic_read(&device->ap_bio_cnt); -+ if (cnt) -+ drbd_err(device, "FIXME: ap_bio_cnt %d, expected 0; queued for '%s'\n", -+ cnt, work->why); -+ } - - if (get_ldev(device)) { - drbd_bm_lock(device, work->why, work->flags); -@@ -3659,7 +3664,9 @@ void drbd_queue_bitmap_io(struct drbd_device *device, - - spin_lock_irq(&device->resource->req_lock); - set_bit(BITMAP_IO, &device->flags); -- if (atomic_read(&device->ap_bio_cnt) == 0) { -+ /* don't wait for pending application IO if the caller indicates that -+ * application IO does not conflict anyways. */ -+ if (flags == BM_LOCKED_CHANGE_ALLOWED || atomic_read(&device->ap_bio_cnt) == 0) { - if (!test_and_set_bit(BITMAP_IO_QUEUED, &device->flags)) - drbd_queue_work(&first_peer_device(device)->connection->sender_work, - &device->bm_io_work.w); -@@ -3679,18 +3686,20 @@ void drbd_queue_bitmap_io(struct drbd_device *device, - int drbd_bitmap_io(struct drbd_device *device, int (*io_fn)(struct drbd_device *), - char *why, enum bm_flag flags) - { -+ /* Only suspend io, if some operation is supposed to be locked out */ -+ const bool do_suspend_io = flags & (BM_DONT_CLEAR|BM_DONT_SET|BM_DONT_TEST); - int rv; - - D_ASSERT(device, current != first_peer_device(device)->connection->worker.task); - -- if ((flags & BM_LOCKED_SET_ALLOWED) == 0) -+ if (do_suspend_io) - drbd_suspend_io(device); - - drbd_bm_lock(device, why, flags); - rv = io_fn(device); - drbd_bm_unlock(device); - -- if ((flags & BM_LOCKED_SET_ALLOWED) == 0) -+ if (do_suspend_io) - drbd_resume_io(device); - - return rv; -diff --git a/drbd/drbd_nl.c b/drbd/drbd_nl.c -index 9c14cf3..bb7e1b0 100644 ---- a/drbd/drbd_nl.c -+++ b/drbd/drbd_nl.c -@@ -903,9 +903,11 @@ char *ppsize(char *buf, unsigned long long size) - * and can be long lived. - * This changes an device->flag, is triggered by drbd internals, - * and should be short-lived. */ -+/* It needs to be a counter, since multiple threads might -+ independently suspend and resume IO. */ - void drbd_suspend_io(struct drbd_device *device) - { -- set_bit(SUSPEND_IO, &device->flags); -+ atomic_inc(&device->suspend_cnt); - if (drbd_suspended(device)) - return; - wait_event(device->misc_wait, !atomic_read(&device->ap_bio_cnt)); -@@ -913,8 +915,8 @@ void drbd_suspend_io(struct drbd_device *device) - - void drbd_resume_io(struct drbd_device *device) - { -- clear_bit(SUSPEND_IO, &device->flags); -- wake_up(&device->misc_wait); -+ if (atomic_dec_and_test(&device->suspend_cnt)) -+ wake_up(&device->misc_wait); - } - - /** -@@ -927,27 +929,32 @@ void drbd_resume_io(struct drbd_device *device) - enum determine_dev_size - drbd_determine_dev_size(struct drbd_device *device, enum dds_flags flags, struct resize_parms *rs) __must_hold(local) - { -- sector_t prev_first_sect, prev_size; /* previous meta location */ -- sector_t la_size_sect, u_size; -+ struct md_offsets_and_sizes { -+ u64 last_agreed_sect; -+ u64 md_offset; -+ s32 al_offset; -+ s32 bm_offset; -+ u32 md_size_sect; -+ -+ u32 al_stripes; -+ u32 al_stripe_size_4k; -+ } prev; -+ sector_t u_size, size; - struct drbd_md *md = &device->ldev->md; -- u32 prev_al_stripe_size_4k; -- u32 prev_al_stripes; -- sector_t size; - char ppb[10]; - void *buffer; - - int md_moved, la_size_changed; - enum determine_dev_size rv = DS_UNCHANGED; - -- /* race: -- * application request passes inc_ap_bio, -- * but then cannot get an AL-reference. -- * this function later may wait on ap_bio_cnt == 0. -> deadlock. -+ /* We may change the on-disk offsets of our meta data below. Lock out -+ * anything that may cause meta data IO, to avoid acting on incomplete -+ * layout changes or scribbling over meta data that is in the process -+ * of being moved. - * -- * to avoid that: -- * Suspend IO right here. -- * still lock the act_log to not trigger ASSERTs there. -- */ -+ * Move is not exactly correct, btw, currently we have all our meta -+ * data in core memory, to "move" it we just write it all out, there -+ * are no reads. */ - drbd_suspend_io(device); - buffer = drbd_md_get_buffer(device, __func__); /* Lock meta-data IO */ - if (!buffer) { -@@ -955,19 +962,17 @@ drbd_determine_dev_size(struct drbd_device *device, enum dds_flags flags, struct - return DS_ERROR; - } - -- /* no wait necessary anymore, actually we could assert that */ -- wait_event(device->al_wait, lc_try_lock(device->act_log)); -- -- prev_first_sect = drbd_md_first_sector(device->ldev); -- prev_size = device->ldev->md.md_size_sect; -- la_size_sect = device->ldev->md.la_size_sect; -+ /* remember current offset and sizes */ -+ prev.last_agreed_sect = md->la_size_sect; -+ prev.md_offset = md->md_offset; -+ prev.al_offset = md->al_offset; -+ prev.bm_offset = md->bm_offset; -+ prev.md_size_sect = md->md_size_sect; -+ prev.al_stripes = md->al_stripes; -+ prev.al_stripe_size_4k = md->al_stripe_size_4k; - - if (rs) { - /* rs is non NULL if we should change the AL layout only */ -- -- prev_al_stripes = md->al_stripes; -- prev_al_stripe_size_4k = md->al_stripe_size_4k; -- - md->al_stripes = rs->al_stripes; - md->al_stripe_size_4k = rs->al_stripe_size / 4; - md->al_size_4k = (u64)rs->al_stripes * rs->al_stripe_size / 4; -@@ -980,7 +985,7 @@ drbd_determine_dev_size(struct drbd_device *device, enum dds_flags flags, struct - rcu_read_unlock(); - size = drbd_new_dev_size(device, device->ldev, u_size, flags & DDSF_FORCED); - -- if (size < la_size_sect) { -+ if (size < prev.last_agreed_sect) { - if (rs && u_size == 0) { - /* Remove "rs &&" later. This check should always be active, but - right now the receiver expects the permissive behavior */ -@@ -1001,30 +1006,29 @@ drbd_determine_dev_size(struct drbd_device *device, enum dds_flags flags, struct - err = drbd_bm_resize(device, size, !(flags & DDSF_NO_RESYNC)); - if (unlikely(err)) { - /* currently there is only one error: ENOMEM! */ -- size = drbd_bm_capacity(device)>>1; -+ size = drbd_bm_capacity(device); - if (size == 0) { - drbd_err(device, "OUT OF MEMORY! " - "Could not allocate bitmap!\n"); - } else { - drbd_err(device, "BM resizing failed. " -- "Leaving size unchanged at size = %lu KB\n", -- (unsigned long)size); -+ "Leaving size unchanged\n"); - } - rv = DS_ERROR; - } - /* racy, see comments above. */ - drbd_set_my_capacity(device, size); -- device->ldev->md.la_size_sect = size; -+ md->la_size_sect = size; - drbd_info(device, "size = %s (%llu KB)\n", ppsize(ppb, size>>1), - (unsigned long long)size>>1); - } - if (rv <= DS_ERROR) - goto err_out; - -- la_size_changed = (la_size_sect != device->ldev->md.la_size_sect); -+ la_size_changed = (prev.last_agreed_sect != md->la_size_sect); - -- md_moved = prev_first_sect != drbd_md_first_sector(device->ldev) -- || prev_size != device->ldev->md.md_size_sect; -+ md_moved = prev.md_offset != md->md_offset -+ || prev.md_size_sect != md->md_size_sect; - - if (la_size_changed || md_moved || rs) { - u32 prev_flags; -@@ -1033,20 +1037,29 @@ drbd_determine_dev_size(struct drbd_device *device, enum dds_flags flags, struct - * Clear the timer, to avoid scary "timer expired!" messages, - * "Superblock" is written out at least twice below, anyways. */ - del_timer(&device->md_sync_timer); -- drbd_al_shrink(device); /* All extents inactive. */ - -+ /* We won't change the "al-extents" setting, we just may need -+ * to move the on-disk location of the activity log ringbuffer. -+ * Lock for transaction is good enough, it may well be "dirty" -+ * or even "starving". */ -+ wait_event(device->al_wait, lc_try_lock_for_transaction(device->act_log)); -+ -+ /* mark current on-disk bitmap and activity log as unreliable */ - prev_flags = md->flags; -- md->flags &= ~MDF_PRIMARY_IND; -+ md->flags |= MDF_FULL_SYNC | MDF_AL_DISABLED; - drbd_md_write(device, buffer); - -+ drbd_al_initialize(device, buffer); -+ - drbd_info(device, "Writing the whole bitmap, %s\n", - la_size_changed && md_moved ? "size changed and md moved" : - la_size_changed ? "size changed" : "md moved"); - /* next line implicitly does drbd_suspend_io()+drbd_resume_io() */ - drbd_bitmap_io(device, md_moved ? &drbd_bm_write_all : &drbd_bm_write, - "size changed", BM_LOCKED_MASK); -- drbd_initialize_al(device, buffer); - -+ /* on-disk bitmap and activity log is authoritative again -+ * (unless there was an IO error meanwhile...) */ - md->flags = prev_flags; - drbd_md_write(device, buffer); - -@@ -1055,20 +1068,22 @@ drbd_determine_dev_size(struct drbd_device *device, enum dds_flags flags, struct - md->al_stripes, md->al_stripe_size_4k * 4); - } - -- if (size > la_size_sect) -- rv = la_size_sect ? DS_GREW : DS_GREW_FROM_ZERO; -- if (size < la_size_sect) -+ if (size > prev.last_agreed_sect) -+ rv = prev.last_agreed_sect ? DS_GREW : DS_GREW_FROM_ZERO; -+ if (size < prev.last_agreed_sect) - rv = DS_SHRUNK; - - if (0) { - err_out: -- if (rs) { -- md->al_stripes = prev_al_stripes; -- md->al_stripe_size_4k = prev_al_stripe_size_4k; -- md->al_size_4k = (u64)prev_al_stripes * prev_al_stripe_size_4k; -- -- drbd_md_set_sector_offsets(device, device->ldev); -- } -+ /* restore previous offset and sizes */ -+ md->la_size_sect = prev.last_agreed_sect; -+ md->md_offset = prev.md_offset; -+ md->al_offset = prev.al_offset; -+ md->bm_offset = prev.bm_offset; -+ md->md_size_sect = prev.md_size_sect; -+ md->al_stripes = prev.al_stripes; -+ md->al_stripe_size_4k = prev.al_stripe_size_4k; -+ md->al_size_4k = (u64)prev.al_stripes * prev.al_stripe_size_4k; - } - lc_unlock(device->act_log); - wake_up(&device->al_wait); -@@ -2764,6 +2779,7 @@ int drbd_adm_resize(struct sk_buff *skb, struct genl_info *info) - mutex_unlock(&device->resource->conf_update); - synchronize_rcu(); - kfree(old_disk_conf); -+ new_disk_conf = NULL; - } - - ddsf = (rs.resize_force ? DDSF_FORCED : 0) | (rs.no_resync ? DDSF_NO_RESYNC : 0); -@@ -2797,6 +2813,7 @@ int drbd_adm_resize(struct sk_buff *skb, struct genl_info *info) - - fail_ldev: - put_ldev(device); -+ kfree(new_disk_conf); - goto fail; - } - -@@ -3216,8 +3233,8 @@ static void device_to_statistics(struct device_statistics *s, - q = bdev_get_queue(device->ldev->backing_bdev); - s->dev_lower_blocked = - bdi_congested(&q->backing_dev_info, -- (1 << BDI_async_congested) | -- (1 << BDI_sync_congested)); -+ (1 << WB_async_congested) | -+ (1 << WB_sync_congested)); - put_ldev(device); - } - s->dev_size = drbd_get_capacity(device->this_bdev); -diff --git a/drbd/drbd_receiver.c b/drbd/drbd_receiver.c -index 5e6b149..06e5667 100644 ---- a/drbd/drbd_receiver.c -+++ b/drbd/drbd_receiver.c -@@ -673,7 +673,7 @@ static struct socket *drbd_try_connect(struct drbd_connection *connection, int u - ((struct sockaddr_in *)&src_in6)->sin_port = 0; /* AF_INET & AF_SCI */ - - what = "sock_create_kern_in_try_connect"; -- err = sock_create_kern(((struct sockaddr *)&src_in6)->sa_family, -+ err = sock_create_kern(&init_net, ((struct sockaddr *)&src_in6)->sa_family, - SOCK_STREAM, IPPROTO_TCP, &sock); - if (err < 0) { - sock = NULL; -@@ -767,7 +767,7 @@ static struct socket *create_listen_socket(struct drbd_connection *connection, - rcu_read_unlock(); - - what = "sock_create_kern"; -- err = sock_create_kern(addr->sa_family, SOCK_STREAM, IPPROTO_TCP, &s_listen); -+ err = sock_create_kern(&init_net, addr->sa_family, SOCK_STREAM, IPPROTO_TCP, &s_listen); - if (err) { - s_listen = NULL; - goto out; -@@ -5173,9 +5173,11 @@ static int drbd_disconnected(struct drbd_peer_device *peer_device) - - drbd_md_sync(device); - -- /* serialize with bitmap writeout triggered by the state change, -- * if any. */ -- wait_event(device->misc_wait, !test_bit(BITMAP_IO, &device->flags)); -+ if (get_ldev(device)) { -+ drbd_bitmap_io(device, &drbd_bm_write_copy_pages, -+ "write from disconnected", BM_LOCKED_CHANGE_ALLOWED); -+ put_ldev(device); -+ } - - /* tcp_close and release of sendpage pages can be deferred. I don't - * want to use SO_LINGER, because apparently it can be deferred for -diff --git a/drbd/drbd_req.c b/drbd/drbd_req.c -index 38fe40d..305fe71 100644 ---- a/drbd/drbd_req.c -+++ b/drbd/drbd_req.c -@@ -31,73 +31,41 @@ - #include "drbd_req.h" - - --/* We only support diskstats for 2.6.16 and up. -- * see also commit commit a362357b6cd62643d4dda3b152639303d78473da -- * Author: Jens Axboe -- * Date: Tue Nov 1 09:26:16 2005 +0100 -- * [BLOCK] Unify the separate read/write io stat fields into arrays */ --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) --#define _drbd_start_io_acct(...) do {} while (0) --#define _drbd_end_io_acct(...) do {} while (0) --#else - - static bool drbd_may_do_local_read(struct drbd_device *device, sector_t sector, int size); - -+#ifndef __disk_stat_inc - /* Update disk stats at start of I/O request */ - static void _drbd_start_io_acct(struct drbd_device *device, struct drbd_request *req) - { -- const int rw = bio_data_dir(req->master_bio); --#ifndef __disk_stat_inc -- int cpu; --#endif -- --#ifndef COMPAT_HAVE_ATOMIC_IN_FLIGHT -- spin_lock_irq(&device->resource->req_lock); --#endif -- --#ifdef __disk_stat_inc -- __disk_stat_inc(device->vdisk, ios[rw]); -- __disk_stat_add(device->vdisk, sectors[rw], req->i.size >> 9); -- disk_round_stats(device->vdisk); -- device->vdisk->in_flight++; --#else -- cpu = part_stat_lock(); -- part_round_stats(cpu, &device->vdisk->part0); -- part_stat_inc(cpu, &device->vdisk->part0, ios[rw]); -- part_stat_add(cpu, &device->vdisk->part0, sectors[rw], req->i.size >> 9); -- (void) cpu; /* The macro invocations above want the cpu argument, I do not like -- the compiler warning about cpu only assigned but never used... */ -- part_inc_in_flight(&device->vdisk->part0, rw); -- part_stat_unlock(); --#endif -- --#ifndef COMPAT_HAVE_ATOMIC_IN_FLIGHT -- spin_unlock_irq(&device->resource->req_lock); --#endif -+ generic_start_io_acct(bio_data_dir(req->master_bio), req->i.size >> 9, -+ &device->vdisk->part0); - } - - /* Update disk stats when completing request upwards */ - static void _drbd_end_io_acct(struct drbd_device *device, struct drbd_request *req) - { -- int rw = bio_data_dir(req->master_bio); -+ generic_end_io_acct(bio_data_dir(req->master_bio), -+ &device->vdisk->part0, req->start_jif); -+} -+#else -+static void _drbd_start_io_acct(struct drbd_device *device, struct drbd_request *req) -+{ -+ const int rw = bio_data_dir(req->master_bio); -+ BUILD_BUG_ON(sizeof(atomic_t) != sizeof(device->vdisk->in_flight)); -+ disk_stat_inc(device->vdisk, ios[rw]); -+ disk_stat_add(device->vdisk, sectors[rw], req->i.size >> 9); -+ disk_round_stats(device->vdisk); -+ atomic_inc((atomic_t*)&device->vdisk->in_flight); -+} -+static void _drbd_end_io_acct(struct drbd_device *device, struct drbd_request *req) -+{ -+ const int rw = bio_data_dir(req->master_bio); - unsigned long duration = jiffies - req->start_jif; --#ifndef __disk_stat_inc -- int cpu; --#endif -- --#ifdef __disk_stat_add -- __disk_stat_add(device->vdisk, ticks[rw], duration); -+ disk_stat_add(device->vdisk, ticks[rw], duration); - disk_round_stats(device->vdisk); -- device->vdisk->in_flight--; --#else -- cpu = part_stat_lock(); -- part_stat_add(cpu, &device->vdisk->part0, ticks[rw], duration); -- part_round_stats(cpu, &device->vdisk->part0); -- part_dec_in_flight(&device->vdisk->part0, rw); -- part_stat_unlock(); --#endif -+ atomic_dec((atomic_t*)&device->vdisk->in_flight); - } -- - #endif - - static struct drbd_request *drbd_req_new(struct drbd_device *device, -@@ -509,7 +477,7 @@ static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m, - atomic_add(req->i.size >> 9, &device->ap_in_flight); - set_if_null_req_not_net_done(peer_device, req); - } -- if (s & RQ_NET_PENDING) -+ if (req->rq_state & RQ_NET_PENDING) - set_if_null_req_ack_pending(peer_device, req); - } - -@@ -1028,16 +996,20 @@ static void complete_conflicting_writes(struct drbd_request *req) - sector_t sector = req->i.sector; - int size = req->i.size; - -- i = drbd_find_overlap(&device->write_requests, sector, size); -- if (!i) -- return; -- - for (;;) { -- prepare_to_wait(&device->misc_wait, &wait, TASK_UNINTERRUPTIBLE); -- i = drbd_find_overlap(&device->write_requests, sector, size); -- if (!i) -+ drbd_for_each_overlap(i, &device->write_requests, sector, size) { -+ /* Ignore, if already completed to upper layers. */ -+ if (i->completed) -+ continue; -+ /* Handle the first found overlap. After the schedule -+ * we have to restart the tree walk. */ - break; -+ } -+ if (!i) /* if any */ -+ break; -+ - /* Indicate to wake up device->misc_wait on progress. */ -+ prepare_to_wait(&device->misc_wait, &wait, TASK_UNINTERRUPTIBLE); - i->waiting = true; - spin_unlock_irq(&device->resource->req_lock); - schedule(); -diff --git a/drbd/drbd_state.c b/drbd/drbd_state.c -index a64cf22..4cf2c93 100644 ---- a/drbd/drbd_state.c -+++ b/drbd/drbd_state.c -@@ -1490,7 +1490,7 @@ int drbd_bitmap_io_from_worker(struct drbd_device *device, - D_ASSERT(device, current == first_peer_device(device)->connection->worker.task); - - /* open coded non-blocking drbd_suspend_io(device); */ -- set_bit(SUSPEND_IO, &device->flags); -+ atomic_inc(&device->suspend_cnt); - - drbd_bm_lock(device, why, flags); - rv = io_fn(device); -@@ -1940,12 +1940,17 @@ static void after_state_ch(struct drbd_device *device, union drbd_state os, - - /* This triggers bitmap writeout of potentially still unwritten pages - * if the resync finished cleanly, or aborted because of peer disk -- * failure, or because of connection loss. -+ * failure, or on transition from resync back to AHEAD/BEHIND. -+ * -+ * Connection loss is handled in drbd_disconnected() by the receiver. -+ * - * For resync aborted because of local disk failure, we cannot do - * any bitmap writeout anymore. -+ * - * No harm done if some bits change during this phase. - */ -- if (os.conn > C_CONNECTED && ns.conn <= C_CONNECTED && get_ldev(device)) { -+ if ((os.conn > C_CONNECTED && os.conn < C_AHEAD) && -+ (ns.conn == C_CONNECTED || ns.conn >= C_AHEAD) && get_ldev(device)) { - drbd_queue_bitmap_io(device, &drbd_bm_write_copy_pages, NULL, - "write from resync_finished", BM_LOCKED_CHANGE_ALLOWED); - put_ldev(device); -diff --git a/drbd/drbd_wrappers.h b/drbd/drbd_wrappers.h -index ea2a1fe..d7a4138 100644 ---- a/drbd/drbd_wrappers.h -+++ b/drbd/drbd_wrappers.h -@@ -1421,4 +1421,57 @@ do { \ - } while (0) - #endif - -+#ifndef COMPAT_HAVE_GENERIC_START_IO_ACCT -+#ifndef __disk_stat_inc -+static inline void generic_start_io_acct(int rw, unsigned long sectors, -+ struct hd_struct *part) -+{ -+ int cpu; -+ BUILD_BUG_ON(sizeof(atomic_t) != sizeof(part->in_flight[0])); -+ -+ cpu = part_stat_lock(); -+ part_round_stats(cpu, part); -+ part_stat_inc(cpu, part, ios[rw]); -+ part_stat_add(cpu, part, sectors[rw], sectors); -+ (void) cpu; /* The macro invocations above want the cpu argument, I do not like -+ the compiler warning about cpu only assigned but never used... */ -+ /* part_inc_in_flight(part, rw); */ -+ atomic_inc((atomic_t*)&part->in_flight[rw]); -+ part_stat_unlock(); -+} -+ -+static inline void generic_end_io_acct(int rw, struct hd_struct *part, -+ unsigned long start_time) -+{ -+ unsigned long duration = jiffies - start_time; -+ int cpu; -+ -+ cpu = part_stat_lock(); -+ part_stat_add(cpu, part, ticks[rw], duration); -+ part_round_stats(cpu, part); -+ /* part_dec_in_flight(part, rw); */ -+ atomic_dec((atomic_t*)&part->in_flight[rw]); -+ part_stat_unlock(); -+} -+#endif /* __disk_stat_inc */ -+#endif /* COMPAT_HAVE_GENERIC_START_IO_ACCT */ -+ -+ -+#ifndef COMPAT_SOCK_CREATE_KERN_HAS_FIVE_PARAMETERS -+#define sock_create_kern(N,F,T,P,S) sock_create_kern(F,T,P,S) -+#endif -+ -+#ifndef COMPAT_HAVE_WB_CONGESTED_ENUM -+#define WB_async_congested BDI_async_congested -+#define WB_sync_congested BDI_sync_congested -+#endif -+ -+#ifndef COMPAT_HAVE_SIMPLE_POSITIVE -+#include -+static inline int simple_positive(struct dentry *dentry) -+{ -+ return dentry->d_inode && !d_unhashed(dentry); -+} -+#endif -+ - #endif -diff --git a/drbd/linux/lru_cache.h b/drbd/linux/lru_cache.h -index 98e231c..a1347c5 100644 ---- a/drbd/linux/lru_cache.h -+++ b/drbd/linux/lru_cache.h -@@ -300,7 +300,7 @@ extern unsigned int lc_put(struct lru_cache *lc, struct lc_element *e); - extern void lc_committed(struct lru_cache *lc); - - struct seq_file; --extern size_t lc_seq_printf_stats(struct seq_file *seq, struct lru_cache *lc); -+extern void lc_seq_printf_stats(struct seq_file *seq, struct lru_cache *lc); - - extern void lc_seq_dump_details(struct seq_file *seq, struct lru_cache *lc, char *utext, - void (*detail) (struct seq_file *, struct lc_element *)); -diff --git a/drbd/lru_cache.c b/drbd/lru_cache.c -index 76308df..038c986 100644 ---- a/drbd/lru_cache.c -+++ b/drbd/lru_cache.c -@@ -233,7 +233,7 @@ void lc_reset(struct lru_cache *lc) - * @seq: the seq_file to print into - * @lc: the lru cache to print statistics of - */ --size_t lc_seq_printf_stats(struct seq_file *seq, struct lru_cache *lc) -+void lc_seq_printf_stats(struct seq_file *seq, struct lru_cache *lc) - { - /* NOTE: - * total calls to lc_get are -@@ -242,10 +242,9 @@ size_t lc_seq_printf_stats(struct seq_file *seq, struct lru_cache *lc) - * progress) and "changed", when this in fact lead to an successful - * update of the cache. - */ -- return seq_printf(seq, "\t%s: used:%u/%u " -- "hits:%lu misses:%lu starving:%lu locked:%lu changed:%lu\n", -- lc->name, lc->used, lc->nr_elements, -- lc->hits, lc->misses, lc->starving, lc->locked, lc->changed); -+ seq_printf(seq, "\t%s: used:%u/%u hits:%lu misses:%lu starving:%lu locked:%lu changed:%lu\n", -+ lc->name, lc->used, lc->nr_elements, -+ lc->hits, lc->misses, lc->starving, lc->locked, lc->changed); - } - - static struct hlist_head *lc_hash_slot(struct lru_cache *lc, unsigned int enr) -diff --git a/preamble b/preamble -index 603c8ca..a230a24 100644 ---- a/preamble -+++ b/preamble -@@ -1,5 +1,5 @@ - # always require a suitable userland --Requires: drbd-utils = 8.4.5 -+Requires: drbd-utils >= 8.9.2 - - %if %{defined suse_kernel_module_package} - %if 0%{?sles_version} == 10