]> Git Repo - linux.git/commitdiff
Merge tag 'io_uring-5.10-2020-11-20' of git://git.kernel.dk/linux-block
authorLinus Torvalds <[email protected]>
Fri, 20 Nov 2020 19:47:22 +0000 (11:47 -0800)
committerLinus Torvalds <[email protected]>
Fri, 20 Nov 2020 19:47:22 +0000 (11:47 -0800)
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

1  2 
fs/io_uring.c

diff --combined fs/io_uring.c
index 4ead291b2976f30ce5cf0b545d14e6212048308f,7d4b755ab451da2aa554b36756456b292c73089f..a8c136a1cf4e628306d032d4ddfc467c130043e8
@@@ -205,6 -205,7 +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 +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 +2579,6 @@@ static bool io_resubmit_prep(struct io_
        }
  end_req:
        req_set_fail_links(req);
-       io_req_complete(req, ret);
        return false;
  }
  #endif
@@@ -3547,7 -3548,8 +3548,7 @@@ static int io_write(struct io_kiocb *re
         * we return to userspace.
         */
        if (req->flags & REQ_F_ISREG) {
 -              __sb_start_write(file_inode(req->file)->i_sb,
 -                                      SB_FREEZE_WRITE, true);
 +              sb_start_write(file_inode(req->file)->i_sb);
                __sb_writers_release(file_inode(req->file)->i_sb,
                                        SB_FREEZE_WRITE);
        }
@@@ -3795,6 -3797,7 +3796,7 @@@ static int __io_openat_prep(struct io_k
                return ret;
        }
        req->open.nofile = rlimit(RLIMIT_NOFILE);
+       req->open.ignore_nonblock = false;
        req->flags |= REQ_F_NEED_CLEANUP;
        return 0;
  }
@@@ -3838,7 -3841,7 +3840,7 @@@ static int io_openat2(struct io_kiocb *
        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);
        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 -6975,7 +6974,7 @@@ static int io_sqe_files_unregister(stru
                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 -7324,6 +7323,6 @@@ static void __io_file_put_work(struct f
                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 -7350,32 +7349,32 @@@ static void io_file_put_work(struct wor
  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)
@@@ -7372,6 -7399,7 +7398,7 @@@ static struct fixed_file_ref_node *allo
        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 -7495,7 +7494,7 @@@ static int io_sqe_files_register(struc
  
        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 -7654,7 +7653,7 @@@ static int __io_sqe_files_update(struc
        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);
This page took 0.082219 seconds and 4 git commands to generate.