* Cancel an already dispatched task given the task id. Still pending tasks * will be immediately canceled, and if the task is active the function will * block until it completes. Preallocated tasks which are canceled must be * freed by the caller. */
| 512 | * freed by the caller. |
| 513 | */ |
| 514 | int |
| 515 | taskq_cancel_id(taskq_t *tq, taskqid_t id) |
| 516 | { |
| 517 | taskq_ent_t *t; |
| 518 | int rc = ENOENT; |
| 519 | unsigned long flags; |
| 520 | |
| 521 | ASSERT(tq); |
| 522 | |
| 523 | spin_lock_irqsave_nested(&tq->tq_lock, flags, tq->tq_lock_class); |
| 524 | t = taskq_find(tq, id); |
| 525 | if (t && t != ERR_PTR(-EBUSY)) { |
| 526 | list_del_init(&t->tqent_list); |
| 527 | t->tqent_flags |= TQENT_FLAG_CANCEL; |
| 528 | |
| 529 | /* |
| 530 | * When canceling the lowest outstanding task id we |
| 531 | * must recalculate the new lowest outstanding id. |
| 532 | */ |
| 533 | if (tq->tq_lowest_id == t->tqent_id) { |
| 534 | tq->tq_lowest_id = taskq_lowest_id(tq); |
| 535 | ASSERT3S(tq->tq_lowest_id, >, t->tqent_id); |
| 536 | } |
| 537 | |
| 538 | /* |
| 539 | * The task_expire() function takes the tq->tq_lock so drop |
| 540 | * drop the lock before synchronously cancelling the timer. |
| 541 | */ |
| 542 | if (timer_pending(&t->tqent_timer)) { |
| 543 | spin_unlock_irqrestore(&tq->tq_lock, flags); |
| 544 | del_timer_sync(&t->tqent_timer); |
| 545 | spin_lock_irqsave_nested(&tq->tq_lock, flags, |
| 546 | tq->tq_lock_class); |
| 547 | } |
| 548 | |
| 549 | if (!(t->tqent_flags & TQENT_FLAG_PREALLOC)) |
| 550 | task_done(tq, t); |
| 551 | |
| 552 | rc = 0; |
| 553 | } |
| 554 | spin_unlock_irqrestore(&tq->tq_lock, flags); |
| 555 | |
| 556 | if (t == ERR_PTR(-EBUSY)) { |
| 557 | taskq_wait_id(tq, id); |
| 558 | rc = EBUSY; |
| 559 | } |
| 560 | |
| 561 | return (rc); |
| 562 | } |
| 563 | EXPORT_SYMBOL(taskq_cancel_id); |
| 564 | |
| 565 | static int taskq_thread_spawn(taskq_t *tq); |
no test coverage detected