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

cciss: switch to using hlist for command list management

This both cleans up the code and also helps detect the spurious case
of a command attempted being removed from a queue it doesn't belong
to.

Acked-by: Mike Miller <mike.miller@hp.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>

+33 -46
+30 -42
drivers/block/cciss.c
··· 215 215 /* 216 216 * Enqueuing and dequeuing functions for cmdlists. 217 217 */ 218 - static inline void addQ(CommandList_struct **Qptr, CommandList_struct *c) 218 + static inline void addQ(struct hlist_head *list, CommandList_struct *c) 219 219 { 220 - if (*Qptr == NULL) { 221 - *Qptr = c; 222 - c->next = c->prev = c; 223 - } else { 224 - c->prev = (*Qptr)->prev; 225 - c->next = (*Qptr); 226 - (*Qptr)->prev->next = c; 227 - (*Qptr)->prev = c; 228 - } 220 + hlist_add_head(&c->list, list); 229 221 } 230 222 231 - static inline CommandList_struct *removeQ(CommandList_struct **Qptr, 232 - CommandList_struct *c) 223 + static inline void removeQ(CommandList_struct *c) 233 224 { 234 - if (c && c->next != c) { 235 - if (*Qptr == c) 236 - *Qptr = c->next; 237 - c->prev->next = c->next; 238 - c->next->prev = c->prev; 239 - } else { 240 - *Qptr = NULL; 241 - } 242 - return c; 225 + if (WARN_ON(hlist_unhashed(&c->list))) 226 + return; 227 + 228 + hlist_del_init(&c->list); 243 229 } 244 230 245 231 #include "cciss_scsi.c" /* For SCSI tape support */ ··· 492 506 c->cmdindex = i; 493 507 } 494 508 509 + INIT_HLIST_NODE(&c->list); 495 510 c->busaddr = (__u32) cmd_dma_handle; 496 511 temp64.val = (__u64) err_dma_handle; 497 512 c->ErrDesc.Addr.lower = temp64.val32.lower; ··· 2535 2548 { 2536 2549 CommandList_struct *c; 2537 2550 2538 - while ((c = h->reqQ) != NULL) { 2551 + while (!hlist_empty(&h->reqQ)) { 2552 + c = hlist_entry(h->reqQ.first, CommandList_struct, list); 2539 2553 /* can't do anything if fifo is full */ 2540 2554 if ((h->access.fifo_full(h))) { 2541 2555 printk(KERN_WARNING "cciss: fifo full\n"); ··· 2544 2556 } 2545 2557 2546 2558 /* Get the first entry from the Request Q */ 2547 - removeQ(&(h->reqQ), c); 2559 + removeQ(c); 2548 2560 h->Qdepth--; 2549 2561 2550 2562 /* Tell the controller execute command */ 2551 2563 h->access.submit_command(h, c); 2552 2564 2553 2565 /* Put job onto the completed Q */ 2554 - addQ(&(h->cmpQ), c); 2566 + addQ(&h->cmpQ, c); 2555 2567 } 2556 2568 } 2557 2569 ··· 2564 2576 memset(c->err_info, 0, sizeof(ErrorInfo_struct)); 2565 2577 2566 2578 /* add it to software queue and then send it to the controller */ 2567 - addQ(&(h->reqQ), c); 2579 + addQ(&h->reqQ, c); 2568 2580 h->Qdepth++; 2569 2581 if (h->Qdepth > h->maxQsinceinit) 2570 2582 h->maxQsinceinit = h->Qdepth; ··· 2885 2897 2886 2898 spin_lock_irq(q->queue_lock); 2887 2899 2888 - addQ(&(h->reqQ), c); 2900 + addQ(&h->reqQ, c); 2889 2901 h->Qdepth++; 2890 2902 if (h->Qdepth > h->maxQsinceinit) 2891 2903 h->maxQsinceinit = h->Qdepth; ··· 2973 2985 a = c->busaddr; 2974 2986 2975 2987 } else { 2988 + struct hlist_node *tmp; 2989 + 2976 2990 a &= ~3; 2977 - if ((c = h->cmpQ) == NULL) { 2978 - printk(KERN_WARNING 2979 - "cciss: Completion of %08x ignored\n", 2980 - a1); 2981 - continue; 2982 - } 2983 - while (c->busaddr != a) { 2984 - c = c->next; 2985 - if (c == h->cmpQ) 2991 + c = NULL; 2992 + hlist_for_each_entry(c, tmp, &h->cmpQ, list) { 2993 + if (c->busaddr == a) 2986 2994 break; 2987 2995 } 2988 2996 } ··· 2986 3002 * If we've found the command, take it off the 2987 3003 * completion Q and free it 2988 3004 */ 2989 - if (c->busaddr == a) { 2990 - removeQ(&h->cmpQ, c); 3005 + if (c && c->busaddr == a) { 3006 + removeQ(c); 2991 3007 if (c->cmd_type == CMD_RWREQ) { 2992 3008 complete_command(h, c, 0); 2993 3009 } else if (c->cmd_type == CMD_IOCTL_PEND) { ··· 3407 3423 return -1; 3408 3424 3409 3425 hba[i]->busy_initializing = 1; 3426 + INIT_HLIST_HEAD(&hba[i]->cmpQ); 3427 + INIT_HLIST_HEAD(&hba[i]->reqQ); 3410 3428 3411 3429 if (cciss_pci_init(hba[i], pdev) != 0) 3412 3430 goto clean1; ··· 3716 3730 pci_disable_device(h->pdev); /* Make sure it is really dead. */ 3717 3731 3718 3732 /* move everything off the request queue onto the completed queue */ 3719 - while ((c = h->reqQ) != NULL) { 3720 - removeQ(&(h->reqQ), c); 3733 + while (!hlist_empty(&h->reqQ)) { 3734 + c = hlist_entry(h->reqQ.first, CommandList_struct, list); 3735 + removeQ(c); 3721 3736 h->Qdepth--; 3722 - addQ(&(h->cmpQ), c); 3737 + addQ(&h->cmpQ, c); 3723 3738 } 3724 3739 3725 3740 /* Now, fail everything on the completed queue with a HW error */ 3726 - while ((c = h->cmpQ) != NULL) { 3727 - removeQ(&h->cmpQ, c); 3741 + while (!hlist_empty(&h->cmpQ)) { 3742 + c = hlist_entry(h->cmpQ.first, CommandList_struct, list); 3743 + removeQ(c); 3728 3744 c->err_info->CommandStatus = CMD_HARDWARE_ERR; 3729 3745 if (c->cmd_type == CMD_RWREQ) { 3730 3746 complete_command(h, c, 0);
+2 -2
drivers/block/cciss.h
··· 89 89 struct access_method access; 90 90 91 91 /* queue and queue Info */ 92 - CommandList_struct *reqQ; 93 - CommandList_struct *cmpQ; 92 + struct hlist_head reqQ; 93 + struct hlist_head cmpQ; 94 94 unsigned int Qdepth; 95 95 unsigned int maxQsinceinit; 96 96 unsigned int maxSG;
+1 -2
drivers/block/cciss_cmd.h
··· 265 265 int ctlr; 266 266 int cmd_type; 267 267 long cmdindex; 268 - struct _CommandList_struct *prev; 269 - struct _CommandList_struct *next; 268 + struct hlist_node list; 270 269 struct request * rq; 271 270 struct completion *waiting; 272 271 int retry_count;