Skip to content

Commit fa5fca7

Browse files
committed
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
2 parents 4ccf7a0 + e297822 commit fa5fca7

3 files changed

Lines changed: 63 additions & 19 deletions

File tree

fs/io_uring.c

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ struct fixed_file_ref_node {
205205
struct list_head file_list;
206206
struct fixed_file_data *file_data;
207207
struct llist_node llist;
208+
bool done;
208209
};
209210

210211
struct fixed_file_data {
@@ -478,6 +479,7 @@ struct io_sr_msg {
478479
struct io_open {
479480
struct file *file;
480481
int dfd;
482+
bool ignore_nonblock;
481483
struct filename *filename;
482484
struct open_how how;
483485
unsigned long nofile;
@@ -2577,7 +2579,6 @@ static bool io_resubmit_prep(struct io_kiocb *req, int error)
25772579
}
25782580
end_req:
25792581
req_set_fail_links(req);
2580-
io_req_complete(req, ret);
25812582
return false;
25822583
}
25832584
#endif
@@ -3795,6 +3796,7 @@ static int __io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe
37953796
return ret;
37963797
}
37973798
req->open.nofile = rlimit(RLIMIT_NOFILE);
3799+
req->open.ignore_nonblock = false;
37983800
req->flags |= REQ_F_NEED_CLEANUP;
37993801
return 0;
38003802
}
@@ -3838,7 +3840,7 @@ static int io_openat2(struct io_kiocb *req, bool force_nonblock)
38383840
struct file *file;
38393841
int ret;
38403842

3841-
if (force_nonblock)
3843+
if (force_nonblock && !req->open.ignore_nonblock)
38423844
return -EAGAIN;
38433845

38443846
ret = build_open_flags(&req->open.how, &op);
@@ -3853,6 +3855,21 @@ static int io_openat2(struct io_kiocb *req, bool force_nonblock)
38533855
if (IS_ERR(file)) {
38543856
put_unused_fd(ret);
38553857
ret = PTR_ERR(file);
3858+
/*
3859+
* A work-around to ensure that /proc/self works that way
3860+
* that it should - if we get -EOPNOTSUPP back, then assume
3861+
* that proc_self_get_link() failed us because we're in async
3862+
* context. We should be safe to retry this from the task
3863+
* itself with force_nonblock == false set, as it should not
3864+
* block on lookup. Would be nice to know this upfront and
3865+
* avoid the async dance, but doesn't seem feasible.
3866+
*/
3867+
if (ret == -EOPNOTSUPP && io_wq_current_is_worker()) {
3868+
req->open.ignore_nonblock = true;
3869+
refcount_inc(&req->refs);
3870+
io_req_task_queue(req);
3871+
return 0;
3872+
}
38563873
} else {
38573874
fsnotify_open(file);
38583875
fd_install(ret, file);
@@ -6957,9 +6974,7 @@ static int io_sqe_files_unregister(struct io_ring_ctx *ctx)
69576974
return -ENXIO;
69586975

69596976
spin_lock(&data->lock);
6960-
if (!list_empty(&data->ref_list))
6961-
ref_node = list_first_entry(&data->ref_list,
6962-
struct fixed_file_ref_node, node);
6977+
ref_node = data->node;
69636978
spin_unlock(&data->lock);
69646979
if (ref_node)
69656980
percpu_ref_kill(&ref_node->refs);
@@ -7308,10 +7323,6 @@ static void __io_file_put_work(struct fixed_file_ref_node *ref_node)
73087323
kfree(pfile);
73097324
}
73107325

