aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWinston Wen <[email protected]>2024-03-05 14:18:04 +0800
committerJan Kara <[email protected]>2024-03-07 12:59:51 +0100
commit0045fb1bab4eaa8f415c2fd76020bf7b2a3be47a (patch)
tree4e73396cdf45dc8e271d51dcd2217ae4d1acba7d
parent8c2c2549fb32f2e6dd247cfed2e23cf8456dd458 (diff)
fanotify: allow freeze when waiting response for permission events
This is a long-standing issue that uninterruptible sleep in fanotify could make system hibernation fail if the usperspace server gets frozen before the process waiting for the response (as reported e.g. [1][2]). A few years ago, there was an attempt to switch to interruptible sleep while waiting [3], but that would lead to EINTR returns from open(2) and break userspace [4], so it's been changed to only killable [5]. And the core freezer logic had been rewritten [6][7] in v6.1, allowing freezing in uninterrupted sleep, so we can solve this problem now. [1] https://lore.kernel.org/lkml/[email protected]/ [2] https://lore.kernel.org/lkml/[email protected]/ [3] https://lore.kernel.org/linux-fsdevel/[email protected]/ [4] https://lore.kernel.org/linux-fsdevel/[email protected]/ [5] https://lore.kernel.org/linux-fsdevel/[email protected]/ [6] https://lore.kernel.org/lkml/[email protected]/ [7] https://lore.kernel.org/lkml/20230908-avoid-spurious-freezer-wakeups-v4-0-6155aa3dafae@quicinc.com/ Signed-off-by: Winston Wen <[email protected]> Signed-off-by: Jan Kara <[email protected]> Message-Id: <[email protected]>
-rw-r--r--fs/notify/fanotify/fanotify.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 1e4def21811e..224bccaab4cc 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -228,8 +228,10 @@ static int fanotify_get_response(struct fsnotify_group *group,
pr_debug("%s: group=%p event=%p\n", __func__, group, event);
- ret = wait_event_killable(group->fanotify_data.access_waitq,
- event->state == FAN_EVENT_ANSWERED);
+ ret = wait_event_state(group->fanotify_data.access_waitq,
+ event->state == FAN_EVENT_ANSWERED,
+ (TASK_KILLABLE|TASK_FREEZABLE));
+
/* Signal pending? */
if (ret < 0) {
spin_lock(&group->notification_lock);