aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorEd Cashin <ecashin@coraid.com>2012-12-17 19:03:51 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-17 20:15:24 -0500
commit3fc9b032489d365957ce531d32e225b2d0b3ed11 (patch)
tree4e3ba6f0c3e89d98cede84bec580230b410cd0e1 /drivers
parent5f0c9c48e7265039c3f945aaf44a1c6ae8adbd01 (diff)
aoe: commands in retransmit queue use new destination on failure
When one remote MAC address isn't working as a destination for AoE commands, the frames used to track information associated with the AoE commands are moved to a new aoetgt (defined by the tuple of {AoE major, AoE minor, target MAC address}). This patch makes sure that the frames on the queue for retransmits that need to be done are updated to use the new destination, so that retransmits will be sent through a working network path. Without this change, packets on the retransmit queue will be needlessly retransmitted to the unresponsive destination MAC, possibly causing premature target failure before there's time for the retransmit timer to run again, decide to retransmit again, and finally update the destination to a working MAC address on the AoE target. Signed-off-by: Ed Cashin <ecashin@coraid.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/aoe/aoe.h1
-rw-r--r--drivers/block/aoe/aoecmd.c75
-rw-r--r--drivers/block/aoe/aoedev.c32
3 files changed, 75 insertions, 33 deletions
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h
index 9fb68fc3b280..c253cca4985b 100644
--- a/drivers/block/aoe/aoe.h
+++ b/drivers/block/aoe/aoe.h
@@ -108,6 +108,7 @@ struct frame {
108 struct timeval sent; /* high-res time packet was sent */ 108 struct timeval sent; /* high-res time packet was sent */
109 u32 sent_jiffs; /* low-res jiffies-based sent time */ 109 u32 sent_jiffs; /* low-res jiffies-based sent time */
110 ulong waited; 110 ulong waited;
111 ulong waited_total;
111 struct aoetgt *t; /* parent target I belong to */ 112 struct aoetgt *t; /* parent target I belong to */
112 sector_t lba; 113 sector_t lba;
113 struct sk_buff *skb; /* command skb freed on module exit */ 114 struct sk_buff *skb; /* command skb freed on module exit */
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index a99220ad6262..d9bc6ff56f49 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -352,6 +352,7 @@ aoecmd_ata_rw(struct aoedev *d)
352 fhash(f); 352 fhash(f);
353 t->nout++; 353 t->nout++;
354 f->waited = 0; 354 f->waited = 0;
355 f->waited_total = 0;
355 f->buf = buf; 356 f->buf = buf;
356 f->bcnt = bcnt; 357 f->bcnt = bcnt;
357 f->lba = buf->sector; 358 f->lba = buf->sector;
@@ -556,46 +557,69 @@ ejectif(struct aoetgt *t, struct aoeif *ifp)
556 dev_put(nd); 557 dev_put(nd);
557} 558}
558 559
560static struct frame *
561reassign_frame(struct list_head *pos)
562{
563 struct frame *f;
564 struct frame *nf;
565 struct sk_buff *skb;
566
567 f = list_entry(pos, struct frame, head);
568 nf = newframe(f->t->d);
569 if (!nf)
570 return NULL;
571
572 list_del(pos);
573
574 skb = nf->skb;
575 nf->skb = f->skb;
576 nf->buf = f->buf;
577 nf->bcnt = f->bcnt;
578 nf->lba = f->lba;
579 nf->bv = f->bv;
580 nf->bv_off = f->bv_off;
581 nf->waited = 0;
582 nf->waited_total = f->waited_total;
583 nf->sent = f->sent;
584 f->skb = skb;
585 aoe_freetframe(f);
586 f->t->nout--;
587 nf->t->nout++;
588
589 return nf;
590}
591
559static int 592static int
560sthtith(struct aoedev *d) 593sthtith(struct aoedev *d)
561{ 594{
562 struct frame *f, *nf; 595 struct frame *f, *nf;
563 struct list_head *nx, *pos, *head; 596 struct list_head *nx, *pos, *head;
564 struct sk_buff *skb;
565 struct aoetgt *ht = d->htgt; 597 struct aoetgt *ht = d->htgt;
566 int i; 598 int i;
567 599
600 /* look through the active and pending retransmit frames */
568 for (i = 0; i < NFACTIVE; i++) { 601 for (i = 0; i < NFACTIVE; i++) {
569 head = &d->factive[i]; 602 head = &d->factive[i];
570 list_for_each_safe(pos, nx, head) { 603 list_for_each_safe(pos, nx, head) {
571 f = list_entry(pos, struct frame, head); 604 f = list_entry(pos, struct frame, head);
572 if (f->t != ht) 605 if (f->t != ht)
573 continue; 606 continue;
574 607 nf = reassign_frame(pos);
575 nf = newframe(d);
576 if (!nf) 608 if (!nf)
577 return 0; 609 return 0;
578
579 /* remove frame from active list */
580 list_del(pos);
581
582 /* reassign all pertinent bits to new outbound frame */
583 skb = nf->skb;
584 nf->skb = f->skb;
585 nf->buf = f->buf;
586 nf->bcnt = f->bcnt;
587 nf->lba = f->lba;
588 nf->bv = f->bv;
589 nf->bv_off = f->bv_off;
590 nf->waited = 0;
591 nf->sent_jiffs = f->sent_jiffs;
592 f->skb = skb;
593 aoe_freetframe(f);
594 ht->nout--;
595 nf->t->nout++;
596 resend(d, nf); 610 resend(d, nf);
597 } 611 }
598 } 612 }
613 head = &d->rexmitq;
614 list_for_each_safe(pos, nx, head) {
615 f = list_entry(pos, struct frame, head);
616 if (f->t != ht)
617 continue;
618 nf = reassign_frame(pos);
619 if (!nf)
620 return 0;
621 resend(d, nf);
622 }
599 /* We've cleaned up the outstanding so take away his 623 /* We've cleaned up the outstanding so take away his
600 * interfaces so he won't be used. We should remove him from 624 * interfaces so he won't be used. We should remove him from
601 * the target array here, but cleaning up a target is 625 * the target array here, but cleaning up a target is
@@ -612,6 +636,7 @@ rexmit_deferred(struct aoedev *d)
612 struct aoetgt *t; 636 struct aoetgt *t;
613 struct frame *f; 637 struct frame *f;
614 struct list_head *pos, *nx, *head; 638 struct list_head *pos, *nx, *head;
639 int since;
615 640
616 head = &d->rexmitq; 641 head = &d->rexmitq;
617 list_for_each_safe(pos, nx, head) { 642 list_for_each_safe(pos, nx, head) {
@@ -621,6 +646,9 @@ rexmit_deferred(struct aoedev *d)
621 continue; 646 continue;
622 list_del(pos); 647 list_del(pos);
623 t->nout++; 648 t->nout++;
649 since = tsince_hr(f);
650 f->waited += since;
651 f->waited_total += since;
624 resend(d, f); 652 resend(d, f);
625 } 653 }
626} 654}
@@ -637,6 +665,7 @@ rexmit_timer(ulong vp)
637 register long timeout; 665 register long timeout;
638 ulong flags, n; 666 ulong flags, n;
639 int i; 667 int i;
668 int since;
640 669
641 d = (struct aoedev *) vp; 670 d = (struct aoedev *) vp;
642 671
@@ -669,7 +698,8 @@ rexmit_timer(ulong vp)
669 while (!list_empty(&flist)) { 698 while (!list_empty(&flist)) {
670 pos = flist.next; 699 pos = flist.next;
671 f = list_entry(pos, struct frame, head); 700 f = list_entry(pos, struct frame, head);
672 n = f->waited += tsince_hr(f); 701 since = tsince_hr(f);
702 n = f->waited_total + since;
673 n /= USEC_PER_SEC; 703 n /= USEC_PER_SEC;
674 if (n > aoe_deadsecs) { 704 if (n > aoe_deadsecs) {
675 /* Waited too long. Device failure. 705 /* Waited too long. Device failure.
@@ -1301,6 +1331,7 @@ aoecmd_ata_id(struct aoedev *d)
1301 fhash(f); 1331 fhash(f);
1302 t->nout++; 1332 t->nout++;
1303 f->waited = 0; 1333 f->waited = 0;
1334 f->waited_total = 0;
1304 1335
1305 /* set up ata header */ 1336 /* set up ata header */
1306 ah->scnt = 1; 1337 ah->scnt = 1;
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c
index 3c3aef208106..91f7c99eb2a9 100644
--- a/drivers/block/aoe/aoedev.c
+++ b/drivers/block/aoe/aoedev.c
@@ -170,30 +170,40 @@ aoe_failip(struct aoedev *d)
170 aoe_end_request(d, rq, 0); 170 aoe_end_request(d, rq, 0);
171} 171}
172 172
173static void
174downdev_frame(struct list_head *pos)
175{
176 struct frame *f;
177
178 f = list_entry(pos, struct frame, head);
179 list_del(pos);
180 if (f->buf) {
181 f->buf->nframesout--;
182 aoe_failbuf(f->t->d, f->buf);
183 }
184 aoe_freetframe(f);
185}
186
173void 187void
174aoedev_downdev(struct aoedev *d) 188aoedev_downdev(struct aoedev *d)
175{ 189{
176 struct aoetgt *t, **tt, **te; 190 struct aoetgt *t, **tt, **te;
177 struct frame *f;
178 struct list_head *head, *pos, *nx; 191 struct list_head *head, *pos, *nx;
179 struct request *rq; 192 struct request *rq;
180 int i; 193 int i;
181 194
182 d->flags &= ~DEVFL_UP; 195 d->flags &= ~DEVFL_UP;
183 196
184 /* clean out active buffers */ 197 /* clean out active and to-be-retransmitted buffers */
185 for (i = 0; i < NFACTIVE; i++) { 198 for (i = 0; i < NFACTIVE; i++) {
186 head = &d->factive[i]; 199 head = &d->factive[i];
187 list_for_each_safe(pos, nx, head) { 200 list_for_each_safe(pos, nx, head)
188 f = list_entry(pos, struct frame, head); 201 downdev_frame(pos);
189 list_del(pos);
190 if (f->buf) {
191 f->buf->nframesout--;
192 aoe_failbuf(d, f->buf);
193 }
194 aoe_freetframe(f);
195 }
196 } 202 }
203 head = &d->rexmitq;
204 list_for_each_safe(pos, nx, head)
205 downdev_frame(pos);
206
197 /* reset window dressings */ 207 /* reset window dressings */
198 tt = d->targets; 208 tt = d->targets;
199 te = tt + NTARGETS; 209 te = tt + NTARGETS;