Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #ifndef _LINUX_FS_NOTIFY_H
0003 #define _LINUX_FS_NOTIFY_H
0004 
0005 /*
0006  * include/linux/fsnotify.h - generic hooks for filesystem notification, to
0007  * reduce in-source duplication from both dnotify and inotify.
0008  *
0009  * We don't compile any of this away in some complicated menagerie of ifdefs.
0010  * Instead, we rely on the code inside to optimize away as needed.
0011  *
0012  * (C) Copyright 2005 Robert Love
0013  */
0014 
0015 #include <linux/fsnotify_backend.h>
0016 #include <linux/audit.h>
0017 #include <linux/slab.h>
0018 #include <linux/bug.h>
0019 
0020 /*
0021  * Notify this @dir inode about a change in a child directory entry.
0022  * The directory entry may have turned positive or negative or its inode may
0023  * have changed (i.e. renamed over).
0024  *
0025  * Unlike fsnotify_parent(), the event will be reported regardless of the
0026  * FS_EVENT_ON_CHILD mask on the parent inode and will not be reported if only
0027  * the child is interested and not the parent.
0028  */
0029 static inline int fsnotify_name(__u32 mask, const void *data, int data_type,
0030                 struct inode *dir, const struct qstr *name,
0031                 u32 cookie)
0032 {
0033     if (atomic_long_read(&dir->i_sb->s_fsnotify_connectors) == 0)
0034         return 0;
0035 
0036     return fsnotify(mask, data, data_type, dir, name, NULL, cookie);
0037 }
0038 
0039 static inline void fsnotify_dirent(struct inode *dir, struct dentry *dentry,
0040                    __u32 mask)
0041 {
0042     fsnotify_name(mask, dentry, FSNOTIFY_EVENT_DENTRY, dir, &dentry->d_name, 0);
0043 }
0044 
0045 static inline void fsnotify_inode(struct inode *inode, __u32 mask)
0046 {
0047     if (atomic_long_read(&inode->i_sb->s_fsnotify_connectors) == 0)
0048         return;
0049 
0050     if (S_ISDIR(inode->i_mode))
0051         mask |= FS_ISDIR;
0052 
0053     fsnotify(mask, inode, FSNOTIFY_EVENT_INODE, NULL, NULL, inode, 0);
0054 }
0055 
0056 /* Notify this dentry's parent about a child's events. */
0057 static inline int fsnotify_parent(struct dentry *dentry, __u32 mask,
0058                   const void *data, int data_type)
0059 {
0060     struct inode *inode = d_inode(dentry);
0061 
0062     if (atomic_long_read(&inode->i_sb->s_fsnotify_connectors) == 0)
0063         return 0;
0064 
0065     if (S_ISDIR(inode->i_mode)) {
0066         mask |= FS_ISDIR;
0067 
0068         /* sb/mount marks are not interested in name of directory */
0069         if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED))
0070             goto notify_child;
0071     }
0072 
0073     /* disconnected dentry cannot notify parent */
0074     if (IS_ROOT(dentry))
0075         goto notify_child;
0076 
0077     return __fsnotify_parent(dentry, mask, data, data_type);
0078 
0079 notify_child:
0080     return fsnotify(mask, data, data_type, NULL, NULL, inode, 0);
0081 }
0082 
0083 /*
0084  * Simple wrappers to consolidate calls to fsnotify_parent() when an event
0085  * is on a file/dentry.
0086  */
0087 static inline void fsnotify_dentry(struct dentry *dentry, __u32 mask)
0088 {
0089     fsnotify_parent(dentry, mask, dentry, FSNOTIFY_EVENT_DENTRY);
0090 }
0091 
0092 static inline int fsnotify_file(struct file *file, __u32 mask)
0093 {
0094     const struct path *path = &file->f_path;
0095 
0096     if (file->f_mode & FMODE_NONOTIFY)
0097         return 0;
0098 
0099     return fsnotify_parent(path->dentry, mask, path, FSNOTIFY_EVENT_PATH);
0100 }
0101 
0102 /* Simple call site for access decisions */
0103 static inline int fsnotify_perm(struct file *file, int mask)
0104 {
0105     int ret;
0106     __u32 fsnotify_mask = 0;
0107 
0108     if (!(mask & (MAY_READ | MAY_OPEN)))
0109         return 0;
0110 
0111     if (mask & MAY_OPEN) {
0112         fsnotify_mask = FS_OPEN_PERM;
0113 
0114         if (file->f_flags & __FMODE_EXEC) {
0115             ret = fsnotify_file(file, FS_OPEN_EXEC_PERM);
0116 
0117             if (ret)
0118                 return ret;
0119         }
0120     } else if (mask & MAY_READ) {
0121         fsnotify_mask = FS_ACCESS_PERM;
0122     }
0123 
0124     return fsnotify_file(file, fsnotify_mask);
0125 }
0126 
0127 /*
0128  * fsnotify_link_count - inode's link count changed
0129  */
0130 static inline void fsnotify_link_count(struct inode *inode)
0131 {
0132     fsnotify_inode(inode, FS_ATTRIB);
0133 }
0134 
0135 /*
0136  * fsnotify_move - file old_name at old_dir was moved to new_name at new_dir
0137  */
0138 static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
0139                  const struct qstr *old_name,
0140                  int isdir, struct inode *target,
0141                  struct dentry *moved)
0142 {
0143     struct inode *source = moved->d_inode;
0144     u32 fs_cookie = fsnotify_get_cookie();
0145     __u32 old_dir_mask = FS_MOVED_FROM;
0146     __u32 new_dir_mask = FS_MOVED_TO;
0147     __u32 rename_mask = FS_RENAME;
0148     const struct qstr *new_name = &moved->d_name;
0149 
0150     if (isdir) {
0151         old_dir_mask |= FS_ISDIR;
0152         new_dir_mask |= FS_ISDIR;
0153         rename_mask |= FS_ISDIR;
0154     }
0155 
0156     /* Event with information about both old and new parent+name */
0157     fsnotify_name(rename_mask, moved, FSNOTIFY_EVENT_DENTRY,
0158               old_dir, old_name, 0);
0159 
0160     fsnotify_name(old_dir_mask, source, FSNOTIFY_EVENT_INODE,
0161               old_dir, old_name, fs_cookie);
0162     fsnotify_name(new_dir_mask, source, FSNOTIFY_EVENT_INODE,
0163               new_dir, new_name, fs_cookie);
0164 
0165     if (target)
0166         fsnotify_link_count(target);
0167     fsnotify_inode(source, FS_MOVE_SELF);
0168     audit_inode_child(new_dir, moved, AUDIT_TYPE_CHILD_CREATE);
0169 }
0170 
0171 /*
0172  * fsnotify_inode_delete - and inode is being evicted from cache, clean up is needed
0173  */
0174 static inline void fsnotify_inode_delete(struct inode *inode)
0175 {
0176     __fsnotify_inode_delete(inode);
0177 }
0178 
0179 /*
0180  * fsnotify_vfsmount_delete - a vfsmount is being destroyed, clean up is needed
0181  */
0182 static inline void fsnotify_vfsmount_delete(struct vfsmount *mnt)
0183 {
0184     __fsnotify_vfsmount_delete(mnt);
0185 }
0186 
0187 /*
0188  * fsnotify_inoderemove - an inode is going away
0189  */
0190 static inline void fsnotify_inoderemove(struct inode *inode)
0191 {
0192     fsnotify_inode(inode, FS_DELETE_SELF);
0193     __fsnotify_inode_delete(inode);
0194 }
0195 
0196 /*
0197  * fsnotify_create - 'name' was linked in
0198  *
0199  * Caller must make sure that dentry->d_name is stable.
0200  * Note: some filesystems (e.g. kernfs) leave @dentry negative and instantiate
0201  * ->d_inode later
0202  */
0203 static inline void fsnotify_create(struct inode *dir, struct dentry *dentry)
0204 {
0205     audit_inode_child(dir, dentry, AUDIT_TYPE_CHILD_CREATE);
0206 
0207     fsnotify_dirent(dir, dentry, FS_CREATE);
0208 }
0209 
0210 /*
0211  * fsnotify_link - new hardlink in 'inode' directory
0212  *
0213  * Caller must make sure that new_dentry->d_name is stable.
0214  * Note: We have to pass also the linked inode ptr as some filesystems leave
0215  *   new_dentry->d_inode NULL and instantiate inode pointer later
0216  */
0217 static inline void fsnotify_link(struct inode *dir, struct inode *inode,
0218                  struct dentry *new_dentry)
0219 {
0220     fsnotify_link_count(inode);
0221     audit_inode_child(dir, new_dentry, AUDIT_TYPE_CHILD_CREATE);
0222 
0223     fsnotify_name(FS_CREATE, inode, FSNOTIFY_EVENT_INODE,
0224               dir, &new_dentry->d_name, 0);
0225 }
0226 
0227 /*
0228  * fsnotify_delete - @dentry was unlinked and unhashed
0229  *
0230  * Caller must make sure that dentry->d_name is stable.
0231  *
0232  * Note: unlike fsnotify_unlink(), we have to pass also the unlinked inode
0233  * as this may be called after d_delete() and old_dentry may be negative.
0234  */
0235 static inline void fsnotify_delete(struct inode *dir, struct inode *inode,
0236                    struct dentry *dentry)
0237 {
0238     __u32 mask = FS_DELETE;
0239 
0240     if (S_ISDIR(inode->i_mode))
0241         mask |= FS_ISDIR;
0242 
0243     fsnotify_name(mask, inode, FSNOTIFY_EVENT_INODE, dir, &dentry->d_name,
0244               0);
0245 }
0246 
0247 /**
0248  * d_delete_notify - delete a dentry and call fsnotify_delete()
0249  * @dentry: The dentry to delete
0250  *
0251  * This helper is used to guaranty that the unlinked inode cannot be found
0252  * by lookup of this name after fsnotify_delete() event has been delivered.
0253  */
0254 static inline void d_delete_notify(struct inode *dir, struct dentry *dentry)
0255 {
0256     struct inode *inode = d_inode(dentry);
0257 
0258     ihold(inode);
0259     d_delete(dentry);
0260     fsnotify_delete(dir, inode, dentry);
0261     iput(inode);
0262 }
0263 
0264 /*
0265  * fsnotify_unlink - 'name' was unlinked
0266  *
0267  * Caller must make sure that dentry->d_name is stable.
0268  */
0269 static inline void fsnotify_unlink(struct inode *dir, struct dentry *dentry)
0270 {
0271     if (WARN_ON_ONCE(d_is_negative(dentry)))
0272         return;
0273 
0274     fsnotify_delete(dir, d_inode(dentry), dentry);
0275 }
0276 
0277 /*
0278  * fsnotify_mkdir - directory 'name' was created
0279  *
0280  * Caller must make sure that dentry->d_name is stable.
0281  * Note: some filesystems (e.g. kernfs) leave @dentry negative and instantiate
0282  * ->d_inode later
0283  */
0284 static inline void fsnotify_mkdir(struct inode *dir, struct dentry *dentry)
0285 {
0286     audit_inode_child(dir, dentry, AUDIT_TYPE_CHILD_CREATE);
0287 
0288     fsnotify_dirent(dir, dentry, FS_CREATE | FS_ISDIR);
0289 }
0290 
0291 /*
0292  * fsnotify_rmdir - directory 'name' was removed
0293  *
0294  * Caller must make sure that dentry->d_name is stable.
0295  */
0296 static inline void fsnotify_rmdir(struct inode *dir, struct dentry *dentry)
0297 {
0298     if (WARN_ON_ONCE(d_is_negative(dentry)))
0299         return;
0300 
0301     fsnotify_delete(dir, d_inode(dentry), dentry);
0302 }
0303 
0304 /*
0305  * fsnotify_access - file was read
0306  */
0307 static inline void fsnotify_access(struct file *file)
0308 {
0309     fsnotify_file(file, FS_ACCESS);
0310 }
0311 
0312 /*
0313  * fsnotify_modify - file was modified
0314  */
0315 static inline void fsnotify_modify(struct file *file)
0316 {
0317     fsnotify_file(file, FS_MODIFY);
0318 }
0319 
0320 /*
0321  * fsnotify_open - file was opened
0322  */
0323 static inline void fsnotify_open(struct file *file)
0324 {
0325     __u32 mask = FS_OPEN;
0326 
0327     if (file->f_flags & __FMODE_EXEC)
0328         mask |= FS_OPEN_EXEC;
0329 
0330     fsnotify_file(file, mask);
0331 }
0332 
0333 /*
0334  * fsnotify_close - file was closed
0335  */
0336 static inline void fsnotify_close(struct file *file)
0337 {
0338     __u32 mask = (file->f_mode & FMODE_WRITE) ? FS_CLOSE_WRITE :
0339                             FS_CLOSE_NOWRITE;
0340 
0341     fsnotify_file(file, mask);
0342 }
0343 
0344 /*
0345  * fsnotify_xattr - extended attributes were changed
0346  */
0347 static inline void fsnotify_xattr(struct dentry *dentry)
0348 {
0349     fsnotify_dentry(dentry, FS_ATTRIB);
0350 }
0351 
0352 /*
0353  * fsnotify_change - notify_change event.  file was modified and/or metadata
0354  * was changed.
0355  */
0356 static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid)
0357 {
0358     __u32 mask = 0;
0359 
0360     if (ia_valid & ATTR_UID)
0361         mask |= FS_ATTRIB;
0362     if (ia_valid & ATTR_GID)
0363         mask |= FS_ATTRIB;
0364     if (ia_valid & ATTR_SIZE)
0365         mask |= FS_MODIFY;
0366 
0367     /* both times implies a utime(s) call */
0368     if ((ia_valid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME))
0369         mask |= FS_ATTRIB;
0370     else if (ia_valid & ATTR_ATIME)
0371         mask |= FS_ACCESS;
0372     else if (ia_valid & ATTR_MTIME)
0373         mask |= FS_MODIFY;
0374 
0375     if (ia_valid & ATTR_MODE)
0376         mask |= FS_ATTRIB;
0377 
0378     if (mask)
0379         fsnotify_dentry(dentry, mask);
0380 }
0381 
0382 static inline int fsnotify_sb_error(struct super_block *sb, struct inode *inode,
0383                     int error)
0384 {
0385     struct fs_error_report report = {
0386         .error = error,
0387         .inode = inode,
0388         .sb = sb,
0389     };
0390 
0391     return fsnotify(FS_ERROR, &report, FSNOTIFY_EVENT_ERROR,
0392             NULL, NULL, NULL, 0);
0393 }
0394 
0395 #endif  /* _LINUX_FS_NOTIFY_H */