#ifdef __KERNEL__
+#include <linux/idr.h> /* inotify uses this */
#include <linux/fs.h> /* struct inode */
#include <linux/list.h>
#include <linux/path.h> /* struct path */
/* listeners that hard code group numbers near the top */
#define DNOTIFY_GROUP_NUM UINT_MAX
+#define INOTIFY_GROUP_NUM (DNOTIFY_GROUP_NUM-1)
struct fsnotify_group;
struct fsnotify_event;
struct fsnotify_mark_entry;
+struct fsnotify_event_private_data;
/*
* Each group much define these ops. The fsnotify infrastructure will call
int (*handle_event)(struct fsnotify_group *group, struct fsnotify_event *event);
void (*free_group_priv)(struct fsnotify_group *group);
void (*freeing_mark)(struct fsnotify_mark_entry *entry, struct fsnotify_group *group);
+ void (*free_event_priv)(struct fsnotify_event_private_data *priv);
};
/*
/* groups can define private fields here or use the void *private */
union {
void *private;
+#ifdef CONFIG_INOTIFY_USER
+ struct inotify_group_private_data {
+ spinlock_t idr_lock;
+ struct idr idr;
+ u32 last_wd;
+ struct fasync_struct *fa; /* async notification */
+ struct user_struct *user;
+ } inotify_data;
+#endif
};
};
struct list_head event_list;
};
+/*
+ * Inotify needs to tack data onto an event. This struct lets us later find the
+ * correct private data of the correct group.
+ */
+struct fsnotify_event_private_data {
+ struct fsnotify_group *group;
+ struct list_head event_list;
+};
+
/*
* all of the information about the original object we want to now send to
* a group. If you want to carry more info from the accessing task to the
u32 sync_cookie; /* used to corrolate events, namely inotify mv events */
char *file_name;
size_t name_len;
+
+ struct list_head private_data_list; /* groups can store private data here */
};
/*
assert_spin_locked(&dentry->d_lock);
parent = dentry->d_parent;
- if (fsnotify_inode_watches_children(parent->d_inode))
+ if (parent->d_inode && fsnotify_inode_watches_children(parent->d_inode))
dentry->d_flags |= DCACHE_FSNOTIFY_PARENT_WATCHED;
else
dentry->d_flags &= ~DCACHE_FSNOTIFY_PARENT_WATCHED;
/* take a reference to an event */
extern void fsnotify_get_event(struct fsnotify_event *event);
extern void fsnotify_put_event(struct fsnotify_event *event);
-/* find private data previously attached to an event */
-extern struct fsnotify_event_private_data *fsnotify_get_priv_from_event(struct fsnotify_group *group,
- struct fsnotify_event *event);
+/* find private data previously attached to an event and unlink it */
+extern struct fsnotify_event_private_data *fsnotify_remove_priv_from_event(struct fsnotify_group *group,
+ struct fsnotify_event *event);
/* attach the event to the group notification queue */
-extern int fsnotify_add_notify_event(struct fsnotify_group *group, struct fsnotify_event *event);
+extern int fsnotify_add_notify_event(struct fsnotify_group *group, struct fsnotify_event *event,
+ struct fsnotify_event_private_data *priv);
/* true if the group notification queue is empty */
extern bool fsnotify_notify_queue_is_empty(struct fsnotify_group *group);
/* return, but do not dequeue the first event on the notification queue */
extern struct fsnotify_event *fsnotify_peek_notify_event(struct fsnotify_group *group);
-/* reutnr AND dequeue the first event on the notification queue */
+/* return AND dequeue the first event on the notification queue */
extern struct fsnotify_event *fsnotify_remove_notify_event(struct fsnotify_group *group);
/* functions used to manipulate the marks attached to inodes */
extern void fsnotify_clear_marks_by_group(struct fsnotify_group *group);
extern void fsnotify_get_mark(struct fsnotify_mark_entry *entry);
extern void fsnotify_put_mark(struct fsnotify_mark_entry *entry);
+extern void fsnotify_unmount_inodes(struct list_head *list);
/* put here because inotify does some weird stuff when destroying watches */
extern struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask,
return 0;
}
+static inline void fsnotify_unmount_inodes(struct list_head *list)
+{}
+
#endif /* CONFIG_FSNOTIFY */
#endif /* __KERNEL __ */