@@ -230,6 +230,9 @@ struct eventpoll {
/* used to track busy poll napi_id */
unsigned int napi_id;
#endif
+
+ /* used to free itself */
+ struct rcu_head rcu;
};
/* Wait structure used by the poll hooks */
@@ -818,6 +821,12 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi)
return 0;
}
+static void ep_rcu_free(struct rcu_head *head)
+{
+ struct eventpoll *ep = container_of(head, struct eventpoll, rcu);
+ kfree(ep);
+}
+
static void ep_free(struct eventpoll *ep)
{
struct rb_node *rbp;
@@ -877,7 +886,8 @@ static void ep_free(struct eventpoll *ep)
mutex_destroy(&ep->mtx);
free_uid(ep->user);
wakeup_source_unregister(ep->ws);
- kfree(ep);
+
+ call_rcu(&ep->rcu, ep_rcu_free);
}
static int ep_eventpoll_release(struct inode *inode, struct file *file)
Before the removal of epmutex, it's OK to access epi->ep in reverse_path_check_proc(), because the freeing of ep will be blocked on ep_free(). After the removal of epmutex, when accessing epi->ep in reverse_path_check_proc(), it's possible that it has been release because this eventpoll struct belongs to an epoll fd which also polls the target file. So freeing eventpoll by rcu to ensure the accessed fields of eventpoll are still valid when invoking reverse_path_check_proc(). Signed-off-by: Hou Tao <houtao1@huawei.com> --- fs/eventpoll.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)