15
15
16
16
struct io_msg {
17
17
struct file * file ;
18
+ struct file * src_file ;
18
19
u64 user_data ;
19
20
u32 len ;
20
21
u32 cmd ;
@@ -23,6 +24,17 @@ struct io_msg {
23
24
u32 flags ;
24
25
};
25
26
27
+ void io_msg_ring_cleanup (struct io_kiocb * req )
28
+ {
29
+ struct io_msg * msg = io_kiocb_to_cmd (req , struct io_msg );
30
+
31
+ if (WARN_ON_ONCE (!msg -> src_file ))
32
+ return ;
33
+
34
+ fput (msg -> src_file );
35
+ msg -> src_file = NULL ;
36
+ }
37
+
26
38
static int io_msg_ring_data (struct io_kiocb * req )
27
39
{
28
40
struct io_ring_ctx * target_ctx = req -> file -> private_data ;
@@ -37,17 +49,13 @@ static int io_msg_ring_data(struct io_kiocb *req)
37
49
return - EOVERFLOW ;
38
50
}
39
51
40
- static void io_double_unlock_ctx (struct io_ring_ctx * ctx ,
41
- struct io_ring_ctx * octx ,
52
+ static void io_double_unlock_ctx (struct io_ring_ctx * octx ,
42
53
unsigned int issue_flags )
43
54
{
44
- if (issue_flags & IO_URING_F_UNLOCKED )
45
- mutex_unlock (& ctx -> uring_lock );
46
55
mutex_unlock (& octx -> uring_lock );
47
56
}
48
57
49
- static int io_double_lock_ctx (struct io_ring_ctx * ctx ,
50
- struct io_ring_ctx * octx ,
58
+ static int io_double_lock_ctx (struct io_ring_ctx * octx ,
51
59
unsigned int issue_flags )
52
60
{
53
61
/*
@@ -60,52 +68,56 @@ static int io_double_lock_ctx(struct io_ring_ctx *ctx,
60
68
return - EAGAIN ;
61
69
return 0 ;
62
70
}
71
+ mutex_lock (& octx -> uring_lock );
72
+ return 0 ;
73
+ }
63
74
64
- /* Always grab smallest value ctx first. We know ctx != octx. */
65
- if (ctx < octx ) {
66
- mutex_lock (& ctx -> uring_lock );
67
- mutex_lock (& octx -> uring_lock );
68
- } else {
69
- mutex_lock (& octx -> uring_lock );
70
- mutex_lock (& ctx -> uring_lock );
75
+ static struct file * io_msg_grab_file (struct io_kiocb * req , unsigned int issue_flags )
76
+ {
77
+ struct io_msg * msg = io_kiocb_to_cmd (req , struct io_msg );
78
+ struct io_ring_ctx * ctx = req -> ctx ;
79
+ struct file * file = NULL ;
80
+ unsigned long file_ptr ;
81
+ int idx = msg -> src_fd ;
82
+
83
+ io_ring_submit_lock (ctx , issue_flags );
84
+ if (likely (idx < ctx -> nr_user_files )) {
85
+ idx = array_index_nospec (idx , ctx -> nr_user_files );
86
+ file_ptr = io_fixed_file_slot (& ctx -> file_table , idx )-> file_ptr ;
87
+ file = (struct file * ) (file_ptr & FFS_MASK );
88
+ if (file )
89
+ get_file (file );
71
90
}
72
-
73
- return 0 ;
91
+ io_ring_submit_unlock ( ctx , issue_flags );
92
+ return file ;
74
93
}
75
94
76
95
static int io_msg_send_fd (struct io_kiocb * req , unsigned int issue_flags )
77
96
{
78
97
struct io_ring_ctx * target_ctx = req -> file -> private_data ;
79
98
struct io_msg * msg = io_kiocb_to_cmd (req , struct io_msg );
80
99
struct io_ring_ctx * ctx = req -> ctx ;
81
- unsigned long file_ptr ;
82
- struct file * src_file ;
100
+ struct file * src_file = msg -> src_file ;
83
101
int ret ;
84
102
85
103
if (target_ctx == ctx )
86
104
return - EINVAL ;
105
+ if (!src_file ) {
106
+ src_file = io_msg_grab_file (req , issue_flags );
107
+ if (!src_file )
108
+ return - EBADF ;
109
+ msg -> src_file = src_file ;
110
+ req -> flags |= REQ_F_NEED_CLEANUP ;
111
+ }
87
112
88
- ret = io_double_lock_ctx (ctx , target_ctx , issue_flags );
89
- if (unlikely (ret ))
90
- return ret ;
91
-
92
- ret = - EBADF ;
93
- if (unlikely (msg -> src_fd >= ctx -> nr_user_files ))
94
- goto out_unlock ;
95
-
96
- msg -> src_fd = array_index_nospec (msg -> src_fd , ctx -> nr_user_files );
97
- file_ptr = io_fixed_file_slot (& ctx -> file_table , msg -> src_fd )-> file_ptr ;
98
- if (!file_ptr )
99
- goto out_unlock ;
100
-
101
- src_file = (struct file * ) (file_ptr & FFS_MASK );
102
- get_file (src_file );
113
+ if (unlikely (io_double_lock_ctx (target_ctx , issue_flags )))
114
+ return - EAGAIN ;
103
115
104
116
ret = __io_fixed_fd_install (target_ctx , src_file , msg -> dst_fd );
105
- if (ret < 0 ) {
106
- fput (src_file );
117
+ if (ret < 0 )
107
118
goto out_unlock ;
108
- }
119
+ msg -> src_file = NULL ;
120
+ req -> flags &= ~REQ_F_NEED_CLEANUP ;
109
121
110
122
if (msg -> flags & IORING_MSG_RING_CQE_SKIP )
111
123
goto out_unlock ;
@@ -119,7 +131,7 @@ static int io_msg_send_fd(struct io_kiocb *req, unsigned int issue_flags)
119
131
if (!io_post_aux_cqe (target_ctx , msg -> user_data , msg -> len , 0 ))
120
132
ret = - EOVERFLOW ;
121
133
out_unlock :
122
- io_double_unlock_ctx (ctx , target_ctx , issue_flags );
134
+ io_double_unlock_ctx (target_ctx , issue_flags );
123
135
return ret ;
124
136
}
125
137
@@ -130,6 +142,7 @@ int io_msg_ring_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
130
142
if (unlikely (sqe -> buf_index || sqe -> personality ))
131
143
return - EINVAL ;
132
144
145
+ msg -> src_file = NULL ;
133
146
msg -> user_data = READ_ONCE (sqe -> off );
134
147
msg -> len = READ_ONCE (sqe -> len );
135
148
msg -> cmd = READ_ONCE (sqe -> addr );
0 commit comments