2 * Copyright (C) 2005-2013 Junjiro R. Okajima
4 * This program, aufs 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 of the License, or
7 * (at your option) any later version.
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.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * fsnotify for the lower directories
25 /* FS_IN_IGNORED is unnecessary */
26 static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE
27 | FS_CREATE | FS_EVENT_ON_CHILD);
28 static DECLARE_WAIT_QUEUE_HEAD(au_hfsn_wq);
29 static __cacheline_aligned_in_smp atomic64_t au_hfsn_ifree = ATOMIC64_INIT(0);
31 static void au_hfsn_free_mark(struct fsnotify_mark *mark)
33 struct au_hnotify *hn = container_of(mark, struct au_hnotify,
36 au_cache_free_hnotify(hn);
37 smp_mb__before_atomic_dec();
38 atomic64_dec(&au_hfsn_ifree);
42 static int au_hfsn_alloc(struct au_hinode *hinode)
44 struct au_hnotify *hn;
45 struct super_block *sb;
47 struct fsnotify_mark *mark;
50 hn = hinode->hi_notify;
51 sb = hn->hn_aufs_inode->i_sb;
52 bindex = au_br_index(sb, hinode->hi_id);
53 br = au_sbr(sb, bindex);
55 fsnotify_init_mark(mark, au_hfsn_free_mark);
56 mark->mask = AuHfsnMask;
58 * by udba rename or rmdir, aufs assign a new inode to the known
59 * h_inode, so specify 1 to allow dups.
61 return fsnotify_add_mark(mark, br->br_hfsn_group, hinode->hi_inode,
62 /*mnt*/NULL, /*allow_dups*/1);
65 static int au_hfsn_free(struct au_hinode *hinode, struct au_hnotify *hn)
67 struct fsnotify_mark *mark;
68 unsigned long long ull;
70 ull = atomic64_inc_return(&au_hfsn_ifree);
74 fsnotify_destroy_mark(mark);
75 fsnotify_put_mark(mark);
77 /* free hn by myself */
81 /* ---------------------------------------------------------------------- */
83 static void au_hfsn_ctl(struct au_hinode *hinode, int do_set)
85 struct fsnotify_mark *mark;
87 mark = &hinode->hi_notify->hn_mark;
88 spin_lock(&mark->lock);
90 AuDebugOn(mark->mask & AuHfsnMask);
91 mark->mask |= AuHfsnMask;
93 AuDebugOn(!(mark->mask & AuHfsnMask));
94 mark->mask &= ~AuHfsnMask;
96 spin_unlock(&mark->lock);
97 /* fsnotify_recalc_inode_mask(hinode->hi_inode); */
100 /* ---------------------------------------------------------------------- */
102 /* #define AuDbgHnotify */
104 static char *au_hfsn_name(u32 mask)
106 #ifdef CONFIG_AUFS_DEBUG
107 #define test_ret(flag) \
115 test_ret(FS_CLOSE_WRITE);
116 test_ret(FS_CLOSE_NOWRITE);
118 test_ret(FS_MOVED_FROM);
119 test_ret(FS_MOVED_TO);
122 test_ret(FS_DELETE_SELF);
123 test_ret(FS_MOVE_SELF);
124 test_ret(FS_UNMOUNT);
125 test_ret(FS_Q_OVERFLOW);
126 test_ret(FS_IN_IGNORED);
127 test_ret(FS_IN_ISDIR);
128 test_ret(FS_IN_ONESHOT);
129 test_ret(FS_EVENT_ON_CHILD);
138 /* ---------------------------------------------------------------------- */
140 static int au_hfsn_handle_event(struct fsnotify_group *group,
141 struct fsnotify_mark *inode_mark,
142 struct fsnotify_mark *vfsmount_mark,
143 struct fsnotify_event *event)
146 struct au_hnotify *hnotify;
147 struct inode *h_dir, *h_inode;
149 struct qstr h_child_qstr = {
150 .name = event->file_name,
151 .len = event->name_len
154 AuDebugOn(event->data_type != FSNOTIFY_EVENT_INODE);
157 /* if FS_UNMOUNT happens, there must be another bug */
159 AuDebugOn(mask & FS_UNMOUNT);
160 if (mask & (FS_IN_IGNORED | FS_UNMOUNT))
163 h_dir = event->to_tell;
164 h_inode = event->inode;
167 if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1
168 || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) {
169 AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n",
170 h_dir->i_ino, mask, au_hfsn_name(mask),
171 AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0);
177 AuDebugOn(!inode_mark);
178 hnotify = container_of(inode_mark, struct au_hnotify, hn_mark);
179 err = au_hnotify(h_dir, hnotify, mask, &h_child_qstr, h_inode);
185 /* isn't it waste to ask every registered 'group'? */
186 /* copied from linux/fs/notify/inotify/inotify_fsnotiry.c */
187 /* it should be exported to modules */
188 static bool au_hfsn_should_send_event(struct fsnotify_group *group,
189 struct inode *h_inode,
190 struct fsnotify_mark *inode_mark,
191 struct fsnotify_mark *vfsmount_mark,
192 __u32 mask, void *data, int data_type)
194 mask = (mask & ~FS_EVENT_ON_CHILD);
195 return inode_mark->mask & mask;
198 static struct fsnotify_ops au_hfsn_ops = {
199 .should_send_event = au_hfsn_should_send_event,
200 .handle_event = au_hfsn_handle_event
203 /* ---------------------------------------------------------------------- */
205 static void au_hfsn_fin_br(struct au_branch *br)
207 if (br->br_hfsn_group)
208 fsnotify_put_group(br->br_hfsn_group);
211 static int au_hfsn_init_br(struct au_branch *br, int perm)
213 br->br_hfsn_group = NULL;
214 br->br_hfsn_ops = au_hfsn_ops;
218 static int au_hfsn_reset_br(unsigned int udba, struct au_branch *br, int perm)
223 if (udba != AuOpt_UDBA_HNOTIFY
224 || !au_br_hnotifyable(perm)) {
226 br->br_hfsn_group = NULL;
230 if (br->br_hfsn_group)
233 br->br_hfsn_group = fsnotify_alloc_group(&br->br_hfsn_ops);
234 if (IS_ERR(br->br_hfsn_group)) {
235 err = PTR_ERR(br->br_hfsn_group);
236 pr_err("fsnotify_alloc_group() failed, %d\n", err);
237 br->br_hfsn_group = NULL;
245 /* ---------------------------------------------------------------------- */
247 static void au_hfsn_fin(void)
249 AuDbg("au_hfsn_ifree %lld\n", (long long)atomic64_read(&au_hfsn_ifree));
250 wait_event(au_hfsn_wq, !atomic64_read(&au_hfsn_ifree));
253 const struct au_hnotify_op au_hnotify_op = {
255 .alloc = au_hfsn_alloc,
256 .free = au_hfsn_free,
260 .reset_br = au_hfsn_reset_br,
261 .fin_br = au_hfsn_fin_br,
262 .init_br = au_hfsn_init_br