diff options
author | Andreas Gruenbacher <agruen@linbit.com> | 2011-02-21 20:15:32 -0500 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2011-10-14 10:47:51 -0400 |
commit | 7be8da0798f08fb9564d4f64fe4a7d6fb4fab20b (patch) | |
tree | cdcc85b5152562bd40065cecec7f571098851881 /drivers/block/drbd/drbd_int.h | |
parent | 71b1c1eb9c544141e743c4d14b3c576fd4c31a5a (diff) |
drbd: Improve how conflicting writes are handled
The previous algorithm for dealing with overlapping concurrent writes
was generating unnecessary warnings for scenarios which could be
legitimate, and did not always handle partially overlapping requests
correctly. Improve it algorithm as follows:
* While local or remote write requests are in progress, conflicting new
local write requests will be delayed (commit 82172f7).
* When a conflict between a local and remote write request is detected,
the node with the discard flag decides how to resolve the conflict: It
will ask its peer to discard conflicting requests which are fully
contained in the local request and retry requests which overlap only
partially. This involves a protocol change.
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block/drbd/drbd_int.h')
-rw-r--r-- | drivers/block/drbd/drbd_int.h | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 3213808a898a..17e905d0582d 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h | |||
@@ -200,7 +200,7 @@ enum drbd_packet { | |||
200 | P_RECV_ACK = 0x15, /* Used in protocol B */ | 200 | P_RECV_ACK = 0x15, /* Used in protocol B */ |
201 | P_WRITE_ACK = 0x16, /* Used in protocol C */ | 201 | P_WRITE_ACK = 0x16, /* Used in protocol C */ |
202 | P_RS_WRITE_ACK = 0x17, /* Is a P_WRITE_ACK, additionally call set_in_sync(). */ | 202 | P_RS_WRITE_ACK = 0x17, /* Is a P_WRITE_ACK, additionally call set_in_sync(). */ |
203 | P_DISCARD_ACK = 0x18, /* Used in proto C, two-primaries conflict detection */ | 203 | P_DISCARD_WRITE = 0x18, /* Used in proto C, two-primaries conflict detection */ |
204 | P_NEG_ACK = 0x19, /* Sent if local disk is unusable */ | 204 | P_NEG_ACK = 0x19, /* Sent if local disk is unusable */ |
205 | P_NEG_DREPLY = 0x1a, /* Local disk is broken... */ | 205 | P_NEG_DREPLY = 0x1a, /* Local disk is broken... */ |
206 | P_NEG_RS_DREPLY = 0x1b, /* Local disk is broken... */ | 206 | P_NEG_RS_DREPLY = 0x1b, /* Local disk is broken... */ |
@@ -223,8 +223,9 @@ enum drbd_packet { | |||
223 | P_RS_CANCEL = 0x29, /* meta: Used to cancel RS_DATA_REQUEST packet by SyncSource */ | 223 | P_RS_CANCEL = 0x29, /* meta: Used to cancel RS_DATA_REQUEST packet by SyncSource */ |
224 | P_CONN_ST_CHG_REQ = 0x2a, /* data sock: Connection wide state request */ | 224 | P_CONN_ST_CHG_REQ = 0x2a, /* data sock: Connection wide state request */ |
225 | P_CONN_ST_CHG_REPLY = 0x2b, /* meta sock: Connection side state req reply */ | 225 | P_CONN_ST_CHG_REPLY = 0x2b, /* meta sock: Connection side state req reply */ |
226 | P_RETRY_WRITE = 0x2c, /* Protocol C: retry conflicting write request */ | ||
226 | 227 | ||
227 | P_MAX_CMD = 0x2c, | 228 | P_MAX_CMD = 0x2d, |
228 | P_MAY_IGNORE = 0x100, /* Flag to test if (cmd > P_MAY_IGNORE) ... */ | 229 | P_MAY_IGNORE = 0x100, /* Flag to test if (cmd > P_MAY_IGNORE) ... */ |
229 | P_MAX_OPT_CMD = 0x101, | 230 | P_MAX_OPT_CMD = 0x101, |
230 | 231 | ||
@@ -350,7 +351,7 @@ struct p_data { | |||
350 | * commands which share a struct: | 351 | * commands which share a struct: |
351 | * p_block_ack: | 352 | * p_block_ack: |
352 | * P_RECV_ACK (proto B), P_WRITE_ACK (proto C), | 353 | * P_RECV_ACK (proto B), P_WRITE_ACK (proto C), |
353 | * P_DISCARD_ACK (proto C, two-primaries conflict detection) | 354 | * P_DISCARD_WRITE (proto C, two-primaries conflict detection) |
354 | * p_block_req: | 355 | * p_block_req: |
355 | * P_DATA_REQUEST, P_RS_DATA_REQUEST | 356 | * P_DATA_REQUEST, P_RS_DATA_REQUEST |
356 | */ | 357 | */ |
@@ -362,7 +363,6 @@ struct p_block_ack { | |||
362 | u32 seq_num; | 363 | u32 seq_num; |
363 | } __packed; | 364 | } __packed; |
364 | 365 | ||
365 | |||
366 | struct p_block_req { | 366 | struct p_block_req { |
367 | struct p_header head; | 367 | struct p_header head; |
368 | u64 sector; | 368 | u64 sector; |
@@ -655,6 +655,8 @@ struct drbd_work { | |||
655 | 655 | ||
656 | #include "drbd_interval.h" | 656 | #include "drbd_interval.h" |
657 | 657 | ||
658 | extern int drbd_wait_misc(struct drbd_conf *, struct drbd_interval *); | ||
659 | |||
658 | struct drbd_request { | 660 | struct drbd_request { |
659 | struct drbd_work w; | 661 | struct drbd_work w; |
660 | 662 | ||
@@ -752,12 +754,16 @@ enum { | |||
752 | 754 | ||
753 | /* This ee has a pointer to a digest instead of a block id */ | 755 | /* This ee has a pointer to a digest instead of a block id */ |
754 | __EE_HAS_DIGEST, | 756 | __EE_HAS_DIGEST, |
757 | |||
758 | /* Conflicting local requests need to be restarted after this request */ | ||
759 | __EE_RESTART_REQUESTS, | ||
755 | }; | 760 | }; |
756 | #define EE_CALL_AL_COMPLETE_IO (1<<__EE_CALL_AL_COMPLETE_IO) | 761 | #define EE_CALL_AL_COMPLETE_IO (1<<__EE_CALL_AL_COMPLETE_IO) |
757 | #define EE_MAY_SET_IN_SYNC (1<<__EE_MAY_SET_IN_SYNC) | 762 | #define EE_MAY_SET_IN_SYNC (1<<__EE_MAY_SET_IN_SYNC) |
758 | #define EE_RESUBMITTED (1<<__EE_RESUBMITTED) | 763 | #define EE_RESUBMITTED (1<<__EE_RESUBMITTED) |
759 | #define EE_WAS_ERROR (1<<__EE_WAS_ERROR) | 764 | #define EE_WAS_ERROR (1<<__EE_WAS_ERROR) |
760 | #define EE_HAS_DIGEST (1<<__EE_HAS_DIGEST) | 765 | #define EE_HAS_DIGEST (1<<__EE_HAS_DIGEST) |
766 | #define EE_RESTART_REQUESTS (1<<__EE_RESTART_REQUESTS) | ||
761 | 767 | ||
762 | /* flag bits per mdev */ | 768 | /* flag bits per mdev */ |
763 | enum { | 769 | enum { |
@@ -1478,6 +1484,7 @@ extern void drbd_free_tconn(struct drbd_tconn *tconn); | |||
1478 | extern int proc_details; | 1484 | extern int proc_details; |
1479 | 1485 | ||
1480 | /* drbd_req */ | 1486 | /* drbd_req */ |
1487 | extern int __drbd_make_request(struct drbd_conf *, struct bio *, unsigned long); | ||
1481 | extern int drbd_make_request(struct request_queue *q, struct bio *bio); | 1488 | extern int drbd_make_request(struct request_queue *q, struct bio *bio); |
1482 | extern int drbd_read_remote(struct drbd_conf *mdev, struct drbd_request *req); | 1489 | extern int drbd_read_remote(struct drbd_conf *mdev, struct drbd_request *req); |
1483 | extern int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct bio_vec *bvec); | 1490 | extern int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct bio_vec *bvec); |