Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

aoe: improve handling of misbehaving network paths

An AoE target can have multiple network ports used for AoE, and in the
aoe driver, those are tracked by the aoetgt struct. These changes allow
the aoe driver to handle network paths, or aoetgts, that are not working
well, compared to the others.

Paths that do not get responses despite the retransmission of AoE
commands are marked as "tainted", and non-tainted paths are preferred.

Meanwhile, the aoe driver attempts to "probe" the tainted path in the
background by issuing reads of LBA 0 that are padded out to full
(possibly jumbo-frame) size. If the probes get responses, then the path
is "redeemed", and its taint is removed.

This mechanism has been shown to be helpful in transparently handling
and recovering from real-world network "brown outs" in ways that the
earlier "shoot the help-needing target in the head" mechanism could not.

Signed-off-by: Ed Cashin <ecashin@coraid.com>
Cc: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Ed Cashin and committed by
Linus Torvalds
bbb44e30 b91316f2

+268 -121
+10 -1
drivers/block/aoe/aoe.h
··· 91 91 RTTDSCALE = 3, 92 92 RTTAVG_INIT = USEC_PER_SEC / 4 << RTTSCALE, 93 93 RTTDEV_INIT = RTTAVG_INIT / 4, 94 + 95 + HARD_SCORN_SECS = 10, /* try another remote port after this */ 96 + MAX_TAINT = 1000, /* cap on aoetgt taint */ 94 97 }; 95 98 96 99 struct buf { ··· 104 101 struct bio *bio; 105 102 struct bio_vec *bv; 106 103 struct request *rq; 104 + }; 105 + 106 + enum frame_flags { 107 + FFL_PROBE = 1, 107 108 }; 108 109 109 110 struct frame { ··· 125 118 struct bio_vec *bv; 126 119 ulong bcnt; 127 120 ulong bv_off; 121 + char flags; 128 122 }; 129 123 130 124 struct aoeif { ··· 146 138 ushort next_cwnd; /* incr maxout after decrementing to zero */ 147 139 ushort ssthresh; /* slow start threshold */ 148 140 ulong falloc; /* number of allocated frames */ 141 + int taint; /* how much we want to avoid this aoetgt */ 149 142 int minbcnt; 150 143 int wpkts, rpkts; 144 + char nout_probes; 151 145 }; 152 146 153 147 struct aoedev { ··· 184 174 struct list_head rexmitq; /* deferred retransmissions */ 185 175 struct aoetgt *targets[NTARGETS]; 186 176 struct aoetgt **tgt; /* target in use when working */ 187 - struct aoetgt *htgt; /* target needing rexmit assistance */ 188 177 ulong ntargets; 189 178 ulong kicked; 190 179 char ident[512];
+258 -119
drivers/block/aoe/aoecmd.c
··· 22 22 #define MAXIOC (8192) /* default meant to avoid most soft lockups */ 23 23 24 24 static void ktcomplete(struct frame *, struct sk_buff *); 25 + static int count_targets(struct aoedev *d, int *untainted); 25 26 26 27 static struct buf *nextbuf(struct aoedev *); 27 28 ··· 43 42 struct list_head head; 44 43 spinlock_t lock; 45 44 } iocq; 45 + 46 + static struct page *empty_page; 46 47 47 48 static struct sk_buff * 48 49 new_skb(ulong len) ··· 182 179 183 180 t = f->t; 184 181 f->buf = NULL; 182 + f->lba = 0; 185 183 f->bv = NULL; 186 184 f->r_skb = NULL; 185 + f->flags = 0; 187 186 list_add(&f->head, &t->ffree); 188 187 } 189 188 ··· 239 234 struct frame *f; 240 235 struct aoetgt *t, **tt; 241 236 int totout = 0; 237 + int use_tainted; 238 + int has_untainted; 242 239 243 240 if (d->targets[0] == NULL) { /* shouldn't happen, but I'm paranoid */ 244 241 printk(KERN_ERR "aoe: NULL TARGETS!\n"); 245 242 return NULL; 246 243 } 247 244 tt = d->tgt; /* last used target */ 248 - for (;;) { 245 + for (use_tainted = 0, has_untainted = 0;;) { 249 246 tt++; 250 247 if (tt >= &d->targets[NTARGETS] || !*tt) 251 248 tt = d->targets; 252 249 t = *tt; 253 - totout += t->nout; 250 + if (!t->taint) { 251 + has_untainted = 1; 252 + totout += t->nout; 253 + } 254 254 if (t->nout < t->maxout 255 - && t != d->htgt 255 + && (use_tainted || !t->taint) 256 256 && t->ifp->nd) { 257 257 f = newtframe(d, t); 258 258 if (f) { ··· 266 256 return f; 267 257 } 268 258 } 269 - if (tt == d->tgt) /* we've looped and found nada */ 270 - break; 259 + if (tt == d->tgt) { /* we've looped and found nada */ 260 + if (!use_tainted && !has_untainted) 261 + use_tainted = 1; 262 + else 263 + break; 264 + } 271 265 } 272 266 if (totout == 0) { 273 267 d->kicked++; ··· 308 294 list_add_tail(&f->head, &d->factive[n]); 309 295 } 310 296 297 + static void 298 + ata_rw_frameinit(struct frame *f) 299 + { 300 + struct aoetgt *t; 301 + struct aoe_hdr *h; 302 + struct aoe_atahdr *ah; 303 + struct sk_buff *skb; 304 + char writebit, extbit; 305 + 306 + skb = f->skb; 307 + h = (struct aoe_hdr *) skb_mac_header(skb); 308 + ah = (struct aoe_atahdr *) (h + 1); 309 + skb_put(skb, sizeof(*h) + sizeof(*ah)); 310 + memset(h, 0, skb->len); 311 + 312 + writebit = 0x10; 313 + extbit = 0x4; 314 + 315 + t = f->t; 316 + f->tag = aoehdr_atainit(t->d, t, h); 317 + fhash(f); 318 + t->nout++; 319 + f->waited = 0; 320 + f->waited_total = 0; 321 + if (f->buf) 322 + f->lba = f->buf->sector; 323 + 324 + /* set up ata header */ 325 + ah->scnt = f->bcnt >> 9; 326 + put_lba(ah, f->lba); 327 + if (t->d->flags & DEVFL_EXT) { 328 + ah->aflags |= AOEAFL_EXT; 329 + } else { 330 + extbit = 0; 331 + ah->lba3 &= 0x0f; 332 + ah->lba3 |= 0xe0; /* LBA bit + obsolete 0xa0 */ 333 + } 334 + if (f->buf && bio_data_dir(f->buf->bio) == WRITE) { 335 + skb_fillup(skb, f->bv, f->bv_off, f->bcnt); 336 + ah->aflags |= AOEAFL_WRITE; 337 + skb->len += f->bcnt; 338 + skb->data_len = f->bcnt; 339 + skb->truesize += f->bcnt; 340 + t->wpkts++; 341 + } else { 342 + t->rpkts++; 343 + writebit = 0; 344 + } 345 + 346 + ah->cmdstat = ATA_CMD_PIO_READ | writebit | extbit; 347 + skb->dev = t->ifp->nd; 348 + } 349 + 311 350 static int 312 351 aoecmd_ata_rw(struct aoedev *d) 313 352 { 314 353 struct frame *f; 315 - struct aoe_hdr *h; 316 - struct aoe_atahdr *ah; 317 354 struct buf *buf; 318 355 struct aoetgt *t; 319 356 struct sk_buff *skb; 320 357 struct sk_buff_head queue; 321 358 ulong bcnt, fbcnt; 322 - char writebit, extbit; 323 - 324 - writebit = 0x10; 325 - extbit = 0x4; 326 359 327 360 buf = nextbuf(d); 328 361 if (buf == NULL) ··· 404 343 } while (fbcnt); 405 344 406 345 /* initialize the headers & frame */ 407 - skb = f->skb; 408 - h = (struct aoe_hdr *) skb_mac_header(skb); 409 - ah = (struct aoe_atahdr *) (h+1); 410 - skb_put(skb, sizeof *h + sizeof *ah); 411 - memset(h, 0, skb->len); 412 - f->tag = aoehdr_atainit(d, t, h); 413 - fhash(f); 414 - t->nout++; 415 - f->waited = 0; 416 - f->waited_total = 0; 417 346 f->buf = buf; 418 347 f->bcnt = bcnt; 419 - f->lba = buf->sector; 420 - 421 - /* set up ata header */ 422 - ah->scnt = bcnt >> 9; 423 - put_lba(ah, buf->sector); 424 - if (d->flags & DEVFL_EXT) { 425 - ah->aflags |= AOEAFL_EXT; 426 - } else { 427 - extbit = 0; 428 - ah->lba3 &= 0x0f; 429 - ah->lba3 |= 0xe0; /* LBA bit + obsolete 0xa0 */ 430 - } 431 - if (bio_data_dir(buf->bio) == WRITE) { 432 - skb_fillup(skb, f->bv, f->bv_off, bcnt); 433 - ah->aflags |= AOEAFL_WRITE; 434 - skb->len += bcnt; 435 - skb->data_len = bcnt; 436 - skb->truesize += bcnt; 437 - t->wpkts++; 438 - } else { 439 - t->rpkts++; 440 - writebit = 0; 441 - } 442 - 443 - ah->cmdstat = ATA_CMD_PIO_READ | writebit | extbit; 348 + ata_rw_frameinit(f); 444 349 445 350 /* mark all tracking fields and load out */ 446 351 buf->nframesout += 1; 447 352 buf->sector += bcnt >> 9; 448 353 449 - skb->dev = t->ifp->nd; 450 - skb = skb_clone(skb, GFP_ATOMIC); 354 + skb = skb_clone(f->skb, GFP_ATOMIC); 451 355 if (skb) { 452 356 do_gettimeofday(&f->sent); 453 357 f->sent_jiffs = (u32) jiffies; ··· 488 462 h = (struct aoe_hdr *) skb_mac_header(skb); 489 463 ah = (struct aoe_atahdr *) (h+1); 490 464 491 - snprintf(buf, sizeof buf, 492 - "%15s e%ld.%d oldtag=%08x@%08lx newtag=%08x s=%pm d=%pm nout=%d\n", 493 - "retransmit", d->aoemajor, d->aoeminor, f->tag, jiffies, n, 494 - h->src, h->dst, t->nout); 495 - aoechr_error(buf); 465 + if (!(f->flags & FFL_PROBE)) { 466 + snprintf(buf, sizeof(buf), 467 + "%15s e%ld.%d oldtag=%08x@%08lx newtag=%08x s=%pm d=%pm nout=%d\n", 468 + "retransmit", d->aoemajor, d->aoeminor, 469 + f->tag, jiffies, n, 470 + h->src, h->dst, t->nout); 471 + aoechr_error(buf); 472 + } 496 473 497 474 f->tag = n; 498 475 fhash(f); ··· 587 558 } 588 559 589 560 static struct frame * 590 - reassign_frame(struct list_head *pos) 561 + reassign_frame(struct frame *f) 591 562 { 592 - struct frame *f; 593 563 struct frame *nf; 594 564 struct sk_buff *skb; 595 565 596 - f = list_entry(pos, struct frame, head); 597 566 nf = newframe(f->t->d); 598 567 if (!nf) 599 568 return NULL; 600 - 601 - list_del(pos); 569 + if (nf->t == f->t) { 570 + aoe_freetframe(nf); 571 + return NULL; 572 + } 602 573 603 574 skb = nf->skb; 604 575 nf->skb = f->skb; ··· 612 583 nf->sent = f->sent; 613 584 nf->sent_jiffs = f->sent_jiffs; 614 585 f->skb = skb; 615 - aoe_freetframe(f); 616 - f->t->nout--; 617 - nf->t->nout++; 618 586 619 587 return nf; 620 588 } 621 589 622 - static int 623 - sthtith(struct aoedev *d) 590 + static void 591 + probe(struct aoetgt *t) 624 592 { 625 - struct frame *f, *nf; 626 - struct list_head *nx, *pos, *head; 627 - struct aoetgt *ht = d->htgt; 628 - int i; 593 + struct aoedev *d; 594 + struct frame *f; 595 + struct sk_buff *skb; 596 + struct sk_buff_head queue; 597 + size_t n, m; 598 + int frag; 629 599 630 - /* look through the active and pending retransmit frames */ 631 - for (i = 0; i < NFACTIVE; i++) { 632 - head = &d->factive[i]; 633 - list_for_each_safe(pos, nx, head) { 634 - f = list_entry(pos, struct frame, head); 635 - if (f->t != ht) 636 - continue; 637 - nf = reassign_frame(pos); 638 - if (!nf) 639 - return 0; 640 - resend(d, nf); 641 - } 600 + d = t->d; 601 + f = newtframe(d, t); 602 + if (!f) { 603 + pr_err("%s %pm for e%ld.%d: %s\n", 604 + "aoe: cannot probe remote address", 605 + t->addr, 606 + (long) d->aoemajor, d->aoeminor, 607 + "no frame available"); 608 + return; 642 609 } 643 - head = &d->rexmitq; 644 - list_for_each_safe(pos, nx, head) { 645 - f = list_entry(pos, struct frame, head); 646 - if (f->t != ht) 647 - continue; 648 - nf = reassign_frame(pos); 649 - if (!nf) 650 - return 0; 651 - resend(d, nf); 610 + f->flags |= FFL_PROBE; 611 + ifrotate(t); 612 + f->bcnt = t->d->maxbcnt ? t->d->maxbcnt : DEFAULTBCNT; 613 + ata_rw_frameinit(f); 614 + skb = f->skb; 615 + for (frag = 0, n = f->bcnt; n > 0; ++frag, n -= m) { 616 + if (n < PAGE_SIZE) 617 + m = n; 618 + else 619 + m = PAGE_SIZE; 620 + skb_fill_page_desc(skb, frag, empty_page, 0, m); 652 621 } 653 - /* We've cleaned up the outstanding so take away his 654 - * interfaces so he won't be used. We should remove him from 655 - * the target array here, but cleaning up a target is 656 - * involved. PUNT! 657 - */ 658 - memset(ht->ifs, 0, sizeof ht->ifs); 659 - d->htgt = NULL; 660 - return 1; 622 + skb->len += f->bcnt; 623 + skb->data_len = f->bcnt; 624 + skb->truesize += f->bcnt; 625 + 626 + skb = skb_clone(f->skb, GFP_ATOMIC); 627 + if (skb) { 628 + do_gettimeofday(&f->sent); 629 + f->sent_jiffs = (u32) jiffies; 630 + __skb_queue_head_init(&queue); 631 + __skb_queue_tail(&queue, skb); 632 + aoenet_xmit(&queue); 633 + } 634 + } 635 + 636 + static long 637 + rto(struct aoedev *d) 638 + { 639 + long t; 640 + 641 + t = 2 * d->rttavg >> RTTSCALE; 642 + t += 8 * d->rttdev >> RTTDSCALE; 643 + if (t == 0) 644 + t = 1; 645 + 646 + return t; 661 647 } 662 648 663 649 static void ··· 680 636 { 681 637 struct aoetgt *t; 682 638 struct frame *f; 639 + struct frame *nf; 683 640 struct list_head *pos, *nx, *head; 684 641 int since; 642 + int untainted; 643 + 644 + count_targets(d, &untainted); 685 645 686 646 head = &d->rexmitq; 687 647 list_for_each_safe(pos, nx, head) { 688 648 f = list_entry(pos, struct frame, head); 689 649 t = f->t; 650 + if (t->taint) { 651 + if (!(f->flags & FFL_PROBE)) { 652 + nf = reassign_frame(f); 653 + if (nf) { 654 + if (t->nout_probes == 0 655 + && untainted > 0) { 656 + probe(t); 657 + t->nout_probes++; 658 + } 659 + list_replace(&f->head, &nf->head); 660 + pos = &nf->head; 661 + aoe_freetframe(f); 662 + f = nf; 663 + t = f->t; 664 + } 665 + } else if (untainted < 1) { 666 + /* don't probe w/o other untainted aoetgts */ 667 + goto stop_probe; 668 + } else if (tsince_hr(f) < t->taint * rto(d)) { 669 + /* reprobe slowly when taint is high */ 670 + continue; 671 + } 672 + } else if (f->flags & FFL_PROBE) { 673 + stop_probe: /* don't probe untainted aoetgts */ 674 + list_del(pos); 675 + aoe_freetframe(f); 676 + /* leaving d->kicked, because this is routine */ 677 + f->t->d->flags |= DEVFL_KICKME; 678 + continue; 679 + } 690 680 if (t->nout >= t->maxout) 691 681 continue; 692 682 list_del(pos); 693 683 t->nout++; 684 + if (f->flags & FFL_PROBE) 685 + t->nout_probes++; 694 686 since = tsince_hr(f); 695 687 f->waited += since; 696 688 f->waited_total += since; 697 689 resend(d, f); 698 690 } 691 + } 692 + 693 + /* An aoetgt accumulates demerits quickly, and successful 694 + * probing redeems the aoetgt slowly. 695 + */ 696 + static void 697 + scorn(struct aoetgt *t) 698 + { 699 + int n; 700 + 701 + n = t->taint++; 702 + t->taint += t->taint * 2; 703 + if (n > t->taint) 704 + t->taint = n; 705 + if (t->taint > MAX_TAINT) 706 + t->taint = MAX_TAINT; 707 + } 708 + 709 + static int 710 + count_targets(struct aoedev *d, int *untainted) 711 + { 712 + int i, good; 713 + 714 + for (i = good = 0; i < d->ntargets && d->targets[i]; ++i) 715 + if (d->targets[i]->taint == 0) 716 + good++; 717 + 718 + if (untainted) 719 + *untainted = good; 720 + return i; 699 721 } 700 722 701 723 static void ··· 776 666 register long timeout; 777 667 ulong flags, n; 778 668 int i; 669 + int utgts; /* number of aoetgt descriptors (not slots) */ 779 670 int since; 780 671 781 672 d = (struct aoedev *) vp; ··· 784 673 spin_lock_irqsave(&d->lock, flags); 785 674 786 675 /* timeout based on observed timings and variations */ 787 - timeout = 2 * d->rttavg >> RTTSCALE; 788 - timeout += 8 * d->rttdev >> RTTDSCALE; 789 - if (timeout == 0) 790 - timeout = 1; 676 + timeout = rto(d); 677 + 678 + utgts = count_targets(d, NULL); 791 679 792 680 if (d->flags & DEVFL_TKILL) { 793 681 spin_unlock_irqrestore(&d->lock, flags); ··· 812 702 since = tsince_hr(f); 813 703 n = f->waited_total + since; 814 704 n /= USEC_PER_SEC; 815 - if (n > aoe_deadsecs) { 705 + if (n > aoe_deadsecs && !(f->flags & FFL_PROBE)) { 816 706 /* Waited too long. Device failure. 817 707 * Hang all frames on first hash bucket for downdev 818 708 * to clean up. ··· 823 713 } 824 714 825 715 t = f->t; 826 - if (n > aoe_deadsecs/2) 827 - d->htgt = t; /* see if another target can help */ 716 + n = f->waited + since; 717 + n /= USEC_PER_SEC; 718 + if (aoe_deadsecs && utgts > 0 719 + && (n > aoe_deadsecs / utgts || n > HARD_SCORN_SECS)) 720 + scorn(t); /* avoid this target */ 828 721 829 722 if (t->maxout != 1) { 830 723 t->ssthresh = t->maxout / 2; 831 724 t->maxout = 1; 832 725 } 833 726 834 - ifp = getif(t, f->skb->dev); 835 - if (ifp && ++ifp->lost > (t->nframes << 1) 836 - && (ifp != t->ifs || t->ifs[1].nd)) { 837 - ejectif(t, ifp); 838 - ifp = NULL; 727 + if (f->flags & FFL_PROBE) { 728 + t->nout_probes--; 729 + } else { 730 + ifp = getif(t, f->skb->dev); 731 + if (ifp && ++ifp->lost > (t->nframes << 1) 732 + && (ifp != t->ifs || t->ifs[1].nd)) { 733 + ejectif(t, ifp); 734 + ifp = NULL; 735 + } 839 736 } 840 737 list_move_tail(pos, &d->rexmitq); 841 738 t->nout--; ··· 850 733 rexmit_deferred(d); 851 734 852 735 out: 853 - if ((d->flags & DEVFL_KICKME || d->htgt) && d->blkq) { 736 + if ((d->flags & DEVFL_KICKME) && d->blkq) { 854 737 d->flags &= ~DEVFL_KICKME; 855 738 d->blkq->request_fn(d->blkq); 856 739 } ··· 971 854 void 972 855 aoecmd_work(struct aoedev *d) 973 856 { 974 - if (d->htgt && !sthtith(d)) 975 - return; 976 857 rexmit_deferred(d); 977 858 while (aoecmd_ata_rw(d)) 978 859 ; ··· 1180 1065 struct aoeif *ifp; 1181 1066 struct aoedev *d; 1182 1067 long n; 1068 + int untainted; 1183 1069 1184 1070 if (f == NULL) 1185 1071 return; 1186 1072 1187 1073 t = f->t; 1188 1074 d = t->d; 1075 + skb = f->r_skb; 1076 + buf = f->buf; 1077 + if (f->flags & FFL_PROBE) 1078 + goto out; 1079 + if (!skb) /* just fail the buf. */ 1080 + goto noskb; 1189 1081 1190 1082 hout = (struct aoe_hdr *) skb_mac_header(f->skb); 1191 1083 ahout = (struct aoe_atahdr *) (hout+1); 1192 - buf = f->buf; 1193 - skb = f->r_skb; 1194 - if (skb == NULL) 1195 - goto noskb; /* just fail the buf. */ 1196 1084 1197 1085 hin = (struct aoe_hdr *) skb->data; 1198 1086 skb_pull(skb, sizeof(*hin)); ··· 1207 1089 d->aoemajor, d->aoeminor); 1208 1090 noskb: if (buf) 1209 1091 clear_bit(BIO_UPTODATE, &buf->bio->bi_flags); 1210 - goto badrsp; 1092 + goto out; 1211 1093 } 1212 1094 1213 1095 n = ahout->scnt << 9; ··· 1227 1109 ifp = getif(t, skb->dev); 1228 1110 if (ifp) 1229 1111 ifp->lost = 0; 1230 - if (d->htgt == t) /* I'll help myself, thank you. */ 1231 - d->htgt = NULL; 1232 1112 spin_unlock_irq(&d->lock); 1233 1113 break; 1234 1114 case ATA_CMD_ID_ATA: ··· 1247 1131 be16_to_cpu(get_unaligned(&hin->major)), 1248 1132 hin->minor); 1249 1133 } 1250 - badrsp: 1134 + out: 1251 1135 spin_lock_irq(&d->lock); 1136 + if (t->taint > 0 1137 + && --t->taint > 0 1138 + && t->nout_probes == 0) { 1139 + count_targets(d, &untainted); 1140 + if (untainted > 0) { 1141 + probe(t); 1142 + t->nout_probes++; 1143 + } 1144 + } 1252 1145 1253 1146 aoe_freetframe(f); 1254 1147 ··· 1386 1261 if (f) { 1387 1262 calc_rttavg(d, f->t, tsince_hr(f)); 1388 1263 f->t->nout--; 1264 + if (f->flags & FFL_PROBE) 1265 + f->t->nout_probes--; 1389 1266 } else { 1390 1267 f = getframe_deferred(d, n); 1391 1268 if (f) { ··· 1506 1379 memcpy(t->addr, addr, sizeof t->addr); 1507 1380 t->ifp = t->ifs; 1508 1381 aoecmd_wreset(t); 1382 + t->maxout = t->nframes / 2; 1509 1383 INIT_LIST_HEAD(&t->ffree); 1510 1384 return *tt = t; 1511 1385 } ··· 1712 1584 int __init 1713 1585 aoecmd_init(void) 1714 1586 { 1587 + void *p; 1588 + 1589 + /* get_zeroed_page returns page with ref count 1 */ 1590 + p = (void *) get_zeroed_page(GFP_KERNEL | __GFP_REPEAT); 1591 + if (!p) 1592 + return -ENOMEM; 1593 + empty_page = virt_to_page(p); 1594 + 1715 1595 INIT_LIST_HEAD(&iocq.head); 1716 1596 spin_lock_init(&iocq.lock); 1717 1597 init_waitqueue_head(&ktiowq); ··· 1735 1599 { 1736 1600 aoe_ktstop(&kts); 1737 1601 aoe_flush_iocq(); 1602 + 1603 + free_page((unsigned long) page_address(empty_page)); 1604 + empty_page = NULL; 1738 1605 }
-1
drivers/block/aoe/aoedev.c
··· 223 223 224 224 /* clean out the in-process request (if any) */ 225 225 aoe_failip(d); 226 - d->htgt = NULL; 227 226 228 227 /* fast fail all pending I/O */ 229 228 if (d->blkq) {