pipe-nonblock-2023-05-06
-----BEGIN PGP SIGNATURE----- iQJEBAABCAAuFiEEwPw5LcreJtl1+l5K99NY+ylx4KYFAmRWK50QHGF4Ym9lQGtl cm5lbC5kawAKCRD301j7KXHgpkP8D/9PKQy4FCTRKRYABomlkqc9UlrsEzkkpXy+ t2kCZ7OmgZ1go/3gRv8AVx0xC/S8zgs8vCwriUXVQH2Q4D2FnV9/Cy5xXzQJ2jE5 sWdj5+Sks2Zerq7hRfItxFxP70Jlvn4r2Ud6n9uoBKI+DirpGQB5xwqCF/Z9I9Ev cAOtq3cvdKqiqAmrA0WAjjpLpvuC/OOEXyQf6n+viQ7iJZgCHDWplpa4jQCamrlJ wDz5eNkptDc3KnZ1QGtfMlCdmzwjFEyi20Eq8VLo6OBkhoP6FymqWC6YkeigibI4 Da+fyx/wJvqnsuXPLCFgla5MXMRHLb9uoRRFbon6XqXABPZ8v4v8kZhswVLUxBzz UjBI8cmKQ8rkHu+4o/522lCRQCMU5h7LxGgCguePi9+Hap2AuBSmpOzpgDqnNDmN ARD6gW4uOkXRU6CgvppOio3hTn3BU9bUs8iN8ym3XW0eQo6nUElRT2mwC1XEJDYn HAM1MqoJWU5rWp1yyAdiw8rLBOmMLMyNaowHlWEjEGiykU2FlfNDp/HJeq/gxjEK NxBC5+qlhbDp3hTqDJVaRa+i8MchrTJLXfJuXzP3el3c1dp2vU5gLO49WYAA6G5d oycxTm2SyX6dUwWNeH06jgocVt99fC7klTuEq59Jm9ykFSfbj2kfv24U+jDi/KvX DW++jNDl+g== =uryD -----END PGP SIGNATURE----- Merge tag 'pipe-nonblock-2023-05-06' of git://git.kernel.dk/linux Pull nonblocking pipe io_uring support from Jens Axboe: "Here's the revised edition of the FMODE_NOWAIT support for pipes, in which we just flag it as such supporting FMODE_NOWAIT unconditionally, but clear it if we ever end up using splice/vmsplice on the pipe. The pipe read/write side is perfectly fine for nonblocking IO, however splice and vmsplice can potentially wait for IO with the pipe lock held" * tag 'pipe-nonblock-2023-05-06' of git://git.kernel.dk/linux: pipe: set FMODE_NOWAIT on pipes splice: clear FMODE_NOWAIT on file if splice/vmsplice is used
This commit is contained in:
Коммит
7644c82319
|
@ -976,6 +976,9 @@ static int __do_pipe_flags(int *fd, struct file **files, int flags)
|
||||||
audit_fd_pair(fdr, fdw);
|
audit_fd_pair(fdr, fdw);
|
||||||
fd[0] = fdr;
|
fd[0] = fdr;
|
||||||
fd[1] = fdw;
|
fd[1] = fdw;
|
||||||
|
/* pipe groks IOCB_NOWAIT */
|
||||||
|
files[0]->f_mode |= FMODE_NOWAIT;
|
||||||
|
files[1]->f_mode |= FMODE_NOWAIT;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_fdr:
|
err_fdr:
|
||||||
|
|
34
fs/splice.c
34
fs/splice.c
|
@ -38,6 +38,22 @@
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Splice doesn't support FMODE_NOWAIT. Since pipes may set this flag to
|
||||||
|
* indicate they support non-blocking reads or writes, we must clear it
|
||||||
|
* here if set to avoid blocking other users of this pipe if splice is
|
||||||
|
* being done on it.
|
||||||
|
*/
|
||||||
|
static noinline void noinline pipe_clear_nowait(struct file *file)
|
||||||
|
{
|
||||||
|
fmode_t fmode = READ_ONCE(file->f_mode);
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (!(fmode & FMODE_NOWAIT))
|
||||||
|
break;
|
||||||
|
} while (!try_cmpxchg(&file->f_mode, &fmode, fmode & ~FMODE_NOWAIT));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attempt to steal a page from a pipe buffer. This should perhaps go into
|
* Attempt to steal a page from a pipe buffer. This should perhaps go into
|
||||||
* a vm helper function, it's already simplified quite a bit by the
|
* a vm helper function, it's already simplified quite a bit by the
|
||||||
|
@ -1219,10 +1235,16 @@ static long __do_splice(struct file *in, loff_t __user *off_in,
|
||||||
ipipe = get_pipe_info(in, true);
|
ipipe = get_pipe_info(in, true);
|
||||||
opipe = get_pipe_info(out, true);
|
opipe = get_pipe_info(out, true);
|
||||||
|
|
||||||
if (ipipe && off_in)
|
if (ipipe) {
|
||||||
return -ESPIPE;
|
if (off_in)
|
||||||
if (opipe && off_out)
|
return -ESPIPE;
|
||||||
return -ESPIPE;
|
pipe_clear_nowait(in);
|
||||||
|
}
|
||||||
|
if (opipe) {
|
||||||
|
if (off_out)
|
||||||
|
return -ESPIPE;
|
||||||
|
pipe_clear_nowait(out);
|
||||||
|
}
|
||||||
|
|
||||||
if (off_out) {
|
if (off_out) {
|
||||||
if (copy_from_user(&offset, off_out, sizeof(loff_t)))
|
if (copy_from_user(&offset, off_out, sizeof(loff_t)))
|
||||||
|
@ -1319,6 +1341,8 @@ static long vmsplice_to_user(struct file *file, struct iov_iter *iter,
|
||||||
if (!pipe)
|
if (!pipe)
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
|
pipe_clear_nowait(file);
|
||||||
|
|
||||||
if (sd.total_len) {
|
if (sd.total_len) {
|
||||||
pipe_lock(pipe);
|
pipe_lock(pipe);
|
||||||
ret = __splice_from_pipe(pipe, &sd, pipe_to_user);
|
ret = __splice_from_pipe(pipe, &sd, pipe_to_user);
|
||||||
|
@ -1347,6 +1371,8 @@ static long vmsplice_to_pipe(struct file *file, struct iov_iter *iter,
|
||||||
if (!pipe)
|
if (!pipe)
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
|
pipe_clear_nowait(file);
|
||||||
|
|
||||||
pipe_lock(pipe);
|
pipe_lock(pipe);
|
||||||
ret = wait_for_space(pipe, flags);
|
ret = wait_for_space(pipe, flags);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче