fsnotify: allow addition of duplicate fsnotify marks
This patch allows a task to add a second fsnotify mark to an inode for the same group. This mark will be added to the end of the inode's list and this will never be found by the stand fsnotify_find_mark() function. This is useful if a user wants to add a new mark before removing the old one. Signed-off-by: Eric Paris <eparis@redhat.com>
This commit is contained in:
Родитель
9e1c74321d
Коммит
40554c3dae
|
@ -362,7 +362,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
|
||||||
dnentry = container_of(entry, struct dnotify_mark_entry, fsn_entry);
|
dnentry = container_of(entry, struct dnotify_mark_entry, fsn_entry);
|
||||||
spin_lock(&entry->lock);
|
spin_lock(&entry->lock);
|
||||||
} else {
|
} else {
|
||||||
fsnotify_add_mark(new_entry, dnotify_group, inode);
|
fsnotify_add_mark(new_entry, dnotify_group, inode, 0);
|
||||||
spin_lock(&new_entry->lock);
|
spin_lock(&new_entry->lock);
|
||||||
entry = new_entry;
|
entry = new_entry;
|
||||||
dnentry = new_dnentry;
|
dnentry = new_dnentry;
|
||||||
|
|
|
@ -312,9 +312,10 @@ void fsnotify_init_mark(struct fsnotify_mark_entry *entry,
|
||||||
* event types should be delivered to which group and for which inodes.
|
* event types should be delivered to which group and for which inodes.
|
||||||
*/
|
*/
|
||||||
int fsnotify_add_mark(struct fsnotify_mark_entry *entry,
|
int fsnotify_add_mark(struct fsnotify_mark_entry *entry,
|
||||||
struct fsnotify_group *group, struct inode *inode)
|
struct fsnotify_group *group, struct inode *inode,
|
||||||
|
int allow_dups)
|
||||||
{
|
{
|
||||||
struct fsnotify_mark_entry *lentry;
|
struct fsnotify_mark_entry *lentry = NULL;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
inode = igrab(inode);
|
inode = igrab(inode);
|
||||||
|
@ -331,6 +332,7 @@ int fsnotify_add_mark(struct fsnotify_mark_entry *entry,
|
||||||
spin_lock(&group->mark_lock);
|
spin_lock(&group->mark_lock);
|
||||||
spin_lock(&inode->i_lock);
|
spin_lock(&inode->i_lock);
|
||||||
|
|
||||||
|
if (!allow_dups)
|
||||||
lentry = fsnotify_find_mark_entry(group, inode);
|
lentry = fsnotify_find_mark_entry(group, inode);
|
||||||
if (!lentry) {
|
if (!lentry) {
|
||||||
entry->group = group;
|
entry->group = group;
|
||||||
|
|
|
@ -651,7 +651,7 @@ static int inotify_new_watch(struct fsnotify_group *group,
|
||||||
goto out_err;
|
goto out_err;
|
||||||
|
|
||||||
/* we are on the idr, now get on the inode */
|
/* we are on the idr, now get on the inode */
|
||||||
ret = fsnotify_add_mark(&tmp_ientry->fsn_entry, group, inode);
|
ret = fsnotify_add_mark(&tmp_ientry->fsn_entry, group, inode, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
/* we failed to get on the inode, get off the idr */
|
/* we failed to get on the inode, get off the idr */
|
||||||
inotify_remove_from_idr(group, tmp_ientry);
|
inotify_remove_from_idr(group, tmp_ientry);
|
||||||
|
|
|
@ -345,7 +345,7 @@ extern struct fsnotify_mark_entry *fsnotify_find_mark_entry(struct fsnotify_grou
|
||||||
/* copy the values from old into new */
|
/* copy the values from old into new */
|
||||||
extern void fsnotify_duplicate_mark(struct fsnotify_mark_entry *new, struct fsnotify_mark_entry *old);
|
extern void fsnotify_duplicate_mark(struct fsnotify_mark_entry *new, struct fsnotify_mark_entry *old);
|
||||||
/* attach the mark to both the group and the inode */
|
/* attach the mark to both the group and the inode */
|
||||||
extern int fsnotify_add_mark(struct fsnotify_mark_entry *entry, struct fsnotify_group *group, struct inode *inode);
|
extern int fsnotify_add_mark(struct fsnotify_mark_entry *entry, struct fsnotify_group *group, struct inode *inode, int allow_dups);
|
||||||
/* given a mark, flag it to be freed when all references are dropped */
|
/* given a mark, flag it to be freed when all references are dropped */
|
||||||
extern void fsnotify_destroy_mark_by_entry(struct fsnotify_mark_entry *entry);
|
extern void fsnotify_destroy_mark_by_entry(struct fsnotify_mark_entry *entry);
|
||||||
/* run all the marks in a group, and flag them to be freed */
|
/* run all the marks in a group, and flag them to be freed */
|
||||||
|
|
|
@ -161,7 +161,7 @@ static struct audit_parent *audit_init_parent(struct nameidata *ndp)
|
||||||
|
|
||||||
fsnotify_init_mark(&parent->mark, audit_watch_free_mark);
|
fsnotify_init_mark(&parent->mark, audit_watch_free_mark);
|
||||||
parent->mark.mask = AUDIT_FS_WATCH;
|
parent->mark.mask = AUDIT_FS_WATCH;
|
||||||
ret = fsnotify_add_mark(&parent->mark, audit_watch_group, inode);
|
ret = fsnotify_add_mark(&parent->mark, audit_watch_group, inode, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
audit_free_parent(parent);
|
audit_free_parent(parent);
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче