1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2005-2021 Junjiro R. Okajima
5 * This program, aufs is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
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
,
35 /* AuDbg("here\n"); */
36 au_cache_free_hnotify(hn
);
37 smp_mb__before_atomic(); /* for atomic64_dec */
38 if (atomic64_dec_and_test(&au_hfsn_ifree
))
42 static int au_hfsn_alloc(struct au_hinode
*hinode
)
45 struct au_hnotify
*hn
;
46 struct super_block
*sb
;
48 struct fsnotify_mark
*mark
;
51 hn
= hinode
->hi_notify
;
52 sb
= hn
->hn_aufs_inode
->i_sb
;
53 bindex
= au_br_index(sb
, hinode
->hi_id
);
54 br
= au_sbr(sb
, bindex
);
55 AuDebugOn(!br
->br_hfsn
);
58 fsnotify_init_mark(mark
, br
->br_hfsn
->hfsn_group
);
59 mark
->mask
= AuHfsnMask
;
61 * by udba rename or rmdir, aufs assign a new inode to the known
62 * h_inode, so specify 1 to allow dups.
65 err
= fsnotify_add_inode_mark(mark
, hinode
->hi_inode
, /*allow_dups*/1);
71 static int au_hfsn_free(struct au_hinode
*hinode
, struct au_hnotify
*hn
)
73 struct fsnotify_mark
*mark
;
74 unsigned long long ull
;
75 struct fsnotify_group
*group
;
77 ull
= atomic64_inc_return(&au_hfsn_ifree
);
81 spin_lock(&mark
->lock
);
83 fsnotify_get_group(group
);
84 spin_unlock(&mark
->lock
);
86 fsnotify_destroy_mark(mark
, group
);
87 fsnotify_put_mark(mark
);
88 fsnotify_put_group(group
);
91 /* free hn by myself */
95 /* ---------------------------------------------------------------------- */
97 static void au_hfsn_ctl(struct au_hinode
*hinode
, int do_set
)
99 struct fsnotify_mark
*mark
;
101 mark
= &hinode
->hi_notify
->hn_mark
;
102 spin_lock(&mark
->lock
);
104 AuDebugOn(mark
->mask
& AuHfsnMask
);
105 mark
->mask
|= AuHfsnMask
;
107 AuDebugOn(!(mark
->mask
& AuHfsnMask
));
108 mark
->mask
&= ~AuHfsnMask
;
110 spin_unlock(&mark
->lock
);
111 /* fsnotify_recalc_inode_mask(hinode->hi_inode); */
114 /* ---------------------------------------------------------------------- */
116 /* #define AuDbgHnotify */
118 static char *au_hfsn_name(u32 mask
)
120 #ifdef CONFIG_AUFS_DEBUG
121 #define test_ret(flag) \
129 test_ret(FS_CLOSE_WRITE
);
130 test_ret(FS_CLOSE_NOWRITE
);
132 test_ret(FS_MOVED_FROM
);
133 test_ret(FS_MOVED_TO
);
136 test_ret(FS_DELETE_SELF
);
137 test_ret(FS_MOVE_SELF
);
138 test_ret(FS_UNMOUNT
);
139 test_ret(FS_Q_OVERFLOW
);
140 test_ret(FS_IN_IGNORED
);
142 test_ret(FS_IN_ONESHOT
);
143 test_ret(FS_EVENT_ON_CHILD
);
152 /* ---------------------------------------------------------------------- */
154 static void au_hfsn_free_group(struct fsnotify_group
*group
)
156 struct au_br_hfsnotify
*hfsn
= group
->private;
158 /* AuDbg("here\n"); */
159 au_kfree_try_rcu(hfsn
);
162 static int au_hfsn_handle_event(struct fsnotify_group
*group
,
163 u32 mask
, const void *data
, int data_type
,
165 const struct qstr
*file_name
, u32 cookie
,
166 struct fsnotify_iter_info
*iter_info
)
169 struct au_hnotify
*hnotify
;
170 struct inode
*h_dir
, *h_inode
;
171 struct fsnotify_mark
*inode_mark
;
173 AuDebugOn(data_type
!= FSNOTIFY_EVENT_INODE
);
176 /* if FS_UNMOUNT happens, there must be another bug */
177 AuDebugOn(mask
& FS_UNMOUNT
);
178 if (mask
& (FS_IN_IGNORED
| FS_UNMOUNT
))
185 if (1 || h_child_qstr
.len
!= sizeof(AUFS_XINO_FNAME
) - 1
186 || strncmp(h_child_qstr
.name
, AUFS_XINO_FNAME
, h_child_qstr
.len
)) {
187 AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n",
188 h_dir
->i_ino
, mask
, au_hfsn_name(mask
),
189 AuLNPair(&h_child_qstr
), h_inode
? h_inode
->i_ino
: 0);
195 inode_mark
= fsnotify_iter_inode_mark(iter_info
);
196 AuDebugOn(!inode_mark
);
197 hnotify
= container_of(inode_mark
, struct au_hnotify
, hn_mark
);
198 err
= au_hnotify(h_dir
, hnotify
, mask
, file_name
, h_inode
);
204 static struct fsnotify_ops au_hfsn_ops
= {
205 .handle_event
= au_hfsn_handle_event
,
206 .free_group_priv
= au_hfsn_free_group
,
207 .free_mark
= au_hfsn_free_mark
210 /* ---------------------------------------------------------------------- */
212 static void au_hfsn_fin_br(struct au_branch
*br
)
214 struct au_br_hfsnotify
*hfsn
;
219 fsnotify_put_group(hfsn
->hfsn_group
);
224 static int au_hfsn_init_br(struct au_branch
*br
, int perm
)
227 struct fsnotify_group
*group
;
228 struct au_br_hfsnotify
*hfsn
;
232 if (!au_br_hnotifyable(perm
))
236 hfsn
= kmalloc(sizeof(*hfsn
), GFP_NOFS
);
241 group
= fsnotify_alloc_group(&au_hfsn_ops
);
243 err
= PTR_ERR(group
);
244 pr_err("fsnotify_alloc_group() failed, %d\n", err
);
248 group
->private = hfsn
;
249 hfsn
->hfsn_group
= group
;
251 goto out
; /* success */
254 au_kfree_try_rcu(hfsn
);
259 static int au_hfsn_reset_br(unsigned int udba
, struct au_branch
*br
, int perm
)
265 err
= au_hfsn_init_br(br
, perm
);
270 /* ---------------------------------------------------------------------- */
272 static void au_hfsn_fin(void)
274 AuDbg("au_hfsn_ifree %lld\n", (long long)atomic64_read(&au_hfsn_ifree
));
275 wait_event(au_hfsn_wq
, !atomic64_read(&au_hfsn_ifree
));
278 const struct au_hnotify_op au_hnotify_op
= {
280 .alloc
= au_hfsn_alloc
,
281 .free
= au_hfsn_free
,
285 .reset_br
= au_hfsn_reset_br
,
286 .fin_br
= au_hfsn_fin_br
,
287 .init_br
= au_hfsn_init_br