Skip to content

Commit

Permalink
Merge tag 'io_uring-5.10-2020-11-20' of git://git.kernel.dk/linux-block
Browse files Browse the repository at this point in the history
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
  • Loading branch information
torvalds committed Nov 20, 2020
2 parents 4ccf7a0 + e297822 commit fa5fca7
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 19 deletions.
57 changes: 42 additions & 15 deletions fs/io_uring.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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;

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(&ctx->file_data->refs))
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)
Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
7 changes: 7 additions & 0 deletions fs/proc/self.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
18 changes: 14 additions & 4 deletions mm/filemap.c
Original file line number Diff line number Diff line change
Expand Up @@ -2347,10 +2347,15 @@ ssize_t generic_file_buffered_read(struct kiocb *iocb,

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;

Expand Down Expand Up @@ -2393,10 +2398,15 @@ ssize_t generic_file_buffered_read(struct kiocb *iocb,
}

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;
Expand Down

0 comments on commit fa5fca7

Please sign in to comment.