forked from Minki/linux
io_uring-5.10-2020-11-20
-----BEGIN PGP SIGNATURE----- iQJEBAABCAAuFiEEwPw5LcreJtl1+l5K99NY+ylx4KYFAl+4DAwQHGF4Ym9lQGtl cm5lbC5kawAKCRD301j7KXHgphdOD/9xOEnYPuekvVH9G9nyNd//Q9fPArG2+j6V /MCnze07GNtDt7z15oR+T07hKXmf+Ejh4nu3JJ6MUNfe/47hhJqHSxRHU6+PJCjk hPrsaTsDedxxLEDiLmvhXnUPzfVzJtefxVAAaKikWOb3SBqLdh7xTFSlor1HbRBl Zk4d343cjBDYfvSSt/zMWDzwwvramdz7rJnnPMKXITu64ITL5314vuK2YVZmBOet YujSah7J8FL1jKhiG1Iw5rayd2Q3smnHWIEQ+lvW6WiTvMJMLOxif2xNF4/VEZs1 CBGJUQt42LI6QGEzRBHohcefZFuPGoxnduSzHCOIhh7d6+k+y9mZfsPGohr3g9Ov NotXpVonnA7GbRqzo1+IfBRve7iRONdZ3/LBwyRmqav4I4jX68wXBNH5IDpVR0Sn c31avxa/ZL7iLIBx32enp0/r3mqNTQotEleSLUdyJQXAZTyG2INRhjLLXTqSQ5BX oVp0fZzKCwsr6HCPZpXZ/f2G7dhzuF0ghoceC02GsOVooni22gdVnQj+AWNus398 e+wcimT4MX6AHNFxO2aUtJow0KWWZRzC1p5Mxu/9W3YiMtJiC0YOGePfSqiTqX0g Uk0H5dOAgBUQrAsusf7bKr0K6W25yEk/JipxhWqi0rC71x42mLTsCT1wxSCvLwqs WxhdtVKroQ== =7PAe -----END PGP SIGNATURE----- Merge tag 'io_uring-5.10-2020-11-20' of git://git.kernel.dk/linux-block Pull io_uring fixes from Jens Axboe: "Mostly regression or stable fodder: - Disallow async path resolution of /proc/self - Tighten constraints for segmented async buffered reads - Fix double completion for a retry error case - Fix for fixed file life times (Pavel)" * tag 'io_uring-5.10-2020-11-20' of git://git.kernel.dk/linux-block: io_uring: order refnode recycling io_uring: get an active ref_node from files_data io_uring: don't double complete failed reissue request mm: never attempt async page lock if we've transferred data already io_uring: handle -EOPNOTSUPP on path resolution proc: don't allow async path resolution of /proc/self components
This commit is contained in:
commit
fa5fca78bb
@ -205,6 +205,7 @@ struct fixed_file_ref_node {
|
||||
struct list_head file_list;
|
||||
struct fixed_file_data *file_data;
|
||||
struct llist_node llist;
|
||||
bool done;
|
||||
};
|
||||
|
||||
struct fixed_file_data {
|
||||
@ -478,6 +479,7 @@ struct io_sr_msg {
|
||||
struct io_open {
|
||||
struct file *file;
|
||||
int dfd;
|
||||
bool ignore_nonblock;
|
||||
struct filename *filename;
|
||||
struct open_how how;
|
||||
unsigned long nofile;
|
||||
@ -2577,7 +2579,6 @@ static bool io_resubmit_prep(struct io_kiocb *req, int error)
|
||||
}
|
||||
end_req:
|
||||
req_set_fail_links(req);
|
||||
io_req_complete(req, ret);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@ -3795,6 +3796,7 @@ static int __io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe
|
||||
return ret;
|
||||
}
|
||||
req->open.nofile = rlimit(RLIMIT_NOFILE);
|
||||
req->open.ignore_nonblock = false;
|
||||
req->flags |= REQ_F_NEED_CLEANUP;
|
||||
return 0;
|
||||
}
|
||||
@ -3838,7 +3840,7 @@ static int io_openat2(struct io_kiocb *req, bool force_nonblock)
|
||||
struct file *file;
|
||||
int ret;
|
||||
|
||||
if (force_nonblock)
|
||||
if (force_nonblock && !req->open.ignore_nonblock)
|
||||
return -EAGAIN;
|
||||
|
||||
ret = build_open_flags(&req->open.how, &op);
|
||||
@ -3853,6 +3855,21 @@ static int io_openat2(struct io_kiocb *req, bool force_nonblock)
|
||||
if (IS_ERR(file)) {
|
||||
put_unused_fd(ret);
|
||||
ret = PTR_ERR(file);
|
||||
/*
|
||||
* A work-around to ensure that /proc/self works that way
|
||||
* that it should - if we get -EOPNOTSUPP back, then assume
|
||||
* that proc_self_get_link() failed us because we're in async
|
||||
* context. We should be safe to retry this from the task
|
||||
* itself with force_nonblock == false set, as it should not
|
||||
* block on lookup. Would be nice to know this upfront and
|
||||
* avoid the async dance, but doesn't seem feasible.
|
||||
*/
|
||||
if (ret == -EOPNOTSUPP && io_wq_current_is_worker()) {
|
||||
req->open.ignore_nonblock = true;
|
||||
refcount_inc(&req->refs);
|
||||
io_req_task_queue(req);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
fsnotify_open(file);
|
||||
fd_install(ret, file);
|
||||
@ -6957,9 +6974,7 @@ static int io_sqe_files_unregister(struct io_ring_ctx *ctx)
|
||||
return -ENXIO;
|
||||
|
||||
spin_lock(&data->lock);
|
||||
if (!list_empty(&data->ref_list))
|
||||
ref_node = list_first_entry(&data->ref_list,
|
||||
struct fixed_file_ref_node, node);
|
||||
ref_node = data->node;
|
||||
spin_unlock(&data->lock);
|
||||
if (ref_node)
|
||||
percpu_ref_kill(&ref_node->refs);
|
||||
@ -7308,10 +7323,6 @@ static void __io_file_put_work(struct fixed_file_ref_node *ref_node)
|
||||
kfree(pfile);
|
||||
}
|
||||
|
||||
spin_lock(&file_data->lock);
|
||||
list_del(&ref_node->node);
|
||||
spin_unlock(&file_data->lock);
|
||||
|
||||
percpu_ref_exit(&ref_node->refs);
|
||||
kfree(ref_node);
|
||||
percpu_ref_put(&file_data->refs);
|
||||
@ -7338,17 +7349,32 @@ static void io_file_put_work(struct work_struct *work)
|
||||
static void io_file_data_ref_zero(struct percpu_ref *ref)
|
||||
{
|
||||
struct fixed_file_ref_node *ref_node;
|
||||
struct fixed_file_data *data;
|
||||
struct io_ring_ctx *ctx;
|
||||
bool first_add;
|
||||
bool first_add = false;
|
||||
int delay = HZ;
|
||||
|
||||
ref_node = container_of(ref, struct fixed_file_ref_node, refs);
|
||||
ctx = ref_node->file_data->ctx;
|
||||
data = ref_node->file_data;
|
||||
ctx = data->ctx;
|
||||
|
||||
if (percpu_ref_is_dying(&ctx->file_data->refs))
|
||||
spin_lock(&data->lock);
|
||||
ref_node->done = true;
|
||||
|
||||
while (!list_empty(&data->ref_list)) {
|
||||
ref_node = list_first_entry(&data->ref_list,
|
||||
struct fixed_file_ref_node, node);
|
||||
/* recycle ref nodes in order */
|
||||
if (!ref_node->done)
|
||||
break;
|
||||
list_del(&ref_node->node);
|
||||
first_add |= llist_add(&ref_node->llist, &ctx->file_put_llist);
|
||||
}
|
||||
spin_unlock(&data->lock);
|
||||
|
||||
if (percpu_ref_is_dying(&data->refs))
|
||||
delay = 0;
|
||||
|
||||
first_add = llist_add(&ref_node->llist, &ctx->file_put_llist);
|
||||
if (!delay)
|
||||
mod_delayed_work(system_wq, &ctx->file_put_work, 0);
|
||||
else if (first_add)
|
||||
@ -7372,6 +7398,7 @@ static struct fixed_file_ref_node *alloc_fixed_file_ref_node(
|
||||
INIT_LIST_HEAD(&ref_node->node);
|
||||
INIT_LIST_HEAD(&ref_node->file_list);
|
||||
ref_node->file_data = ctx->file_data;
|
||||
ref_node->done = false;
|
||||
return ref_node;
|
||||
}
|
||||
|
||||
@ -7467,7 +7494,7 @@ static int io_sqe_files_register(struct io_ring_ctx *ctx, void __user *arg,
|
||||
|
||||
file_data->node = ref_node;
|
||||
spin_lock(&file_data->lock);
|
||||
list_add(&ref_node->node, &file_data->ref_list);
|
||||
list_add_tail(&ref_node->node, &file_data->ref_list);
|
||||
spin_unlock(&file_data->lock);
|
||||
percpu_ref_get(&file_data->refs);
|
||||
return ret;
|
||||
@ -7626,7 +7653,7 @@ static int __io_sqe_files_update(struct io_ring_ctx *ctx,
|
||||
if (needs_switch) {
|
||||
percpu_ref_kill(&data->node->refs);
|
||||
spin_lock(&data->lock);
|
||||
list_add(&ref_node->node, &data->ref_list);
|
||||
list_add_tail(&ref_node->node, &data->ref_list);
|
||||
data->node = ref_node;
|
||||
spin_unlock(&data->lock);
|
||||
percpu_ref_get(&ctx->file_data->refs);
|
||||
|
@ -16,6 +16,13 @@ static const char *proc_self_get_link(struct dentry *dentry,
|
||||
pid_t tgid = task_tgid_nr_ns(current, ns);
|
||||
char *name;
|
||||
|
||||
/*
|
||||
* Not currently supported. Once we can inherit all of struct pid,
|
||||
* we can allow this.
|
||||
*/
|
||||
if (current->flags & PF_KTHREAD)
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
|
||||
if (!tgid)
|
||||
return ERR_PTR(-ENOENT);
|
||||
/* max length of unsigned int in decimal + NULL term */
|
||||
|
18
mm/filemap.c
18
mm/filemap.c
@ -2347,10 +2347,15 @@ page_ok:
|
||||
|
||||
page_not_up_to_date:
|
||||
/* Get exclusive access to the page ... */
|
||||
if (iocb->ki_flags & IOCB_WAITQ)
|
||||
if (iocb->ki_flags & IOCB_WAITQ) {
|
||||
if (written) {
|
||||
put_page(page);
|
||||
goto out;
|
||||
}
|
||||
error = lock_page_async(page, iocb->ki_waitq);
|
||||
else
|
||||
} else {
|
||||
error = lock_page_killable(page);
|
||||
}
|
||||
if (unlikely(error))
|
||||
goto readpage_error;
|
||||
|
||||
@ -2393,10 +2398,15 @@ readpage:
|
||||
}
|
||||
|
||||
if (!PageUptodate(page)) {
|
||||
if (iocb->ki_flags & IOCB_WAITQ)
|
||||
if (iocb->ki_flags & IOCB_WAITQ) {
|
||||
if (written) {
|
||||
put_page(page);
|
||||
goto out;
|
||||
}
|
||||
error = lock_page_async(page, iocb->ki_waitq);
|
||||
else
|
||||
} else {
|
||||
error = lock_page_killable(page);
|
||||
}
|
||||
|
||||
if (unlikely(error))
|
||||
goto readpage_error;
|
||||
|
Loading…
Reference in New Issue
Block a user