7311-
spin_lock(&file_data->lock);
7312-
list_del(&ref_node->node);
7313-
spin_unlock(&file_data->lock);
7314-
73157326
percpu_ref_exit(&ref_node->refs);
73167327
kfree(ref_node);
73177328
percpu_ref_put(&file_data->refs);
@@ -7338,17 +7349,32 @@ static void io_file_put_work(struct work_struct *work)
73387349
static void io_file_data_ref_zero(struct percpu_ref *ref)
73397350
{
73407351
struct fixed_file_ref_node *ref_node;
7352+
struct fixed_file_data *data;
73417353
struct io_ring_ctx *ctx;
7342-
bool first_add;
7354+
bool first_add = false;
73437355
int delay = HZ;
73447356

73457357
ref_node = container_of(ref, struct fixed_file_ref_node, refs);
7346-
ctx = ref_node->file_data->ctx;
7358+
data = ref_node->file_data;
7359+
ctx = data->ctx;
7360+
7361+
spin_lock(&data->lock);
7362+
ref_node->done = true;
7363+
7364+
while (!list_empty(&data->ref_list)) {
7365+
ref_node = list_first_entry(&data->ref_list,
7366+
struct fixed_file_ref_node, node);
7367+
/* recycle ref nodes in order */
7368+
if (!ref_node->done)
7369+
break;
7370+
list_del(&ref_node->node);
7371+
first_add |= llist_add(&ref_node->llist, &ctx->file_put_llist);
7372+
}
7373+
spin_unlock(&data->lock);
73477374

7348-
if (percpu_ref_is_dying(&ctx->file_data->refs))
7375+
if (percpu_ref_is_dying(&data->refs))
73497376
delay = 0;
73507377

7351-
first_add = llist_add(&ref_node->llist, &ctx->file_put_llist);
73527378
if (!delay)
73537379
mod_delayed_work(system_wq, &ctx->file_put_work, 0);
73547380
else if (first_add)
@@ -7372,6 +7398,7 @@ static struct fixed_file_ref_node *alloc_fixed_file_ref_node(
73727398
INIT_LIST_HEAD(&ref_node->node);
73737399
INIT_LIST_HEAD(&ref_node->file_list);
73747400
ref_node->file_data = ctx->file_data;
7401+
ref_node->done = false;
73757402
return ref_node;
73767403
}
73777404

@@ -7467,7 +7494,7 @@ static int io_sqe_files_register(struct io_ring_ctx *ctx, void __user *arg,
74677494

74687495
file_data->node = ref_node;
74697496
spin_lock(&file_data->lock);
7470-
list_add(&ref_node->node, &file_data->ref_list);
7497+
list_add_tail(&ref_node->node, &file_data->ref_list);
74717498
spin_unlock(&file_data->lock);
74727499
percpu_ref_get(&file_data->refs);
74737500
return ret;
@@ -7626,7 +7653,7 @@ static int __io_sqe_files_update(struct io_ring_ctx *ctx,
76267653
if (needs_switch) {
76277654
percpu_ref_kill(&data->node->refs);
76287655
spin_lock(&data->lock);
7629-
list_add(&ref_node->node, &data->ref_list);
7656+
list_add_tail(&ref_node->node, &data->ref_list);
76307657
data->node = ref_node;
76317658
spin_unlock(&data->lock);
76327659
percpu_ref_get(&ctx->file_data->refs);

fs/proc/self.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ static const char *proc_self_get_link(struct dentry *dentry,
1616
pid_t tgid = task_tgid_nr_ns(current, ns);
1717
char *name;
1818

19+
/*
20+
* Not currently supported. Once we can inherit all of struct pid,
21+
* we can allow this.
22+
*/
23+
if (current->flags & PF_KTHREAD)
24+
return ERR_PTR(-EOPNOTSUPP);
25+
1926
if (!tgid)
2027
return ERR_PTR(-ENOENT);
2128
/* max length of unsigned int in decimal + NULL term */

mm/filemap.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2347,10 +2347,15 @@ ssize_t generic_file_buffered_read(struct kiocb *iocb,
23472347

23482348
page_not_up_to_date:
23492349
/* Get exclusive access to the page ... */
2350-
if (iocb->ki_flags & IOCB_WAITQ)
2350+
if (iocb->ki_flags & IOCB_WAITQ) {
2351+
if (written) {
2352+
put_page(page);
2353+
goto out;
2354+
}
23512355
error = lock_page_async(page, iocb->ki_waitq);
2352-
else
2356+
} else {
23532357
error = lock_page_killable(page);
2358+
}
23542359
if (unlikely(error))
23552360
goto readpage_error;
23562361

@@ -2393,10 +2398,15 @@ ssize_t generic_file_buffered_read(struct kiocb *iocb,
23932398
}
23942399

23952400
if (!PageUptodate(page)) {
2396-
if (iocb->ki_flags & IOCB_WAITQ)
2401+
if (iocb->ki_flags & IOCB_WAITQ) {
2402+
if (written) {
2403+
put_page(page);
2404+
goto out;
2405+
}
23972406
error = lock_page_async(page, iocb->ki_waitq);
2398-
else
2407+
} else {
23992408
error = lock_page_killable(page);
2409+
}
24002410

24012411
if (unlikely(error))
24022412
goto readpage_error;

0 commit comments

Comments
 (0)