Skip to content

Commit 07422c9

Browse files
committed
eventpoll: drop vestigial epi->dying flag
With ep_remove() now pinning @file via epi_fget() across the f_ep clear and hlist_del_rcu(), the dying flag no longer orchestrates anything: it was set in eventpoll_release_file() (which only runs from __fput(), i.e. after @file's refcount has reached zero) and read in __ep_remove() / ep_remove() as a cheap bail before attempting the same synchronization epi_fget() now provides unconditionally. The implication is simple: epi->dying == true always coincides with file_ref_get(&file->f_ref) == false, because __fput() is reachable only once the refcount hits zero and the refcount is monotone in that state. The READ_ONCE(epi->dying) in ep_remove() therefore selects exactly the same callers that epi_fget() would reject, just one atomic cheaper. That's not worth a struct field, a second coordination mechanism, and the comments on both. Refresh the eventpoll_release_file() comment to describe what actually makes the path race-free now (the pin in ep_remove()). No functional change: the correctness argument is unchanged, only the mechanism is now a single one instead of two. Link: https://patch.msgid.link/[email protected] Signed-off-by: Christian Brauner (Amutable) <[email protected]>
1 parent 3a4551e commit 07422c9

1 file changed

Lines changed: 7 additions & 20 deletions

File tree

fs/eventpoll.c

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -148,13 +148,6 @@ struct epitem {
148148
/* The file descriptor information this item refers to */
149149
struct epoll_filefd ffd;
150150

151-
/*
152-
* Protected by file->f_lock, true for to-be-released epitem already
153-
* removed from the "struct file" items list; together with
154-
* eventpoll->refcount orchestrates "struct eventpoll" disposal
155-
*/
156-
bool dying;
157-
158151
/* List containing poll wait queues */
159152
struct eppoll_entry *pwqlist;
160153

@@ -220,10 +213,7 @@ struct eventpoll {
220213
struct hlist_head refs;
221214
u8 loop_check_depth;
222215

223-
/*
224-
* usage count, used together with epitem->dying to
225-
* orchestrate the disposal of this struct
226-
*/
216+
/* usage count, orchestrates "struct eventpoll" disposal */
227217
refcount_t refcount;
228218

229219
/* used to defer freeing past ep_get_upwards_depth_proc() RCU walk */
@@ -918,13 +908,10 @@ static void ep_remove(struct eventpoll *ep, struct epitem *epi)
918908

919909
ep_unregister_pollwait(ep, epi);
920910

921-
/* cheap sync with eventpoll_release_file() */
922-
if (unlikely(READ_ONCE(epi->dying)))
923-
return;
924-
925911
/*
926912
* If we manage to grab a reference it means we're not in
927-
* eventpoll_release_file() and aren't going to be.
913+
* eventpoll_release_file() and aren't going to be: once @file's
914+
* refcount has reached zero, file_ref_get() cannot bring it back.
928915
*/
929916
file = epi_fget(epi);
930917
if (!file)
@@ -1126,15 +1113,15 @@ void eventpoll_release_file(struct file *file)
11261113
struct epitem *epi;
11271114

11281115
/*
1129-
* Use the 'dying' flag to prevent a concurrent ep_clear_and_put() from
1130-
* touching the epitems list before eventpoll_release_file() can access
1131-
* the ep->mtx.
1116+
* A concurrent ep_remove() cannot outrace us: it pins @file via
1117+
* epi_fget(), which fails once __fput() has dropped the refcount
1118+
* to zero -- the path we're on. So any racing ep_remove() bails
1119+
* and leaves the epi for us to clean up here.
11321120
*/
11331121
again:
11341122
spin_lock(&file->f_lock);
11351123
if (file->f_ep && file->f_ep->first) {
11361124
epi = hlist_entry(file->f_ep->first, struct epitem, fllink);
1137-
WRITE_ONCE(epi->dying, true);
11381125
spin_unlock(&file->f_lock);
11391126

11401127
/*

0 commit comments

Comments
 (0)