From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx2.suse.de ([195.135.220.15]:39771 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1762263AbdAFKoV (ORCPT ); Fri, 6 Jan 2017 05:44:21 -0500 From: Jan Kara To: linux-fsdevel@vger.kernel.org Cc: Amir Goldstein , Paul Moore , Miklos Szeredi , Jan Kara Subject: [PATCH 13/22] fanotify: Release SRCU lock when waiting for userspace response Date: Fri, 6 Jan 2017 11:43:52 +0100 Message-Id: <20170106104401.5894-14-jack@suse.cz> In-Reply-To: <20170106104401.5894-1-jack@suse.cz> References: <20170106104401.5894-1-jack@suse.cz> Sender: linux-fsdevel-owner@vger.kernel.org List-ID: When userspace task processing fanotify permission events screws up and does not respond, fsnotify_mark_srcu SRCU is held indefinitely which causes further hangs in the whole notification subsystem. Although we cannot easily solve the problem of operations blocked waiting for response from userspace, we can at least somewhat localize the damage by dropping SRCU lock before waiting for userspace response and reacquiring it when userspace responds. Reviewed-by: Amir Goldstein Signed-off-by: Jan Kara --- fs/notify/fanotify/fanotify.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index 2e8ca885fb3e..1e1c4cf2e6db 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -61,7 +61,10 @@ static int fanotify_merge(struct list_head *list, struct fsnotify_event *event) #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS static int fanotify_get_response(struct fsnotify_group *group, - struct fanotify_perm_event_info *event) + struct fsnotify_mark *inode_mark, + struct fsnotify_mark *vfsmount_mark, + struct fanotify_perm_event_info *event, + int *srcu_idx) { int ret; @@ -69,6 +72,19 @@ static int fanotify_get_response(struct fsnotify_group *group, wait_event(group->fanotify_data.access_waitq, event->response); + /* + * fsnotify_prepare_user_wait() fails if we race with mark deletion. + * Just let the operation pass in that case. + */ + if (!fsnotify_prepare_user_wait(inode_mark, vfsmount_mark, srcu_idx)) { + event->response = FAN_ALLOW; + goto out; + } + + wait_event(group->fanotify_data.access_waitq, event->response); + + fsnotify_finish_user_wait(inode_mark, vfsmount_mark, srcu_idx); +out: /* userspace responded, convert to something usable */ switch (event->response) { case FAN_ALLOW: @@ -220,7 +236,8 @@ static int fanotify_handle_event(struct fsnotify_group *group, #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS if (mask & FAN_ALL_PERM_EVENTS) { - ret = fanotify_get_response(group, FANOTIFY_PE(fsn_event)); + ret = fanotify_get_response(group, inode_mark, fanotify_mark, + FANOTIFY_PE(fsn_event), srcu_idx); fsnotify_destroy_event(group, fsn_event); } #endif -- 2.10.2