aboutsummaryrefslogtreecommitdiffstats
path: root/fs/inotify_user.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/inotify_user.c')
-rw-r--r--fs/inotify_user.c43
1 files changed, 35 insertions, 8 deletions
diff --git a/fs/inotify_user.c b/fs/inotify_user.c
index 5e009331c01f..7b94a1e3c015 100644
--- a/fs/inotify_user.c
+++ b/fs/inotify_user.c
@@ -41,9 +41,9 @@ static struct kmem_cache *event_cachep __read_mostly;
41static struct vfsmount *inotify_mnt __read_mostly; 41static struct vfsmount *inotify_mnt __read_mostly;
42 42
43/* these are configurable via /proc/sys/fs/inotify/ */ 43/* these are configurable via /proc/sys/fs/inotify/ */
44int inotify_max_user_instances __read_mostly; 44static int inotify_max_user_instances __read_mostly;
45int inotify_max_user_watches __read_mostly; 45static int inotify_max_user_watches __read_mostly;
46int inotify_max_queued_events __read_mostly; 46static int inotify_max_queued_events __read_mostly;
47 47
48/* 48/*
49 * Lock ordering: 49 * Lock ordering:
@@ -79,6 +79,7 @@ struct inotify_device {
79 atomic_t count; /* reference count */ 79 atomic_t count; /* reference count */
80 struct user_struct *user; /* user who opened this dev */ 80 struct user_struct *user; /* user who opened this dev */
81 struct inotify_handle *ih; /* inotify handle */ 81 struct inotify_handle *ih; /* inotify handle */
82 struct fasync_struct *fa; /* async notification */
82 unsigned int queue_size; /* size of the queue (bytes) */ 83 unsigned int queue_size; /* size of the queue (bytes) */
83 unsigned int event_count; /* number of pending events */ 84 unsigned int event_count; /* number of pending events */
84 unsigned int max_events; /* maximum number of events */ 85 unsigned int max_events; /* maximum number of events */
@@ -248,6 +249,19 @@ inotify_dev_get_event(struct inotify_device *dev)
248} 249}
249 250
250/* 251/*
252 * inotify_dev_get_last_event - return the last event in the given dev's queue
253 *
254 * Caller must hold dev->ev_mutex.
255 */
256static inline struct inotify_kernel_event *
257inotify_dev_get_last_event(struct inotify_device *dev)
258{
259 if (list_empty(&dev->events))
260 return NULL;
261 return list_entry(dev->events.prev, struct inotify_kernel_event, list);
262}
263
264/*
251 * inotify_dev_queue_event - event handler registered with core inotify, adds 265 * inotify_dev_queue_event - event handler registered with core inotify, adds
252 * a new event to the given device 266 * a new event to the given device
253 * 267 *
@@ -269,11 +283,11 @@ static void inotify_dev_queue_event(struct inotify_watch *w, u32 wd, u32 mask,
269 /* we can safely put the watch as we don't reference it while 283 /* we can safely put the watch as we don't reference it while
270 * generating the event 284 * generating the event
271 */ 285 */
272 if (mask & IN_IGNORED || mask & IN_ONESHOT) 286 if (mask & IN_IGNORED || w->mask & IN_ONESHOT)
273 put_inotify_watch(w); /* final put */ 287 put_inotify_watch(w); /* final put */
274 288
275 /* coalescing: drop this event if it is a dupe of the previous */ 289 /* coalescing: drop this event if it is a dupe of the previous */
276 last = inotify_dev_get_event(dev); 290 last = inotify_dev_get_last_event(dev);
277 if (last && last->event.mask == mask && last->event.wd == wd && 291 if (last && last->event.mask == mask && last->event.wd == wd &&
278 last->event.cookie == cookie) { 292 last->event.cookie == cookie) {
279 const char *lastname = last->name; 293 const char *lastname = last->name;
@@ -302,6 +316,7 @@ static void inotify_dev_queue_event(struct inotify_watch *w, u32 wd, u32 mask,
302 dev->queue_size += sizeof(struct inotify_event) + kevent->event.len; 316 dev->queue_size += sizeof(struct inotify_event) + kevent->event.len;
303 list_add_tail(&kevent->list, &dev->events); 317 list_add_tail(&kevent->list, &dev->events);
304 wake_up_interruptible(&dev->wq); 318 wake_up_interruptible(&dev->wq);
319 kill_fasync(&dev->fa, SIGIO, POLL_IN);
305 320
306out: 321out:
307 mutex_unlock(&dev->ev_mutex); 322 mutex_unlock(&dev->ev_mutex);
@@ -352,7 +367,7 @@ static int find_inode(const char __user *dirname, struct nameidata *nd,
352 /* you can only watch an inode if you have read permissions on it */ 367 /* you can only watch an inode if you have read permissions on it */
353 error = vfs_permission(nd, MAY_READ); 368 error = vfs_permission(nd, MAY_READ);
354 if (error) 369 if (error)
355 path_release(nd); 370 path_put(&nd->path);
356 return error; 371 return error;
357} 372}
358 373
@@ -490,6 +505,13 @@ static ssize_t inotify_read(struct file *file, char __user *buf,
490 return ret; 505 return ret;
491} 506}
492 507
508static int inotify_fasync(int fd, struct file *file, int on)
509{
510 struct inotify_device *dev = file->private_data;
511
512 return fasync_helper(fd, file, on, &dev->fa) >= 0 ? 0 : -EIO;
513}
514
493static int inotify_release(struct inode *ignored, struct file *file) 515static int inotify_release(struct inode *ignored, struct file *file)
494{ 516{
495 struct inotify_device *dev = file->private_data; 517 struct inotify_device *dev = file->private_data;
@@ -502,6 +524,9 @@ static int inotify_release(struct inode *ignored, struct file *file)
502 inotify_dev_event_dequeue(dev); 524 inotify_dev_event_dequeue(dev);
503 mutex_unlock(&dev->ev_mutex); 525 mutex_unlock(&dev->ev_mutex);
504 526
527 if (file->f_flags & FASYNC)
528 inotify_fasync(-1, file, 0);
529
505 /* free this device: the put matching the get in inotify_init() */ 530 /* free this device: the put matching the get in inotify_init() */
506 put_inotify_dev(dev); 531 put_inotify_dev(dev);
507 532
@@ -530,6 +555,7 @@ static long inotify_ioctl(struct file *file, unsigned int cmd,
530static const struct file_operations inotify_fops = { 555static const struct file_operations inotify_fops = {
531 .poll = inotify_poll, 556 .poll = inotify_poll,
532 .read = inotify_read, 557 .read = inotify_read,
558 .fasync = inotify_fasync,
533 .release = inotify_release, 559 .release = inotify_release,
534 .unlocked_ioctl = inotify_ioctl, 560 .unlocked_ioctl = inotify_ioctl,
535 .compat_ioctl = inotify_ioctl, 561 .compat_ioctl = inotify_ioctl,
@@ -577,6 +603,7 @@ asmlinkage long sys_inotify_init(void)
577 goto out_free_dev; 603 goto out_free_dev;
578 } 604 }
579 dev->ih = ih; 605 dev->ih = ih;
606 dev->fa = NULL;
580 607
581 filp->f_op = &inotify_fops; 608 filp->f_op = &inotify_fops;
582 filp->f_path.mnt = mntget(inotify_mnt); 609 filp->f_path.mnt = mntget(inotify_mnt);
@@ -640,7 +667,7 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
640 goto fput_and_out; 667 goto fput_and_out;
641 668
642 /* inode held in place by reference to nd; dev by fget on fd */ 669 /* inode held in place by reference to nd; dev by fget on fd */
643 inode = nd.dentry->d_inode; 670 inode = nd.path.dentry->d_inode;
644 dev = filp->private_data; 671 dev = filp->private_data;
645 672
646 mutex_lock(&dev->up_mutex); 673 mutex_lock(&dev->up_mutex);
@@ -649,7 +676,7 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
649 ret = create_watch(dev, inode, mask); 676 ret = create_watch(dev, inode, mask);
650 mutex_unlock(&dev->up_mutex); 677 mutex_unlock(&dev->up_mutex);
651 678
652 path_release(&nd); 679 path_put(&nd.path);
653fput_and_out: 680fput_and_out:
654 fput_light(filp, fput_needed); 681 fput_light(filp, fput_needed);
655 return ret; 682 return ret;