diff options
-rw-r--r-- | drivers/block/drbd/drbd_actlog.c | 10 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_int.h | 14 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_main.c | 10 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_receiver.c | 10 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_req.c | 44 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_req.h | 4 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_worker.c | 16 | ||||
-rw-r--r-- | include/linux/drbd.h | 2 |
8 files changed, 91 insertions, 19 deletions
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index b4adb58c7472..33f6cc537d08 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c | |||
@@ -1007,22 +1007,22 @@ void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, int size, | |||
1007 | * called by tl_clear and drbd_send_dblock (==drbd_make_request). | 1007 | * called by tl_clear and drbd_send_dblock (==drbd_make_request). |
1008 | * so this can be _any_ process. | 1008 | * so this can be _any_ process. |
1009 | */ | 1009 | */ |
1010 | void __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size, | 1010 | int __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size, |
1011 | const char *file, const unsigned int line) | 1011 | const char *file, const unsigned int line) |
1012 | { | 1012 | { |
1013 | unsigned long sbnr, ebnr, lbnr, flags; | 1013 | unsigned long sbnr, ebnr, lbnr, flags; |
1014 | sector_t esector, nr_sectors; | 1014 | sector_t esector, nr_sectors; |
1015 | unsigned int enr, count; | 1015 | unsigned int enr, count = 0; |
1016 | struct lc_element *e; | 1016 | struct lc_element *e; |
1017 | 1017 | ||
1018 | if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) { | 1018 | if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) { |
1019 | dev_err(DEV, "sector: %llus, size: %d\n", | 1019 | dev_err(DEV, "sector: %llus, size: %d\n", |
1020 | (unsigned long long)sector, size); | 1020 | (unsigned long long)sector, size); |
1021 | return; | 1021 | return 0; |
1022 | } | 1022 | } |
1023 | 1023 | ||
1024 | if (!get_ldev(mdev)) | 1024 | if (!get_ldev(mdev)) |
1025 | return; /* no disk, no metadata, no bitmap to set bits in */ | 1025 | return 0; /* no disk, no metadata, no bitmap to set bits in */ |
1026 | 1026 | ||
1027 | nr_sectors = drbd_get_capacity(mdev->this_bdev); | 1027 | nr_sectors = drbd_get_capacity(mdev->this_bdev); |
1028 | esector = sector + (size >> 9) - 1; | 1028 | esector = sector + (size >> 9) - 1; |
@@ -1052,6 +1052,8 @@ void __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size, | |||
1052 | 1052 | ||
1053 | out: | 1053 | out: |
1054 | put_ldev(mdev); | 1054 | put_ldev(mdev); |
1055 | |||
1056 | return count; | ||
1055 | } | 1057 | } |
1056 | 1058 | ||
1057 | static | 1059 | static |
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 21b7439438cd..471331236826 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h | |||
@@ -212,6 +212,7 @@ enum drbd_packets { | |||
212 | /* P_CKPT_FENCE_REQ = 0x25, * currently reserved for protocol D */ | 212 | /* P_CKPT_FENCE_REQ = 0x25, * currently reserved for protocol D */ |
213 | /* P_CKPT_DISABLE_REQ = 0x26, * currently reserved for protocol D */ | 213 | /* P_CKPT_DISABLE_REQ = 0x26, * currently reserved for protocol D */ |
214 | P_DELAY_PROBE = 0x27, /* is used on BOTH sockets */ | 214 | P_DELAY_PROBE = 0x27, /* is used on BOTH sockets */ |
215 | P_OUT_OF_SYNC = 0x28, /* Mark as out of sync (Outrunning), data socket */ | ||
215 | 216 | ||
216 | P_MAX_CMD = 0x28, | 217 | P_MAX_CMD = 0x28, |
217 | P_MAY_IGNORE = 0x100, /* Flag to test if (cmd > P_MAY_IGNORE) ... */ | 218 | P_MAY_IGNORE = 0x100, /* Flag to test if (cmd > P_MAY_IGNORE) ... */ |
@@ -269,6 +270,7 @@ static inline const char *cmdname(enum drbd_packets cmd) | |||
269 | [P_RS_IS_IN_SYNC] = "CsumRSIsInSync", | 270 | [P_RS_IS_IN_SYNC] = "CsumRSIsInSync", |
270 | [P_COMPRESSED_BITMAP] = "CBitmap", | 271 | [P_COMPRESSED_BITMAP] = "CBitmap", |
271 | [P_DELAY_PROBE] = "DelayProbe", | 272 | [P_DELAY_PROBE] = "DelayProbe", |
273 | [P_OUT_OF_SYNC] = "OutOfSync", | ||
272 | [P_MAX_CMD] = NULL, | 274 | [P_MAX_CMD] = NULL, |
273 | }; | 275 | }; |
274 | 276 | ||
@@ -550,6 +552,13 @@ struct p_discard { | |||
550 | u32 pad; | 552 | u32 pad; |
551 | } __packed; | 553 | } __packed; |
552 | 554 | ||
555 | struct p_block_desc { | ||
556 | struct p_header80 head; | ||
557 | u64 sector; | ||
558 | u32 blksize; | ||
559 | u32 pad; /* to multiple of 8 Byte */ | ||
560 | } __packed; | ||
561 | |||
553 | /* Valid values for the encoding field. | 562 | /* Valid values for the encoding field. |
554 | * Bump proto version when changing this. */ | 563 | * Bump proto version when changing this. */ |
555 | enum drbd_bitmap_code { | 564 | enum drbd_bitmap_code { |
@@ -647,6 +656,7 @@ union p_polymorph { | |||
647 | struct p_block_req block_req; | 656 | struct p_block_req block_req; |
648 | struct p_delay_probe93 delay_probe93; | 657 | struct p_delay_probe93 delay_probe93; |
649 | struct p_rs_uuid rs_uuid; | 658 | struct p_rs_uuid rs_uuid; |
659 | struct p_block_desc block_desc; | ||
650 | } __packed; | 660 | } __packed; |
651 | 661 | ||
652 | /**********************************************************************/ | 662 | /**********************************************************************/ |
@@ -1221,6 +1231,7 @@ extern int drbd_send_ack_dp(struct drbd_conf *mdev, enum drbd_packets cmd, | |||
1221 | struct p_data *dp, int data_size); | 1231 | struct p_data *dp, int data_size); |
1222 | extern int drbd_send_ack_ex(struct drbd_conf *mdev, enum drbd_packets cmd, | 1232 | extern int drbd_send_ack_ex(struct drbd_conf *mdev, enum drbd_packets cmd, |
1223 | sector_t sector, int blksize, u64 block_id); | 1233 | sector_t sector, int blksize, u64 block_id); |
1234 | extern int drbd_send_oos(struct drbd_conf *mdev, struct drbd_request *req); | ||
1224 | extern int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd, | 1235 | extern int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd, |
1225 | struct drbd_epoch_entry *e); | 1236 | struct drbd_epoch_entry *e); |
1226 | extern int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req); | 1237 | extern int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req); |
@@ -1534,6 +1545,7 @@ extern int w_send_read_req(struct drbd_conf *, struct drbd_work *, int); | |||
1534 | extern int w_prev_work_done(struct drbd_conf *, struct drbd_work *, int); | 1545 | extern int w_prev_work_done(struct drbd_conf *, struct drbd_work *, int); |
1535 | extern int w_e_reissue(struct drbd_conf *, struct drbd_work *, int); | 1546 | extern int w_e_reissue(struct drbd_conf *, struct drbd_work *, int); |
1536 | extern int w_restart_disk_io(struct drbd_conf *, struct drbd_work *, int); | 1547 | extern int w_restart_disk_io(struct drbd_conf *, struct drbd_work *, int); |
1548 | extern int w_send_oos(struct drbd_conf *, struct drbd_work *, int); | ||
1537 | 1549 | ||
1538 | extern void resync_timer_fn(unsigned long data); | 1550 | extern void resync_timer_fn(unsigned long data); |
1539 | 1551 | ||
@@ -1626,7 +1638,7 @@ extern void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector, | |||
1626 | int size, const char *file, const unsigned int line); | 1638 | int size, const char *file, const unsigned int line); |
1627 | #define drbd_set_in_sync(mdev, sector, size) \ | 1639 | #define drbd_set_in_sync(mdev, sector, size) \ |
1628 | __drbd_set_in_sync(mdev, sector, size, __FILE__, __LINE__) | 1640 | __drbd_set_in_sync(mdev, sector, size, __FILE__, __LINE__) |
1629 | extern void __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, | 1641 | extern int __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, |
1630 | int size, const char *file, const unsigned int line); | 1642 | int size, const char *file, const unsigned int line); |
1631 | #define drbd_set_out_of_sync(mdev, sector, size) \ | 1643 | #define drbd_set_out_of_sync(mdev, sector, size) \ |
1632 | __drbd_set_out_of_sync(mdev, sector, size, __FILE__, __LINE__) | 1644 | __drbd_set_out_of_sync(mdev, sector, size, __FILE__, __LINE__) |
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 46f27d6c0b21..0dc93f43a476 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c | |||
@@ -2634,6 +2634,16 @@ int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd, | |||
2634 | return ok; | 2634 | return ok; |
2635 | } | 2635 | } |
2636 | 2636 | ||
2637 | int drbd_send_oos(struct drbd_conf *mdev, struct drbd_request *req) | ||
2638 | { | ||
2639 | struct p_block_desc p; | ||
2640 | |||
2641 | p.sector = cpu_to_be64(req->sector); | ||
2642 | p.blksize = cpu_to_be32(req->size); | ||
2643 | |||
2644 | return drbd_send_cmd(mdev, USE_DATA_SOCKET, P_OUT_OF_SYNC, &p.head, sizeof(p)); | ||
2645 | } | ||
2646 | |||
2637 | /* | 2647 | /* |
2638 | drbd_send distinguishes two cases: | 2648 | drbd_send distinguishes two cases: |
2639 | 2649 | ||
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index b19e8b2c4ce5..04a08e7541cc 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c | |||
@@ -3562,6 +3562,15 @@ static int receive_UnplugRemote(struct drbd_conf *mdev, enum drbd_packets cmd, u | |||
3562 | return TRUE; | 3562 | return TRUE; |
3563 | } | 3563 | } |
3564 | 3564 | ||
3565 | static int receive_out_of_sync(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size) | ||
3566 | { | ||
3567 | struct p_block_desc *p = &mdev->data.rbuf.block_desc; | ||
3568 | |||
3569 | drbd_set_out_of_sync(mdev, be64_to_cpu(p->sector), be32_to_cpu(p->blksize)); | ||
3570 | |||
3571 | return TRUE; | ||
3572 | } | ||
3573 | |||
3565 | typedef int (*drbd_cmd_handler_f)(struct drbd_conf *, enum drbd_packets cmd, unsigned int to_receive); | 3574 | typedef int (*drbd_cmd_handler_f)(struct drbd_conf *, enum drbd_packets cmd, unsigned int to_receive); |
3566 | 3575 | ||
3567 | struct data_cmd { | 3576 | struct data_cmd { |
@@ -3592,6 +3601,7 @@ static struct data_cmd drbd_cmd_handler[] = { | |||
3592 | [P_OV_REPLY] = { 1, sizeof(struct p_block_req), receive_DataRequest }, | 3601 | [P_OV_REPLY] = { 1, sizeof(struct p_block_req), receive_DataRequest }, |
3593 | [P_CSUM_RS_REQUEST] = { 1, sizeof(struct p_block_req), receive_DataRequest }, | 3602 | [P_CSUM_RS_REQUEST] = { 1, sizeof(struct p_block_req), receive_DataRequest }, |
3594 | [P_DELAY_PROBE] = { 0, sizeof(struct p_delay_probe93), receive_skip }, | 3603 | [P_DELAY_PROBE] = { 0, sizeof(struct p_delay_probe93), receive_skip }, |
3604 | [P_OUT_OF_SYNC] = { 0, sizeof(struct p_block_desc), receive_out_of_sync }, | ||
3595 | /* anything missing from this table is in | 3605 | /* anything missing from this table is in |
3596 | * the asender_tbl, see get_asender_cmd */ | 3606 | * the asender_tbl, see get_asender_cmd */ |
3597 | [P_MAX_CMD] = { 0, 0, NULL }, | 3607 | [P_MAX_CMD] = { 0, 0, NULL }, |
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 60288fb3c4d7..a8d1ff2bda27 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c | |||
@@ -142,7 +142,7 @@ static void _about_to_complete_local_write(struct drbd_conf *mdev, | |||
142 | 142 | ||
143 | /* before we can signal completion to the upper layers, | 143 | /* before we can signal completion to the upper layers, |
144 | * we may need to close the current epoch */ | 144 | * we may need to close the current epoch */ |
145 | if (mdev->state.conn >= C_CONNECTED && | 145 | if (mdev->state.conn >= C_CONNECTED && mdev->state.conn < C_AHEAD && |
146 | req->epoch == mdev->newest_tle->br_number) | 146 | req->epoch == mdev->newest_tle->br_number) |
147 | queue_barrier(mdev); | 147 | queue_barrier(mdev); |
148 | 148 | ||
@@ -545,6 +545,14 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, | |||
545 | 545 | ||
546 | break; | 546 | break; |
547 | 547 | ||
548 | case queue_for_send_oos: | ||
549 | req->rq_state |= RQ_NET_QUEUED; | ||
550 | req->w.cb = w_send_oos; | ||
551 | drbd_queue_work(&mdev->data.work, &req->w); | ||
552 | break; | ||
553 | |||
554 | case oos_handed_to_network: | ||
555 | /* actually the same */ | ||
548 | case send_canceled: | 556 | case send_canceled: |
549 | /* treat it the same */ | 557 | /* treat it the same */ |
550 | case send_failed: | 558 | case send_failed: |
@@ -756,7 +764,7 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) | |||
756 | const sector_t sector = bio->bi_sector; | 764 | const sector_t sector = bio->bi_sector; |
757 | struct drbd_tl_epoch *b = NULL; | 765 | struct drbd_tl_epoch *b = NULL; |
758 | struct drbd_request *req; | 766 | struct drbd_request *req; |
759 | int local, remote; | 767 | int local, remote, send_oos = 0; |
760 | int err = -EIO; | 768 | int err = -EIO; |
761 | int ret = 0; | 769 | int ret = 0; |
762 | 770 | ||
@@ -820,8 +828,11 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) | |||
820 | } | 828 | } |
821 | 829 | ||
822 | remote = remote && (mdev->state.pdsk == D_UP_TO_DATE || | 830 | remote = remote && (mdev->state.pdsk == D_UP_TO_DATE || |
823 | (mdev->state.pdsk == D_INCONSISTENT && | 831 | (mdev->state.pdsk >= D_INCONSISTENT && |
824 | mdev->state.conn >= C_CONNECTED)); | 832 | mdev->state.conn >= C_CONNECTED && |
833 | mdev->state.conn < C_AHEAD)); | ||
834 | send_oos = (rw == WRITE && mdev->state.conn == C_AHEAD && | ||
835 | mdev->state.pdsk >= D_INCONSISTENT); | ||
825 | 836 | ||
826 | if (!(local || remote) && !is_susp(mdev->state)) { | 837 | if (!(local || remote) && !is_susp(mdev->state)) { |
827 | if (__ratelimit(&drbd_ratelimit_state)) | 838 | if (__ratelimit(&drbd_ratelimit_state)) |
@@ -835,7 +846,7 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio) | |||
835 | * but there is a race between testing the bit and pointer outside the | 846 | * but there is a race between testing the bit and pointer outside the |
836 | * spinlock, and grabbing the spinlock. | 847 | * spinlock, and grabbing the spinlock. |
837 | * if we lost that race, we retry. */ | 848 | * if we lost that race, we retry. */ |
838 | if (rw == WRITE && remote && | 849 | if (rw == WRITE && (remote || send_oos) && |
839 | mdev->unused_spare_tle == NULL && | 850 | mdev->unused_spare_tle == NULL && |
840 | test_bit(CREATE_BARRIER, &mdev->flags)) { | 851 | test_bit(CREATE_BARRIER, &mdev->flags)) { |
841 | allocate_barrier: | 852 | allocate_barrier: |
@@ -860,11 +871,15 @@ allocate_barrier: | |||
860 | goto fail_free_complete; | 871 | goto fail_free_complete; |
861 | } | 872 | } |
862 | 873 | ||
863 | if (remote) { | 874 | if (remote || send_oos) { |
864 | remote = (mdev->state.pdsk == D_UP_TO_DATE || | 875 | remote = (mdev->state.pdsk == D_UP_TO_DATE || |
865 | (mdev->state.pdsk == D_INCONSISTENT && | 876 | (mdev->state.pdsk >= D_INCONSISTENT && |
866 | mdev->state.conn >= C_CONNECTED)); | 877 | mdev->state.conn >= C_CONNECTED && |
867 | if (!remote) | 878 | mdev->state.conn < C_AHEAD)); |
879 | send_oos = (rw == WRITE && mdev->state.conn == C_AHEAD && | ||
880 | mdev->state.pdsk >= D_INCONSISTENT); | ||
881 | |||
882 | if (!(remote || send_oos)) | ||
868 | dev_warn(DEV, "lost connection while grabbing the req_lock!\n"); | 883 | dev_warn(DEV, "lost connection while grabbing the req_lock!\n"); |
869 | if (!(local || remote)) { | 884 | if (!(local || remote)) { |
870 | dev_err(DEV, "IO ERROR: neither local nor remote disk\n"); | 885 | dev_err(DEV, "IO ERROR: neither local nor remote disk\n"); |
@@ -877,7 +892,7 @@ allocate_barrier: | |||
877 | mdev->unused_spare_tle = b; | 892 | mdev->unused_spare_tle = b; |
878 | b = NULL; | 893 | b = NULL; |
879 | } | 894 | } |
880 | if (rw == WRITE && remote && | 895 | if (rw == WRITE && (remote || send_oos) && |
881 | mdev->unused_spare_tle == NULL && | 896 | mdev->unused_spare_tle == NULL && |
882 | test_bit(CREATE_BARRIER, &mdev->flags)) { | 897 | test_bit(CREATE_BARRIER, &mdev->flags)) { |
883 | /* someone closed the current epoch | 898 | /* someone closed the current epoch |
@@ -900,7 +915,7 @@ allocate_barrier: | |||
900 | * barrier packet. To get the write ordering right, we only have to | 915 | * barrier packet. To get the write ordering right, we only have to |
901 | * make sure that, if this is a write request and it triggered a | 916 | * make sure that, if this is a write request and it triggered a |
902 | * barrier packet, this request is queued within the same spinlock. */ | 917 | * barrier packet, this request is queued within the same spinlock. */ |
903 | if (remote && mdev->unused_spare_tle && | 918 | if ((remote || send_oos) && mdev->unused_spare_tle && |
904 | test_and_clear_bit(CREATE_BARRIER, &mdev->flags)) { | 919 | test_and_clear_bit(CREATE_BARRIER, &mdev->flags)) { |
905 | _tl_add_barrier(mdev, mdev->unused_spare_tle); | 920 | _tl_add_barrier(mdev, mdev->unused_spare_tle); |
906 | mdev->unused_spare_tle = NULL; | 921 | mdev->unused_spare_tle = NULL; |
@@ -948,8 +963,11 @@ allocate_barrier: | |||
948 | ? queue_for_net_write | 963 | ? queue_for_net_write |
949 | : queue_for_net_read); | 964 | : queue_for_net_read); |
950 | } | 965 | } |
966 | if (send_oos && drbd_set_out_of_sync(mdev, sector, size)) | ||
967 | _req_mod(req, queue_for_send_oos); | ||
951 | 968 | ||
952 | if (remote && mdev->net_conf->on_congestion != OC_BLOCK) { | 969 | if (remote && |
970 | mdev->net_conf->on_congestion != OC_BLOCK && mdev->agreed_pro_version >= 96) { | ||
953 | int congested = 0; | 971 | int congested = 0; |
954 | 972 | ||
955 | if (mdev->net_conf->cong_fill && | 973 | if (mdev->net_conf->cong_fill && |
@@ -964,6 +982,8 @@ allocate_barrier: | |||
964 | } | 982 | } |
965 | 983 | ||
966 | if (congested) { | 984 | if (congested) { |
985 | queue_barrier(mdev); | ||
986 | |||
967 | if (mdev->net_conf->on_congestion == OC_PULL_AHEAD) | 987 | if (mdev->net_conf->on_congestion == OC_PULL_AHEAD) |
968 | _drbd_set_state(_NS(mdev, conn, C_AHEAD), 0, NULL); | 988 | _drbd_set_state(_NS(mdev, conn, C_AHEAD), 0, NULL); |
969 | else /*mdev->net_conf->on_congestion == OC_DISCONNECT */ | 989 | else /*mdev->net_conf->on_congestion == OC_DISCONNECT */ |
diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h index 69d350fe7c1e..40d3dcd8fc81 100644 --- a/drivers/block/drbd/drbd_req.h +++ b/drivers/block/drbd/drbd_req.h | |||
@@ -82,14 +82,16 @@ enum drbd_req_event { | |||
82 | to_be_submitted, | 82 | to_be_submitted, |
83 | 83 | ||
84 | /* XXX yes, now I am inconsistent... | 84 | /* XXX yes, now I am inconsistent... |
85 | * these two are not "events" but "actions" | 85 | * these are not "events" but "actions" |
86 | * oh, well... */ | 86 | * oh, well... */ |
87 | queue_for_net_write, | 87 | queue_for_net_write, |
88 | queue_for_net_read, | 88 | queue_for_net_read, |
89 | queue_for_send_oos, | ||
89 | 90 | ||
90 | send_canceled, | 91 | send_canceled, |
91 | send_failed, | 92 | send_failed, |
92 | handed_over_to_network, | 93 | handed_over_to_network, |
94 | oos_handed_to_network, | ||
93 | connection_lost_while_pending, | 95 | connection_lost_while_pending, |
94 | read_retry_remote_canceled, | 96 | read_retry_remote_canceled, |
95 | recv_acked_by_peer, | 97 | recv_acked_by_peer, |
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 782d87237cb4..67499077c482 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c | |||
@@ -1237,6 +1237,22 @@ int w_send_write_hint(struct drbd_conf *mdev, struct drbd_work *w, int cancel) | |||
1237 | return drbd_send_short_cmd(mdev, P_UNPLUG_REMOTE); | 1237 | return drbd_send_short_cmd(mdev, P_UNPLUG_REMOTE); |
1238 | } | 1238 | } |
1239 | 1239 | ||
1240 | int w_send_oos(struct drbd_conf *mdev, struct drbd_work *w, int cancel) | ||
1241 | { | ||
1242 | struct drbd_request *req = container_of(w, struct drbd_request, w); | ||
1243 | int ok; | ||
1244 | |||
1245 | if (unlikely(cancel)) { | ||
1246 | req_mod(req, send_canceled); | ||
1247 | return 1; | ||
1248 | } | ||
1249 | |||
1250 | ok = drbd_send_oos(mdev, req); | ||
1251 | req_mod(req, oos_handed_to_network); | ||
1252 | |||
1253 | return ok; | ||
1254 | } | ||
1255 | |||
1240 | /** | 1256 | /** |
1241 | * w_send_dblock() - Worker callback to send a P_DATA packet in order to mirror a write request | 1257 | * w_send_dblock() - Worker callback to send a P_DATA packet in order to mirror a write request |
1242 | * @mdev: DRBD device. | 1258 | * @mdev: DRBD device. |
diff --git a/include/linux/drbd.h b/include/linux/drbd.h index 23f31be6f00d..41da654cc0b1 100644 --- a/include/linux/drbd.h +++ b/include/linux/drbd.h | |||
@@ -56,7 +56,7 @@ extern const char *drbd_buildtag(void); | |||
56 | #define REL_VERSION "8.3.9" | 56 | #define REL_VERSION "8.3.9" |
57 | #define API_VERSION 88 | 57 | #define API_VERSION 88 |
58 | #define PRO_VERSION_MIN 86 | 58 | #define PRO_VERSION_MIN 86 |
59 | #define PRO_VERSION_MAX 95 | 59 | #define PRO_VERSION_MAX 96 |
60 | 60 | ||
61 | 61 | ||
62 | enum drbd_io_error_p { | 62 | enum drbd_io_error_p { |