@@ -587,6 +587,7 @@ struct io_cancel {
587587 struct file * file ;
588588 u64 addr ;
589589 u32 flags ;
590+ s32 fd ;
590591};
591592
592593struct io_timeout {
@@ -992,7 +993,10 @@ struct io_defer_entry {
992993
993994struct io_cancel_data {
994995 struct io_ring_ctx * ctx ;
995- u64 data ;
996+ union {
997+ u64 data ;
998+ struct file * file ;
999+ };
9961000 u32 flags ;
9971001 int seq ;
9981002};
@@ -6332,6 +6336,29 @@ static struct io_kiocb *io_poll_find(struct io_ring_ctx *ctx, bool poll_only,
63326336 return NULL ;
63336337}
63346338
6339+ static struct io_kiocb * io_poll_file_find (struct io_ring_ctx * ctx ,
6340+ struct io_cancel_data * cd )
6341+ __must_hold (& ctx - > completion_lock )
6342+ {
6343+ struct io_kiocb * req ;
6344+ int i ;
6345+
6346+ for (i = 0 ; i < (1U << ctx -> cancel_hash_bits ); i ++ ) {
6347+ struct hlist_head * list ;
6348+
6349+ list = & ctx -> cancel_hash [i ];
6350+ hlist_for_each_entry (req , list , hash_node ) {
6351+ if (req -> file != cd -> file )
6352+ continue ;
6353+ if (cd -> seq == req -> work .cancel_seq )
6354+ continue ;
6355+ req -> work .cancel_seq = cd -> seq ;
6356+ return req ;
6357+ }
6358+ }
6359+ return NULL ;
6360+ }
6361+
63356362static bool io_poll_disarm (struct io_kiocb * req )
63366363 __must_hold (& ctx - > completion_lock )
63376364{
@@ -6345,8 +6372,12 @@ static bool io_poll_disarm(struct io_kiocb *req)
63456372static int io_poll_cancel (struct io_ring_ctx * ctx , struct io_cancel_data * cd )
63466373 __must_hold (& ctx - > completion_lock )
63476374{
6348- struct io_kiocb * req = io_poll_find ( ctx , false, cd ) ;
6375+ struct io_kiocb * req ;
63496376
6377+ if (cd -> flags & IORING_ASYNC_CANCEL_FD )
6378+ req = io_poll_file_find (ctx , cd );
6379+ else
6380+ req = io_poll_find (ctx , false, cd );
63506381 if (!req )
63516382 return - ENOENT ;
63526383 io_poll_cancel_req (req );
@@ -6796,8 +6827,13 @@ static bool io_cancel_cb(struct io_wq_work *work, void *data)
67966827
67976828 if (req -> ctx != cd -> ctx )
67986829 return false;
6799- if (req -> cqe .user_data != cd -> data )
6800- return false;
6830+ if (cd -> flags & IORING_ASYNC_CANCEL_FD ) {
6831+ if (req -> file != cd -> file )
6832+ return false;
6833+ } else {
6834+ if (req -> cqe .user_data != cd -> data )
6835+ return false;
6836+ }
68016837 if (cd -> flags & IORING_ASYNC_CANCEL_ALL ) {
68026838 if (cd -> seq == req -> work .cancel_seq )
68036839 return false;
@@ -6851,7 +6887,8 @@ static int io_try_cancel(struct io_kiocb *req, struct io_cancel_data *cd)
68516887 ret = io_poll_cancel (ctx , cd );
68526888 if (ret != - ENOENT )
68536889 goto out ;
6854- ret = io_timeout_cancel (ctx , cd );
6890+ if (!(cd -> flags & IORING_ASYNC_CANCEL_FD ))
6891+ ret = io_timeout_cancel (ctx , cd );
68556892out :
68566893 spin_unlock (& ctx -> completion_lock );
68576894 return ret ;
@@ -6862,15 +6899,17 @@ static int io_async_cancel_prep(struct io_kiocb *req,
68626899{
68636900 if (unlikely (req -> ctx -> flags & IORING_SETUP_IOPOLL ))
68646901 return - EINVAL ;
6865- if (unlikely (req -> flags & ( REQ_F_FIXED_FILE | REQ_F_BUFFER_SELECT ) ))
6902+ if (unlikely (req -> flags & REQ_F_BUFFER_SELECT ))
68666903 return - EINVAL ;
68676904 if (sqe -> ioprio || sqe -> off || sqe -> len || sqe -> splice_fd_in )
68686905 return - EINVAL ;
68696906
68706907 req -> cancel .addr = READ_ONCE (sqe -> addr );
68716908 req -> cancel .flags = READ_ONCE (sqe -> cancel_flags );
6872- if (req -> cancel .flags & ~IORING_ASYNC_CANCEL_ALL )
6909+ if (req -> cancel .flags & ~( IORING_ASYNC_CANCEL_ALL | IORING_ASYNC_CANCEL_FD ) )
68736910 return - EINVAL ;
6911+ if (req -> cancel .flags & IORING_ASYNC_CANCEL_FD )
6912+ req -> cancel .fd = READ_ONCE (sqe -> fd );
68746913
68756914 return 0 ;
68766915}
@@ -6919,7 +6958,21 @@ static int io_async_cancel(struct io_kiocb *req, unsigned int issue_flags)
69196958 };
69206959 int ret ;
69216960
6961+ if (cd .flags & IORING_ASYNC_CANCEL_FD ) {
6962+ if (req -> flags & REQ_F_FIXED_FILE )
6963+ req -> file = io_file_get_fixed (req , req -> cancel .fd ,
6964+ issue_flags );
6965+ else
6966+ req -> file = io_file_get_normal (req , req -> cancel .fd );
6967+ if (!req -> file ) {
6968+ ret = - EBADF ;
6969+ goto done ;
6970+ }
6971+ cd .file = req -> file ;
6972+ }
6973+
69226974 ret = __io_async_cancel (& cd , req , issue_flags );
6975+ done :
69236976 if (ret < 0 )
69246977 req_set_fail (req );
69256978 io_req_complete_post (req , ret , 0 );
0 commit comments