static void au_hfsn_free(struct au_hinode *hinode) { struct au_hnotify *hn; struct fsnotify_mark *mark; hn = hinode->hi_notify; mark = &hn->hn_mark; fsnotify_destroy_mark(mark); fsnotify_put_mark(mark); /* TODO: bad approach */ wait_event(au_hfsn_wq, hn->hn_mark_dead); }
static int inotify_handle_event(struct fsnotify_group *group, struct fsnotify_event *event) { struct fsnotify_mark_entry *entry; struct inotify_inode_mark_entry *ientry; struct inode *to_tell; struct inotify_event_private_data *event_priv; struct fsnotify_event_private_data *fsn_event_priv; int wd, ret; to_tell = event->to_tell; spin_lock(&to_tell->i_lock); entry = fsnotify_find_mark_entry(group, to_tell); spin_unlock(&to_tell->i_lock); /* race with watch removal? We already passes should_send */ if (unlikely(!entry)) return 0; ientry = container_of(entry, struct inotify_inode_mark_entry, fsn_entry); wd = ientry->wd; event_priv = kmem_cache_alloc(event_priv_cachep, GFP_KERNEL); if (unlikely(!event_priv)) return -ENOMEM; fsn_event_priv = &event_priv->fsnotify_event_priv_data; fsn_event_priv->group = group; event_priv->wd = wd; ret = fsnotify_add_notify_event(group, event, fsn_event_priv); if (ret) { inotify_free_event_priv(fsn_event_priv); /* EEXIST says we tail matched, EOVERFLOW isn't something * to report up the stack. */ if ((ret == -EEXIST) || (ret == -EOVERFLOW)) ret = 0; } if (entry->mask & IN_ONESHOT) fsnotify_destroy_mark_by_entry(entry); /* * If we hold the entry until after the event is on the queue * IN_IGNORED won't be able to pass this event in the queue */ fsnotify_put_mark(entry); return ret; }
/* * Destroy all marks in the given list. The marks must be already detached from * the original inode / vfsmount. */ void fsnotify_destroy_marks(struct list_head *to_free) { struct fsnotify_mark *mark, *lmark; struct fsnotify_group *group; list_for_each_entry_safe(mark, lmark, to_free, free_list) { spin_lock(&mark->lock); fsnotify_get_group(mark->group); group = mark->group; spin_unlock(&mark->lock); fsnotify_destroy_mark(mark, group); fsnotify_put_mark(mark); fsnotify_put_group(group); }
static int au_hfsn_free(struct au_hinode *hinode, struct au_hnotify *hn) { struct fsnotify_mark *mark; unsigned long long ull; ull = atomic64_inc_return(&au_hfsn_ifree); BUG_ON(!ull); mark = &hn->hn_mark; fsnotify_destroy_mark(mark); fsnotify_put_mark(mark); /* free hn by myself */ return 0; }
static bool inotify_should_send_event(struct fsnotify_group *group, struct inode *inode, __u32 mask) { struct fsnotify_mark_entry *entry; bool send; spin_lock(&inode->i_lock); entry = fsnotify_find_mark_entry(group, inode); spin_unlock(&inode->i_lock); if (!entry) return false; mask = (mask & ~FS_EVENT_ON_CHILD); send = (entry->mask & mask); /* find took a reference */ fsnotify_put_mark(entry); return send; }
void audit_remove_mark(struct audit_fsnotify_mark *audit_mark) { fsnotify_destroy_mark(&audit_mark->mark, audit_fsnotify_group); fsnotify_put_mark(&audit_mark->mark); }