Introduces mutex in the read() path to prevent a threaded client reading from the same fd consuming events out of order.
This will matter when avoiding taking the spinlock when consuming each event in the read() path. Signed-off-by: Jes Sorensen <jsoren...@fb.com> Reviewed-by: Josef Bacik <jba...@fb.com> --- fs/notify/inotify/inotify_fsnotify.c | 1 + fs/notify/inotify/inotify_user.c | 4 ++++ include/linux/fsnotify_backend.h | 3 +++ 3 files changed, 8 insertions(+) diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index 1aeb837..63c071f 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c @@ -168,6 +168,7 @@ static void inotify_free_group_priv(struct fsnotify_group *group) idr_destroy(&group->inotify_data.idr); if (group->inotify_data.ucounts) dec_inotify_instances(group->inotify_data.ucounts); + mutex_destroy(&group->inotify_data.consumer_mutex); } static void inotify_free_event(struct fsnotify_event *fsn_event) diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 498d609..6f5b360 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -230,6 +230,7 @@ static ssize_t inotify_read(struct file *file, char __user *buf, start = buf; group = file->private_data; + mutex_lock(&group->inotify_data.consumer_mutex); add_wait_queue(&group->notification_waitq, &wait); while (1) { spin_lock(&group->notification_lock); @@ -264,6 +265,7 @@ static ssize_t inotify_read(struct file *file, char __user *buf, wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); } remove_wait_queue(&group->notification_waitq, &wait); + mutex_unlock(&group->inotify_data.consumer_mutex); if (start != buf && ret != -EFAULT) ret = buf - start; @@ -650,6 +652,8 @@ static struct fsnotify_group *inotify_new_group(unsigned int max_events) group->max_events = max_events; + mutex_init(&group->inotify_data.consumer_mutex); + spin_lock_init(&group->inotify_data.idr_lock); idr_init(&group->inotify_data.idr); group->inotify_data.ucounts = inc_ucount(current_user_ns(), diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index e6e689b..e0686ed 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -172,6 +172,9 @@ struct fsnotify_group { spinlock_t idr_lock; struct idr idr; struct ucounts *ucounts; + struct mutex consumer_mutex; /* Prevent out of order + * delivery of events + * to threaded consumers */ } inotify_data; #endif #ifdef CONFIG_FANOTIFY -- 2.9.3