io_uring: grab ->fs as part of async preparation
This passes it in to io-wq, so it assumes the right fs_struct when executing async work that may need to do lookups. Cc: stable@vger.kernel.org # 5.3+ Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
9392a27d88
commit
ff002b3018
@ -75,6 +75,7 @@
|
|||||||
#include <linux/fsnotify.h>
|
#include <linux/fsnotify.h>
|
||||||
#include <linux/fadvise.h>
|
#include <linux/fadvise.h>
|
||||||
#include <linux/eventpoll.h>
|
#include <linux/eventpoll.h>
|
||||||
|
#include <linux/fs_struct.h>
|
||||||
|
|
||||||
#define CREATE_TRACE_POINTS
|
#define CREATE_TRACE_POINTS
|
||||||
#include <trace/events/io_uring.h>
|
#include <trace/events/io_uring.h>
|
||||||
@ -611,6 +612,8 @@ struct io_op_def {
|
|||||||
unsigned not_supported : 1;
|
unsigned not_supported : 1;
|
||||||
/* needs file table */
|
/* needs file table */
|
||||||
unsigned file_table : 1;
|
unsigned file_table : 1;
|
||||||
|
/* needs ->fs */
|
||||||
|
unsigned needs_fs : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct io_op_def io_op_defs[] = {
|
static const struct io_op_def io_op_defs[] = {
|
||||||
@ -653,12 +656,14 @@ static const struct io_op_def io_op_defs[] = {
|
|||||||
.needs_mm = 1,
|
.needs_mm = 1,
|
||||||
.needs_file = 1,
|
.needs_file = 1,
|
||||||
.unbound_nonreg_file = 1,
|
.unbound_nonreg_file = 1,
|
||||||
|
.needs_fs = 1,
|
||||||
},
|
},
|
||||||
[IORING_OP_RECVMSG] = {
|
[IORING_OP_RECVMSG] = {
|
||||||
.async_ctx = 1,
|
.async_ctx = 1,
|
||||||
.needs_mm = 1,
|
.needs_mm = 1,
|
||||||
.needs_file = 1,
|
.needs_file = 1,
|
||||||
.unbound_nonreg_file = 1,
|
.unbound_nonreg_file = 1,
|
||||||
|
.needs_fs = 1,
|
||||||
},
|
},
|
||||||
[IORING_OP_TIMEOUT] = {
|
[IORING_OP_TIMEOUT] = {
|
||||||
.async_ctx = 1,
|
.async_ctx = 1,
|
||||||
@ -689,6 +694,7 @@ static const struct io_op_def io_op_defs[] = {
|
|||||||
.needs_file = 1,
|
.needs_file = 1,
|
||||||
.fd_non_neg = 1,
|
.fd_non_neg = 1,
|
||||||
.file_table = 1,
|
.file_table = 1,
|
||||||
|
.needs_fs = 1,
|
||||||
},
|
},
|
||||||
[IORING_OP_CLOSE] = {
|
[IORING_OP_CLOSE] = {
|
||||||
.needs_file = 1,
|
.needs_file = 1,
|
||||||
@ -702,6 +708,7 @@ static const struct io_op_def io_op_defs[] = {
|
|||||||
.needs_mm = 1,
|
.needs_mm = 1,
|
||||||
.needs_file = 1,
|
.needs_file = 1,
|
||||||
.fd_non_neg = 1,
|
.fd_non_neg = 1,
|
||||||
|
.needs_fs = 1,
|
||||||
},
|
},
|
||||||
[IORING_OP_READ] = {
|
[IORING_OP_READ] = {
|
||||||
.needs_mm = 1,
|
.needs_mm = 1,
|
||||||
@ -733,6 +740,7 @@ static const struct io_op_def io_op_defs[] = {
|
|||||||
.needs_file = 1,
|
.needs_file = 1,
|
||||||
.fd_non_neg = 1,
|
.fd_non_neg = 1,
|
||||||
.file_table = 1,
|
.file_table = 1,
|
||||||
|
.needs_fs = 1,
|
||||||
},
|
},
|
||||||
[IORING_OP_EPOLL_CTL] = {
|
[IORING_OP_EPOLL_CTL] = {
|
||||||
.unbound_nonreg_file = 1,
|
.unbound_nonreg_file = 1,
|
||||||
@ -907,6 +915,16 @@ static inline void io_req_work_grab_env(struct io_kiocb *req,
|
|||||||
}
|
}
|
||||||
if (!req->work.creds)
|
if (!req->work.creds)
|
||||||
req->work.creds = get_current_cred();
|
req->work.creds = get_current_cred();
|
||||||
|
if (!req->work.fs && def->needs_fs) {
|
||||||
|
spin_lock(¤t->fs->lock);
|
||||||
|
if (!current->fs->in_exec) {
|
||||||
|
req->work.fs = current->fs;
|
||||||
|
req->work.fs->users++;
|
||||||
|
} else {
|
||||||
|
req->work.flags |= IO_WQ_WORK_CANCEL;
|
||||||
|
}
|
||||||
|
spin_unlock(¤t->fs->lock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void io_req_work_drop_env(struct io_kiocb *req)
|
static inline void io_req_work_drop_env(struct io_kiocb *req)
|
||||||
@ -919,6 +937,16 @@ static inline void io_req_work_drop_env(struct io_kiocb *req)
|
|||||||
put_cred(req->work.creds);
|
put_cred(req->work.creds);
|
||||||
req->work.creds = NULL;
|
req->work.creds = NULL;
|
||||||
}
|
}
|
||||||
|
if (req->work.fs) {
|
||||||
|
struct fs_struct *fs = req->work.fs;
|
||||||
|
|
||||||
|
spin_lock(&req->work.fs->lock);
|
||||||
|
if (--fs->users)
|
||||||
|
fs = NULL;
|
||||||
|
spin_unlock(&req->work.fs->lock);
|
||||||
|
if (fs)
|
||||||
|
free_fs_struct(fs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool io_prep_async_work(struct io_kiocb *req,
|
static inline bool io_prep_async_work(struct io_kiocb *req,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user