2022-07-12 23:52:38 +03:00
# include <linux/kernel.h>
# include <linux/errno.h>
# include <linux/file.h>
# include <linux/slab.h>
# include <linux/net.h>
# include <linux/io_uring.h>
# include "io_uring.h"
# include "notif.h"
2022-07-12 23:52:41 +03:00
# include "rsrc.h"
2022-07-12 23:52:38 +03:00
2022-07-27 12:30:41 +03:00
static void __io_notif_complete_tw ( struct io_kiocb * notif , bool * locked )
2022-07-12 23:52:38 +03:00
{
2022-07-27 12:30:41 +03:00
struct io_notif_data * nd = io_notif_to_data ( notif ) ;
2022-07-12 23:52:38 +03:00
struct io_ring_ctx * ctx = notif - > ctx ;
2022-07-27 12:30:41 +03:00
if ( nd - > account_pages & & ctx - > user ) {
__io_unaccount_mem ( ctx - > user , nd - > account_pages ) ;
nd - > account_pages = 0 ;
2022-07-12 23:52:44 +03:00
}
2022-10-27 21:34:45 +03:00
if ( nd - > zc_report & & ( nd - > zc_copied | | ! nd - > zc_used ) )
notif - > cqe . res | = IORING_NOTIF_USAGE_ZC_COPIED ;
2022-07-27 12:30:41 +03:00
io_req_task_complete ( notif , locked ) ;
2022-07-12 23:52:38 +03:00
}
static void io_uring_tx_zerocopy_callback ( struct sk_buff * skb ,
struct ubuf_info * uarg ,
bool success )
{
2022-07-27 12:30:41 +03:00
struct io_notif_data * nd = container_of ( uarg , struct io_notif_data , uarg ) ;
struct io_kiocb * notif = cmd_to_io_kiocb ( nd ) ;
2022-07-12 23:52:39 +03:00
2022-10-27 21:34:45 +03:00
if ( nd - > zc_report ) {
if ( success & & ! nd - > zc_used & & skb )
WRITE_ONCE ( nd - > zc_used , true ) ;
else if ( ! success & & ! nd - > zc_copied )
WRITE_ONCE ( nd - > zc_copied , true ) ;
}
2022-11-04 13:59:42 +03:00
if ( refcount_dec_and_test ( & uarg - > refcnt ) )
2022-07-27 12:30:41 +03:00
io_req_task_work_add ( notif ) ;
2022-07-12 23:52:39 +03:00
}
2022-09-01 13:54:04 +03:00
struct io_kiocb * io_alloc_notif ( struct io_ring_ctx * ctx )
2022-07-12 23:52:38 +03:00
__must_hold ( & ctx - > uring_lock )
{
2022-07-27 12:30:41 +03:00
struct io_kiocb * notif ;
struct io_notif_data * nd ;
if ( unlikely ( ! io_alloc_req_refill ( ctx ) ) )
return NULL ;
notif = io_alloc_req ( ctx ) ;
notif - > opcode = IORING_OP_NOP ;
notif - > flags = 0 ;
notif - > file = NULL ;
notif - > task = current ;
io_get_task_refs ( 1 ) ;
notif - > rsrc_node = NULL ;
2022-11-04 13:59:42 +03:00
notif - > io_task_work . func = __io_notif_complete_tw ;
2022-07-27 12:30:41 +03:00
nd = io_notif_to_data ( notif ) ;
nd - > account_pages = 0 ;
nd - > uarg . flags = SKBFL_ZEROCOPY_FRAG | SKBFL_DONT_ORPHAN ;
nd - > uarg . callback = io_uring_tx_zerocopy_callback ;
2022-10-27 21:34:45 +03:00
nd - > zc_report = nd - > zc_used = nd - > zc_copied = false ;
2022-07-27 12:30:41 +03:00
refcount_set ( & nd - > uarg . refcnt , 1 ) ;
2022-07-12 23:52:38 +03:00
return notif ;
}
2022-09-01 13:54:04 +03:00
void io_notif_flush ( struct io_kiocb * notif )
2022-08-24 15:07:38 +03:00
__must_hold ( & slot - > notif - > ctx - > uring_lock )
2022-07-12 23:52:38 +03:00
{
2022-07-27 12:30:41 +03:00
struct io_notif_data * nd = io_notif_to_data ( notif ) ;
2022-07-12 23:52:38 +03:00
/* drop slot's master ref */
2022-11-04 13:59:42 +03:00
if ( refcount_dec_and_test ( & nd - > uarg . refcnt ) )
2022-08-24 15:07:41 +03:00
io_req_task_work_add ( notif ) ;
2022-07-12 23:52:38 +03:00
}