Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 147746
b: refs/heads/master
c: 3be25f4
h: refs/heads/master
v: v3
  • Loading branch information
Eric Paris committed Jun 11, 2009
1 parent 66e28bd commit 5ec5843
Show file tree
Hide file tree
Showing 10 changed files with 484 additions and 4 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 90586523eb4b349806887c62ee70685a49415124
refs/heads/master: 3be25f49b9d6a97eae9bcb96d3292072b7658bd8
9 changes: 9 additions & 0 deletions trunk/fs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <linux/cdev.h>
#include <linux/bootmem.h>
#include <linux/inotify.h>
#include <linux/fsnotify.h>
#include <linux/mount.h>
#include <linux/async.h>

Expand Down Expand Up @@ -189,6 +190,10 @@ struct inode *inode_init_always(struct super_block *sb, struct inode *inode)
inode->i_private = NULL;
inode->i_mapping = mapping;

#ifdef CONFIG_FSNOTIFY
inode->i_fsnotify_mask = 0;
#endif

return inode;

out_free_security:
Expand Down Expand Up @@ -221,6 +226,7 @@ void destroy_inode(struct inode *inode)
BUG_ON(inode_has_buffers(inode));
ima_inode_free(inode);
security_inode_free(inode);
fsnotify_inode_delete(inode);
if (inode->i_sb->s_op->destroy_inode)
inode->i_sb->s_op->destroy_inode(inode);
else
Expand Down Expand Up @@ -252,6 +258,9 @@ void inode_init_once(struct inode *inode)
INIT_LIST_HEAD(&inode->inotify_watches);
mutex_init(&inode->inotify_mutex);
#endif
#ifdef CONFIG_FSNOTIFY
INIT_HLIST_HEAD(&inode->i_fsnotify_mark_entries);
#endif
}
EXPORT_SYMBOL(inode_init_once);

Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/notify/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
obj-$(CONFIG_FSNOTIFY) += fsnotify.o notification.o group.o
obj-$(CONFIG_FSNOTIFY) += fsnotify.o notification.o group.o inode_mark.o

obj-y += dnotify/
obj-y += inotify/
13 changes: 13 additions & 0 deletions trunk/fs/notify/fsnotify.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@
#include <linux/fsnotify_backend.h>
#include "fsnotify.h"

/*
* Clear all of the marks on an inode when it is being evicted from core
*/
void __fsnotify_inode_delete(struct inode *inode)
{
fsnotify_clear_marks_by_inode(inode);
}
EXPORT_SYMBOL_GPL(__fsnotify_inode_delete);

/*
* This is the main call to fsnotify. The VFS calls into hook specific functions
* in linux/fsnotify.h. Those functions then in turn call here. Here will call
Expand All @@ -43,6 +52,8 @@ void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is)
if (!(mask & fsnotify_mask))
return;

if (!(mask & to_tell->i_fsnotify_mask))
return;
/*
* SRCU!! the groups list is very very much read only and the path is
* very hot. The VAST majority of events are not going to need to do
Expand All @@ -51,6 +62,8 @@ void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is)
idx = srcu_read_lock(&fsnotify_grp_srcu);
list_for_each_entry_rcu(group, &fsnotify_groups, group_list) {
if (mask & group->mask) {
if (!group->ops->should_send_event(group, to_tell, mask))
continue;
if (!event) {
event = fsnotify_create_event(to_tell, mask, data, data_is);
/* shit, we OOM'd and now we can't tell, maybe
Expand Down
5 changes: 5 additions & 0 deletions trunk/fs/notify/fsnotify.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,9 @@ extern struct srcu_struct fsnotify_grp_srcu;
extern struct list_head fsnotify_groups;
/* all bitwise OR of all event types (FS_*) for all fsnotify_groups */
extern __u32 fsnotify_mask;

/* final kfree of a group */
extern void fsnotify_final_destroy_group(struct fsnotify_group *group);
/* run the list of all marks associated with inode and flag them to be freed */
extern void fsnotify_clear_marks_by_inode(struct inode *inode);
#endif /* __FS_NOTIFY_FSNOTIFY_H_ */
49 changes: 48 additions & 1 deletion trunk/fs/notify/group.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,29 @@ void fsnotify_recalc_global_mask(void)
fsnotify_mask = mask;
}

/*
* Update the group->mask by running all of the marks associated with this
* group and finding the bitwise | of all of the mark->mask. If we change
* the group->mask we need to update the global mask of events interesting
* to the system.
*/
void fsnotify_recalc_group_mask(struct fsnotify_group *group)
{
__u32 mask = 0;
__u32 old_mask = group->mask;
struct fsnotify_mark_entry *entry;

spin_lock(&group->mark_lock);
list_for_each_entry(entry, &group->mark_entries, g_list)
mask |= entry->mask;
spin_unlock(&group->mark_lock);

group->mask = mask;

if (old_mask != mask)
fsnotify_recalc_global_mask();
}

/*
* Take a reference to a group so things found under the fsnotify_grp_mutex
* can't get freed under us
Expand All @@ -66,14 +89,32 @@ static void fsnotify_get_group(struct fsnotify_group *group)
/*
* Final freeing of a group
*/
static void fsnotify_destroy_group(struct fsnotify_group *group)
void fsnotify_final_destroy_group(struct fsnotify_group *group)
{
if (group->ops->free_group_priv)
group->ops->free_group_priv(group);

kfree(group);
}

/*
* Trying to get rid of a group. We need to first get rid of any outstanding
* allocations and then free the group. Remember that fsnotify_clear_marks_by_group
* could miss marks that are being freed by inode and those marks could still
* hold a reference to this group (via group->num_marks) If we get into that
* situtation, the fsnotify_final_destroy_group will get called when that final
* mark is freed.
*/
static void fsnotify_destroy_group(struct fsnotify_group *group)
{
/* clear all inode mark entries for this group */
fsnotify_clear_marks_by_group(group);

/* past the point of no return, matches the initial value of 1 */
if (atomic_dec_and_test(&group->num_marks))
fsnotify_final_destroy_group(group);
}

/*
* Remove this group from the global list of groups that will get events
* this can be done even if there are still references and things still using
Expand Down Expand Up @@ -173,6 +214,10 @@ struct fsnotify_group *fsnotify_obtain_group(unsigned int group_num, __u32 mask,
group->group_num = group_num;
group->mask = mask;

spin_lock_init(&group->mark_lock);
atomic_set(&group->num_marks, 0);
INIT_LIST_HEAD(&group->mark_entries);

group->ops = ops;

mutex_lock(&fsnotify_grp_mutex);
Expand All @@ -188,6 +233,8 @@ struct fsnotify_group *fsnotify_obtain_group(unsigned int group_num, __u32 mask,
/* group not found, add a new one */
list_add_rcu(&group->group_list, &fsnotify_groups);
group->on_group_list = 1;
/* being on the fsnotify_groups list holds one num_marks */
atomic_inc(&group->num_marks);

mutex_unlock(&fsnotify_grp_mutex);

Expand Down
Loading

0 comments on commit 5ec5843

Please sign in to comment.