]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blame - include/linux/fsnotify.h
fsnotify: add marks to inodes so groups can interpret how to handle those inodes
[mirror_ubuntu-focal-kernel.git] / include / linux / fsnotify.h
CommitLineData
0eeca283
RL
1#ifndef _LINUX_FS_NOTIFY_H
2#define _LINUX_FS_NOTIFY_H
3
4/*
5 * include/linux/fsnotify.h - generic hooks for filesystem notification, to
6 * reduce in-source duplication from both dnotify and inotify.
7 *
8 * We don't compile any of this away in some complicated menagerie of ifdefs.
9 * Instead, we rely on the code inside to optimize away as needed.
10 *
11 * (C) Copyright 2005 Robert Love
12 */
13
0eeca283
RL
14#include <linux/dnotify.h>
15#include <linux/inotify.h>
90586523 16#include <linux/fsnotify_backend.h>
73241ccc 17#include <linux/audit.h>
0eeca283 18
c32ccd87
NP
19/*
20 * fsnotify_d_instantiate - instantiate a dentry for inode
21 * Called with dcache_lock held.
22 */
23static inline void fsnotify_d_instantiate(struct dentry *entry,
24 struct inode *inode)
25{
26 inotify_d_instantiate(entry, inode);
27}
28
29/*
30 * fsnotify_d_move - entry has been moved
31 * Called with dcache_lock and entry->d_lock held.
32 */
33static inline void fsnotify_d_move(struct dentry *entry)
34{
35 inotify_d_move(entry);
36}
37
90586523
EP
38/*
39 * fsnotify_link_count - inode's link count changed
40 */
41static inline void fsnotify_link_count(struct inode *inode)
42{
43 inotify_inode_queue_event(inode, IN_ATTRIB, 0, NULL, NULL);
44
45 fsnotify(inode, FS_ATTRIB, inode, FSNOTIFY_EVENT_INODE);
46}
47
0eeca283
RL
48/*
49 * fsnotify_move - file old_name at old_dir was moved to new_name at new_dir
50 */
51static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
52 const char *old_name, const char *new_name,
5a190ae6 53 int isdir, struct inode *target, struct dentry *moved)
0eeca283 54{
5a190ae6 55 struct inode *source = moved->d_inode;
0eeca283 56 u32 cookie = inotify_get_cookie();
90586523
EP
57 __u32 old_dir_mask = 0;
58 __u32 new_dir_mask = 0;
0eeca283 59
90586523 60 if (old_dir == new_dir) {
0eeca283 61 inode_dir_notify(old_dir, DN_RENAME);
90586523
EP
62 old_dir_mask = FS_DN_RENAME;
63 } else {
0eeca283 64 inode_dir_notify(old_dir, DN_DELETE);
90586523 65 old_dir_mask = FS_DELETE;
0eeca283 66 inode_dir_notify(new_dir, DN_CREATE);
90586523 67 new_dir_mask = FS_CREATE;
0eeca283
RL
68 }
69
90586523 70 if (isdir) {
0eeca283 71 isdir = IN_ISDIR;
90586523
EP
72 old_dir_mask |= FS_IN_ISDIR;
73 new_dir_mask |= FS_IN_ISDIR;
74 }
75
76 old_dir_mask |= FS_MOVED_FROM;
77 new_dir_mask |= FS_MOVED_TO;
78
7c297722
AG
79 inotify_inode_queue_event(old_dir, IN_MOVED_FROM|isdir,cookie,old_name,
80 source);
81 inotify_inode_queue_event(new_dir, IN_MOVED_TO|isdir, cookie, new_name,
82 source);
75449536 83
90586523
EP
84 fsnotify(old_dir, old_dir_mask, old_dir, FSNOTIFY_EVENT_INODE);
85 fsnotify(new_dir, new_dir_mask, new_dir, FSNOTIFY_EVENT_INODE);
86
75449536 87 if (target) {
7c297722 88 inotify_inode_queue_event(target, IN_DELETE_SELF, 0, NULL, NULL);
75449536 89 inotify_inode_is_dead(target);
90586523
EP
90
91 /* this is really a link_count change not a removal */
92 fsnotify_link_count(target);
75449536 93 }
89204c40
JM
94
95 if (source) {
7c297722 96 inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL, NULL);
90586523 97 fsnotify(source, FS_MOVE_SELF, moved->d_inode, FSNOTIFY_EVENT_INODE);
89204c40 98 }
5a190ae6 99 audit_inode_child(new_name, moved, new_dir);
0eeca283
RL
100}
101
3be25f49
EP
102/*
103 * fsnotify_inode_delete - and inode is being evicted from cache, clean up is needed
104 */
105static inline void fsnotify_inode_delete(struct inode *inode)
106{
107 __fsnotify_inode_delete(inode);
108}
109
7a91bf7f
JM
110/*
111 * fsnotify_nameremove - a filename was removed from a directory
112 */
113static inline void fsnotify_nameremove(struct dentry *dentry, int isdir)
114{
90586523
EP
115 __u32 mask = FS_DELETE;
116
7a91bf7f 117 if (isdir)
90586523 118 mask |= FS_IN_ISDIR;
7a91bf7f 119 dnotify_parent(dentry, DN_DELETE);
90586523 120 inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
7a91bf7f
JM
121}
122
123/*
124 * fsnotify_inoderemove - an inode is going away
125 */
126static inline void fsnotify_inoderemove(struct inode *inode)
127{
7c297722 128 inotify_inode_queue_event(inode, IN_DELETE_SELF, 0, NULL, NULL);
7a91bf7f 129 inotify_inode_is_dead(inode);
7a91bf7f 130
90586523 131 fsnotify(inode, FS_DELETE_SELF, inode, FSNOTIFY_EVENT_INODE);
3be25f49 132 __fsnotify_inode_delete(inode);
ece95912
JK
133}
134
0eeca283
RL
135/*
136 * fsnotify_create - 'name' was linked in
137 */
f38aa942 138static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
0eeca283
RL
139{
140 inode_dir_notify(inode, DN_CREATE);
7c297722
AG
141 inotify_inode_queue_event(inode, IN_CREATE, 0, dentry->d_name.name,
142 dentry->d_inode);
5a190ae6 143 audit_inode_child(dentry->d_name.name, dentry, inode);
90586523
EP
144
145 fsnotify(inode, FS_CREATE, dentry->d_inode, FSNOTIFY_EVENT_INODE);
0eeca283
RL
146}
147
ece95912
JK
148/*
149 * fsnotify_link - new hardlink in 'inode' directory
150 * Note: We have to pass also the linked inode ptr as some filesystems leave
151 * new_dentry->d_inode NULL and instantiate inode pointer later
152 */
153static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct dentry *new_dentry)
154{
155 inode_dir_notify(dir, DN_CREATE);
156 inotify_inode_queue_event(dir, IN_CREATE, 0, new_dentry->d_name.name,
157 inode);
158 fsnotify_link_count(inode);
159 audit_inode_child(new_dentry->d_name.name, new_dentry, dir);
90586523
EP
160
161 fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE);
ece95912
JK
162}
163
0eeca283
RL
164/*
165 * fsnotify_mkdir - directory 'name' was created
166 */
f38aa942 167static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
0eeca283 168{
90586523
EP
169 __u32 mask = (FS_CREATE | FS_IN_ISDIR);
170 struct inode *d_inode = dentry->d_inode;
171
0eeca283 172 inode_dir_notify(inode, DN_CREATE);
90586523 173 inotify_inode_queue_event(inode, mask, 0, dentry->d_name.name, d_inode);
5a190ae6 174 audit_inode_child(dentry->d_name.name, dentry, inode);
90586523
EP
175
176 fsnotify(inode, mask, d_inode, FSNOTIFY_EVENT_INODE);
0eeca283
RL
177}
178
179/*
180 * fsnotify_access - file was read
181 */
182static inline void fsnotify_access(struct dentry *dentry)
183{
184 struct inode *inode = dentry->d_inode;
90586523 185 __u32 mask = FS_ACCESS;
0eeca283
RL
186
187 if (S_ISDIR(inode->i_mode))
90586523 188 mask |= FS_IN_ISDIR;
0eeca283
RL
189
190 dnotify_parent(dentry, DN_ACCESS);
191 inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
7c297722 192 inotify_inode_queue_event(inode, mask, 0, NULL, NULL);
90586523
EP
193
194 fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE);
0eeca283
RL
195}
196
197/*
198 * fsnotify_modify - file was modified
199 */
200static inline void fsnotify_modify(struct dentry *dentry)
201{
202 struct inode *inode = dentry->d_inode;
90586523 203 __u32 mask = FS_MODIFY;
0eeca283
RL
204
205 if (S_ISDIR(inode->i_mode))
90586523 206 mask |= FS_IN_ISDIR;
0eeca283
RL
207
208 dnotify_parent(dentry, DN_MODIFY);
209 inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
7c297722 210 inotify_inode_queue_event(inode, mask, 0, NULL, NULL);
90586523
EP
211
212 fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE);
0eeca283
RL
213}
214
215/*
216 * fsnotify_open - file was opened
217 */
218static inline void fsnotify_open(struct dentry *dentry)
219{
220 struct inode *inode = dentry->d_inode;
90586523 221 __u32 mask = FS_OPEN;
0eeca283
RL
222
223 if (S_ISDIR(inode->i_mode))
90586523 224 mask |= FS_IN_ISDIR;
0eeca283 225
0eeca283 226 inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
7c297722 227 inotify_inode_queue_event(inode, mask, 0, NULL, NULL);
90586523
EP
228
229 fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE);
0eeca283
RL
230}
231
232/*
233 * fsnotify_close - file was closed
234 */
235static inline void fsnotify_close(struct file *file)
236{
0f7fc9e4 237 struct dentry *dentry = file->f_path.dentry;
0eeca283
RL
238 struct inode *inode = dentry->d_inode;
239 const char *name = dentry->d_name.name;
aeb5d727 240 fmode_t mode = file->f_mode;
90586523 241 __u32 mask = (mode & FMODE_WRITE) ? FS_CLOSE_WRITE : FS_CLOSE_NOWRITE;
0eeca283
RL
242
243 if (S_ISDIR(inode->i_mode))
90586523 244 mask |= FS_IN_ISDIR;
0eeca283
RL
245
246 inotify_dentry_parent_queue_event(dentry, mask, 0, name);
7c297722 247 inotify_inode_queue_event(inode, mask, 0, NULL, NULL);
90586523
EP
248
249 fsnotify(inode, mask, file, FSNOTIFY_EVENT_FILE);
0eeca283
RL
250}
251
252/*
253 * fsnotify_xattr - extended attributes were changed
254 */
255static inline void fsnotify_xattr(struct dentry *dentry)
256{
257 struct inode *inode = dentry->d_inode;
90586523 258 __u32 mask = FS_ATTRIB;
0eeca283
RL
259
260 if (S_ISDIR(inode->i_mode))
90586523 261 mask |= FS_IN_ISDIR;
0eeca283
RL
262
263 inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
7c297722 264 inotify_inode_queue_event(inode, mask, 0, NULL, NULL);
90586523
EP
265
266 fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE);
0eeca283
RL
267}
268
269/*
270 * fsnotify_change - notify_change event. file was modified and/or metadata
271 * was changed.
272 */
273static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid)
274{
275 struct inode *inode = dentry->d_inode;
276 int dn_mask = 0;
90586523 277 __u32 in_mask = 0;
0eeca283
RL
278
279 if (ia_valid & ATTR_UID) {
90586523 280 in_mask |= FS_ATTRIB;
0eeca283
RL
281 dn_mask |= DN_ATTRIB;
282 }
283 if (ia_valid & ATTR_GID) {
90586523 284 in_mask |= FS_ATTRIB;
0eeca283
RL
285 dn_mask |= DN_ATTRIB;
286 }
287 if (ia_valid & ATTR_SIZE) {
90586523 288 in_mask |= FS_MODIFY;
0eeca283
RL
289 dn_mask |= DN_MODIFY;
290 }
291 /* both times implies a utime(s) call */
292 if ((ia_valid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME))
293 {
90586523 294 in_mask |= FS_ATTRIB;
0eeca283
RL
295 dn_mask |= DN_ATTRIB;
296 } else if (ia_valid & ATTR_ATIME) {
90586523 297 in_mask |= FS_ACCESS;
0eeca283
RL
298 dn_mask |= DN_ACCESS;
299 } else if (ia_valid & ATTR_MTIME) {
90586523 300 in_mask |= FS_MODIFY;
0eeca283
RL
301 dn_mask |= DN_MODIFY;
302 }
303 if (ia_valid & ATTR_MODE) {
90586523 304 in_mask |= FS_ATTRIB;
0eeca283
RL
305 dn_mask |= DN_ATTRIB;
306 }
307
308 if (dn_mask)
309 dnotify_parent(dentry, dn_mask);
310 if (in_mask) {
311 if (S_ISDIR(inode->i_mode))
90586523 312 in_mask |= FS_IN_ISDIR;
7c297722 313 inotify_inode_queue_event(inode, in_mask, 0, NULL, NULL);
0eeca283
RL
314 inotify_dentry_parent_queue_event(dentry, in_mask, 0,
315 dentry->d_name.name);
90586523 316 fsnotify(inode, in_mask, inode, FSNOTIFY_EVENT_INODE);
0eeca283
RL
317 }
318}
319
90586523 320#if defined(CONFIG_INOTIFY) || defined(CONFIG_FSNOTIFY) /* notify helpers */
0eeca283
RL
321
322/*
323 * fsnotify_oldname_init - save off the old filename before we change it
324 */
325static inline const char *fsnotify_oldname_init(const char *name)
326{
327 return kstrdup(name, GFP_KERNEL);
328}
329
330/*
331 * fsnotify_oldname_free - free the name we got from fsnotify_oldname_init
332 */
333static inline void fsnotify_oldname_free(const char *old_name)
334{
335 kfree(old_name);
336}
337
90586523 338#else /* CONFIG_INOTIFY || CONFIG_FSNOTIFY */
0eeca283
RL
339
340static inline const char *fsnotify_oldname_init(const char *name)
341{
342 return NULL;
343}
344
345static inline void fsnotify_oldname_free(const char *old_name)
346{
347}
348
349#endif /* ! CONFIG_INOTIFY */
350
0eeca283 351#endif /* _LINUX_FS_NOTIFY_H */