@@ -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
210211struct fixed_file_data {
@@ -478,6 +479,7 @@ struct io_sr_msg {
478479struct 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 }
25782580end_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)
73387349static 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 );
0 commit comments