aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/drbd/drbd_receiver.c
diff options
context:
space:
mode:
authorPhilipp Reisner <philipp.reisner@linbit.com>2011-01-17 12:39:18 -0500
committerPhilipp Reisner <philipp.reisner@linbit.com>2011-03-10 05:45:40 -0500
commit2deb8336d04106f215c21ad1b029e78d12033d02 (patch)
tree19a6efb58bf425002630c58826c6b53099fe73a1 /drivers/block/drbd/drbd_receiver.c
parent94f2b05f03fbc605f83ae501682c85ff4535bb6d (diff)
drbd: Fixed P_NEG_ACK processing for protocol A and B
Protocol A has no P_WRITE_ACKs, but has P_NEG_ACKs. The master bio might already be completed, therefore the request is no longer in the collision hash. => Do not try to validate block_id as request In Protocol B we might already have got a P_RECV_ACK but then get a P_NEG_ACK after wards. 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_receiver.c')
-rw-r--r--drivers/block/drbd/drbd_receiver.c45
1 files changed, 33 insertions, 12 deletions
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 2207d2886f8..a7f5b6d134e 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -1633,9 +1633,6 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
1633 u32 dp_flags; 1633 u32 dp_flags;
1634 1634
1635 if (!get_ldev(mdev)) { 1635 if (!get_ldev(mdev)) {
1636 if (__ratelimit(&drbd_ratelimit_state))
1637 dev_err(DEV, "Can not write mirrored data block "
1638 "to local disk.\n");
1639 spin_lock(&mdev->peer_seq_lock); 1636 spin_lock(&mdev->peer_seq_lock);
1640 if (mdev->peer_seq+1 == be32_to_cpu(p->seq_num)) 1637 if (mdev->peer_seq+1 == be32_to_cpu(p->seq_num))
1641 mdev->peer_seq++; 1638 mdev->peer_seq++;
@@ -4247,8 +4244,6 @@ static struct drbd_request *_ack_id_to_req(struct drbd_conf *mdev,
4247 return req; 4244 return req;
4248 } 4245 }
4249 } 4246 }
4250 dev_err(DEV, "_ack_id_to_req: failed to find req %p, sector %llus in list\n",
4251 (void *)(unsigned long)id, (unsigned long long)sector);
4252 return NULL; 4247 return NULL;
4253} 4248}
4254 4249
@@ -4266,7 +4261,9 @@ static int validate_req_change_req_state(struct drbd_conf *mdev,
4266 req = validator(mdev, id, sector); 4261 req = validator(mdev, id, sector);
4267 if (unlikely(!req)) { 4262 if (unlikely(!req)) {
4268 spin_unlock_irq(&mdev->req_lock); 4263 spin_unlock_irq(&mdev->req_lock);
4269 dev_err(DEV, "%s: got a corrupt block_id/sector pair\n", func); 4264
4265 dev_err(DEV, "%s: failed to find req %p, sector %llus\n", func,
4266 (void *)(unsigned long)id, (unsigned long long)sector);
4270 return false; 4267 return false;
4271 } 4268 }
4272 __req_mod(req, what, &m); 4269 __req_mod(req, what, &m);
@@ -4321,20 +4318,44 @@ static int got_NegAck(struct drbd_conf *mdev, struct p_header80 *h)
4321{ 4318{
4322 struct p_block_ack *p = (struct p_block_ack *)h; 4319 struct p_block_ack *p = (struct p_block_ack *)h;
4323 sector_t sector = be64_to_cpu(p->sector); 4320 sector_t sector = be64_to_cpu(p->sector);
4324 4321 int size = be32_to_cpu(p->blksize);
4325 if (__ratelimit(&drbd_ratelimit_state)) 4322 struct drbd_request *req;
4326 dev_warn(DEV, "Got NegAck packet. Peer is in troubles?\n"); 4323 struct bio_and_error m;
4327 4324
4328 update_peer_seq(mdev, be32_to_cpu(p->seq_num)); 4325 update_peer_seq(mdev, be32_to_cpu(p->seq_num));
4329 4326
4330 if (is_syncer_block_id(p->block_id)) { 4327 if (is_syncer_block_id(p->block_id)) {
4331 int size = be32_to_cpu(p->blksize);
4332 dec_rs_pending(mdev); 4328 dec_rs_pending(mdev);
4333 drbd_rs_failed_io(mdev, sector, size); 4329 drbd_rs_failed_io(mdev, sector, size);
4334 return true; 4330 return true;
4335 } 4331 }
4336 return validate_req_change_req_state(mdev, p->block_id, sector, 4332
4337 _ack_id_to_req, __func__ , neg_acked); 4333 spin_lock_irq(&mdev->req_lock);
4334 req = _ack_id_to_req(mdev, p->block_id, sector);
4335 if (!req) {
4336 spin_unlock_irq(&mdev->req_lock);
4337 if (mdev->net_conf->wire_protocol == DRBD_PROT_A ||
4338 mdev->net_conf->wire_protocol == DRBD_PROT_B) {
4339 /* Protocol A has no P_WRITE_ACKs, but has P_NEG_ACKs.
4340 The master bio might already be completed, therefore the
4341 request is no longer in the collision hash.
4342 => Do not try to validate block_id as request. */
4343 /* In Protocol B we might already have got a P_RECV_ACK
4344 but then get a P_NEG_ACK after wards. */
4345 drbd_set_out_of_sync(mdev, sector, size);
4346 return true;
4347 } else {
4348 dev_err(DEV, "%s: failed to find req %p, sector %llus\n", __func__,
4349 (void *)(unsigned long)p->block_id, (unsigned long long)sector);
4350 return false;
4351 }
4352 }
4353 __req_mod(req, neg_acked, &m);
4354 spin_unlock_irq(&mdev->req_lock);
4355
4356 if (m.bio)
4357 complete_master_bio(mdev, &m);
4358 return true;
4338} 4359}
4339 4360
4340static int got_NegDReply(struct drbd_conf *mdev, struct p_header80 *h) 4361static int got_NegDReply(struct drbd_conf *mdev, struct p_header80 *h)