diff options
Diffstat (limited to 'include/linux/fsnotify.h')
| -rw-r--r-- | include/linux/fsnotify.h | 49 | 
1 files changed, 43 insertions, 6 deletions
| diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index 3a2d7dc3c607..bb8467cd11ae 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -225,16 +225,53 @@ static inline void fsnotify_link(struct inode *dir, struct inode *inode,  }  /* + * fsnotify_delete - @dentry was unlinked and unhashed + * + * Caller must make sure that dentry->d_name is stable. + * + * Note: unlike fsnotify_unlink(), we have to pass also the unlinked inode + * as this may be called after d_delete() and old_dentry may be negative. + */ +static inline void fsnotify_delete(struct inode *dir, struct inode *inode, +				   struct dentry *dentry) +{ +	__u32 mask = FS_DELETE; + +	if (S_ISDIR(inode->i_mode)) +		mask |= FS_ISDIR; + +	fsnotify_name(mask, inode, FSNOTIFY_EVENT_INODE, dir, &dentry->d_name, +		      0); +} + +/** + * d_delete_notify - delete a dentry and call fsnotify_delete() + * @dentry: The dentry to delete + * + * This helper is used to guaranty that the unlinked inode cannot be found + * by lookup of this name after fsnotify_delete() event has been delivered. + */ +static inline void d_delete_notify(struct inode *dir, struct dentry *dentry) +{ +	struct inode *inode = d_inode(dentry); + +	ihold(inode); +	d_delete(dentry); +	fsnotify_delete(dir, inode, dentry); +	iput(inode); +} + +/*   * fsnotify_unlink - 'name' was unlinked   *   * Caller must make sure that dentry->d_name is stable.   */  static inline void fsnotify_unlink(struct inode *dir, struct dentry *dentry)  { -	/* Expected to be called before d_delete() */ -	WARN_ON_ONCE(d_is_negative(dentry)); +	if (WARN_ON_ONCE(d_is_negative(dentry))) +		return; -	fsnotify_dirent(dir, dentry, FS_DELETE); +	fsnotify_delete(dir, d_inode(dentry), dentry);  }  /* @@ -258,10 +295,10 @@ static inline void fsnotify_mkdir(struct inode *dir, struct dentry *dentry)   */  static inline void fsnotify_rmdir(struct inode *dir, struct dentry *dentry)  { -	/* Expected to be called before d_delete() */ -	WARN_ON_ONCE(d_is_negative(dentry)); +	if (WARN_ON_ONCE(d_is_negative(dentry))) +		return; -	fsnotify_dirent(dir, dentry, FS_DELETE | FS_ISDIR); +	fsnotify_delete(dir, d_inode(dentry), dentry);  }  /* |