@@ -93,6 +93,32 @@ static void io_poll_req_delete(struct io_kiocb *req, struct io_ring_ctx *ctx)
9393 spin_unlock (lock );
9494}
9595
96+ static void io_poll_req_insert_locked (struct io_kiocb * req )
97+ {
98+ struct io_hash_table * table = & req -> ctx -> cancel_table_locked ;
99+ u32 index = hash_long (req -> cqe .user_data , table -> hash_bits );
100+
101+ hlist_add_head (& req -> hash_node , & table -> hbs [index ].list );
102+ }
103+
104+ static void io_poll_tw_hash_eject (struct io_kiocb * req , bool * locked )
105+ {
106+ struct io_ring_ctx * ctx = req -> ctx ;
107+
108+ if (req -> flags & REQ_F_HASH_LOCKED ) {
109+ /*
110+ * ->cancel_table_locked is protected by ->uring_lock in
111+ * contrast to per bucket spinlocks. Likely, tctx_task_work()
112+ * already grabbed the mutex for us, but there is a chance it
113+ * failed.
114+ */
115+ io_tw_lock (ctx , locked );
116+ hash_del (& req -> hash_node );
117+ } else {
118+ io_poll_req_delete (req , ctx );
119+ }
120+ }
121+
96122static void io_init_poll_iocb (struct io_poll * poll , __poll_t events ,
97123 wait_queue_func_t wake_func )
98124{
@@ -217,7 +243,6 @@ static int io_poll_check_events(struct io_kiocb *req, bool *locked)
217243
218244static void io_poll_task_func (struct io_kiocb * req , bool * locked )
219245{
220- struct io_ring_ctx * ctx = req -> ctx ;
221246 int ret ;
222247
223248 ret = io_poll_check_events (req , locked );
@@ -234,7 +259,8 @@ static void io_poll_task_func(struct io_kiocb *req, bool *locked)
234259 }
235260
236261 io_poll_remove_entries (req );
237- io_poll_req_delete (req , ctx );
262+ io_poll_tw_hash_eject (req , locked );
263+
238264 io_req_set_res (req , req -> cqe .res , 0 );
239265 io_req_task_complete (req , locked );
240266}
@@ -248,7 +274,7 @@ static void io_apoll_task_func(struct io_kiocb *req, bool *locked)
248274 return ;
249275
250276 io_poll_remove_entries (req );
251- io_poll_req_delete (req , req -> ctx );
277+ io_poll_tw_hash_eject (req , locked );
252278
253279 if (!ret )
254280 io_req_task_submit (req , locked );
@@ -444,7 +470,10 @@ static int __io_arm_poll_handler(struct io_kiocb *req,
444470 return 0 ;
445471 }
446472
447- io_poll_req_insert (req );
473+ if (req -> flags & REQ_F_HASH_LOCKED )
474+ io_poll_req_insert_locked (req );
475+ else
476+ io_poll_req_insert (req );
448477
449478 if (mask && (poll -> events & EPOLLET )) {
450479 /* can't multishot if failed, just queue the event we've got */
@@ -485,6 +514,15 @@ int io_arm_poll_handler(struct io_kiocb *req, unsigned issue_flags)
485514 __poll_t mask = POLLPRI | POLLERR | EPOLLET ;
486515 int ret ;
487516
517+ /*
518+ * apoll requests already grab the mutex to complete in the tw handler,
519+ * so removal from the mutex-backed hash is free, use it by default.
520+ */
521+ if (issue_flags & IO_URING_F_UNLOCKED )
522+ req -> flags &= ~REQ_F_HASH_LOCKED ;
523+ else
524+ req -> flags |= REQ_F_HASH_LOCKED ;
525+
488526 if (!def -> pollin && !def -> pollout )
489527 return IO_APOLL_ABORTED ;
490528 if (!file_can_poll (req -> file ))
@@ -534,13 +572,10 @@ int io_arm_poll_handler(struct io_kiocb *req, unsigned issue_flags)
534572 return IO_APOLL_OK ;
535573}
536574
537- /*
538- * Returns true if we found and killed one or more poll requests
539- */
540- __cold bool io_poll_remove_all (struct io_ring_ctx * ctx , struct task_struct * tsk ,
541- bool cancel_all )
575+ static __cold bool io_poll_remove_all_table (struct task_struct * tsk ,
576+ struct io_hash_table * table ,
577+ bool cancel_all )
542578{
543- struct io_hash_table * table = & ctx -> cancel_table ;
544579 unsigned nr_buckets = 1U << table -> hash_bits ;
545580 struct hlist_node * tmp ;
546581 struct io_kiocb * req ;
@@ -563,6 +598,17 @@ __cold bool io_poll_remove_all(struct io_ring_ctx *ctx, struct task_struct *tsk,
563598 return found ;
564599}
565600
601+ /*
602+ * Returns true if we found and killed one or more poll requests
603+ */
604+ __cold bool io_poll_remove_all (struct io_ring_ctx * ctx , struct task_struct * tsk ,
605+ bool cancel_all )
606+ __must_hold (& ctx - > uring_lock )
607+ {
608+ return io_poll_remove_all_table (tsk , & ctx -> cancel_table , cancel_all ) |
609+ io_poll_remove_all_table (tsk , & ctx -> cancel_table_locked , cancel_all );
610+ }
611+
566612static struct io_kiocb * io_poll_find (struct io_ring_ctx * ctx , bool poll_only ,
567613 struct io_cancel_data * cd ,
568614 struct io_hash_table * table ,
@@ -622,13 +668,15 @@ static struct io_kiocb *io_poll_file_find(struct io_ring_ctx *ctx,
622668 return NULL ;
623669}
624670
625- static bool io_poll_disarm (struct io_kiocb * req )
671+ static int io_poll_disarm (struct io_kiocb * req )
626672{
673+ if (!req )
674+ return - ENOENT ;
627675 if (!io_poll_get_ownership (req ))
628- return false ;
676+ return - EALREADY ;
629677 io_poll_remove_entries (req );
630678 hash_del (& req -> hash_node );
631- return true ;
679+ return 0 ;
632680}
633681
634682static int __io_poll_cancel (struct io_ring_ctx * ctx , struct io_cancel_data * cd ,
@@ -652,7 +700,16 @@ static int __io_poll_cancel(struct io_ring_ctx *ctx, struct io_cancel_data *cd,
652700int io_poll_cancel (struct io_ring_ctx * ctx , struct io_cancel_data * cd ,
653701 unsigned issue_flags )
654702{
655- return __io_poll_cancel (ctx , cd , & ctx -> cancel_table );
703+ int ret ;
704+
705+ ret = __io_poll_cancel (ctx , cd , & ctx -> cancel_table );
706+ if (ret != - ENOENT )
707+ return ret ;
708+
709+ io_ring_submit_lock (ctx , issue_flags );
710+ ret = __io_poll_cancel (ctx , cd , & ctx -> cancel_table_locked );
711+ io_ring_submit_unlock (ctx , issue_flags );
712+ return ret ;
656713}
657714
658715static __poll_t io_poll_parse_events (const struct io_uring_sqe * sqe ,
@@ -727,6 +784,16 @@ int io_poll_add(struct io_kiocb *req, unsigned int issue_flags)
727784
728785 ipt .pt ._qproc = io_poll_queue_proc ;
729786
787+ /*
788+ * If sqpoll or single issuer, there is no contention for ->uring_lock
789+ * and we'll end up holding it in tw handlers anyway.
790+ */
791+ if (!(issue_flags & IO_URING_F_UNLOCKED ) &&
792+ (req -> ctx -> flags & (IORING_SETUP_SQPOLL | IORING_SETUP_SINGLE_ISSUER )))
793+ req -> flags |= REQ_F_HASH_LOCKED ;
794+ else
795+ req -> flags &= ~REQ_F_HASH_LOCKED ;
796+
730797 ret = __io_arm_poll_handler (req , poll , & ipt , poll -> events );
731798 if (ret ) {
732799 io_req_set_res (req , ret , 0 );
@@ -751,20 +818,28 @@ int io_poll_remove(struct io_kiocb *req, unsigned int issue_flags)
751818 bool locked ;
752819
753820 preq = io_poll_find (ctx , true, & cd , & ctx -> cancel_table , & bucket );
754- if (preq )
755- ret2 = io_poll_disarm (preq );
821+ ret2 = io_poll_disarm (preq );
756822 if (bucket )
757823 spin_unlock (& bucket -> lock );
758-
759- if (!preq ) {
760- ret = - ENOENT ;
824+ if (!ret2 )
825+ goto found ;
826+ if (ret2 != - ENOENT ) {
827+ ret = ret2 ;
761828 goto out ;
762829 }
763- if (!ret2 ) {
764- ret = - EALREADY ;
830+
831+ io_ring_submit_lock (ctx , issue_flags );
832+ preq = io_poll_find (ctx , true, & cd , & ctx -> cancel_table_locked , & bucket );
833+ ret2 = io_poll_disarm (preq );
834+ if (bucket )
835+ spin_unlock (& bucket -> lock );
836+ io_ring_submit_unlock (ctx , issue_flags );
837+ if (ret2 ) {
838+ ret = ret2 ;
765839 goto out ;
766840 }
767841
842+ found :
768843 if (poll_update -> update_events || poll_update -> update_user_data ) {
769844 /* only mask one event flags, keep behavior flags */
770845 if (poll_update -> update_events ) {
0 commit comments