Linux Audio

Check our new training course

Loading...
v5.14.15
  1/* SPDX-License-Identifier: GPL-2.0 */
  2#ifndef _LINUX_FS_NOTIFY_H
  3#define _LINUX_FS_NOTIFY_H
  4
  5/*
  6 * include/linux/fsnotify.h - generic hooks for filesystem notification, to
  7 * reduce in-source duplication from both dnotify and inotify.
  8 *
  9 * We don't compile any of this away in some complicated menagerie of ifdefs.
 10 * Instead, we rely on the code inside to optimize away as needed.
 11 *
 12 * (C) Copyright 2005 Robert Love
 13 */
 14
 15#include <linux/fsnotify_backend.h>
 16#include <linux/audit.h>
 17#include <linux/slab.h>
 18#include <linux/bug.h>
 19
 20/*
 21 * Notify this @dir inode about a change in a child directory entry.
 22 * The directory entry may have turned positive or negative or its inode may
 23 * have changed (i.e. renamed over).
 24 *
 25 * Unlike fsnotify_parent(), the event will be reported regardless of the
 26 * FS_EVENT_ON_CHILD mask on the parent inode and will not be reported if only
 27 * the child is interested and not the parent.
 28 */
 29static inline void fsnotify_name(struct inode *dir, __u32 mask,
 30				 struct inode *child,
 31				 const struct qstr *name, u32 cookie)
 32{
 33	fsnotify(mask, child, FSNOTIFY_EVENT_INODE, dir, name, NULL, cookie);
 34}
 35
 36static inline void fsnotify_dirent(struct inode *dir, struct dentry *dentry,
 37				   __u32 mask)
 38{
 39	fsnotify_name(dir, mask, d_inode(dentry), &dentry->d_name, 0);
 40}
 41
 42static inline void fsnotify_inode(struct inode *inode, __u32 mask)
 43{
 44	if (S_ISDIR(inode->i_mode))
 45		mask |= FS_ISDIR;
 46
 47	fsnotify(mask, inode, FSNOTIFY_EVENT_INODE, NULL, NULL, inode, 0);
 48}
 49
 50/* Notify this dentry's parent about a child's events. */
 51static inline int fsnotify_parent(struct dentry *dentry, __u32 mask,
 52				  const void *data, int data_type)
 53{
 54	struct inode *inode = d_inode(dentry);
 55
 56	if (S_ISDIR(inode->i_mode)) {
 57		mask |= FS_ISDIR;
 58
 59		/* sb/mount marks are not interested in name of directory */
 60		if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED))
 61			goto notify_child;
 62	}
 63
 64	/* disconnected dentry cannot notify parent */
 65	if (IS_ROOT(dentry))
 66		goto notify_child;
 67
 68	return __fsnotify_parent(dentry, mask, data, data_type);
 69
 70notify_child:
 71	return fsnotify(mask, data, data_type, NULL, NULL, inode, 0);
 72}
 73
 74/*
 75 * Simple wrappers to consolidate calls to fsnotify_parent() when an event
 76 * is on a file/dentry.
 77 */
 78static inline void fsnotify_dentry(struct dentry *dentry, __u32 mask)
 79{
 80	fsnotify_parent(dentry, mask, d_inode(dentry), FSNOTIFY_EVENT_INODE);
 81}
 82
 83static inline int fsnotify_file(struct file *file, __u32 mask)
 84{
 85	const struct path *path = &file->f_path;
 86
 87	if (file->f_mode & FMODE_NONOTIFY)
 88		return 0;
 89
 90	return fsnotify_parent(path->dentry, mask, path, FSNOTIFY_EVENT_PATH);
 91}
 92
 93/* Simple call site for access decisions */
 94static inline int fsnotify_perm(struct file *file, int mask)
 95{
 96	int ret;
 
 97	__u32 fsnotify_mask = 0;
 
 98
 
 
 99	if (!(mask & (MAY_READ | MAY_OPEN)))
100		return 0;
101
102	if (mask & MAY_OPEN) {
103		fsnotify_mask = FS_OPEN_PERM;
 
 
 
 
104
105		if (file->f_flags & __FMODE_EXEC) {
106			ret = fsnotify_file(file, FS_OPEN_EXEC_PERM);
 
107
108			if (ret)
109				return ret;
110		}
111	} else if (mask & MAY_READ) {
112		fsnotify_mask = FS_ACCESS_PERM;
113	}
114
115	return fsnotify_file(file, fsnotify_mask);
 
 
 
 
 
 
 
 
 
116}
117
118/*
119 * fsnotify_link_count - inode's link count changed
120 */
121static inline void fsnotify_link_count(struct inode *inode)
122{
123	fsnotify_inode(inode, FS_ATTRIB);
124}
125
126/*
127 * fsnotify_move - file old_name at old_dir was moved to new_name at new_dir
128 */
129static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
130				 const struct qstr *old_name,
131				 int isdir, struct inode *target,
132				 struct dentry *moved)
133{
134	struct inode *source = moved->d_inode;
135	u32 fs_cookie = fsnotify_get_cookie();
136	__u32 old_dir_mask = FS_MOVED_FROM;
137	__u32 new_dir_mask = FS_MOVED_TO;
138	const struct qstr *new_name = &moved->d_name;
139
140	if (old_dir == new_dir)
141		old_dir_mask |= FS_DN_RENAME;
142
143	if (isdir) {
144		old_dir_mask |= FS_ISDIR;
145		new_dir_mask |= FS_ISDIR;
146	}
147
148	fsnotify_name(old_dir, old_dir_mask, source, old_name, fs_cookie);
149	fsnotify_name(new_dir, new_dir_mask, source, new_name, fs_cookie);
150
151	if (target)
152		fsnotify_link_count(target);
153	fsnotify_inode(source, FS_MOVE_SELF);
154	audit_inode_child(new_dir, moved, AUDIT_TYPE_CHILD_CREATE);
 
 
155}
156
157/*
158 * fsnotify_inode_delete - and inode is being evicted from cache, clean up is needed
159 */
160static inline void fsnotify_inode_delete(struct inode *inode)
161{
162	__fsnotify_inode_delete(inode);
163}
164
165/*
166 * fsnotify_vfsmount_delete - a vfsmount is being destroyed, clean up is needed
167 */
168static inline void fsnotify_vfsmount_delete(struct vfsmount *mnt)
169{
170	__fsnotify_vfsmount_delete(mnt);
171}
172
173/*
 
 
 
 
 
 
 
 
 
 
 
 
 
174 * fsnotify_inoderemove - an inode is going away
175 */
176static inline void fsnotify_inoderemove(struct inode *inode)
177{
178	fsnotify_inode(inode, FS_DELETE_SELF);
179	__fsnotify_inode_delete(inode);
180}
181
182/*
183 * fsnotify_create - 'name' was linked in
184 */
185static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
186{
187	audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE);
188
189	fsnotify_dirent(inode, dentry, FS_CREATE);
190}
191
192/*
193 * fsnotify_link - new hardlink in 'inode' directory
194 * Note: We have to pass also the linked inode ptr as some filesystems leave
195 *   new_dentry->d_inode NULL and instantiate inode pointer later
196 */
197static inline void fsnotify_link(struct inode *dir, struct inode *inode,
198				 struct dentry *new_dentry)
199{
200	fsnotify_link_count(inode);
201	audit_inode_child(dir, new_dentry, AUDIT_TYPE_CHILD_CREATE);
202
203	fsnotify_name(dir, FS_CREATE, inode, &new_dentry->d_name, 0);
204}
205
206/*
207 * fsnotify_unlink - 'name' was unlinked
208 *
209 * Caller must make sure that dentry->d_name is stable.
210 */
211static inline void fsnotify_unlink(struct inode *dir, struct dentry *dentry)
212{
213	/* Expected to be called before d_delete() */
214	WARN_ON_ONCE(d_is_negative(dentry));
215
216	fsnotify_dirent(dir, dentry, FS_DELETE);
217}
218
219/*
220 * fsnotify_mkdir - directory 'name' was created
221 */
222static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
223{
224	audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE);
 
