diff mbox

[RFC,4/8] epoll: free eventpoll by rcu to provide existence guarantee

Message ID 1509195507-29037-5-git-send-email-houtao1@huawei.com (mailing list archive)
State New, archived
Headers show

Commit Message

Hou Tao Oct. 28, 2017, 12:58 p.m. UTC
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(-)
diff mbox

Patch

diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 998c635..18de596 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -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)