summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2019-01-08 13:52:31 +0100
committerJan Kara <jack@suse.cz>2019-02-18 12:40:46 +0100
commit8c5544666c9d88046bfd60aa7d5fea5c6d3d59bd (patch)
tree5847fbd0406327fe8fcb19bb2edfa292474b63c6
parentaf6a51130626bfd3e60041d80335b2c31590d56d (diff)
downloadlinux-8c5544666c9d88046bfd60aa7d5fea5c6d3d59bd.tar.bz2
fanotify: Move locking inside get_one_event()
get_one_event() has a single caller and that just locks notification_lock around the call. Move locking inside get_one_event() as that will make using ->response field for permission event state easier. Reviewed-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Jan Kara <jack@suse.cz>
-rw-r--r--fs/notify/fanotify/fanotify_user.c32
1 files changed, 13 insertions, 19 deletions
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index e47d2a7709bf..121c84fc55ee 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -65,35 +65,32 @@ static int fanotify_event_info_len(struct fanotify_event *event)
* Get an fsnotify notification event if one exists and is small
* enough to fit in "count". Return an error pointer if the count
* is not large enough.
- *
- * Called with the group->notification_lock held.
*/
static struct fsnotify_event *get_one_event(struct fsnotify_group *group,
size_t count)
{
size_t event_size = FAN_EVENT_METADATA_LEN;
- struct fanotify_event *event;
-
- assert_spin_locked(&group->notification_lock);
+ struct fsnotify_event *fsn_event = NULL;
pr_debug("%s: group=%p count=%zd\n", __func__, group, count);
+ spin_lock(&group->notification_lock);
if (fsnotify_notify_queue_is_empty(group))
- return NULL;
+ goto out;
if (FAN_GROUP_FLAG(group, FAN_REPORT_FID)) {
- event = FANOTIFY_E(fsnotify_peek_first_event(group));
- event_size += fanotify_event_info_len(event);
+ event_size += fanotify_event_info_len(
+ FANOTIFY_E(fsnotify_peek_first_event(group)));
}
- if (event_size > count)
- return ERR_PTR(-EINVAL);
-
- /*
- * Held the notification_lock the whole time, so this is the
- * same event we peeked above
- */
- return fsnotify_remove_first_event(group);
+ if (event_size > count) {
+ fsn_event = ERR_PTR(-EINVAL);
+ goto out;
+ }
+ fsn_event = fsnotify_remove_first_event(group);
+out:
+ spin_unlock(&group->notification_lock);
+ return fsn_event;
}
static int create_fd(struct fsnotify_group *group,
@@ -316,10 +313,7 @@ static ssize_t fanotify_read(struct file *file, char __user *buf,
add_wait_queue(&group->notification_waitq, &wait);
while (1) {
- spin_lock(&group->notification_lock);
kevent = get_one_event(group, count);
- spin_unlock(&group->notification_lock);
-
if (IS_ERR(kevent)) {
ret = PTR_ERR(kevent);
break;