Branch data Line data Source code
1 : : /*
2 : : * Copyright (C) 2008 Red Hat, Inc., Eric Paris <eparis@redhat.com>
3 : : *
4 : : * This program is free software; you can redistribute it and/or modify
5 : : * it under the terms of the GNU General Public License as published by
6 : : * the Free Software Foundation; either version 2, or (at your option)
7 : : * any later version.
8 : : *
9 : : * This program is distributed in the hope that it will be useful,
10 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : : * GNU General Public License for more details.
13 : : *
14 : : * You should have received a copy of the GNU General Public License
15 : : * along with this program; see the file COPYING. If not, write to
16 : : * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
17 : : */
18 : :
19 : : #include <linux/list.h>
20 : : #include <linux/mutex.h>
21 : : #include <linux/slab.h>
22 : : #include <linux/srcu.h>
23 : : #include <linux/rculist.h>
24 : : #include <linux/wait.h>
25 : :
26 : : #include <linux/fsnotify_backend.h>
27 : : #include "fsnotify.h"
28 : :
29 : : #include <linux/atomic.h>
30 : :
31 : : /*
32 : : * Final freeing of a group
33 : : */
34 : 0 : void fsnotify_final_destroy_group(struct fsnotify_group *group)
35 : : {
36 [ + - ]: 7 : if (group->ops->free_group_priv)
37 : 7 : group->ops->free_group_priv(group);
38 : :
39 : 7 : kfree(group);
40 : 7 : }
41 : :
42 : : /*
43 : : * Trying to get rid of a group. Remove all marks, flush all events and release
44 : : * the group reference.
45 : : * Note that another thread calling fsnotify_clear_marks_by_group() may still
46 : : * hold a ref to the group.
47 : : */
48 : 0 : void fsnotify_destroy_group(struct fsnotify_group *group)
49 : : {
50 : : /* clear all inode marks for this group */
51 : 7 : fsnotify_clear_marks_by_group(group);
52 : :
53 : 7 : synchronize_srcu(&fsnotify_mark_srcu);
54 : :
55 : : /* clear the notification queue of all events */
56 : 7 : fsnotify_flush_notify(group);
57 : :
58 : 7 : fsnotify_put_group(group);
59 : 7 : }
60 : :
61 : : /*
62 : : * Get reference to a group.
63 : : */
64 : 0 : void fsnotify_get_group(struct fsnotify_group *group)
65 : : {
66 : 27649 : atomic_inc(&group->refcnt);
67 : 27649 : }
68 : :
69 : : /*
70 : : * Drop a reference to a group. Free it if it's through.
71 : : */
72 : 0 : void fsnotify_put_group(struct fsnotify_group *group)
73 : : {
74 [ + + ]: 27656 : if (atomic_dec_and_test(&group->refcnt))
75 : 7 : fsnotify_final_destroy_group(group);
76 : 0 : }
77 : :
78 : : /*
79 : : * Create a new fsnotify_group and hold a reference for the group returned.
80 : : */
81 : 0 : struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
82 : : {
83 : : struct fsnotify_group *group;
84 : :
85 : : group = kzalloc(sizeof(struct fsnotify_group), GFP_KERNEL);
86 [ + - ]: 7 : if (!group)
87 : : return ERR_PTR(-ENOMEM);
88 : :
89 : : /* set to 0 when there a no external references to this group */
90 : 7 : atomic_set(&group->refcnt, 1);
91 : 7 : atomic_set(&group->num_marks, 0);
92 : :
93 : 7 : mutex_init(&group->notification_mutex);
94 : 7 : INIT_LIST_HEAD(&group->notification_list);
95 : 7 : init_waitqueue_head(&group->notification_waitq);
96 : 7 : group->max_events = UINT_MAX;
97 : :
98 : 7 : mutex_init(&group->mark_mutex);
99 : 7 : INIT_LIST_HEAD(&group->marks_list);
100 : :
101 : 7 : group->ops = ops;
102 : :
103 : 7 : return group;
104 : : }
105 : :
106 : 0 : int fsnotify_fasync(int fd, struct file *file, int on)
107 : : {
108 : 0 : struct fsnotify_group *group = file->private_data;
109 : :
110 [ # # ]: 0 : return fasync_helper(fd, file, on, &group->fsn_fa) >= 0 ? 0 : -EIO;
111 : : }
|