aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorPhilipp Reisner <philipp.reisner@linbit.com>2010-10-27 08:33:00 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2011-03-10 05:34:48 -0500
commit73a01a18b9c28a0fab1131ece5b0a9bc00a879b8 (patch)
tree36ed1ea31bd18def918717906a58355a77b39cba /drivers/block
parent67531718d8f1259f01ab84c2aa25f7b03c7afd46 (diff)
drbd: New packet for Ahead/Behind mode: P_OUT_OF_SYNC
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/drbd/drbd_actlog.c10
-rw-r--r--drivers/block/drbd/drbd_int.h14
-rw-r--r--drivers/block/drbd/drbd_main.c10
-rw-r--r--drivers/block/drbd/drbd_receiver.c10
-rw-r--r--drivers/block/drbd/drbd_req.c44
-rw-r--r--drivers/block/drbd/drbd_req.h4
-rw-r--r--drivers/block/drbd/drbd_worker.c16
7 files changed, 90 insertions, 18 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 */
1010void __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size, 1010int __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
1053out: 1053out:
1054 put_ldev(mdev); 1054 put_ldev(mdev);
1055
1056 return count;
1055} 1057}
1056 1058
1057static 1059static
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
555struct 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. */
555enum drbd_bitmap_code { 564enum 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);
1222extern int drbd_send_ack_ex(struct drbd_conf *mdev, enum drbd_packets cmd, 1232extern 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);
1234extern int drbd_send_oos(struct drbd_conf *mdev, struct drbd_request *req);
1224extern int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd, 1235extern int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd,
1225 struct drbd_epoch_entry *e); 1236 struct drbd_epoch_entry *e);
1226extern int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req); 1237extern 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);
1534extern int w_prev_work_done(struct drbd_conf *, struct drbd_work *, int); 1545extern int w_prev_work_done(struct drbd_conf *, struct drbd_work *, int);
1535extern int w_e_reissue(struct drbd_conf *, struct drbd_work *, int); 1546extern int w_e_reissue(struct drbd_conf *, struct drbd_work *, int);
1536extern int w_restart_disk_io(struct drbd_conf *, struct drbd_work *, int); 1547extern int w_restart_disk_io(struct drbd_conf *, struct drbd_work *, int);
1548extern int w_send_oos(struct drbd_conf *, struct drbd_work *, int);
1537 1549
1538extern void resync_timer_fn(unsigned long data); 1550extern 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__)
1629extern void __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, 1641extern 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
2637int 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
3565static 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
3565typedef int (*drbd_cmd_handler_f)(struct drbd_conf *, enum drbd_packets cmd, unsigned int to_receive); 3574typedef int (*drbd_cmd_handler_f)(struct drbd_conf *, enum drbd_packets cmd, unsigned int to_receive);
3566 3575
3567struct data_cmd { 3576struct 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)) {
841allocate_barrier: 852allocate_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
1240int 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.