Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

io_uring: change io_get_ext_arg() to use uaccess begin + end

In scenarios where a high frequency of wait events are seen, the copy
of the struct io_uring_getevents_arg is quite noticeable in the
profiles in terms of time spent. It can be seen as up to 3.5-4.5%.
Rewrite the copy-in logic, saving about 0.5% of the time.

Reviewed-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

+17 -1
+17 -1
io_uring/io_uring.c
··· 3240 3240 static int io_get_ext_arg(unsigned flags, const void __user *argp, 3241 3241 struct ext_arg *ext_arg) 3242 3242 { 3243 + const struct io_uring_getevents_arg __user *uarg = argp; 3243 3244 struct io_uring_getevents_arg arg; 3244 3245 3245 3246 /* ··· 3258 3257 */ 3259 3258 if (ext_arg->argsz != sizeof(arg)) 3260 3259 return -EINVAL; 3261 - if (copy_from_user(&arg, argp, sizeof(arg))) 3260 + #ifdef CONFIG_64BIT 3261 + if (!user_access_begin(uarg, sizeof(*uarg))) 3262 3262 return -EFAULT; 3263 + unsafe_get_user(arg.sigmask, &uarg->sigmask, uaccess_end); 3264 + unsafe_get_user(arg.sigmask_sz, &uarg->sigmask_sz, uaccess_end); 3265 + unsafe_get_user(arg.min_wait_usec, &uarg->min_wait_usec, uaccess_end); 3266 + unsafe_get_user(arg.ts, &uarg->ts, uaccess_end); 3267 + user_access_end(); 3268 + #else 3269 + if (copy_from_user(&arg, uarg, sizeof(arg))) 3270 + return -EFAULT; 3271 + #endif 3263 3272 ext_arg->min_time = arg.min_wait_usec * NSEC_PER_USEC; 3264 3273 ext_arg->sig = u64_to_user_ptr(arg.sigmask); 3265 3274 ext_arg->argsz = arg.sigmask_sz; ··· 3279 3268 ext_arg->ts_set = true; 3280 3269 } 3281 3270 return 0; 3271 + #ifdef CONFIG_64BIT 3272 + uaccess_end: 3273 + user_access_end(); 3274 + return -EFAULT; 3275 + #endif 3282 3276 } 3283 3277 3284 3278 SYSCALL_DEFINE6(io_uring_enter, unsigned int, fd, u32, to_submit,