source: scripts/untested/blfs-patches/inotify-0.18-rml-2.6.10-4.patch@ 66f17d5

clfs-1.2 clfs-2.1 clfs-3.0.0-systemd clfs-3.0.0-sysvinit systemd sysvinit
Last change on this file since 66f17d5 was 617118d, checked in by Jim Gifford <clfs@…>, 19 years ago

r561@server (orig r559): root | 2005-06-05 02:38:49 -0700
Fixed Directory Structure

  • Property mode set to 100644
File size: 46.3 KB
RevLine 
[617118d]1inotify, bitches.
2
3Signed-off-by: Robert Love <rml@novell.com>
4
5 drivers/char/Kconfig | 13
6 drivers/char/Makefile | 2
7 drivers/char/inotify.c | 1067 +++++++++++++++++++++++++++++++++++++++++++++
8 drivers/char/misc.c | 14
9 fs/attr.c | 73 ++-
10 fs/file_table.c | 7
11 fs/inode.c | 3
12 fs/namei.c | 36 +
13 fs/open.c | 5
14 fs/read_write.c | 33 +
15 fs/super.c | 2
16 include/linux/fs.h | 7
17 include/linux/inotify.h | 160 ++++++
18 include/linux/miscdevice.h | 5
19 include/linux/sched.h | 2
20 kernel/user.c | 2
21 16 files changed, 1392 insertions(+), 39 deletions(-)
22
23diff -urN linux-2.6.10/drivers/char/inotify.c linux/drivers/char/inotify.c
24--- linux-2.6.10/drivers/char/inotify.c 1969-12-31 19:00:00.000000000 -0500
25+++ linux/drivers/char/inotify.c 2005-01-07 17:24:48.959115376 -0500
26@@ -0,0 +1,1067 @@
27+/*
28+ * Inode based directory notifications for Linux.
29+ *
30+ * Copyright (C) 2004 John McCutchan
31+ *
32+ * This program is free software; you can redistribute it and/or modify it
33+ * under the terms of the GNU General Public License as published by the
34+ * Free Software Foundation; either version 2, or (at your option) any
35+ * later version.
36+ *
37+ * This program is distributed in the hope that it will be useful, but
38+ * WITHOUT ANY WARRANTY; without even the implied warranty of
39+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
40+ * General Public License for more details.
41+ */
42+
43+#include <linux/module.h>
44+#include <linux/kernel.h>
45+#include <linux/sched.h>
46+#include <linux/spinlock.h>
47+#include <linux/idr.h>
48+#include <linux/slab.h>
49+#include <linux/fs.h>
50+#include <linux/namei.h>
51+#include <linux/poll.h>
52+#include <linux/device.h>
53+#include <linux/miscdevice.h>
54+#include <linux/init.h>
55+#include <linux/list.h>
56+#include <linux/writeback.h>
57+#include <linux/inotify.h>
58+
59+#include <asm/ioctls.h>
60+
61+static atomic_t inotify_cookie;
62+static kmem_cache_t *watch_cachep;
63+static kmem_cache_t *event_cachep;
64+static kmem_cache_t *inode_data_cachep;
65+
66+static int sysfs_attrib_max_user_devices;
67+static int sysfs_attrib_max_user_watches;
68+static unsigned int sysfs_attrib_max_queued_events;
69+
70+/*
71+ * struct inotify_device - represents an open instance of an inotify device
72+ *
73+ * For each inotify device, we need to keep track of the events queued on it,
74+ * a list of the inodes that we are watching, and so on.
75+ *
76+ * This structure is protected by 'lock'. Lock ordering:
77+ *
78+ * dev->lock (protects dev)
79+ * inode_lock (used to safely walk inode_in_use list)
80+ * inode->i_lock (only needed for getting ref on inode_data)
81+ */
82+struct inotify_device {
83+ wait_queue_head_t wait;
84+ struct idr idr;
85+ struct list_head events;
86+ struct list_head watches;
87+ spinlock_t lock;
88+ unsigned int queue_size;
89+ unsigned int event_count;
90+ unsigned int max_events;
91+ struct user_struct *user;
92+};
93+
94+struct inotify_watch {
95+ s32 wd; /* watch descriptor */
96+ u32 mask;
97+ struct inode *inode;
98+ struct inotify_device *dev;
99+ struct list_head d_list; /* device list */
100+ struct list_head i_list; /* inode list */
101+};
102+
103+static ssize_t show_max_queued_events(struct class_device *class, char *buf)
104+{
105+ return sprintf(buf, "%d\n", sysfs_attrib_max_queued_events);
106+}
107+
108+static ssize_t store_max_queued_events(struct class_device *class,
109+ const char *buf, size_t count)
110+{
111+ unsigned int max;
112+
113+ if (sscanf(buf, "%u", &max) > 0 && max > 0) {
114+ sysfs_attrib_max_queued_events = max;
115+ return strlen(buf);
116+ }
117+ return -EINVAL;
118+}
119+
120+static ssize_t show_max_user_devices(struct class_device *class, char *buf)
121+{
122+ return sprintf(buf, "%d\n", sysfs_attrib_max_user_devices);
123+}
124+
125+static ssize_t store_max_user_devices(struct class_device *class,
126+ const char *buf, size_t count)
127+{
128+ int max;
129+
130+ if (sscanf(buf, "%d", &max) > 0 && max > 0) {
131+ sysfs_attrib_max_user_devices = max;
132+ return strlen(buf);
133+ }
134+ return -EINVAL;
135+}
136+
137+static ssize_t show_max_user_watches(struct class_device *class, char *buf)
138+{
139+ return sprintf(buf, "%d\n", sysfs_attrib_max_user_watches);
140+}
141+
142+static ssize_t store_max_user_watches(struct class_device *class,
143+ const char *buf, size_t count)
144+{
145+ int max;
146+
147+ if (sscanf(buf, "%d", &max) > 0 && max > 0) {
148+ sysfs_attrib_max_user_watches = max;
149+ return strlen(buf);
150+ }
151+ return -EINVAL;
152+}
153+
154+static CLASS_DEVICE_ATTR(max_queued_events, S_IRUGO | S_IWUSR,
155+ show_max_queued_events, store_max_queued_events);
156+static CLASS_DEVICE_ATTR(max_user_devices, S_IRUGO | S_IWUSR,
157+ show_max_user_devices, store_max_user_devices);
158+static CLASS_DEVICE_ATTR(max_user_watches, S_IRUGO | S_IWUSR,
159+ show_max_user_watches, store_max_user_watches);
160+
161+/*
162+ * A list of these is attached to each instance of the driver
163+ * when the drivers read() gets called, this list is walked and
164+ * all events that can fit in the buffer get delivered
165+ */
166+struct inotify_kernel_event {
167+ struct list_head list;
168+ struct inotify_event event;
169+};
170+
171+static inline void __get_inode_data(struct inotify_inode_data *data)
172+{
173+ atomic_inc(&data->count);
174+}
175+
176+/*
177+ * get_inode_data - pin an inotify_inode_data structure. Returns the structure
178+ * if successful and NULL on failure, which can only occur if inotify_data is
179+ * not yet allocated. The inode must be pinned prior to invocation.
180+ */
181+static inline struct inotify_inode_data * get_inode_data(struct inode *inode)
182+{
183+ struct inotify_inode_data *data;
184+
185+ spin_lock(&inode->i_lock);
186+ data = inode->inotify_data;
187+ if (data)
188+ __get_inode_data(data);
189+ spin_unlock(&inode->i_lock);
190+
191+ return data;
192+}
193+
194+/*
195+ * put_inode_data - drop our reference on an inotify_inode_data and the
196+ * inode structure in which it lives. If the reference count on inotify_data
197+ * reaches zero, free it.
198+ */
199+static inline void put_inode_data(struct inode *inode)
200+{
201+ //spin_lock(&inode->i_lock);
202+ if (atomic_dec_and_test(&inode->inotify_data->count)) {
203+ kmem_cache_free(inode_data_cachep, inode->inotify_data);
204+ inode->inotify_data = NULL;
205+ }
206+ //spin_unlock(&inode->i_lock);
207+}
208+
209+/*
210+ * find_inode - resolve a user-given path to a specific inode and iget() it
211+ */
212+static struct inode * find_inode(const char __user *dirname)
213+{
214+ struct inode *inode;
215+ struct nameidata nd;
216+ int error;
217+
218+ error = __user_walk(dirname, LOOKUP_FOLLOW, &nd);
219+ if (error)
220+ return ERR_PTR(error);
221+
222+ inode = nd.dentry->d_inode;
223+
224+ /* you can only watch an inode if you have read permissions on it */
225+ error = permission(inode, MAY_READ, NULL);
226+ if (error) {
227+ inode = ERR_PTR(error);
228+ goto release_and_out;
229+ }
230+
231+ spin_lock(&inode_lock);
232+ __iget(inode);
233+ spin_unlock(&inode_lock);
234+release_and_out:
235+ path_release(&nd);
236+ return inode;
237+}
238+
239+struct inotify_kernel_event * kernel_event(s32 wd, u32 mask, u32 cookie,
240+ const char *filename)
241+{
242+ struct inotify_kernel_event *kevent;
243+
244+ kevent = kmem_cache_alloc(event_cachep, GFP_ATOMIC);
245+ if (!kevent)
246+ return NULL;
247+
248+ /* we hand this out to user-space, so zero it out just in case */
249+ memset(kevent, 0, sizeof(struct inotify_kernel_event));
250+
251+ kevent->event.wd = wd;
252+ kevent->event.mask = mask;
253+ kevent->event.cookie = cookie;
254+ INIT_LIST_HEAD(&kevent->list);
255+
256+ if (filename) {
257+ size_t len;
258+
259+ len = strlen(filename);
260+ kevent->event.filename = kmalloc(len+1, GFP_ATOMIC);
261+ if (!kevent->event.filename) {
262+ kmem_cache_free (event_cachep, kevent);
263+ return NULL;
264+ }
265+ memset(kevent->event.filename, 0, len+1);
266+ strncpy(kevent->event.filename, filename, len);
267+ kevent->event.len = len;
268+ } else
269+ kevent->event.filename = NULL;
270+
271+ return kevent;
272+}
273+
274+void delete_kernel_event(struct inotify_kernel_event *kevent)
275+{
276+ if (!kevent)
277+ return;
278+
279+ if (kevent->event.filename)
280+ kfree (kevent->event.filename);
281+ kmem_cache_free(event_cachep, kevent);
282+}
283+
284+#define list_to_inotify_kernel_event(pos) \
285+ list_entry((pos), struct inotify_kernel_event, list)
286+
287+#define inotify_dev_get_event(dev) \
288+ (list_to_inotify_kernel_event(dev->events.next))
289+
290+/* Does this events mask get sent to the watch ? */
291+#define event_and(event_mask,watches_mask) ((event_mask == IN_UNMOUNT) || \
292+ (event_mask == IN_IGNORED) || \
293+ (event_mask & watches_mask))
294+
295+/*
296+ * inotify_dev_queue_event - add a new event to the given device
297+ *
298+ * Caller must hold dev->lock.
299+ */
300+static void inotify_dev_queue_event(struct inotify_device *dev,
301+ struct inotify_watch *watch, u32 mask,
302+ u32 cookie, const char *filename)
303+{
304+ struct inotify_kernel_event *kevent, *last;
305+
306+ /* Check if the new event is a duplicate of the last event queued. */
307+ last = inotify_dev_get_event(dev);
308+ if (dev->event_count && last->event.mask == mask &&
309+ last->event.wd == watch->wd) {
310+ /* Check if the filenames match */
311+ if (!filename && last->event.filename[0] == '\0')
312+ return;
313+ if (filename && !strcmp(last->event.filename, filename))
314+ return;
315+ }
316+
317+ /*
318+ * the queue has already overflowed and we have already sent the
319+ * Q_OVERFLOW event
320+ */
321+ if (dev->event_count > dev->max_events)
322+ return;
323+
324+ /* the queue has just overflowed and we need to notify user space */
325+ if (dev->event_count == dev->max_events) {
326+ kevent = kernel_event(-1, IN_Q_OVERFLOW, cookie, NULL);
327+ goto add_event_to_queue;
328+ }
329+
330+ if (!event_and(mask, watch->inode->inotify_data->watch_mask) ||
331+ !event_and(mask, watch->mask))
332+ return;
333+
334+ kevent = kernel_event(watch->wd, mask, cookie, filename);
335+
336+add_event_to_queue:
337+ if (!kevent)
338+ return;
339+
340+ /* queue the event and wake up anyone waiting */
341+ dev->event_count++;
342+ dev->queue_size += sizeof(struct inotify_event) + kevent->event.len -
343+ sizeof(char *) + 1;
344+ list_add_tail(&kevent->list, &dev->events);
345+ wake_up_interruptible(&dev->wait);
346+}
347+
348+static inline int inotify_dev_has_events(struct inotify_device *dev)
349+{
350+ return !list_empty(&dev->events);
351+}
352+
353+/*
354+ * inotify_dev_event_dequeue - destroy an event on the given device
355+ *
356+ * Caller must hold dev->lock.
357+ */
358+static void inotify_dev_event_dequeue(struct inotify_device *dev)
359+{
360+ struct inotify_kernel_event *kevent;
361+
362+ if (!inotify_dev_has_events(dev))
363+ return;
364+
365+ kevent = inotify_dev_get_event(dev);
366+ list_del_init(&kevent->list);
367+ dev->event_count--;
368+ dev->queue_size -= sizeof(struct inotify_event) + kevent->event.len -
369+ sizeof(char *) + 1;
370+ delete_kernel_event(kevent);
371+}
372+
373+/*
374+ * inotify_dev_get_wd - returns the next WD for use by the given dev
375+ *
376+ * This function can sleep.
377+ */
378+static int inotify_dev_get_wd(struct inotify_device *dev,
379+ struct inotify_watch *watch)
380+{
381+ int ret;
382+
383+ if (atomic_read(&dev->user->inotify_watches) >=
384+ sysfs_attrib_max_user_watches)
385+ return -ENOSPC;
386+
387+repeat:
388+ if (!idr_pre_get(&dev->idr, GFP_KERNEL))
389+ return -ENOSPC;
390+ spin_lock(&dev->lock);
391+ ret = idr_get_new(&dev->idr, watch, &watch->wd);
392+ spin_unlock(&dev->lock);
393+ if (ret == -EAGAIN) /* more memory is required, try again */
394+ goto repeat;
395+ else if (ret) /* the idr is full! */
396+ return -ENOSPC;
397+
398+ atomic_inc(&dev->user->inotify_watches);
399+
400+ return 0;
401+}
402+
403+/*
404+ * inotify_dev_put_wd - release the given WD on the given device
405+ *
406+ * Caller must hold dev->lock.
407+ */
408+static int inotify_dev_put_wd(struct inotify_device *dev, s32 wd)
409+{
410+ if (!dev || wd < 0)
411+ return -1;
412+
413+ atomic_dec(&dev->user->inotify_watches);
414+ idr_remove(&dev->idr, wd);
415+
416+ return 0;
417+}
418+
419+/*
420+ * create_watch - creates a watch on the given device.
421+ *
422+ * Grabs dev->lock, so the caller must not hold it.
423+ */
424+static struct inotify_watch *create_watch(struct inotify_device *dev,
425+ u32 mask, struct inode *inode)
426+{
427+ struct inotify_watch *watch;
428+
429+ watch = kmem_cache_alloc(watch_cachep, GFP_KERNEL);
430+ if (!watch)
431+ return NULL;
432+
433+ watch->mask = mask;
434+ watch->inode = inode;
435+ watch->dev = dev;
436+ INIT_LIST_HEAD(&watch->d_list);
437+ INIT_LIST_HEAD(&watch->i_list);
438+
439+ if (inotify_dev_get_wd(dev, watch)) {
440+ kmem_cache_free(watch_cachep, watch);
441+ return NULL;
442+ }
443+
444+ return watch;
445+}
446+
447+/*
448+ * delete_watch - removes the given 'watch' from the given 'dev'
449+ *
450+ * Caller must hold dev->lock.
451+ */
452+static void delete_watch(struct inotify_device *dev,
453+ struct inotify_watch *watch)
454+{
455+ inotify_dev_put_wd(dev, watch->wd);
456+ kmem_cache_free(watch_cachep, watch);
457+}
458+
459+/*
460+ * inotify_find_dev - find the watch associated with the given inode and dev
461+ *
462+ * Caller must hold dev->lock.
463+ * FIXME: Needs inotify_data->lock too. Don't need dev->lock, just pin it.
464+ */
465+static struct inotify_watch *inode_find_dev(struct inode *inode,
466+ struct inotify_device *dev)
467+{
468+ struct inotify_watch *watch;
469+
470+ if (!inode->inotify_data)
471+ return NULL;
472+
473+ list_for_each_entry(watch, &inode->inotify_data->watches, i_list) {
474+ if (watch->dev == dev)
475+ return watch;
476+ }
477+
478+ return NULL;
479+}
480+
481+/*
482+ * dev_find_wd - given a (dev,wd) pair, returns the matching inotify_watcher
483+ *
484+ * Returns the results of looking up (dev,wd) in the idr layer. NULL is
485+ * returned on error.
486+ *
487+ * The caller must hold dev->lock.
488+ */
489+static inline struct inotify_watch *dev_find_wd(struct inotify_device *dev,
490+ u32 wd)
491+{
492+ return idr_find(&dev->idr, wd);
493+}
494+
495+static int inotify_dev_is_watching_inode(struct inotify_device *dev,
496+ struct inode *inode)
497+{
498+ struct inotify_watch *watch;
499+
500+ list_for_each_entry(watch, &dev->watches, d_list) {
501+ if (watch->inode == inode)
502+ return 1;
503+ }
504+
505+ return 0;
506+}
507+
508+/*
509+ * inotify_dev_add_watcher - add the given watcher to the given device instance
510+ *
511+ * Caller must hold dev->lock.
512+ */
513+static int inotify_dev_add_watch(struct inotify_device *dev,
514+ struct inotify_watch *watch)
515+{
516+ if (!dev || !watch)
517+ return -EINVAL;
518+
519+ list_add(&watch->d_list, &dev->watches);
520+ return 0;
521+}
522+
523+/*
524+ * inotify_dev_rm_watch - remove the given watch from the given device
525+ *
526+ * Caller must hold dev->lock because we call inotify_dev_queue_event().
527+ */
528+static int inotify_dev_rm_watch(struct inotify_device *dev,
529+ struct inotify_watch *watch)
530+{
531+ if (!watch)
532+ return -EINVAL;
533+
534+ inotify_dev_queue_event(dev, watch, IN_IGNORED, 0, NULL);
535+ list_del_init(&watch->d_list);
536+
537+ return 0;
538+}
539+
540+/*
541+ * inode_update_watch_mask - update inode->inotify_data->watch_mask
542+ *
543+ * Grabs inode->inotify_data->lock.
544+ */
545+static void inode_update_watch_mask(struct inode *inode)
546+{
547+ struct inotify_inode_data *data;
548+ struct inotify_watch *watch;
549+ u32 new_mask;
550+
551+ data = get_inode_data(inode);
552+ if (!data) /* FIXME: this should never happen */
553+ return;
554+ spin_lock(&data->lock);
555+
556+ new_mask = 0;
557+ list_for_each_entry(watch, &data->watches, i_list)
558+ new_mask |= watch->mask;
559+
560+ data->watch_mask = new_mask;
561+
562+ spin_unlock(&data->lock);
563+ put_inode_data(inode);
564+}
565+
566+/*
567+ * inode_add_watch - add a watch to the given inode
568+ *
569+ * Callers must hold dev->lock, because we call inode_find_dev().
570+ */
571+static int inode_add_watch(struct inode *inode, struct inotify_watch *watch)
572+{
573+ int ret;
574+
575+ if (!inode || !watch)
576+ return -EINVAL;
577+
578+ spin_lock(&inode->i_lock);
579+ if (!inode->inotify_data) {
580+ /* inotify_data is not attached to the inode, so add it */
581+ inode->inotify_data = kmem_cache_alloc(inode_data_cachep,
582+ GFP_ATOMIC);
583+ if (!inode->inotify_data) {
584+ ret = -ENOMEM;
585+ goto out_lock;
586+ }
587+
588+ atomic_set(&inode->inotify_data->count, 0);
589+ INIT_LIST_HEAD(&inode->inotify_data->watches);
590+ inode->inotify_data->watch_mask = 0;
591+ spin_lock_init(&inode->inotify_data->lock);
592+ } else if (inode_find_dev(inode, watch->dev)) {
593+ /* a watch is already associated with this (inode,dev) pair */
594+ ret = -EINVAL;
595+ goto out_lock;
596+ }
597+ __get_inode_data(inode->inotify_data);
598+ spin_unlock(&inode->i_lock);
599+
600+ list_add(&watch->i_list, &inode->inotify_data->watches);
601+ inode_update_watch_mask(inode);
602+
603+ return 0;
604+out_lock:
605+ spin_unlock(&inode->i_lock);
606+ return ret;
607+}
608+
609+static int inode_rm_watch(struct inode *inode,
610+ struct inotify_watch *watch)
611+{
612+ if (!inode || !watch || !inode->inotify_data)
613+ return -EINVAL;
614+
615+ list_del_init(&watch->i_list);
616+ inode_update_watch_mask(inode);
617+
618+ /* clean up inode->inotify_data */
619+ put_inode_data(inode);
620+
621+ return 0;
622+}
623+
624+/* Kernel API */
625+
626+/*
627+ * inotify_inode_queue_event - queue an event with the given mask, cookie, and
628+ * filename to any watches associated with the given inode.
629+ *
630+ * inode must be pinned prior to calling.
631+ */
632+void inotify_inode_queue_event(struct inode *inode, u32 mask, u32 cookie,
633+ const char *filename)
634+{
635+ struct inotify_watch *watch;
636+
637+ if (!inode->inotify_data)
638+ return;
639+
640+ list_for_each_entry(watch, &inode->inotify_data->watches, i_list) {
641+ spin_lock(&watch->dev->lock);
642+ inotify_dev_queue_event(watch->dev, watch, mask, cookie,
643+ filename);
644+ spin_unlock(&watch->dev->lock);
645+ }
646+}
647+EXPORT_SYMBOL_GPL(inotify_inode_queue_event);
648+
649+void inotify_dentry_parent_queue_event(struct dentry *dentry, u32 mask,
650+ u32 cookie, const char *filename)
651+{
652+ struct dentry *parent;
653+
654+ parent = dget_parent(dentry);
655+ inotify_inode_queue_event(parent->d_inode, mask, cookie, filename);
656+ dput(parent);
657+}
658+EXPORT_SYMBOL_GPL(inotify_dentry_parent_queue_event);
659+
660+u32 inotify_get_cookie(void)
661+{
662+ atomic_inc(&inotify_cookie);
663+ return atomic_read(&inotify_cookie);
664+}
665+EXPORT_SYMBOL_GPL(inotify_get_cookie);
666+
667+/*
668+ * watch->inode must be pinned. We drop a reference before returning.
669+ */
670+static void ignore_helper(struct inotify_watch *watch, int event)
671+{
672+ struct inotify_device *dev;
673+ struct inode *inode;
674+
675+ inode = watch->inode;
676+ dev = watch->dev;
677+
678+ spin_lock(&dev->lock);
679+
680+ if (event)
681+ inotify_dev_queue_event(dev, watch, event, 0, NULL);
682+
683+ inode_rm_watch(inode, watch);
684+ inotify_dev_rm_watch(watch->dev, watch);
685+
686+ delete_watch(dev, watch);
687+ spin_unlock(&dev->lock);
688+
689+ iput(inode);
690+}
691+
692+void inotify_super_block_umount(struct super_block *sb)
693+{
694+ struct inode *inode;
695+
696+ spin_lock(&inode_lock);
697+
698+ /*
699+ * We hold the inode_lock, so the inodes are not going anywhere, and
700+ * we grab a reference on inotify_data before walking its list of
701+ * watches.
702+ */
703+ list_for_each_entry(inode, &inode_in_use, i_list) {
704+ struct inotify_inode_data *inode_data;
705+ struct inotify_watch *watch;
706+
707+ if (inode->i_sb != sb)
708+ continue;
709+
710+ inode_data = get_inode_data(inode);
711+ if (!inode_data)
712+ continue;
713+
714+ list_for_each_entry(watch, &inode_data->watches, i_list)
715+ ignore_helper(watch, IN_UNMOUNT);
716+ put_inode_data(inode);
717+ }
718+
719+ spin_unlock(&inode_lock);
720+}
721+EXPORT_SYMBOL_GPL(inotify_super_block_umount);
722+
723+/*
724+ * inotify_inode_is_dead - an inode has been deleted, cleanup any watches
725+ */
726+void inotify_inode_is_dead(struct inode *inode)
727+{
728+ struct inotify_watch *watch, *next;
729+ struct inotify_inode_data *data;
730+
731+ data = get_inode_data(inode);
732+ if (!data)
733+ return;
734+ list_for_each_entry_safe(watch, next, &data->watches, i_list)
735+ ignore_helper(watch, 0);
736+ put_inode_data(inode);
737+}
738+EXPORT_SYMBOL_GPL(inotify_inode_is_dead);
739+
740+/* The driver interface is implemented below */
741+
742+static unsigned int inotify_poll(struct file *file, poll_table *wait)
743+{
744+ struct inotify_device *dev;
745+
746+ dev = file->private_data;
747+
748+ poll_wait(file, &dev->wait, wait);
749+
750+ if (inotify_dev_has_events(dev))
751+ return POLLIN | POLLRDNORM;
752+
753+ return 0;
754+}
755+
756+static ssize_t inotify_read(struct file *file, char __user *buf,
757+ size_t count, loff_t *pos)
758+{
759+ size_t event_size;
760+ struct inotify_device *dev;
761+ char __user *start;
762+ DECLARE_WAITQUEUE(wait, current);
763+
764+ start = buf;
765+ dev = file->private_data;
766+
767+ /* We only hand out full inotify events */
768+ event_size = sizeof(struct inotify_event) - sizeof(char *);
769+
770+ if (count < event_size)
771+ return -EINVAL;
772+
773+ while (1) {
774+ int has_events;
775+
776+ spin_lock(&dev->lock);
777+ has_events = inotify_dev_has_events(dev);
778+ spin_unlock(&dev->lock);
779+ if (has_events)
780+ break;
781+
782+ if (file->f_flags & O_NONBLOCK)
783+ return -EAGAIN;
784+
785+ if (signal_pending(current))
786+ return -ERESTARTSYS;
787+
788+ add_wait_queue(&dev->wait, &wait);
789+ set_current_state(TASK_INTERRUPTIBLE);
790+
791+ schedule();
792+
793+ set_current_state(TASK_RUNNING);
794+ remove_wait_queue(&dev->wait, &wait);
795+ }
796+
797+ while (count >= event_size) {
798+ struct inotify_kernel_event *kevent;
799+
800+ spin_lock(&dev->lock);
801+ if (!inotify_dev_has_events(dev)) {
802+ spin_unlock(&dev->lock);
803+ break;
804+ }
805+ kevent = inotify_dev_get_event(dev);
806+
807+ /* We can't send this event, not enough space in the buffer */
808+ if ((event_size + kevent->event.len + 1) > count) {
809+ spin_unlock(&dev->lock);
810+ break;
811+ }
812+ spin_unlock(&dev->lock);
813+
814+ /* Copy the entire event except the string to user space */
815+ if (copy_to_user(buf, &kevent->event, event_size))
816+ return -EFAULT;
817+
818+ buf += event_size;
819+ count -= event_size;
820+
821+ /* Copy the filename to user space */
822+ if (kevent->event.filename) {
823+ if (copy_to_user(buf, kevent->event.filename,
824+ kevent->event.len+1))
825+ return -EFAULT;
826+ buf += kevent->event.len + 1;
827+ count -= kevent->event.len + 1;
828+ } else {
829+ int z = 0;
830+ /* Copy the NULL */
831+ if (copy_to_user(buf, &z, 1))
832+ return -EFAULT;
833+
834+ buf += 1;
835+ count -= 1;
836+ }
837+
838+ spin_lock(&dev->lock);
839+ inotify_dev_event_dequeue(dev);
840+ spin_unlock(&dev->lock);
841+ }
842+
843+ return buf - start;
844+}
845+
846+static int inotify_open(struct inode *inode, struct file *file)
847+{
848+ struct inotify_device *dev;
849+ struct user_struct *user;
850+ int ret;
851+
852+ user = get_uid(current->user);
853+
854+ if (atomic_read(&user->inotify_devs) >= sysfs_attrib_max_user_devices) {
855+ ret = -ENOSPC;
856+ goto out_err;
857+ }
858+
859+ atomic_inc(&current->user->inotify_devs);
860+
861+ dev = kmalloc(sizeof(struct inotify_device), GFP_KERNEL);
862+ if (!dev) {
863+ ret = -ENOMEM;
864+ goto out_err;
865+ }
866+
867+ idr_init(&dev->idr);
868+
869+ INIT_LIST_HEAD(&dev->events);
870+ INIT_LIST_HEAD(&dev->watches);
871+ init_waitqueue_head(&dev->wait);
872+
873+ dev->event_count = 0;
874+ dev->queue_size = 0;
875+ dev->max_events = sysfs_attrib_max_queued_events;
876+ dev->user = user;
877+ spin_lock_init(&dev->lock);
878+
879+ file->private_data = dev;
880+
881+ return 0;
882+out_err:
883+ free_uid(current->user);
884+ return ret;
885+}
886+
887+/*
888+ * inotify_release_all_watches - destroy all watches on a given device
889+ *
890+ * FIXME: Do we want a lock here?
891+ */
892+static void inotify_release_all_watches(struct inotify_device *dev)
893+{
894+ struct inotify_watch *watch, *next;
895+
896+ list_for_each_entry_safe(watch, next, &dev->watches, d_list)
897+ ignore_helper(watch, 0);
898+}
899+
900+/*
901+ * inotify_release_all_events - destroy all of the events on a given device
902+ */
903+static void inotify_release_all_events(struct inotify_device *dev)
904+{
905+ spin_lock(&dev->lock);
906+ while (inotify_dev_has_events(dev))
907+ inotify_dev_event_dequeue(dev);
908+ spin_unlock(&dev->lock);
909+}
910+
911+static int inotify_release(struct inode *inode, struct file *file)
912+{
913+ struct inotify_device *dev;
914+
915+ dev = file->private_data;
916+
917+ inotify_release_all_watches(dev);
918+ inotify_release_all_events(dev);
919+
920+ atomic_dec(&dev->user->inotify_devs);
921+ free_uid(dev->user);
922+
923+ kfree(dev);
924+
925+ return 0;
926+}
927+
928+static int inotify_add_watch(struct inotify_device *dev,
929+ struct inotify_watch_request *request)
930+{
931+ struct inode *inode;
932+ struct inotify_watch *watch;
933+ int ret;
934+
935+ inode = find_inode((const char __user*) request->dirname);
936+ if (IS_ERR(inode))
937+ return PTR_ERR(inode);
938+
939+ spin_lock(&dev->lock);
940+
941+ /*
942+ * This handles the case of re-adding a directory we are already
943+ * watching, we just update the mask and return 0
944+ */
945+ if (inotify_dev_is_watching_inode(dev, inode)) {
946+ struct inotify_watch *owatch; /* the old watch */
947+
948+ owatch = inode_find_dev(inode, dev);
949+ owatch->mask = request->mask;
950+ inode_update_watch_mask(inode);
951+ spin_unlock(&dev->lock);
952+ iput(inode);
953+
954+ return owatch->wd;
955+ }
956+
957+ spin_unlock(&dev->lock);
958+
959+ watch = create_watch(dev, request->mask, inode);
960+ if (!watch) {
961+ iput(inode);
962+ return -ENOSPC;
963+ }
964+
965+ spin_lock(&dev->lock);
966+
967+ /* We can't add anymore watches to this device */
968+ if (inotify_dev_add_watch(dev, watch)) {
969+ delete_watch(dev, watch);
970+ spin_unlock(&dev->lock);
971+ iput(inode);
972+ return -EINVAL;
973+ }
974+
975+ ret = inode_add_watch(inode, watch);
976+ if (ret < 0) {
977+ list_del_init(&watch->d_list);
978+ delete_watch(dev, watch);
979+ spin_unlock(&dev->lock);
980+ iput(inode);
981+ return ret;
982+ }
983+
984+ spin_unlock(&dev->lock);
985+
986+ return watch->wd;
987+}
988+
989+static int inotify_ignore(struct inotify_device *dev, s32 wd)
990+{
991+ struct inotify_watch *watch;
992+
993+ /*
994+ * FIXME: Silly to grab dev->lock here and then drop it, when
995+ * ignore_helper() grabs it anyway a few lines down.
996+ */
997+ spin_lock(&dev->lock);
998+ watch = dev_find_wd(dev, wd);
999+ spin_unlock(&dev->lock);
1000+ if (!watch)
1001+ return -EINVAL;
1002+ ignore_helper(watch, 0);
1003+
1004+ return 0;
1005+}
1006+
1007+/*
1008+ * inotify_ioctl() - our device file's ioctl method
1009+ *
1010+ * The VFS serializes all of our calls via the BKL and we rely on that. We
1011+ * could, alternatively, grab dev->lock. Right now lower levels grab that
1012+ * where needed.
1013+ */
1014+static int inotify_ioctl(struct inode *ip, struct file *fp,
1015+ unsigned int cmd, unsigned long arg)
1016+{
1017+ struct inotify_device *dev;
1018+ struct inotify_watch_request request;
1019+ void __user *p;
1020+ s32 wd;
1021+
1022+ dev = fp->private_data;
1023+ p = (void __user *) arg;
1024+
1025+ switch (cmd) {
1026+ case INOTIFY_WATCH:
1027+ if (copy_from_user(&request, p, sizeof (request)))
1028+ return -EFAULT;
1029+ return inotify_add_watch(dev, &request);
1030+ case INOTIFY_IGNORE:
1031+ if (copy_from_user(&wd, p, sizeof (wd)))
1032+ return -EFAULT;
1033+ return inotify_ignore(dev, wd);
1034+ case FIONREAD:
1035+ return put_user(dev->queue_size, (int __user *) p);
1036+ default:
1037+ return -ENOTTY;
1038+ }
1039+}
1040+
1041+static struct file_operations inotify_fops = {
1042+ .owner = THIS_MODULE,
1043+ .poll = inotify_poll,
1044+ .read = inotify_read,
1045+ .open = inotify_open,
1046+ .release = inotify_release,
1047+ .ioctl = inotify_ioctl,
1048+};
1049+
1050+struct miscdevice inotify_device = {
1051+ .minor = MISC_DYNAMIC_MINOR,
1052+ .name = "inotify",
1053+ .fops = &inotify_fops,
1054+};
1055+
1056+static int __init inotify_init(void)
1057+{
1058+ struct class_device *class;
1059+ int ret;
1060+
1061+ ret = misc_register(&inotify_device);
1062+ if (ret)
1063+ return ret;
1064+
1065+ sysfs_attrib_max_queued_events = 512;
1066+ sysfs_attrib_max_user_devices = 64;
1067+ sysfs_attrib_max_user_watches = 16384;
1068+
1069+ class = inotify_device.class;
1070+ class_device_create_file(class, &class_device_attr_max_queued_events);
1071+ class_device_create_file(class, &class_device_attr_max_user_devices);
1072+ class_device_create_file(class, &class_device_attr_max_user_watches);
1073+
1074+ atomic_set(&inotify_cookie, 0);
1075+
1076+ watch_cachep = kmem_cache_create("inotify_watch_cache",
1077+ sizeof(struct inotify_watch), 0, SLAB_PANIC,
1078+ NULL, NULL);
1079+
1080+ event_cachep = kmem_cache_create("inotify_event_cache",
1081+ sizeof(struct inotify_kernel_event), 0,
1082+ SLAB_PANIC, NULL, NULL);
1083+
1084+ inode_data_cachep = kmem_cache_create("inotify_inode_data_cache",
1085+ sizeof(struct inotify_inode_data), 0, SLAB_PANIC,
1086+ NULL, NULL);
1087+
1088+ printk(KERN_INFO "inotify device minor=%d\n", inotify_device.minor);
1089+
1090+ return 0;
1091+}
1092+
1093+module_init(inotify_init);
1094diff -urN linux-2.6.10/drivers/char/Kconfig linux/drivers/char/Kconfig
1095--- linux-2.6.10/drivers/char/Kconfig 2004-12-24 16:33:49.000000000 -0500
1096+++ linux/drivers/char/Kconfig 2005-01-06 15:04:03.741780048 -0500
1097@@ -62,6 +62,19 @@
1098 depends on VT && !S390 && !USERMODE
1099 default y
1100
1101+config INOTIFY
1102+ bool "Inotify file change notification support"
1103+ default y
1104+ ---help---
1105+ Say Y here to enable inotify support and the /dev/inotify character
1106+ device. Inotify is a file change notification system and a
1107+ replacement for dnotify. Inotify fixes numerous shortcomings in
1108+ dnotify and introduces several new features. It allows monitoring
1109+ of both files and directories via a single open fd. Multiple file
1110+ events are supported.
1111+
1112+ If unsure, say Y.
1113+
1114 config SERIAL_NONSTANDARD
1115 bool "Non-standard serial port support"
1116 ---help---
1117diff -urN linux-2.6.10/drivers/char/Makefile linux/drivers/char/Makefile
1118--- linux-2.6.10/drivers/char/Makefile 2004-12-24 16:35:29.000000000 -0500
1119+++ linux/drivers/char/Makefile 2005-01-06 15:04:03.741780048 -0500
1120@@ -9,6 +9,8 @@
1121
1122 obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o
1123
1124+
1125+obj-$(CONFIG_INOTIFY) += inotify.o
1126 obj-$(CONFIG_LEGACY_PTYS) += pty.o
1127 obj-$(CONFIG_UNIX98_PTYS) += pty.o
1128 obj-y += misc.o
1129diff -urN linux-2.6.10/drivers/char/misc.c linux/drivers/char/misc.c
1130--- linux-2.6.10/drivers/char/misc.c 2004-12-24 16:35:28.000000000 -0500
1131+++ linux/drivers/char/misc.c 2005-01-06 15:04:03.742779896 -0500
1132@@ -207,10 +207,9 @@
1133 int misc_register(struct miscdevice * misc)
1134 {
1135 struct miscdevice *c;
1136- struct class_device *class;
1137 dev_t dev;
1138 int err;
1139-
1140+
1141 down(&misc_sem);
1142 list_for_each_entry(c, &misc_list, list) {
1143 if (c->minor == misc->minor) {
1144@@ -224,8 +223,7 @@
1145 while (--i >= 0)
1146 if ( (misc_minors[i>>3] & (1 << (i&7))) == 0)
1147 break;
1148- if (i<0)
1149- {
1150+ if (i<0) {
1151 up(&misc_sem);
1152 return -EBUSY;
1153 }
1154@@ -240,10 +238,10 @@
1155 }
1156 dev = MKDEV(MISC_MAJOR, misc->minor);
1157
1158- class = class_simple_device_add(misc_class, dev,
1159- misc->dev, misc->name);
1160- if (IS_ERR(class)) {
1161- err = PTR_ERR(class);
1162+ misc->class = class_simple_device_add(misc_class, dev,
1163+ misc->dev, misc->name);
1164+ if (IS_ERR(misc->class)) {
1165+ err = PTR_ERR(misc->class);
1166 goto out;
1167 }
1168
1169diff -urN linux-2.6.10/fs/attr.c linux/fs/attr.c
1170--- linux-2.6.10/fs/attr.c 2004-12-24 16:34:00.000000000 -0500
1171+++ linux/fs/attr.c 2005-01-06 15:04:03.743779744 -0500
1172@@ -11,6 +11,7 @@
1173 #include <linux/string.h>
1174 #include <linux/smp_lock.h>
1175 #include <linux/dnotify.h>
1176+#include <linux/inotify.h>
1177 #include <linux/fcntl.h>
1178 #include <linux/quotaops.h>
1179 #include <linux/security.h>
1180@@ -103,29 +104,51 @@
1181 out:
1182 return error;
1183 }
1184-
1185 EXPORT_SYMBOL(inode_setattr);
1186
1187-int setattr_mask(unsigned int ia_valid)
1188+void setattr_mask (unsigned int ia_valid, int *dn_mask, u32 *in_mask)
1189 {
1190- unsigned long dn_mask = 0;
1191+ int dnmask;
1192+ u32 inmask;
1193
1194- if (ia_valid & ATTR_UID)
1195- dn_mask |= DN_ATTRIB;
1196- if (ia_valid & ATTR_GID)
1197- dn_mask |= DN_ATTRIB;
1198- if (ia_valid & ATTR_SIZE)
1199- dn_mask |= DN_MODIFY;
1200- /* both times implies a utime(s) call */
1201- if ((ia_valid & (ATTR_ATIME|ATTR_MTIME)) == (ATTR_ATIME|ATTR_MTIME))
1202- dn_mask |= DN_ATTRIB;
1203- else if (ia_valid & ATTR_ATIME)
1204- dn_mask |= DN_ACCESS;
1205- else if (ia_valid & ATTR_MTIME)
1206- dn_mask |= DN_MODIFY;
1207- if (ia_valid & ATTR_MODE)
1208- dn_mask |= DN_ATTRIB;
1209- return dn_mask;
1210+ inmask = 0;
1211+ dnmask = 0;
1212+
1213+ if (!dn_mask || !in_mask) {
1214+ return;
1215+ }
1216+ if (ia_valid & ATTR_UID) {
1217+ inmask |= IN_ATTRIB;
1218+ dnmask |= DN_ATTRIB;
1219+ }
1220+ if (ia_valid & ATTR_GID) {
1221+ inmask |= IN_ATTRIB;
1222+ dnmask |= DN_ATTRIB;
1223+ }
1224+ if (ia_valid & ATTR_SIZE) {
1225+ inmask |= IN_MODIFY;
1226+ dnmask |= DN_MODIFY;
1227+ }
1228+ /* both times implies a utime(s) call */
1229+ if ((ia_valid & (ATTR_ATIME|ATTR_MTIME)) == (ATTR_ATIME|ATTR_MTIME)) {
1230+ inmask |= IN_ATTRIB;
1231+ dnmask |= DN_ATTRIB;
1232+ }
1233+ else if (ia_valid & ATTR_ATIME) {
1234+ inmask |= IN_ACCESS;
1235+ dnmask |= DN_ACCESS;
1236+ }
1237+ else if (ia_valid & ATTR_MTIME) {
1238+ inmask |= IN_MODIFY;
1239+ dnmask |= DN_MODIFY;
1240+ }
1241+ if (ia_valid & ATTR_MODE) {
1242+ inmask |= IN_ATTRIB;
1243+ dnmask |= DN_ATTRIB;
1244+ }
1245+
1246+ *in_mask = inmask;
1247+ *dn_mask = dnmask;
1248 }
1249
1250 int notify_change(struct dentry * dentry, struct iattr * attr)
1251@@ -184,9 +207,19 @@
1252 }
1253 }
1254 if (!error) {
1255- unsigned long dn_mask = setattr_mask(ia_valid);
1256+ int dn_mask;
1257+ u32 in_mask;
1258+
1259+ setattr_mask (ia_valid, &dn_mask, &in_mask);
1260+
1261 if (dn_mask)
1262 dnotify_parent(dentry, dn_mask);
1263+ if (in_mask) {
1264+ inotify_inode_queue_event(dentry->d_inode, in_mask, 0,
1265+ NULL);
1266+ inotify_dentry_parent_queue_event(dentry, in_mask, 0,
1267+ dentry->d_name.name);
1268+ }
1269 }
1270 return error;
1271 }
1272diff -urN linux-2.6.10/fs/file_table.c linux/fs/file_table.c
1273--- linux-2.6.10/fs/file_table.c 2004-12-24 16:33:50.000000000 -0500
1274+++ linux/fs/file_table.c 2005-01-06 15:04:03.743779744 -0500
1275@@ -16,6 +16,7 @@
1276 #include <linux/eventpoll.h>
1277 #include <linux/mount.h>
1278 #include <linux/cdev.h>
1279+#include <linux/inotify.h>
1280
1281 /* sysctl tunables... */
1282 struct files_stat_struct files_stat = {
1283@@ -120,6 +121,12 @@
1284 struct dentry *dentry = file->f_dentry;
1285 struct vfsmount *mnt = file->f_vfsmnt;
1286 struct inode *inode = dentry->d_inode;
1287+ u32 mask;
1288+
1289+
1290+ mask = (file->f_mode & FMODE_WRITE) ? IN_CLOSE_WRITE : IN_CLOSE_NOWRITE;
1291+ inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
1292+ inotify_inode_queue_event(inode, mask, 0, NULL);
1293
1294 might_sleep();
1295 /*
1296diff -urN linux-2.6.10/fs/inode.c linux/fs/inode.c
1297--- linux-2.6.10/fs/inode.c 2004-12-24 16:35:40.000000000 -0500
1298+++ linux/fs/inode.c 2005-01-06 15:04:03.744779592 -0500
1299@@ -130,6 +130,9 @@
1300 #ifdef CONFIG_QUOTA
1301 memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
1302 #endif
1303+#ifdef CONFIG_INOTIFY
1304+ inode->inotify_data = NULL;
1305+#endif
1306 inode->i_pipe = NULL;
1307 inode->i_bdev = NULL;
1308 inode->i_cdev = NULL;
1309diff -urN linux-2.6.10/fs/namei.c linux/fs/namei.c
1310--- linux-2.6.10/fs/namei.c 2004-12-24 16:34:30.000000000 -0500
1311+++ linux/fs/namei.c 2005-01-06 15:30:13.049209056 -0500
1312@@ -22,6 +22,7 @@
1313 #include <linux/quotaops.h>
1314 #include <linux/pagemap.h>
1315 #include <linux/dnotify.h>
1316+#include <linux/inotify.h>
1317 #include <linux/smp_lock.h>
1318 #include <linux/personality.h>
1319 #include <linux/security.h>
1320@@ -1242,6 +1243,8 @@
1321 error = dir->i_op->create(dir, dentry, mode, nd);
1322 if (!error) {
1323 inode_dir_notify(dir, DN_CREATE);
1324+ inotify_inode_queue_event(dir, IN_CREATE_FILE,
1325+ 0, dentry->d_name.name);
1326 security_inode_post_create(dir, dentry, mode);
1327 }
1328 return error;
1329@@ -1556,6 +1559,8 @@
1330 error = dir->i_op->mknod(dir, dentry, mode, dev);
1331 if (!error) {
1332 inode_dir_notify(dir, DN_CREATE);
1333+ inotify_inode_queue_event(dir, IN_CREATE_FILE, 0,
1334+ dentry->d_name.name);
1335 security_inode_post_mknod(dir, dentry, mode, dev);
1336 }
1337 return error;
1338@@ -1629,6 +1634,8 @@
1339 error = dir->i_op->mkdir(dir, dentry, mode);
1340 if (!error) {
1341 inode_dir_notify(dir, DN_CREATE);
1342+ inotify_inode_queue_event(dir, IN_CREATE_SUBDIR, 0,
1343+ dentry->d_name.name);
1344 security_inode_post_mkdir(dir,dentry, mode);
1345 }
1346 return error;
1347@@ -1724,6 +1731,11 @@
1348 up(&dentry->d_inode->i_sem);
1349 if (!error) {
1350 inode_dir_notify(dir, DN_DELETE);
1351+ inotify_inode_queue_event(dir, IN_DELETE_SUBDIR, 0,
1352+ dentry->d_name.name);
1353+ inotify_inode_queue_event(dentry->d_inode, IN_DELETE_SELF, 0,
1354+ NULL);
1355+ inotify_inode_is_dead (dentry->d_inode);
1356 d_delete(dentry);
1357 }
1358 dput(dentry);
1359@@ -1796,8 +1808,13 @@
1360
1361 /* We don't d_delete() NFS sillyrenamed files--they still exist. */
1362 if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) {
1363- d_delete(dentry);
1364 inode_dir_notify(dir, DN_DELETE);
1365+ inotify_inode_queue_event(dir, IN_DELETE_FILE, 0,
1366+ dentry->d_name.name);
1367+ inotify_inode_queue_event(dentry->d_inode, IN_DELETE_SELF, 0,
1368+ NULL);
1369+ inotify_inode_is_dead (dentry->d_inode);
1370+ d_delete(dentry);
1371 }
1372 return error;
1373 }
1374@@ -1873,6 +1890,8 @@
1375 error = dir->i_op->symlink(dir, dentry, oldname);
1376 if (!error) {
1377 inode_dir_notify(dir, DN_CREATE);
1378+ inotify_inode_queue_event(dir, IN_CREATE_FILE, 0,
1379+ dentry->d_name.name);
1380 security_inode_post_symlink(dir, dentry, oldname);
1381 }
1382 return error;
1383@@ -1946,6 +1965,8 @@
1384 up(&old_dentry->d_inode->i_sem);
1385 if (!error) {
1386 inode_dir_notify(dir, DN_CREATE);
1387+ inotify_inode_queue_event(dir, IN_CREATE_FILE, 0,
1388+ new_dentry->d_name.name);
1389 security_inode_post_link(old_dentry, dir, new_dentry);
1390 }
1391 return error;
1392@@ -2109,6 +2130,8 @@
1393 {
1394 int error;
1395 int is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
1396+ char *old_name;
1397+ u32 cookie;
1398
1399 if (old_dentry->d_inode == new_dentry->d_inode)
1400 return 0;
1401@@ -2130,6 +2153,8 @@
1402 DQUOT_INIT(old_dir);
1403 DQUOT_INIT(new_dir);
1404
1405+ old_name = inotify_oldname_init(old_dentry);
1406+
1407 if (is_dir)
1408 error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
1409 else
1410@@ -2141,7 +2166,16 @@
1411 inode_dir_notify(old_dir, DN_DELETE);
1412 inode_dir_notify(new_dir, DN_CREATE);
1413 }
1414+
1415+ cookie = inotify_get_cookie();
1416+
1417+ inotify_inode_queue_event(old_dir, IN_MOVED_FROM, cookie,
1418+ old_name);
1419+ inotify_inode_queue_event(new_dir, IN_MOVED_TO, cookie,
1420+ old_dentry->d_name.name);
1421 }
1422+ inotify_oldname_free(old_name);
1423+
1424 return error;
1425 }
1426
1427diff -urN linux-2.6.10/fs/open.c linux/fs/open.c
1428--- linux-2.6.10/fs/open.c 2004-12-24 16:33:50.000000000 -0500
1429+++ linux/fs/open.c 2005-01-06 15:04:03.747779136 -0500
1430@@ -11,6 +11,7 @@
1431 #include <linux/smp_lock.h>
1432 #include <linux/quotaops.h>
1433 #include <linux/dnotify.h>
1434+#include <linux/inotify.h>
1435 #include <linux/module.h>
1436 #include <linux/slab.h>
1437 #include <linux/tty.h>
1438@@ -956,6 +957,10 @@
1439 error = PTR_ERR(f);
1440 if (IS_ERR(f))
1441 goto out_error;
1442+ inotify_inode_queue_event(f->f_dentry->d_inode,
1443+ IN_OPEN, 0, NULL);
1444+ inotify_dentry_parent_queue_event(f->f_dentry, IN_OPEN,
1445+ 0, f->f_dentry->d_name.name);
1446 fd_install(fd, f);
1447 }
1448 out:
1449diff -urN linux-2.6.10/fs/read_write.c linux/fs/read_write.c
1450--- linux-2.6.10/fs/read_write.c 2004-12-24 16:35:00.000000000 -0500
1451+++ linux/fs/read_write.c 2005-01-06 15:04:03.748778984 -0500
1452@@ -11,6 +11,7 @@
1453 #include <linux/uio.h>
1454 #include <linux/smp_lock.h>
1455 #include <linux/dnotify.h>
1456+#include <linux/inotify.h>
1457 #include <linux/security.h>
1458 #include <linux/module.h>
1459 #include <linux/syscalls.h>
1460@@ -216,8 +217,14 @@
1461 ret = file->f_op->read(file, buf, count, pos);
1462 else
1463 ret = do_sync_read(file, buf, count, pos);
1464- if (ret > 0)
1465- dnotify_parent(file->f_dentry, DN_ACCESS);
1466+ if (ret > 0) {
1467+ struct dentry *dentry = file->f_dentry;
1468+ dnotify_parent(dentry, DN_ACCESS);
1469+ inotify_dentry_parent_queue_event(dentry,
1470+ IN_ACCESS, 0, dentry->d_name.name);
1471+ inotify_inode_queue_event(inode, IN_ACCESS, 0,
1472+ NULL);
1473+ }
1474 }
1475 }
1476
1477@@ -260,8 +267,14 @@
1478 ret = file->f_op->write(file, buf, count, pos);
1479 else
1480 ret = do_sync_write(file, buf, count, pos);
1481- if (ret > 0)
1482- dnotify_parent(file->f_dentry, DN_MODIFY);
1483+ if (ret > 0) {
1484+ struct dentry *dentry = file->f_dentry;
1485+ dnotify_parent(dentry, DN_MODIFY);
1486+ inotify_dentry_parent_queue_event(dentry,
1487+ IN_MODIFY, 0, dentry->d_name.name);
1488+ inotify_inode_queue_event(inode, IN_MODIFY, 0,
1489+ NULL);
1490+ }
1491 }
1492 }
1493
1494@@ -493,9 +506,15 @@
1495 out:
1496 if (iov != iovstack)
1497 kfree(iov);
1498- if ((ret + (type == READ)) > 0)
1499- dnotify_parent(file->f_dentry,
1500- (type == READ) ? DN_ACCESS : DN_MODIFY);
1501+ if ((ret + (type == READ)) > 0) {
1502+ struct dentry *dentry = file->f_dentry;
1503+ dnotify_parent(dentry, (type == READ) ? DN_ACCESS : DN_MODIFY);
1504+ inotify_dentry_parent_queue_event(dentry,
1505+ (type == READ) ? IN_ACCESS : IN_MODIFY, 0,
1506+ dentry->d_name.name);
1507+ inotify_inode_queue_event (dentry->d_inode,
1508+ (type == READ) ? IN_ACCESS : IN_MODIFY, 0, NULL);
1509+ }
1510 return ret;
1511 }
1512
1513diff -urN linux-2.6.10/fs/super.c linux/fs/super.c
1514--- linux-2.6.10/fs/super.c 2004-12-24 16:34:33.000000000 -0500
1515+++ linux/fs/super.c 2005-01-06 15:04:03.748778984 -0500
1516@@ -38,6 +38,7 @@
1517 #include <linux/idr.h>
1518 #include <linux/kobject.h>
1519 #include <asm/uaccess.h>
1520+#include <linux/inotify.h>
1521
1522
1523 void get_filesystem(struct file_system_type *fs);
1524@@ -227,6 +228,7 @@
1525
1526 if (root) {
1527 sb->s_root = NULL;
1528+ inotify_super_block_umount(sb);
1529 shrink_dcache_parent(root);
1530 shrink_dcache_anon(&sb->s_anon);
1531 dput(root);
1532diff -urN linux-2.6.10/include/linux/fs.h linux/include/linux/fs.h
1533--- linux-2.6.10/include/linux/fs.h 2004-12-24 16:34:27.000000000 -0500
1534+++ linux/include/linux/fs.h 2005-01-06 15:04:03.750778680 -0500
1535@@ -27,6 +27,7 @@
1536 struct kstatfs;
1537 struct vm_area_struct;
1538 struct vfsmount;
1539+struct inotify_inode_data;
1540
1541 /*
1542 * It's silly to have NR_OPEN bigger than NR_FILE, but you can change
1543@@ -473,6 +474,10 @@
1544 struct dnotify_struct *i_dnotify; /* for directory notifications */
1545 #endif
1546
1547+#ifdef CONFIG_INOTIFY
1548+ struct inotify_inode_data *inotify_data;
1549+#endif
1550+
1551 unsigned long i_state;
1552 unsigned long dirtied_when; /* jiffies of first dirtying */
1553
1554@@ -1353,7 +1358,7 @@
1555 extern int do_remount_sb(struct super_block *sb, int flags,
1556 void *data, int force);
1557 extern sector_t bmap(struct inode *, sector_t);
1558-extern int setattr_mask(unsigned int);
1559+extern void setattr_mask(unsigned int, int *, u32 *);
1560 extern int notify_change(struct dentry *, struct iattr *);
1561 extern int permission(struct inode *, int, struct nameidata *);
1562 extern int generic_permission(struct inode *, int,
1563diff -urN linux-2.6.10/include/linux/inotify.h linux/include/linux/inotify.h
1564--- linux-2.6.10/include/linux/inotify.h 1969-12-31 19:00:00.000000000 -0500
1565+++ linux/include/linux/inotify.h 2005-01-07 17:18:37.798540360 -0500
1566@@ -0,0 +1,160 @@
1567+/*
1568+ * Inode based directory notification for Linux
1569+ *
1570+ * Copyright (C) 2004 John McCutchan
1571+ */
1572+
1573+#ifndef _LINUX_INOTIFY_H
1574+#define _LINUX_INOTIFY_H
1575+
1576+#include <linux/types.h>
1577+#include <linux/limits.h>
1578+
1579+/* this size could limit things, since technically we could need PATH_MAX */
1580+#define INOTIFY_FILENAME_MAX 256
1581+
1582+/*
1583+ * struct inotify_event - structure read from the inotify device for each event
1584+ *
1585+ * When you are watching a directory, you will receive the filename for events
1586+ * such as IN_CREATE, IN_DELETE, IN_OPEN, IN_CLOSE, ...
1587+ *
1588+ * Note: When reading from the device you must provide a buffer that is a
1589+ * multiple of sizeof(struct inotify_event)
1590+ */
1591+struct inotify_event {
1592+ __s32 wd;
1593+ __u32 mask;
1594+ __u32 cookie;
1595+ size_t len;
1596+#ifdef __KERNEL__
1597+ char *filename;
1598+#else
1599+ char filename[0];
1600+#endif
1601+};
1602+
1603+/*
1604+ * struct inotify_watch_request - represents a watch request
1605+ *
1606+ * Pass to the inotify device via the INOTIFY_WATCH ioctl
1607+ */
1608+struct inotify_watch_request {
1609+ char *dirname; /* directory name */
1610+ __u32 mask; /* event mask */
1611+};
1612+
1613+/* the following are legal, implemented events */
1614+#define IN_ACCESS 0x00000001 /* File was accessed */
1615+#define IN_MODIFY 0x00000002 /* File was modified */
1616+#define IN_ATTRIB 0x00000004 /* File changed attributes */
1617+#define IN_CLOSE_WRITE 0x00000008 /* Writtable file was closed */
1618+#define IN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed */
1619+#define IN_OPEN 0x00000020 /* File was opened */
1620+#define IN_MOVED_FROM 0x00000040 /* File was moved from X */
1621+#define IN_MOVED_TO 0x00000080 /* File was moved to Y */
1622+#define IN_DELETE_SUBDIR 0x00000100 /* Subdir was deleted */
1623+#define IN_DELETE_FILE 0x00000200 /* Subfile was deleted */
1624+#define IN_CREATE_SUBDIR 0x00000400 /* Subdir was created */
1625+#define IN_CREATE_FILE 0x00000800 /* Subfile was created */
1626+#define IN_DELETE_SELF 0x00001000 /* Self was deleted */
1627+#define IN_UNMOUNT 0x00002000 /* Backing fs was unmounted */
1628+#define IN_Q_OVERFLOW 0x00004000 /* Event queued overflowed */
1629+#define IN_IGNORED 0x00008000 /* File was ignored */
1630+
1631+/* special flags */
1632+#define IN_ALL_EVENTS 0xffffffff /* All the events */
1633+#define IN_CLOSE (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)
1634+
1635+#define INOTIFY_IOCTL_MAGIC 'Q'
1636+#define INOTIFY_IOCTL_MAXNR 2
1637+
1638+#define INOTIFY_WATCH _IOR(INOTIFY_IOCTL_MAGIC, 1, struct inotify_watch_request)
1639+#define INOTIFY_IGNORE _IOR(INOTIFY_IOCTL_MAGIC, 2, int)
1640+
1641+#ifdef __KERNEL__
1642+
1643+#include <linux/dcache.h>
1644+#include <linux/fs.h>
1645+#include <linux/config.h>
1646+
1647+struct inotify_inode_data {
1648+ struct list_head watches;
1649+ __u32 watch_mask;
1650+ spinlock_t lock;
1651+ atomic_t count;
1652+};
1653+
1654+#ifdef CONFIG_INOTIFY
1655+
1656+extern void inotify_inode_queue_event(struct inode *, __u32, __u32,
1657+ const char *);
1658+extern void inotify_dentry_parent_queue_event(struct dentry *, __u32, __u32,
1659+ const char *);
1660+extern void inotify_super_block_umount(struct super_block *);
1661+extern void inotify_inode_is_dead(struct inode *);
1662+extern __u32 inotify_get_cookie(void);
1663+extern __u32 setattr_mask_inotify(unsigned int);
1664+
1665+/* this could be kstrdup if only we could add that to lib/string.c */
1666+static inline char * inotify_oldname_init(struct dentry *old_dentry)
1667+{
1668+ char *old_name;
1669+
1670+ old_name = kmalloc(strlen(old_dentry->d_name.name) + 1, GFP_KERNEL);
1671+ if (old_name)
1672+ strcpy(old_name, old_dentry->d_name.name);
1673+ return old_name;
1674+}
1675+
1676+static inline void inotify_oldname_free(const char *old_name)
1677+{
1678+ kfree(old_name);
1679+}
1680+
1681+#else
1682+
1683+static inline void inotify_inode_queue_event(struct inode *inode,
1684+ __u32 mask, __u32 cookie,
1685+ const char *filename)
1686+{
1687+}
1688+
1689+static inline void inotify_dentry_parent_queue_event(struct dentry *dentry,
1690+ __u32 mask, __u32 cookie,
1691+ const char *filename)
1692+{
1693+}
1694+
1695+static inline void inotify_super_block_umount(struct super_block *sb)
1696+{
1697+}
1698+
1699+static inline void inotify_inode_is_dead(struct inode *inode)
1700+{
1701+}
1702+
1703+static inline char * inotify_oldname_init(struct dentry *old_dentry)
1704+{
1705+ return NULL;
1706+}
1707+
1708+static inline __u32 inotify_get_cookie(void)
1709+{
1710+ return 0;
1711+}
1712+
1713+static inline void inotify_oldname_free(const char *old_name)
1714+{
1715+}
1716+
1717+static inline int setattr_mask_inotify(unsigned int ia_mask)
1718+{
1719+ return 0;
1720+}
1721+
1722+#endif /* CONFIG_INOTIFY */
1723+
1724+#endif /* __KERNEL __ */
1725+
1726+#endif /* _LINUX_INOTIFY_H */
1727diff -urN linux-2.6.10/include/linux/miscdevice.h linux/include/linux/miscdevice.h
1728--- linux-2.6.10/include/linux/miscdevice.h 2004-12-24 16:34:58.000000000 -0500
1729+++ linux/include/linux/miscdevice.h 2005-01-06 15:04:03.751778528 -0500
1730@@ -2,6 +2,7 @@
1731 #define _LINUX_MISCDEVICE_H
1732 #include <linux/module.h>
1733 #include <linux/major.h>
1734+#include <linux/device.h>
1735
1736 #define PSMOUSE_MINOR 1
1737 #define MS_BUSMOUSE_MINOR 2
1738@@ -32,13 +33,13 @@
1739
1740 struct device;
1741
1742-struct miscdevice
1743-{
1744+struct miscdevice {
1745 int minor;
1746 const char *name;
1747 struct file_operations *fops;
1748 struct list_head list;
1749 struct device *dev;
1750+ struct class_device *class;
1751 char devfs_name[64];
1752 };
1753
1754diff -urN linux-2.6.10/include/linux/sched.h linux/include/linux/sched.h
1755--- linux-2.6.10/include/linux/sched.h 2004-12-24 16:33:59.000000000 -0500
1756+++ linux/include/linux/sched.h 2005-01-06 15:04:03.752778376 -0500
1757@@ -353,6 +353,8 @@
1758 atomic_t processes; /* How many processes does this user have? */
1759 atomic_t files; /* How many open files does this user have? */
1760 atomic_t sigpending; /* How many pending signals does this user have? */
1761+ atomic_t inotify_watches; /* How many inotify watches does this user have? */
1762+ atomic_t inotify_devs; /* How many inotify devs does this user have opened? */
1763 /* protected by mq_lock */
1764 unsigned long mq_bytes; /* How many bytes can be allocated to mqueue? */
1765 unsigned long locked_shm; /* How many pages of mlocked shm ? */
1766diff -urN linux-2.6.10/kernel/user.c linux/kernel/user.c
1767--- linux-2.6.10/kernel/user.c 2004-12-24 16:34:31.000000000 -0500
1768+++ linux/kernel/user.c 2005-01-06 15:04:03.753778224 -0500
1769@@ -119,6 +119,8 @@
1770 atomic_set(&new->processes, 0);
1771 atomic_set(&new->files, 0);
1772 atomic_set(&new->sigpending, 0);
1773+ atomic_set(&new->inotify_watches, 0);
1774+ atomic_set(&new->inotify_devs, 0);
1775
1776 new->mq_bytes = 0;
1777 new->locked_shm = 0;
Note: See TracBrowser for help on using the repository browser.