225
226	fsnotify_dirent(inode, dentry, FS_CREATE | FS_ISDIR);
227}
228
229/*
230 * fsnotify_rmdir - directory 'name' was removed
231 *
232 * Caller must make sure that dentry->d_name is stable.
233 */
234static inline void fsnotify_rmdir(struct inode *dir, struct dentry *dentry)
235{
236	/* Expected to be called before d_delete() */
237	WARN_ON_ONCE(d_is_negative(dentry));
238
239	fsnotify_dirent(dir, dentry, FS_DELETE | FS_ISDIR);
240}
241
242/*
243 * fsnotify_access - file was read
244 */
245static inline void fsnotify_access(struct file *file)
246{
247	fsnotify_file(file, FS_ACCESS);
 
 
 
 
 
 
 
 
 
 
248}
249
250/*
251 * fsnotify_modify - file was modified
252 */
253static inline void fsnotify_modify(struct file *file)
254{
255	fsnotify_file(file, FS_MODIFY);
 
 
 
 
 
 
 
 
 
 
256}
257
258/*
259 * fsnotify_open - file was opened
260 */
261static inline void fsnotify_open(struct file *file)
262{
 
 
263	__u32 mask = FS_OPEN;
264
265	if (file->f_flags & __FMODE_EXEC)
266		mask |= FS_OPEN_EXEC;
267
268	fsnotify_file(file, mask);
 
269}
270
271/*
272 * fsnotify_close - file was closed
273 */
274static inline void fsnotify_close(struct file *file)
275{
276	__u32 mask = (file->f_mode & FMODE_WRITE) ? FS_CLOSE_WRITE :
277						    FS_CLOSE_NOWRITE;
 
 
 
 
 
278
279	fsnotify_file(file, mask);
 
 
 
280}
281
282/*
283 * fsnotify_xattr - extended attributes were changed
284 */
285static inline void fsnotify_xattr(struct dentry *dentry)
286{
287	fsnotify_dentry(dentry, FS_ATTRIB);
 
 
 
 
 
 
 
288}
289
290/*
291 * fsnotify_change - notify_change event.  file was modified and/or metadata
292 * was changed.
293 */
294static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid)
295{
 
296	__u32 mask = 0;
297
298	if (ia_valid & ATTR_UID)
299		mask |= FS_ATTRIB;
300	if (ia_valid & ATTR_GID)
301		mask |= FS_ATTRIB;
302	if (ia_valid & ATTR_SIZE)
303		mask |= FS_MODIFY;
304
305	/* both times implies a utime(s) call */
306	if ((ia_valid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME))
307		mask |= FS_ATTRIB;
308	else if (ia_valid & ATTR_ATIME)
309		mask |= FS_ACCESS;
310	else if (ia_valid & ATTR_MTIME)
311		mask |= FS_MODIFY;
312
313	if (ia_valid & ATTR_MODE)
314		mask |= FS_ATTRIB;
315
316	if (mask)
317		fsnotify_dentry(dentry, mask);
 
 
 
 
 
318}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
319
320#endif	/* _LINUX_FS_NOTIFY_H */
v3.1
 
  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
 14#include <linux/fsnotify_backend.h>
 15#include <linux/audit.h>
 16#include <linux/slab.h>
 
 17
 18/*
 19 * fsnotify_d_instantiate - instantiate a dentry for inode
 
 
 
 
 
 
 20 */
 21static inline void fsnotify_d_instantiate(struct dentry *dentry,
 22					  struct inode *inode)
 
 
 
 
 
 
 
 23{
 24	__fsnotify_d_instantiate(dentry, inode);
 
 
 
 
 
 
 
 
 25}
 26
 27/* Notify this dentry's parent about a child's events. */
 28static inline int fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 29{
 30	if (!dentry)
 31		dentry = path->dentry;
 
 
 32
 33	return __fsnotify_parent(path, dentry, mask);
 34}
 35
 36/* simple call site for access decisions */
 37static inline int fsnotify_perm(struct file *file, int mask)
 38{
 39	struct path *path = &file->f_path;
 40	struct inode *inode = path->dentry->d_inode;
 41	__u32 fsnotify_mask = 0;
 42	int ret;
 43
 44	if (file->f_mode & FMODE_NONOTIFY)
 45		return 0;
 46	if (!(mask & (MAY_READ | MAY_OPEN)))
 47		return 0;
 48	if (mask & MAY_OPEN)
 
 49		fsnotify_mask = FS_OPEN_PERM;
 50	else if (mask & MAY_READ)
 51		fsnotify_mask = FS_ACCESS_PERM;
 52	else
 53		BUG();
 54
 55	ret = fsnotify_parent(path, NULL, fsnotify_mask);
 56	if (ret)
 57		return ret;
 58
 59	return fsnotify(inode, fsnotify_mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
 60}
 
 
 
 
 61
 62/*
 63 * fsnotify_d_move - dentry has been moved
 64 */
 65static inline void fsnotify_d_move(struct dentry *dentry)
 66{
 67	/*
 68	 * On move we need to update dentry->d_flags to indicate if the new parent
 69	 * cares about events from this dentry.
 70	 */
 71	__fsnotify_update_dcache_flags(dentry);
 72}
 73
 74/*
 75 * fsnotify_link_count - inode's link count changed
 76 */
 77static inline void fsnotify_link_count(struct inode *inode)
 78{
 79	fsnotify(inode, FS_ATTRIB, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
 80}
 81
 82/*
 83 * fsnotify_move - file old_name at old_dir was moved to new_name at new_dir
 84 */
 85static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
 86				 const unsigned char *old_name,
 87				 int isdir, struct inode *target, struct dentry *moved)
 
 88{
 89	struct inode *source = moved->d_inode;
 90	u32 fs_cookie = fsnotify_get_cookie();
 91	__u32 old_dir_mask = (FS_EVENT_ON_CHILD | FS_MOVED_FROM);
 92	__u32 new_dir_mask = (FS_EVENT_ON_CHILD | FS_MOVED_TO);
 93	const unsigned char *new_name = moved->d_name.name;
 94
 95	if (old_dir == new_dir)
 96		old_dir_mask |= FS_DN_RENAME;
 97
 98	if (isdir) {
 99		old_dir_mask |= FS_ISDIR;
100		new_dir_mask |= FS_ISDIR;
101	}
102
103	fsnotify(old_dir, old_dir_mask, old_dir, FSNOTIFY_EVENT_INODE, old_name, fs_cookie);
104	fsnotify(new_dir, new_dir_mask, new_dir, FSNOTIFY_EVENT_INODE, new_name, fs_cookie);
105
106	if (target)
107		fsnotify_link_count(target);
108
109	if (source)
110		fsnotify(source, FS_MOVE_SELF, moved->d_inode, FSNOTIFY_EVENT_INODE, NULL, 0);
111	audit_inode_child(moved, new_dir);
112}
113
114/*
115 * fsnotify_inode_delete - and inode is being evicted from cache, clean up is needed
116 */
117static inline void fsnotify_inode_delete(struct inode *inode)
118{
119	__fsnotify_inode_delete(inode);
120}
121
122/*
123 * fsnotify_vfsmount_delete - a vfsmount is being destroyed, clean up is needed
124 */
125static inline void fsnotify_vfsmount_delete(struct vfsmount *mnt)
126{
127	__fsnotify_vfsmount_delete(mnt);
128}
129
130/*
131 * fsnotify_nameremove - a filename was removed from a directory
132 */
133static inline void fsnotify_nameremove(struct dentry *dentry, int isdir)
134{
135	__u32 mask = FS_DELETE;
136
137	if (isdir)
138		mask |= FS_ISDIR;
139
140	fsnotify_parent(NULL, dentry, mask);
141}
142
143/*
144 * fsnotify_inoderemove - an inode is going away
145 */
146static inline void fsnotify_inoderemove(struct inode *inode)
147{
148	fsnotify(inode, FS_DELETE_SELF, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
149	__fsnotify_inode_delete(inode);
150}
151
152/*
153 * fsnotify_create - 'name' was linked in
154 */
155static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
156{
157	audit_inode_child(dentry, inode);
158
159	fsnotify(inode, FS_CREATE, dentry->d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
160}
161
162/*
163 * fsnotify_link - new hardlink in 'inode' directory
164 * Note: We have to pass also the linked inode ptr as some filesystems leave
165 *   new_dentry->d_inode NULL and instantiate inode pointer later
166 */
167static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct dentry *new_dentry)
 
168{
169	fsnotify_link_count(inode);
170	audit_inode_child(new_dentry, dir);
171
172	fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE, new_dentry->d_name.name, 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
173}
174
175/*
176 * fsnotify_mkdir - directory 'name' was created
177 */
178static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
179{
180	__u32 mask = (FS_CREATE | FS_ISDIR);
181	struct inode *d_inode = dentry->d_inode;
182
183	audit_inode_child(dentry, inode);
 
184
185	fsnotify(inode, mask, d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
 
 
 
 
 
 
 
 
 
 
186}
187
188/*
189 * fsnotify_access - file was read
190 */
191static inline void fsnotify_access(struct file *file)
192{
193	struct path *path = &file->f_path;
194	struct inode *inode = path->dentry->d_inode;
195	__u32 mask = FS_ACCESS;
196
197	if (S_ISDIR(inode->i_mode))
198		mask |= FS_ISDIR;
199
200	if (!(file->f_mode & FMODE_NONOTIFY)) {
201		fsnotify_parent(path, NULL, mask);
202		fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
203	}
204}
205
206/*
207 * fsnotify_modify - file was modified
208 */
209static inline void fsnotify_modify(struct file *file)
210{
211	struct path *path = &file->f_path;
212	struct inode *inode = path->dentry->d_inode;
213	__u32 mask = FS_MODIFY;
214
215	if (S_ISDIR(inode->i_mode))
216		mask |= FS_ISDIR;
217
218	if (!(file->f_mode & FMODE_NONOTIFY)) {
219		fsnotify_parent(path, NULL, mask);
220		fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
221	}
222}
223
224/*
225 * fsnotify_open - file was opened
226 */
227static inline void fsnotify_open(struct file *file)
228{
229	struct path *path = &file->f_path;
230	struct inode *inode = path->dentry->d_inode;
231	__u32 mask = FS_OPEN;
232
233	if (S_ISDIR(inode->i_mode))
234		mask |= FS_ISDIR;
235
236	fsnotify_parent(path, NULL, mask);
237	fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
238}
239
240/*
241 * fsnotify_close - file was closed
242 */
243static inline void fsnotify_close(struct file *file)
244{
245	struct path *path = &file->f_path;
246	struct inode *inode = file->f_path.dentry->d_inode;
247	fmode_t mode = file->f_mode;
248	__u32 mask = (mode & FMODE_WRITE) ? FS_CLOSE_WRITE : FS_CLOSE_NOWRITE;
249
250	if (S_ISDIR(inode->i_mode))
251		mask |= FS_ISDIR;
252
253	if (!(file->f_mode & FMODE_NONOTIFY)) {
254		fsnotify_parent(path, NULL, mask);
255		fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
256	}
257}
258
259/*
260 * fsnotify_xattr - extended attributes were changed
261 */
262static inline void fsnotify_xattr(struct dentry *dentry)
263{
264	struct inode *inode = dentry->d_inode;
265	__u32 mask = FS_ATTRIB;
266
267	if (S_ISDIR(inode->i_mode))
268		mask |= FS_ISDIR;
269
270	fsnotify_parent(NULL, dentry, mask);
271	fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
272}
273
274/*
275 * fsnotify_change - notify_change event.  file was modified and/or metadata
276 * was changed.
277 */
278static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid)
279{
280	struct inode *inode = dentry->d_inode;
281	__u32 mask = 0;
282
283	if (ia_valid & ATTR_UID)
284		mask |= FS_ATTRIB;
285	if (ia_valid & ATTR_GID)
286		mask |= FS_ATTRIB;
287	if (ia_valid & ATTR_SIZE)
288		mask |= FS_MODIFY;
289
290	/* both times implies a utime(s) call */
291	if ((ia_valid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME))
292		mask |= FS_ATTRIB;
293	else if (ia_valid & ATTR_ATIME)
294		mask |= FS_ACCESS;
295	else if (ia_valid & ATTR_MTIME)
296		mask |= FS_MODIFY;
297
298	if (ia_valid & ATTR_MODE)
299		mask |= FS_ATTRIB;
300
301	if (mask) {
302		if (S_ISDIR(inode->i_mode))
303			mask |= FS_ISDIR;
304
305		fsnotify_parent(NULL, dentry, mask);
306		fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
307	}
308}
309
310#if defined(CONFIG_FSNOTIFY)	/* notify helpers */
311
312/*
313 * fsnotify_oldname_init - save off the old filename before we change it
314 */
315static inline const unsigned char *fsnotify_oldname_init(const unsigned char *name)
316{
317	return kstrdup(name, GFP_KERNEL);
318}
319
320/*
321 * fsnotify_oldname_free - free the name we got from fsnotify_oldname_init
322 */
323static inline void fsnotify_oldname_free(const unsigned char *old_name)
324{
325	kfree(old_name);
326}
327
328#else	/* CONFIG_FSNOTIFY */
329
330static inline const char *fsnotify_oldname_init(const unsigned char *name)
331{
332	return NULL;
333}
334
335static inline void fsnotify_oldname_free(const unsigned char *old_name)
336{
337}
338
339#endif	/*  CONFIG_FSNOTIFY */
340
341#endif	/* _LINUX_FS_NOTIFY_H */