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
This commit is contained in:
parent
6a9bae1c9e
commit
f9dc362b8e
@ -1,529 +0,0 @@
|
||||
From e15ba3799caf4cdcdf151078efe01e9a3f3ab206 Mon Sep 17 00:00:00 2001
|
||||
From: Nick Wang <nwang@suse.com>
|
||||
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 <linux/scatterlist.h>
|
||||
|
||||
-#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
|
||||
|
@ -1 +1,2 @@
|
||||
updates/drbd.ko
|
||||
updates/drbd_transport_tcp.ko
|
||||
|
24
_service
Normal file
24
_service
Normal file
@ -0,0 +1,24 @@
|
||||
<services>
|
||||
<service name="tar_scm">
|
||||
<param name="url">git://git.linbit.com/drbd-9.0.git</param>
|
||||
<param name="scm">git</param>
|
||||
<param name="filename">drbd</param>
|
||||
<!--
|
||||
To update to a new release, change "revision" to the desired
|
||||
git commit hash and bump "version" if necessary
|
||||
|
||||
<param name="version">9.0.1</param>
|
||||
-->
|
||||
<param name="versionformat">9.0.1+git.%h</param>
|
||||
<param name="revision">86e443973082570aeb651848db89e0c7b995c306</param>
|
||||
</service>
|
||||
|
||||
<service name="recompress">
|
||||
<param name="file">*drbd*.tar</param>
|
||||
<param name="compression">bz2</param>
|
||||
</service>
|
||||
|
||||
<service name="set_version">
|
||||
<param name="basename">drbd</param>
|
||||
</service>
|
||||
</services>
|
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:35e160ffffed266f54e50db947cf103a544261b7a416cb1b55aa346ea04bf90b
|
||||
size 282912
|
113
_service:set_version:drbd.spec
Normal file
113
_service:set_version:drbd.spec
Normal file
@ -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
|
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c10c4d7a5389a9194eb2f7c094a3c1685b87f52513ae0af15fdc1df6a091d014
|
||||
size 321974
|
@ -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 $@
|
21
drbd.changes
21
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
|
||||
|
59
drbd.spec
59
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
|
||||
make -C %{kernel_source $flavor} modules_install M=$PWD/$flavor
|
||||
done
|
||||
|
||||
mkdir -p %{buildroot}/%{_sbindir}
|
||||
|
1
drbd_git_revision
Normal file
1
drbd_git_revision
Normal file
@ -0,0 +1 @@
|
||||
GIT-hash: 86e443973082570aeb651848db89e0c7b995c306
|
35
kernel-4.5-compat.patch
Normal file
35
kernel-4.5-compat.patch
Normal file
@ -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 <rdma/ib_verbs.h>
|
||||
-
|
||||
-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)
|
@ -1,391 +0,0 @@
|
||||
From 641de14e15547788055e15b1db4601a436f048bb Mon Sep 17 00:00:00 2001
|
||||
From: Nick Wang <nwang@suse.com>
|
||||
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
|
||||
|
1
preamble
1
preamble
@ -1,3 +1,4 @@
|
||||
Requires: kernel-%1
|
||||
Supplements: packageand(kernel-%1:%name)
|
||||
Recommends: drbd
|
||||
Recommends: drbd-utils
|
||||
|
@ -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;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user