fsnotify: report FS_ISDIR flag with MOVE_SELF and DELETE_SELF events
We need to report FS_ISDIR flag with MOVE_SELF and DELETE_SELF events for fanotify, because fanotify API requires the user to explicitly request events on directories by FAN_ONDIR flag. inotify never reported IN_ISDIR with those events. It looks like an oversight, but to avoid the risk of breaking existing inotify programs, mask the FS_ISDIR flag out when reprting those events to inotify backend. We also add the FS_ISDIR flag with FS_ATTRIB event in the case of rename over an empty target directory. inotify did not report IN_ISDIR in this case, but it normally does report IN_ISDIR along with IN_ATTRIB event, so in this case, we do not mask out the FS_ISDIR flag. [JK: Simplify the checks in fsnotify_move()] Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Jan Kara <jack@suse.cz>
This commit is contained in:
parent
73072283a2
commit
0a20df7ed3
|
@ -113,6 +113,15 @@ int inotify_handle_event(struct fsnotify_group *group,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We now report FS_ISDIR flag with MOVE_SELF and DELETE_SELF events
|
||||||
|
* for fanotify. inotify never reported IN_ISDIR with those events.
|
||||||
|
* It looks like an oversight, but to avoid the risk of breaking
|
||||||
|
* existing inotify programs, mask the flag out from those events.
|
||||||
|
*/
|
||||||
|
if (mask & (IN_MOVE_SELF | IN_DELETE_SELF))
|
||||||
|
mask &= ~IN_ISDIR;
|
||||||
|
|
||||||
fsn_event = &event->fse;
|
fsn_event = &event->fse;
|
||||||
fsnotify_init_event(fsn_event, inode);
|
fsnotify_init_event(fsn_event, inode);
|
||||||
event->mask = mask;
|
event->mask = mask;
|
||||||
|
|
|
@ -87,7 +87,12 @@ static inline int fsnotify_perm(struct file *file, int mask)
|
||||||
*/
|
*/
|
||||||
static inline void fsnotify_link_count(struct inode *inode)
|
static inline void fsnotify_link_count(struct inode *inode)
|
||||||
{
|
{
|
||||||
fsnotify(inode, FS_ATTRIB, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
|
__u32 mask = FS_ATTRIB;
|
||||||
|
|
||||||
|
if (S_ISDIR(inode->i_mode))
|
||||||
|
mask |= FS_ISDIR;
|
||||||
|
|
||||||
|
fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -95,12 +100,14 @@ static inline void fsnotify_link_count(struct inode *inode)
|
||||||
*/
|
*/
|
||||||
static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
|
static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
|
||||||
const unsigned char *old_name,
|
const unsigned char *old_name,
|
||||||
int isdir, struct inode *target, struct dentry *moved)
|
int isdir, struct inode *target,
|
||||||
|
struct dentry *moved)
|
||||||
{
|
{
|
||||||
struct inode *source = moved->d_inode;
|
struct inode *source = moved->d_inode;
|
||||||
u32 fs_cookie = fsnotify_get_cookie();
|
u32 fs_cookie = fsnotify_get_cookie();
|
||||||
__u32 old_dir_mask = FS_MOVED_FROM;
|
__u32 old_dir_mask = FS_MOVED_FROM;
|
||||||
__u32 new_dir_mask = FS_MOVED_TO;
|
__u32 new_dir_mask = FS_MOVED_TO;
|
||||||
|
__u32 mask = FS_MOVE_SELF;
|
||||||
const unsigned char *new_name = moved->d_name.name;
|
const unsigned char *new_name = moved->d_name.name;
|
||||||
|
|
||||||
if (old_dir == new_dir)
|
if (old_dir == new_dir)
|
||||||
|
@ -109,6 +116,7 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
|
||||||
if (isdir) {
|
if (isdir) {
|
||||||
old_dir_mask |= FS_ISDIR;
|
old_dir_mask |= FS_ISDIR;
|
||||||
new_dir_mask |= FS_ISDIR;
|
new_dir_mask |= FS_ISDIR;
|
||||||
|
mask |= FS_ISDIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
fsnotify(old_dir, old_dir_mask, source, FSNOTIFY_EVENT_INODE, old_name,
|
fsnotify(old_dir, old_dir_mask, source, FSNOTIFY_EVENT_INODE, old_name,
|
||||||
|
@ -120,7 +128,7 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
|
||||||
fsnotify_link_count(target);
|
fsnotify_link_count(target);
|
||||||
|
|
||||||
if (source)
|
if (source)
|
||||||
fsnotify(source, FS_MOVE_SELF, moved->d_inode, FSNOTIFY_EVENT_INODE, NULL, 0);
|
fsnotify(source, mask, source, FSNOTIFY_EVENT_INODE, NULL, 0);
|
||||||
audit_inode_child(new_dir, moved, AUDIT_TYPE_CHILD_CREATE);
|
audit_inode_child(new_dir, moved, AUDIT_TYPE_CHILD_CREATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +186,12 @@ static inline void fsnotify_nameremove(struct dentry *dentry, int isdir)
|
||||||
*/
|
*/
|
||||||
static inline void fsnotify_inoderemove(struct inode *inode)
|
static inline void fsnotify_inoderemove(struct inode *inode)
|
||||||
{
|
{
|
||||||
fsnotify(inode, FS_DELETE_SELF, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
|
__u32 mask = FS_DELETE_SELF;
|
||||||
|
|
||||||
|
if (S_ISDIR(inode->i_mode))
|
||||||
|
mask |= FS_ISDIR;
|
||||||
|
|
||||||
|
fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
|
||||||
__fsnotify_inode_delete(inode);
|
__fsnotify_inode_delete(inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue