Commit 8c554466 authored by Jan Kara's avatar Jan Kara
Browse files

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: default avatarAmir Goldstein <amir73il@gmail.com>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent af6a5113
Loading
Loading
Loading
Loading
+13 −19
Original line number Diff line number Diff line
@@ -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;