]> git.pld-linux.org Git - packages/kernel.git/blame - inotify-0.22-rml-2.6.12-rc2-mm1-2.patch
- ported from linux-2.4.25-atmdd.patch
[packages/kernel.git] / inotify-0.22-rml-2.6.12-rc2-mm1-2.patch
CommitLineData
3e062538
JR
1inotify!
2
3inotify is intended to correct the deficiencies of dnotify, particularly
4its inability to scale and its terrible user interface:
5
6 * dnotify requires the opening of one fd per each directory
7 that you intend to watch. This quickly results in too many
8 open files and pins removable media, preventing unmount.
9 * dnotify is directory-based. You only learn about changes to
10 directories. Sure, a change to a file in a directory affects
11 the directory, but you are then forced to keep a cache of
12 stat structures.
13 * dnotify's interface to user-space is awful. Signals?
14
15inotify provides a more usable, simple, powerful solution to file change
16notification:
17
18 * inotify's interface is a device node, not SIGIO. You open a
19 single fd to the device node, which is select()-able.
20 * inotify has an event that says "the filesystem that the item
21 you were watching is on was unmounted."
22 * inotify can watch directories or files.
23
24Inotify is currently used by Beagle (a desktop search infrastructure)
25and Gamin (a FAM replacement).
26
27Signed-off-by: Robert Love <rml@novell.com>
28
29 Documentation/filesystems/inotify.txt | 81 ++
30 fs/Kconfig | 13
31 fs/Makefile | 1
32 fs/attr.c | 33 -
33 fs/compat.c | 12
34 fs/file_table.c | 3
35 fs/inode.c | 6
36 fs/inotify.c | 961 ++++++++++++++++++++++++++++++++++
37 fs/namei.c | 30 -
38 fs/open.c | 6
39 fs/read_write.c | 15
40 include/linux/fs.h | 6
41 include/linux/fsnotify.h | 228 ++++++++
42 include/linux/inotify.h | 111 +++
43 include/linux/sched.h | 4
44 kernel/user.c | 4
45 16 files changed, 1458 insertions(+), 56 deletions(-)
46
47diff -urN linux-2.6.12-rc2-mm1/Documentation/filesystems/inotify.txt linux/Documentation/filesystems/inotify.txt
48--- linux-2.6.12-rc2-mm1/Documentation/filesystems/inotify.txt 1969-12-31 19:00:00.000000000 -0500
49+++ linux/Documentation/filesystems/inotify.txt 2005-04-05 12:41:51.000000000 -0400
50@@ -0,0 +1,81 @@
51+ inotify
52+ a powerful yet simple file change notification system
53+
54+
55+
56+Document started 15 Mar 2005 by Robert Love <rml@novell.com>
57+
58+(i) User Interface
59+
60+Inotify is controlled by a device node, /dev/inotify. If you do not use udev,
61+this device may need to be created manually. First step, open it
62+
63+ int dev_fd = open ("/dev/inotify", O_RDONLY);
64+
65+Change events are managed by "watches". A watch is an (object,mask) pair where
66+the object is a file or directory and the mask is a bitmask of one or more
67+inotify events that the application wishes to receive. See <linux/inotify.h>
68+for valid events. A watch is referenced by a watch descriptor, or wd.
69+
70+Watches are added via a file descriptor.
71+
72+Watches on a directory will return events on any files inside of the directory.
73+
74+Adding a watch is simple,
75+
76+ /* 'wd' represents the watch on fd with mask */
77+ struct inotify_request req = { fd, mask };
78+ int wd = ioctl (dev_fd, INOTIFY_WATCH, &req);
79+
80+You can add a large number of files via something like
81+
82+ for each file to watch {
83+ struct inotify_request req;
84+ int file_fd;
85+
86+ file_fd = open (file, O_RDONLY);
87+ if (fd < 0) {
88+ perror ("open");
89+ break;
90+ }
91+
92+ req.fd = file_fd;
93+ req.mask = mask;
94+
95+ wd = ioctl (dev_fd, INOTIFY_WATCH, &req);
96+
97+ close (fd);
98+ }
99+
100+You can update an existing watch in the same manner, by passing in a new mask.
101+
102+An existing watch is removed via the INOTIFY_IGNORE ioctl, for example
103+
104+ ioctl (dev_fd, INOTIFY_IGNORE, wd);
105+
106+Events are provided in the form of an inotify_event structure that is read(2)
107+from /dev/inotify. The filename is of dynamic length and follows the struct.
108+It is of size len. The filename is padded with null bytes to ensure proper
109+alignment. This padding is reflected in len.
110+
111+You can slurp multiple events by passing a large buffer, for example
112+
113+ size_t len = read (fd, buf, BUF_LEN);
114+
115+Will return as many events as are available and fit in BUF_LEN.
116+
117+/dev/inotify is also select() and poll() able.
118+
119+You can find the size of the current event queue via the FIONREAD ioctl.
120+
121+All watches are destroyed and cleaned up on close.
122+
123+
124+(ii) Internal Kernel Implementation
125+
126+Each open inotify device is associated with an inotify_device structure.
127+
128+Each watch is associated with an inotify_watch structure. Watches are chained
129+off of each associated device and each associated inode.
130+
131+See fs/inotify.c for the locking and lifetime rules.
132diff -urN linux-2.6.12-rc2-mm1/fs/attr.c linux/fs/attr.c
133--- linux-2.6.12-rc2-mm1/fs/attr.c 2005-04-05 12:40:03.000000000 -0400
134+++ linux/fs/attr.c 2005-04-05 12:41:51.000000000 -0400
135@@ -10,7 +10,7 @@
136 #include <linux/mm.h>
137 #include <linux/string.h>
138 #include <linux/smp_lock.h>
139-#include <linux/dnotify.h>
140+#include <linux/fsnotify.h>
141 #include <linux/fcntl.h>
142 #include <linux/quotaops.h>
143 #include <linux/security.h>
144@@ -107,31 +107,8 @@
145 out:
146 return error;
147 }
148-
149 EXPORT_SYMBOL(inode_setattr);
150
151-int setattr_mask(unsigned int ia_valid)
152-{
153- unsigned long dn_mask = 0;
154-
155- if (ia_valid & ATTR_UID)
156- dn_mask |= DN_ATTRIB;
157- if (ia_valid & ATTR_GID)
158- dn_mask |= DN_ATTRIB;
159- if (ia_valid & ATTR_SIZE)
160- dn_mask |= DN_MODIFY;
161- /* both times implies a utime(s) call */
162- if ((ia_valid & (ATTR_ATIME|ATTR_MTIME)) == (ATTR_ATIME|ATTR_MTIME))
163- dn_mask |= DN_ATTRIB;
164- else if (ia_valid & ATTR_ATIME)
165- dn_mask |= DN_ACCESS;
166- else if (ia_valid & ATTR_MTIME)
167- dn_mask |= DN_MODIFY;
168- if (ia_valid & ATTR_MODE)
169- dn_mask |= DN_ATTRIB;
170- return dn_mask;
171-}
172-
173 int notify_change(struct dentry * dentry, struct iattr * attr)
174 {
175 struct inode *inode = dentry->d_inode;
176@@ -197,11 +174,9 @@
177 if (ia_valid & ATTR_SIZE)
178 up_write(&dentry->d_inode->i_alloc_sem);
179
180- if (!error) {
181- unsigned long dn_mask = setattr_mask(ia_valid);
182- if (dn_mask)
183- dnotify_parent(dentry, dn_mask);
184- }
185+ if (!error)
186+ fsnotify_change(dentry, ia_valid);
187+
188 return error;
189 }
190
191diff -urN linux-2.6.12-rc2-mm1/fs/compat.c linux/fs/compat.c
192--- linux-2.6.12-rc2-mm1/fs/compat.c 2005-04-05 12:40:03.000000000 -0400
193+++ linux/fs/compat.c 2005-04-05 12:41:51.000000000 -0400
194@@ -36,7 +36,7 @@
195 #include <linux/ctype.h>
196 #include <linux/module.h>
197 #include <linux/dirent.h>
198-#include <linux/dnotify.h>
199+#include <linux/fsnotify.h>
200 #include <linux/highuid.h>
201 #include <linux/sunrpc/svc.h>
202 #include <linux/nfsd/nfsd.h>
203@@ -1233,9 +1233,13 @@
204 out:
205 if (iov != iovstack)
206 kfree(iov);
207- if ((ret + (type == READ)) > 0)
208- dnotify_parent(file->f_dentry,
209- (type == READ) ? DN_ACCESS : DN_MODIFY);
210+ if ((ret + (type == READ)) > 0) {
211+ struct dentry *dentry = file->f_dentry;
212+ if (type == READ)
213+ fsnotify_access(dentry);
214+ else
215+ fsnotify_modify(dentry);
216+ }
217 return ret;
218 }
219
220diff -urN linux-2.6.12-rc2-mm1/fs/file_table.c linux/fs/file_table.c
221--- linux-2.6.12-rc2-mm1/fs/file_table.c 2005-04-05 12:40:03.000000000 -0400
222+++ linux/fs/file_table.c 2005-04-05 12:41:51.000000000 -0400
223@@ -16,6 +16,7 @@
224 #include <linux/eventpoll.h>
225 #include <linux/mount.h>
226 #include <linux/cdev.h>
227+#include <linux/fsnotify.h>
228
229 /* sysctl tunables... */
230 struct files_stat_struct files_stat = {
231@@ -123,6 +124,8 @@
232 struct inode *inode = dentry->d_inode;
233
234 might_sleep();
235+
236+ fsnotify_close(file);
237 /*
238 * The function eventpoll_release() should be the first called
239 * in the file cleanup chain.
240diff -urN linux-2.6.12-rc2-mm1/fs/inode.c linux/fs/inode.c
241--- linux-2.6.12-rc2-mm1/fs/inode.c 2005-04-05 12:40:03.000000000 -0400
242+++ linux/fs/inode.c 2005-04-05 12:41:51.000000000 -0400
243@@ -21,6 +21,7 @@
244 #include <linux/pagemap.h>
245 #include <linux/cdev.h>
246 #include <linux/bootmem.h>
247+#include <linux/inotify.h>
248
249 /*
250 * This is needed for the following functions:
251@@ -131,6 +132,10 @@
252 #ifdef CONFIG_QUOTA
253 memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
254 #endif
255+#ifdef CONFIG_INOTIFY
256+ INIT_LIST_HEAD(&inode->inotify_watches);
257+ sema_init(&inode->inotify_sem, 1);
258+#endif
259 inode->i_pipe = NULL;
260 inode->i_bdev = NULL;
261 inode->i_cdev = NULL;
262@@ -357,6 +362,7 @@
263
264 down(&iprune_sem);
265 spin_lock(&inode_lock);
266+ inotify_unmount_inodes(&sb->s_inodes);
267 busy = invalidate_list(&sb->s_inodes, &throw_away);
268 spin_unlock(&inode_lock);
269
270diff -urN linux-2.6.12-rc2-mm1/fs/inotify.c linux/fs/inotify.c
271--- linux-2.6.12-rc2-mm1/fs/inotify.c 1969-12-31 19:00:00.000000000 -0500
272+++ linux/fs/inotify.c 2005-04-05 12:41:51.000000000 -0400
273@@ -0,0 +1,961 @@
274+/*
275+ * fs/inotify.c - inode-based file event notifications
276+ *
277+ * Authors:
278+ * John McCutchan <ttb@tentacle.dhs.org>
279+ * Robert Love <rml@novell.com>
280+ *
281+ * Copyright (C) 2005 John McCutchan
282+ *
283+ * This program is free software; you can redistribute it and/or modify it
284+ * under the terms of the GNU General Public License as published by the
285+ * Free Software Foundation; either version 2, or (at your option) any
286+ * later version.
287+ *
288+ * This program is distributed in the hope that it will be useful, but
289+ * WITHOUT ANY WARRANTY; without even the implied warranty of
290+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
291+ * General Public License for more details.
292+ */
293+
294+#include <linux/module.h>
295+#include <linux/kernel.h>
296+#include <linux/sched.h>
297+#include <linux/spinlock.h>
298+#include <linux/idr.h>
299+#include <linux/slab.h>
300+#include <linux/fs.h>
301+#include <linux/file.h>
302+#include <linux/namei.h>
303+#include <linux/poll.h>
304+#include <linux/device.h>
305+#include <linux/miscdevice.h>
306+#include <linux/init.h>
307+#include <linux/list.h>
308+#include <linux/writeback.h>
309+#include <linux/inotify.h>
310+
311+#include <asm/ioctls.h>
312+
313+static atomic_t inotify_cookie;
314+
315+static kmem_cache_t *watch_cachep;
316+static kmem_cache_t *event_cachep;
317+
318+static int max_user_devices;
319+static int max_user_watches;
320+static unsigned int max_queued_events;
321+
322+/*
323+ * Lock ordering:
324+ *
325+ * dentry->d_lock (used to keep d_move() away from dentry->d_parent)
326+ * iprune_sem (synchronize versus shrink_icache_memory())
327+ * inode_lock (protects the super_block->s_inodes list)
328+ * inode->inotify_sem (protects inode->inotify_watches and watches->i_list)
329+ * inotify_dev->sem (protects inotify_device and watches->d_list)
330+ */
331+
332+/*
333+ * Lifetimes of the three main data structures--inotify_device, inode, and
334+ * inotify_watch--are managed by reference count.
335+ *
336+ * inotify_device: Lifetime is from open until release. Additional references
337+ * can bump the count via get_inotify_dev() and drop the count via
338+ * put_inotify_dev().
339+ *
340+ * inotify_watch: Lifetime is from create_watch() to destory_watch().
341+ * Additional references can bump the count via get_inotify_watch() and drop
342+ * the count via put_inotify_watch().
343+ *
344+ * inode: Pinned so long as the inode is associated with a watch, from
345+ * create_watch() to put_inotify_watch().
346+ */
347+
348+/*
349+ * struct inotify_device - represents an open instance of an inotify device
350+ *
351+ * This structure is protected by the semaphore 'sem'.
352+ */
353+struct inotify_device {
354+ wait_queue_head_t wq; /* wait queue for i/o */
355+ struct idr idr; /* idr mapping wd -> watch */
356+ struct semaphore sem; /* protects this bad boy */
357+ struct list_head events; /* list of queued events */
358+ struct list_head watches; /* list of watches */
359+ atomic_t count; /* reference count */
360+ struct user_struct *user; /* user who opened this dev */
361+ unsigned int queue_size; /* size of the queue (bytes) */
362+ unsigned int event_count; /* number of pending events */
363+ unsigned int max_events; /* maximum number of events */
364+};
365+
366+/*
367+ * struct inotify_kernel_event - An intofiy event, originating from a watch and
368+ * queued for user-space. A list of these is attached to each instance of the
369+ * device. In read(), this list is walked and all events that can fit in the
370+ * buffer are returned.
371+ *
372+ * Protected by dev->sem of the device in which we are queued.
373+ */
374+struct inotify_kernel_event {
375+ struct inotify_event event; /* the user-space event */
376+ struct list_head list; /* entry in inotify_device's list */
377+ char *name; /* filename, if any */
378+};
379+
380+/*
381+ * struct inotify_watch - represents a watch request on a specific inode
382+ *
383+ * d_list is protected by dev->sem of the associated watch->dev.
384+ * i_list and mask are protected by inode->inotify_sem of the associated inode.
385+ * dev, inode, and wd are never written to once the watch is created.
386+ */
387+struct inotify_watch {
388+ struct list_head d_list; /* entry in inotify_device's list */
389+ struct list_head i_list; /* entry in inode's list */
390+ atomic_t count; /* reference count */
391+ struct inotify_device *dev; /* associated device */
392+ struct inode *inode; /* associated inode */
393+ s32 wd; /* watch descriptor */
394+ u32 mask; /* event mask for this watch */
395+};
396+
397+static ssize_t show_max_queued_events(struct class_device *class, char *buf)
398+{
399+ return sprintf(buf, "%d\n", max_queued_events);
400+}
401+
402+static ssize_t store_max_queued_events(struct class_device *class,
403+ const char *buf, size_t count)
404+{
405+ unsigned int max;
406+
407+ if (sscanf(buf, "%u", &max) > 0 && max > 0) {
408+ max_queued_events = max;
409+ return strlen(buf);
410+ }
411+ return -EINVAL;
412+}
413+
414+static ssize_t show_max_user_devices(struct class_device *class, char *buf)
415+{
416+ return sprintf(buf, "%d\n", max_user_devices);
417+}
418+
419+static ssize_t store_max_user_devices(struct class_device *class,
420+ const char *buf, size_t count)
421+{
422+ int max;
423+
424+ if (sscanf(buf, "%d", &max) > 0 && max > 0) {
425+ max_user_devices = max;
426+ return strlen(buf);
427+ }
428+ return -EINVAL;
429+}
430+
431+static ssize_t show_max_user_watches(struct class_device *class, char *buf)
432+{
433+ return sprintf(buf, "%d\n", max_user_watches);
434+}
435+
436+static ssize_t store_max_user_watches(struct class_device *class,
437+ const char *buf, size_t count)
438+{
439+ int max;
440+
441+ if (sscanf(buf, "%d", &max) > 0 && max > 0) {
442+ max_user_watches = max;
443+ return strlen(buf);
444+ }
445+ return -EINVAL;
446+}
447+
448+static CLASS_DEVICE_ATTR(max_queued_events, S_IRUGO | S_IWUSR,
449+ show_max_queued_events, store_max_queued_events);
450+static CLASS_DEVICE_ATTR(max_user_devices, S_IRUGO | S_IWUSR,
451+ show_max_user_devices, store_max_user_devices);
452+static CLASS_DEVICE_ATTR(max_user_watches, S_IRUGO | S_IWUSR,
453+ show_max_user_watches, store_max_user_watches);
454+
455+static inline void get_inotify_dev(struct inotify_device *dev)
456+{
457+ atomic_inc(&dev->count);
458+}
459+
460+static inline void put_inotify_dev(struct inotify_device *dev)
461+{
462+ if (atomic_dec_and_test(&dev->count)) {
463+ atomic_dec(&dev->user->inotify_devs);
464+ free_uid(dev->user);
465+ kfree(dev);
466+ }
467+}
468+
469+static inline void get_inotify_watch(struct inotify_watch *watch)
470+{
471+ atomic_inc(&watch->count);
472+}
473+
474+/*
475+ * put_inotify_watch - decrements the ref count on a given watch. cleans up
476+ * the watch and its references if the count reaches zero.
477+ */
478+static inline void put_inotify_watch(struct inotify_watch *watch)
479+{
480+ if (atomic_dec_and_test(&watch->count)) {
481+ put_inotify_dev(watch->dev);
482+ iput(watch->inode);
483+ kmem_cache_free(watch_cachep, watch);
484+ }
485+}
486+
487+/*
488+ * kernel_event - create a new kernel event with the given parameters
489+ *
490+ * This function can sleep.
491+ */
492+static struct inotify_kernel_event * kernel_event(s32 wd, u32 mask, u32 cookie,
493+ const char *name)
494+{
495+ struct inotify_kernel_event *kevent;
496+
497+ kevent = kmem_cache_alloc(event_cachep, GFP_KERNEL);
498+ if (unlikely(!kevent))
499+ return NULL;
500+
501+ /* we hand this out to user-space, so zero it just in case */
502+ memset(&kevent->event, 0, sizeof(struct inotify_event));
503+
504+ kevent->event.wd = wd;
505+ kevent->event.mask = mask;
506+ kevent->event.cookie = cookie;
507+
508+ INIT_LIST_HEAD(&kevent->list);
509+
510+ if (name) {
511+ size_t len, rem, event_size = sizeof(struct inotify_event);
512+
513+ /*
514+ * We need to pad the filename so as to properly align an
515+ * array of inotify_event structures. Because the structure is
516+ * small and the common case is a small filename, we just round
517+ * up to the next multiple of the structure's sizeof. This is
518+ * simple and safe for all architectures.
519+ */
520+ len = strlen(name) + 1;
521+ rem = event_size - len;
522+ if (len > event_size) {
523+ rem = event_size - (len % event_size);
524+ if (len % event_size == 0)
525+ rem = 0;
526+ }
527+ len += rem;
528+
529+ kevent->name = kmalloc(len, GFP_KERNEL);
530+ if (unlikely(!kevent->name)) {
531+ kmem_cache_free(event_cachep, kevent);
532+ return NULL;
533+ }
534+ memset(kevent->name, 0, len);
535+ strncpy(kevent->name, name, strlen(name));
536+ kevent->event.len = len;
537+ } else {
538+ kevent->event.len = 0;
539+ kevent->name = NULL;
540+ }
541+
542+ return kevent;
543+}
544+
545+/*
546+ * inotify_dev_get_event - return the next event in the given dev's queue
547+ *
548+ * Caller must hold dev->sem.
549+ */
550+static inline struct inotify_kernel_event *
551+inotify_dev_get_event(struct inotify_device *dev)
552+{
553+ return list_entry(dev->events.next, struct inotify_kernel_event, list);
554+}
555+
556+/*
557+ * inotify_dev_queue_event - add a new event to the given device
558+ *
559+ * Caller must hold dev->sem. Can sleep (calls kernel_event()).
560+ */
561+static void inotify_dev_queue_event(struct inotify_device *dev,
562+ struct inotify_watch *watch, u32 mask,
563+ u32 cookie, const char *name)
564+{
565+ struct inotify_kernel_event *kevent, *last;
566+
567+ /* coalescing: drop this event if it is a dupe of the previous */
568+ last = inotify_dev_get_event(dev);
569+ if (dev->event_count && last->event.mask == mask &&
570+ last->event.cookie == cookie &&
571+ last->event.wd == watch->wd) {
572+ const char *lastname = last->name;
573+
574+ if (!name && !lastname)
575+ return;
576+ if (name && lastname && !strcmp(lastname, name))
577+ return;
578+ }
579+
580+ /* the queue overflowed and we already sent the Q_OVERFLOW event */
581+ if (unlikely(dev->event_count > dev->max_events))
582+ return;
583+
584+ /* if the queue overflows, we need to notify user space */
585+ if (unlikely(dev->event_count == dev->max_events))
586+ kevent = kernel_event(-1, IN_Q_OVERFLOW, cookie, NULL);
587+ else
588+ kevent = kernel_event(watch->wd, mask, cookie, name);
589+
590+ if (unlikely(!kevent))
591+ return;
592+
593+ /* queue the event and wake up anyone waiting */
594+ dev->event_count++;
595+ dev->queue_size += sizeof(struct inotify_event) + kevent->event.len;
596+ list_add_tail(&kevent->list, &dev->events);
597+ wake_up_interruptible(&dev->wq);
598+}
599+
600+/*
601+ * remove_kevent - cleans up and ultimately frees the given kevent
602+ *
603+ * Caller must hold dev->sem.
604+ */
605+static void remove_kevent(struct inotify_device *dev,
606+ struct inotify_kernel_event *kevent)
607+{
608+ list_del(&kevent->list);
609+
610+ dev->event_count--;
611+ dev->queue_size -= sizeof(struct inotify_event) + kevent->event.len;
612+
613+ kfree(kevent->name);
614+ kmem_cache_free(event_cachep, kevent);
615+}
616+
617+/*
618+ * inotify_dev_event_dequeue - destroy an event on the given device
619+ *
620+ * Caller must hold dev->sem.
621+ */
622+static void inotify_dev_event_dequeue(struct inotify_device *dev)
623+{
624+ if (!list_empty(&dev->events)) {
625+ struct inotify_kernel_event *kevent;
626+ kevent = inotify_dev_get_event(dev);
627+ remove_kevent(dev, kevent);
628+ }
629+}
630+
631+/*
632+ * inotify_dev_get_wd - returns the next WD for use by the given dev
633+ *
634+ * Callers must hold dev->sem. This function can sleep.
635+ */
636+static int inotify_dev_get_wd(struct inotify_device *dev,
637+ struct inotify_watch *watch)
638+{
639+ int ret;
640+
641+ do {
642+ if (unlikely(!idr_pre_get(&dev->idr, GFP_KERNEL)))
643+ return -ENOSPC;
644+ ret = idr_get_new(&dev->idr, watch, &watch->wd);
645+ } while (ret == -EAGAIN);
646+
647+ return ret;
648+}
649+
650+/*
651+ * create_watch - creates a watch on the given device.
652+ *
653+ * Callers must hold dev->sem. Calls inotify_dev_get_wd() so may sleep.
654+ * Both 'dev' and 'inode' (by way of nameidata) need to be pinned.
655+ */
656+static struct inotify_watch *create_watch(struct inotify_device *dev,
657+ u32 mask, struct inode *inode)
658+{
659+ struct inotify_watch *watch;
660+ int ret;
661+
662+ if (atomic_read(&dev->user->inotify_watches) >= max_user_watches)
663+ return ERR_PTR(-ENOSPC);
664+
665+ watch = kmem_cache_alloc(watch_cachep, GFP_KERNEL);
666+ if (unlikely(!watch))
667+ return ERR_PTR(-ENOMEM);
668+
669+ ret = inotify_dev_get_wd(dev, watch);
670+ if (unlikely(ret)) {
671+ kmem_cache_free(watch_cachep, watch);
672+ return ERR_PTR(ret);
673+ }
674+
675+ watch->mask = mask;
676+ atomic_set(&watch->count, 0);
677+ INIT_LIST_HEAD(&watch->d_list);
678+ INIT_LIST_HEAD(&watch->i_list);
679+
680+ /* save a reference to device and bump the count to make it official */
681+ get_inotify_dev(dev);
682+ watch->dev = dev;
683+
684+ /*
685+ * Save a reference to the inode and bump the ref count to make it
686+ * official. We hold a reference to nameidata, which makes this safe.
687+ */
688+ watch->inode = igrab(inode);
689+
690+ /* bump our own count, corresponding to our entry in dev->watches */
691+ get_inotify_watch(watch);
692+
693+ atomic_inc(&dev->user->inotify_watches);
694+
695+ return watch;
696+}
697+
698+/*
699+ * inotify_find_dev - find the watch associated with the given inode and dev
700+ *
701+ * Callers must hold inode->inotify_sem.
702+ */
703+static struct inotify_watch *inode_find_dev(struct inode *inode,
704+ struct inotify_device *dev)
705+{
706+ struct inotify_watch *watch;
707+
708+ list_for_each_entry(watch, &inode->inotify_watches, i_list) {
709+ if (watch->dev == dev)
710+ return watch;
711+ }
712+
713+ return NULL;
714+}
715+
716+/*
717+ * inotify_dev_is_watching_inode - is this device watching this inode?
718+ *
719+ * Callers must hold dev->sem.
720+ */
721+static inline int inotify_dev_is_watching_inode(struct inotify_device *dev,
722+ struct inode *inode)
723+{
724+ struct inotify_watch *watch;
725+
726+ list_for_each_entry(watch, &dev->watches, d_list) {
727+ if (watch->inode == inode)
728+ return 1;
729+ }
730+
731+ return 0;
732+}
733+
734+/*
735+ * remove_watch_no_event - remove_watch() without the IN_IGNORED event.
736+ */
737+static void remove_watch_no_event(struct inotify_watch *watch,
738+ struct inotify_device *dev)
739+{
740+ list_del(&watch->i_list);
741+ list_del(&watch->d_list);
742+
743+ atomic_dec(&dev->user->inotify_watches);
744+ idr_remove(&dev->idr, watch->wd);
745+ put_inotify_watch(watch);
746+}
747+
748+/*
749+ * remove_watch - Remove a watch from both the device and the inode. Sends
750+ * the IN_IGNORED event to the given device signifying that the inode is no
751+ * longer watched.
752+ *
753+ * Callers must hold both inode->inotify_sem and dev->sem. We drop a
754+ * reference to the inode before returning.
755+ *
756+ * The inode is not iput() so as to remain atomic. If the inode needs to be
757+ * iput(), the call returns one. Otherwise, it returns zero.
758+ */
759+static void remove_watch(struct inotify_watch *watch,struct inotify_device *dev)
760+{
761+ inotify_dev_queue_event(dev, watch, IN_IGNORED, 0, NULL);
762+ remove_watch_no_event(watch, dev);
763+}
764+
765+/* Kernel API */
766+
767+/**
768+ * inotify_inode_queue_event - queue an event to all watches on this inode
769+ * @inode: inode event is originating from
770+ * @mask: event mask describing this event
771+ * @cookie: cookie for synchronization, or zero
772+ * @name: filename, if any
773+ */
774+void inotify_inode_queue_event(struct inode *inode, u32 mask, u32 cookie,
775+ const char *name)
776+{
777+ struct inotify_watch *watch;
778+
779+ down(&inode->inotify_sem);
780+ list_for_each_entry(watch, &inode->inotify_watches, i_list) {
781+ if (watch->mask & mask) {
782+ struct inotify_device *dev = watch->dev;
783+ down(&dev->sem);
784+ inotify_dev_queue_event(dev, watch, mask, cookie, name);
785+ up(&dev->sem);
786+ }
787+ }
788+ up(&inode->inotify_sem);
789+}
790+EXPORT_SYMBOL_GPL(inotify_inode_queue_event);
791+
792+/**
793+ * inotify_dentry_parent_queue_event - queue an event to a dentry's parent
794+ * @dentry: the dentry in question, we queue against this dentry's parent
795+ * @mask: event mask describing this event
796+ * @cookie: cookie for synchronization, or zero
797+ * @name: filename, if any
798+ */
799+void inotify_dentry_parent_queue_event(struct dentry *dentry, u32 mask,
800+ u32 cookie, const char *name)
801+{
802+ struct dentry *parent;
803+ struct inode *inode;
804+
805+ spin_lock(&dentry->d_lock);
806+ parent = dentry->d_parent;
807+ inode = parent->d_inode;
808+
809+ /* We intentially do the list_empty() lockless. The race is fine. */
810+ if (!list_empty(&inode->inotify_watches)) {
811+ dget(parent);
812+ spin_unlock(&dentry->d_lock);
813+ inotify_inode_queue_event(inode, mask, cookie, name);
814+ dput(parent);
815+ } else
816+ spin_unlock(&dentry->d_lock);
817+}
818+EXPORT_SYMBOL_GPL(inotify_dentry_parent_queue_event);
819+
820+/**
821+ * inotify_get_cookie - return a unique cookie for use in synchronizing events.
822+ */
823+u32 inotify_get_cookie(void)
824+{
825+ return atomic_inc_return(&inotify_cookie);
826+}
827+EXPORT_SYMBOL_GPL(inotify_get_cookie);
828+
829+/**
830+ * inotify_unmount_inodes - an sb is unmounting. handle any watched inodes.
831+ * @list: list of inodes being unmounted (sb->s_inodes)
832+ *
833+ * Called with inode_lock held, protecting the unmounting super block's list
834+ * of inodes, and with iprune_sem held, keeping shrink_icache_memory() at bay.
835+ * We temporarily drop inode_lock, however, and CAN block.
836+ */
837+void inotify_unmount_inodes(struct list_head *list)
838+{
839+ struct inode *inode, *next_i;
840+
841+ list_for_each_entry_safe(inode, next_i, list, i_sb_list) {
842+ struct inotify_watch *watch, *next_w;
843+ struct list_head *watches;
844+
845+ /*
846+ * We can safely drop inode_lock here because the per-sb list
847+ * of inodes must not change during unmount and iprune_sem
848+ * keeps shrink_icache_memory() away.
849+ */
850+ spin_unlock(&inode_lock);
851+
852+ /* for each watch, send IN_UNMOUNT and then remove it */
853+ down(&inode->inotify_sem);
854+ watches = &inode->inotify_watches;
855+ list_for_each_entry_safe(watch, next_w, watches, i_list) {
856+ struct inotify_device *dev = watch->dev;
857+ down(&dev->sem);
858+ inotify_dev_queue_event(dev, watch, IN_UNMOUNT,0,NULL);
859+ remove_watch(watch, dev);
860+ up(&dev->sem);
861+ }
862+ up(&inode->inotify_sem);
863+
864+ spin_lock(&inode_lock);
865+ }
866+}
867+EXPORT_SYMBOL_GPL(inotify_unmount_inodes);
868+
869+/**
870+ * inotify_inode_is_dead - an inode has been deleted, cleanup any watches
871+ * @inode: inode that is about to be removed
872+ */
873+void inotify_inode_is_dead(struct inode *inode)
874+{
875+ struct inotify_watch *watch, *next;
876+
877+ down(&inode->inotify_sem);
878+ list_for_each_entry_safe(watch, next, &inode->inotify_watches, i_list) {
879+ struct inotify_device *dev = watch->dev;
880+ down(&dev->sem);
881+ remove_watch(watch, dev);
882+ up(&dev->sem);
883+ }
884+ up(&inode->inotify_sem);
885+}
886+EXPORT_SYMBOL_GPL(inotify_inode_is_dead);
887+
888+/* Device Interface */
889+
890+static unsigned int inotify_poll(struct file *file, poll_table *wait)
891+{
892+ struct inotify_device *dev = file->private_data;
893+ int ret = 0;
894+
895+ poll_wait(file, &dev->wq, wait);
896+ down(&dev->sem);
897+ if (!list_empty(&dev->events))
898+ ret = POLLIN | POLLRDNORM;
899+ up(&dev->sem);
900+
901+ return ret;
902+}
903+
904+static ssize_t inotify_read(struct file *file, char __user *buf,
905+ size_t count, loff_t *pos)
906+{
907+ size_t event_size = sizeof (struct inotify_event);
908+ struct inotify_device *dev;
909+ char __user *start;
910+ int ret;
911+ DEFINE_WAIT(wait);
912+
913+ start = buf;
914+ dev = file->private_data;
915+
916+ while (1) {
917+ int events;
918+
919+ prepare_to_wait(&dev->wq, &wait, TASK_INTERRUPTIBLE);
920+
921+ down(&dev->sem);
922+ events = !list_empty(&dev->events);
923+ up(&dev->sem);
924+ if (events) {
925+ ret = 0;
926+ break;
927+ }
928+
929+ if (file->f_flags & O_NONBLOCK) {
930+ ret = -EAGAIN;
931+ break;
932+ }
933+
934+ if (signal_pending(current)) {
935+ ret = -EINTR;
936+ break;
937+ }
938+
939+ schedule();
940+ }
941+
942+ finish_wait(&dev->wq, &wait);
943+ if (ret)
944+ return ret;
945+
946+ down(&dev->sem);
947+ while (1) {
948+ struct inotify_kernel_event *kevent;
949+
950+ ret = buf - start;
951+ if (list_empty(&dev->events))
952+ break;
953+
954+ kevent = inotify_dev_get_event(dev);
955+ if (event_size + kevent->event.len > count)
956+ break;
957+
958+ if (copy_to_user(buf, &kevent->event, event_size)) {
959+ ret = -EFAULT;
960+ break;
961+ }
962+ buf += event_size;
963+ count -= event_size;
964+
965+ if (kevent->name) {
966+ if (copy_to_user(buf, kevent->name, kevent->event.len)){
967+ ret = -EFAULT;
968+ break;
969+ }
970+ buf += kevent->event.len;
971+ count -= kevent->event.len;
972+ }
973+
974+ remove_kevent(dev, kevent);
975+ }
976+ up(&dev->sem);
977+
978+ return ret;
979+}
980+
981+static int inotify_open(struct inode *inode, struct file *file)
982+{
983+ struct inotify_device *dev;
984+ struct user_struct *user;
985+ int ret;
986+
987+ user = get_uid(current->user);
988+
989+ if (unlikely(atomic_read(&user->inotify_devs) >= max_user_devices)) {
990+ ret = -EMFILE;
991+ goto out_err;
992+ }
993+
994+ dev = kmalloc(sizeof(struct inotify_device), GFP_KERNEL);
995+ if (unlikely(!dev)) {
996+ ret = -ENOMEM;
997+ goto out_err;
998+ }
999+
1000+ idr_init(&dev->idr);
1001+ INIT_LIST_HEAD(&dev->events);
1002+ INIT_LIST_HEAD(&dev->watches);
1003+ init_waitqueue_head(&dev->wq);
1004+ sema_init(&dev->sem, 1);
1005+
1006+ dev->event_count = 0;
1007+ dev->queue_size = 0;
1008+ dev->max_events = max_queued_events;
1009+ dev->user = user;
1010+ atomic_set(&dev->count, 0);
1011+
1012+ get_inotify_dev(dev);
1013+ atomic_inc(&current->user->inotify_devs);
1014+
1015+ file->private_data = dev;
1016+
1017+ return 0;
1018+out_err:
1019+ free_uid(user);
1020+ return ret;
1021+}
1022+
1023+static int inotify_release(struct inode *ignored, struct file *file)
1024+{
1025+ struct inotify_device *dev = file->private_data;
1026+
1027+ /*
1028+ * Destroy all of the watches on this device. Unfortunately, not very
1029+ * pretty. We cannot do a simple iteration over the list, because we
1030+ * do not know the inode until we iterate to the watch. But we need to
1031+ * hold inode->inotify_sem before dev->sem. The following works.
1032+ */
1033+ while (1) {
1034+ struct inotify_watch *watch;
1035+ struct list_head *watches;
1036+ struct inode *inode;
1037+
1038+ down(&dev->sem);
1039+ watches = &dev->watches;
1040+ if (list_empty(watches)) {
1041+ up(&dev->sem);
1042+ break;
1043+ }
1044+ watch = list_entry(watches->next, struct inotify_watch, d_list);
1045+ get_inotify_watch(watch);
1046+ up(&dev->sem);
1047+
1048+ inode = watch->inode;
1049+ down(&inode->inotify_sem);
1050+ down(&dev->sem);
1051+ remove_watch_no_event(watch, dev);
1052+ up(&dev->sem);
1053+ up(&inode->inotify_sem);
1054+ put_inotify_watch(watch);
1055+ }
1056+
1057+ /* destroy all of the events on this device */
1058+ down(&dev->sem);
1059+ while (!list_empty(&dev->events))
1060+ inotify_dev_event_dequeue(dev);
1061+ up(&dev->sem);
1062+
1063+ /* free this device: the put matching the get in inotify_open() */
1064+ put_inotify_dev(dev);
1065+
1066+ return 0;
1067+}
1068+
1069+static int inotify_add_watch(struct inotify_device *dev,
1070+ int fd, u32 mask)
1071+{
1072+ struct inotify_watch *watch, *old;
1073+ struct inode *inode;
1074+ struct file *filp;
1075+ int ret;
1076+
1077+ filp = fget(fd);
1078+ if (!filp)
1079+ return -EBADF;
1080+ inode = filp->f_dentry->d_inode;
1081+
1082+ down(&inode->inotify_sem);
1083+ down(&dev->sem);
1084+
1085+ /*
1086+ * Handle the case of re-adding a watch on an (inode,dev) pair that we
1087+ * are already watching. We just update the mask and return its wd.
1088+ */
1089+ old = inode_find_dev(inode, dev);
1090+ if (unlikely(old)) {
1091+ old->mask = mask;
1092+ ret = old->wd;
1093+ goto out;
1094+ }
1095+
1096+ watch = create_watch(dev, mask, inode);
1097+ if (unlikely(IS_ERR(watch))) {
1098+ ret = PTR_ERR(watch);
1099+ goto out;
1100+ }
1101+
1102+ /* Add the watch to the device's and the inode's list */
1103+ list_add(&watch->d_list, &dev->watches);
1104+ list_add(&watch->i_list, &inode->inotify_watches);
1105+ ret = watch->wd;
1106+
1107+out:
1108+ up(&dev->sem);
1109+ up(&inode->inotify_sem);
1110+ fput(filp);
1111+
1112+ return ret;
1113+}
1114+
1115+/*
1116+ * inotify_ignore - handle the INOTIFY_IGNORE ioctl, asking that a given wd be
1117+ * removed from the device.
1118+ *
1119+ * Can sleep.
1120+ */
1121+static int inotify_ignore(struct inotify_device *dev, s32 wd)
1122+{
1123+ struct inotify_watch *watch;
1124+ struct inode *inode;
1125+
1126+ down(&dev->sem);
1127+ watch = idr_find(&dev->idr, wd);
1128+ if (unlikely(!watch)) {
1129+ up(&dev->sem);
1130+ return -EINVAL;
1131+ }
1132+ get_inotify_watch(watch);
1133+ up(&dev->sem);
1134+
1135+ inode = watch->inode;
1136+ down(&inode->inotify_sem);
1137+ down(&dev->sem);
1138+ remove_watch(watch, dev);
1139+ up(&dev->sem);
1140+ up(&inode->inotify_sem);
1141+ put_inotify_watch(watch);
1142+
1143+ return 0;
1144+}
1145+
1146+static long inotify_ioctl(struct file *file, unsigned int cmd,
1147+ unsigned long arg)
1148+{
1149+ struct inotify_device *dev;
1150+ struct inotify_watch_request request;
1151+ void __user *p;
1152+ int ret = -ENOTTY;
1153+ s32 wd;
1154+
1155+ dev = file->private_data;
1156+ p = (void __user *) arg;
1157+
1158+ switch (cmd) {
1159+ case INOTIFY_WATCH:
1160+ if (unlikely(copy_from_user(&request, p, sizeof (request)))) {
1161+ ret = -EFAULT;
1162+ break;
1163+ }
1164+ ret = inotify_add_watch(dev, request.fd, request.mask);
1165+ break;
1166+ case INOTIFY_IGNORE:
1167+ if (unlikely(get_user(wd, (int __user *) p))) {
1168+ ret = -EFAULT;
1169+ break;
1170+ }
1171+ ret = inotify_ignore(dev, wd);
1172+ break;
1173+ case FIONREAD:
1174+ ret = put_user(dev->queue_size, (int __user *) p);
1175+ break;
1176+ }
1177+
1178+ return ret;
1179+}
1180+
1181+static struct file_operations inotify_fops = {
1182+ .owner = THIS_MODULE,
1183+ .poll = inotify_poll,
1184+ .read = inotify_read,
1185+ .open = inotify_open,
1186+ .release = inotify_release,
1187+ .unlocked_ioctl = inotify_ioctl,
1188+ .compat_ioctl = inotify_ioctl,
1189+};
1190+
1191+static struct miscdevice inotify_device = {
1192+ .minor = MISC_DYNAMIC_MINOR,
1193+ .name = "inotify",
1194+ .fops = &inotify_fops,
1195+};
1196+
1197+/*
1198+ * inotify_init - Our initialization function. Note that we cannnot return
1199+ * error because we have compiled-in VFS hooks. So an (unlikely) failure here
1200+ * must result in panic().
1201+ */
1202+static int __init inotify_init(void)
1203+{
1204+ struct class_device *class;
1205+ int ret;
1206+
1207+ ret = misc_register(&inotify_device);
1208+ if (unlikely(ret))
1209+ panic("inotify: misc_register returned %d\n", ret);
1210+
1211+ max_queued_events = 512;
1212+ max_user_devices = 64;
1213+ max_user_watches = 16384;
1214+
1215+ class = inotify_device.class;
1216+ class_device_create_file(class, &class_device_attr_max_queued_events);
1217+ class_device_create_file(class, &class_device_attr_max_user_devices);
1218+ class_device_create_file(class, &class_device_attr_max_user_watches);
1219+
1220+ atomic_set(&inotify_cookie, 0);
1221+
1222+ watch_cachep = kmem_cache_create("inotify_watch_cache",
1223+ sizeof(struct inotify_watch),
1224+ 0, SLAB_PANIC, NULL, NULL);
1225+ event_cachep = kmem_cache_create("inotify_event_cache",
1226+ sizeof(struct inotify_kernel_event),
1227+ 0, SLAB_PANIC, NULL, NULL);
1228+
1229+ printk(KERN_INFO "inotify device minor=%d\n", inotify_device.minor);
1230+
1231+ return 0;
1232+}
1233+
1234+module_init(inotify_init);
1235diff -urN linux-2.6.12-rc2-mm1/fs/Kconfig linux/fs/Kconfig
1236--- linux-2.6.12-rc2-mm1/fs/Kconfig 2005-04-05 12:40:03.000000000 -0400
1237+++ linux/fs/Kconfig 2005-04-05 12:41:51.000000000 -0400
1238@@ -341,6 +341,19 @@
1239 If you don't know whether you need it, then you don't need it:
1240 answer N.
1241
1242+config INOTIFY
1243+ bool "Inotify file change notification support"
1244+ default y
1245+ ---help---
1246+ Say Y here to enable inotify support and the /dev/inotify character
1247+ device. Inotify is a file change notification system and a
1248+ replacement for dnotify. Inotify fixes numerous shortcomings in
1249+ dnotify and introduces several new features. It allows monitoring
1250+ of both files and directories via a single open fd. Multiple file
1251+ events are supported.
1252+
1253+ If unsure, say Y.
1254+
1255 config QUOTA
1256 bool "Quota support"
1257 help
1258diff -urN linux-2.6.12-rc2-mm1/fs/Makefile linux/fs/Makefile
1259--- linux-2.6.12-rc2-mm1/fs/Makefile 2005-04-05 12:40:03.000000000 -0400
1260+++ linux/fs/Makefile 2005-04-05 12:41:51.000000000 -0400
1261@@ -12,6 +12,7 @@
1262 seq_file.o xattr.o libfs.o fs-writeback.o mpage.o direct-io.o \
1263 ioprio.o
1264
1265+obj-$(CONFIG_INOTIFY) += inotify.o
1266 obj-$(CONFIG_EPOLL) += eventpoll.o
1267 obj-$(CONFIG_COMPAT) += compat.o
1268
1269diff -urN linux-2.6.12-rc2-mm1/fs/namei.c linux/fs/namei.c
1270--- linux-2.6.12-rc2-mm1/fs/namei.c 2005-04-05 12:40:03.000000000 -0400
1271+++ linux/fs/namei.c 2005-04-05 12:41:51.000000000 -0400
1272@@ -21,7 +21,7 @@
1273 #include <linux/namei.h>
1274 #include <linux/quotaops.h>
1275 #include <linux/pagemap.h>
1276-#include <linux/dnotify.h>
1277+#include <linux/fsnotify.h>
1278 #include <linux/smp_lock.h>
1279 #include <linux/personality.h>
1280 #include <linux/security.h>
1281@@ -1296,7 +1296,7 @@
1282 DQUOT_INIT(dir);
1283 error = dir->i_op->create(dir, dentry, mode, nd);
1284 if (!error) {
1285- inode_dir_notify(dir, DN_CREATE);
1286+ fsnotify_create(dir, dentry->d_name.name);
1287 security_inode_post_create(dir, dentry, mode);
1288 }
1289 return error;
1290@@ -1601,7 +1601,7 @@
1291 DQUOT_INIT(dir);
1292 error = dir->i_op->mknod(dir, dentry, mode, dev);
1293 if (!error) {
1294- inode_dir_notify(dir, DN_CREATE);
1295+ fsnotify_create(dir, dentry->d_name.name);
1296 security_inode_post_mknod(dir, dentry, mode, dev);
1297 }
1298 return error;
1299@@ -1674,7 +1674,7 @@
1300 DQUOT_INIT(dir);
1301 error = dir->i_op->mkdir(dir, dentry, mode);
1302 if (!error) {
1303- inode_dir_notify(dir, DN_CREATE);
1304+ fsnotify_mkdir(dir, dentry->d_name.name);
1305 security_inode_post_mkdir(dir,dentry, mode);
1306 }
1307 return error;
1308@@ -1765,7 +1765,7 @@
1309 }
1310 up(&dentry->d_inode->i_sem);
1311 if (!error) {
1312- inode_dir_notify(dir, DN_DELETE);
1313+ fsnotify_rmdir(dentry, dentry->d_inode, dir);
1314 d_delete(dentry);
1315 }
1316 dput(dentry);
1317@@ -1838,9 +1838,10 @@
1318
1319 /* We don't d_delete() NFS sillyrenamed files--they still exist. */
1320 if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) {
1321+ fsnotify_unlink(dentry, dir);
1322 d_delete(dentry);
1323- inode_dir_notify(dir, DN_DELETE);
1324 }
1325+
1326 return error;
1327 }
1328
1329@@ -1914,7 +1915,7 @@
1330 DQUOT_INIT(dir);
1331 error = dir->i_op->symlink(dir, dentry, oldname);
1332 if (!error) {
1333- inode_dir_notify(dir, DN_CREATE);
1334+ fsnotify_create(dir, dentry->d_name.name);
1335 security_inode_post_symlink(dir, dentry, oldname);
1336 }
1337 return error;
1338@@ -1987,7 +1988,7 @@
1339 error = dir->i_op->link(old_dentry, dir, new_dentry);
1340 up(&old_dentry->d_inode->i_sem);
1341 if (!error) {
1342- inode_dir_notify(dir, DN_CREATE);
1343+ fsnotify_create(dir, new_dentry->d_name.name);
1344 security_inode_post_link(old_dentry, dir, new_dentry);
1345 }
1346 return error;
1347@@ -2151,6 +2152,7 @@
1348 {
1349 int error;
1350 int is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
1351+ char *old_name;
1352
1353 if (old_dentry->d_inode == new_dentry->d_inode)
1354 return 0;
1355@@ -2172,18 +2174,18 @@
1356 DQUOT_INIT(old_dir);
1357 DQUOT_INIT(new_dir);
1358
1359+ old_name = fsnotify_oldname_init(old_dentry);
1360+
1361 if (is_dir)
1362 error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
1363 else
1364 error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
1365 if (!error) {
1366- if (old_dir == new_dir)
1367- inode_dir_notify(old_dir, DN_RENAME);
1368- else {
1369- inode_dir_notify(old_dir, DN_DELETE);
1370- inode_dir_notify(new_dir, DN_CREATE);
1371- }
1372+ const char *new_name = old_dentry->d_name.name;
1373+ fsnotify_move(old_dir, new_dir, old_name, new_name);
1374 }
1375+ fsnotify_oldname_free(old_name);
1376+
1377 return error;
1378 }
1379
1380diff -urN linux-2.6.12-rc2-mm1/fs/open.c linux/fs/open.c
1381--- linux-2.6.12-rc2-mm1/fs/open.c 2005-04-05 12:40:03.000000000 -0400
1382+++ linux/fs/open.c 2005-04-05 12:41:51.000000000 -0400
1383@@ -10,7 +10,7 @@
1384 #include <linux/file.h>
1385 #include <linux/smp_lock.h>
1386 #include <linux/quotaops.h>
1387-#include <linux/dnotify.h>
1388+#include <linux/fsnotify.h>
1389 #include <linux/module.h>
1390 #include <linux/slab.h>
1391 #include <linux/tty.h>
1392@@ -944,9 +944,11 @@
1393 fd = get_unused_fd();
1394 if (fd >= 0) {
1395 struct file *f = filp_open(tmp, flags, mode);
1396+
1397 error = PTR_ERR(f);
1398 if (IS_ERR(f))
1399 goto out_error;
1400+ fsnotify_open(f->f_dentry);
1401 fd_install(fd, f);
1402 }
1403 out:
1404@@ -998,7 +1000,7 @@
1405 retval = err;
1406 }
1407
1408- dnotify_flush(filp, id);
1409+ fsnotify_flush(filp, id);
1410 locks_remove_posix(filp, id);
1411 fput(filp);
1412 return retval;
1413diff -urN linux-2.6.12-rc2-mm1/fs/read_write.c linux/fs/read_write.c
1414--- linux-2.6.12-rc2-mm1/fs/read_write.c 2005-04-05 12:40:03.000000000 -0400
1415+++ linux/fs/read_write.c 2005-04-05 12:41:51.000000000 -0400
1416@@ -10,7 +10,7 @@
1417 #include <linux/file.h>
1418 #include <linux/uio.h>
1419 #include <linux/smp_lock.h>
1420-#include <linux/dnotify.h>
1421+#include <linux/fsnotify.h>
1422 #include <linux/security.h>
1423 #include <linux/module.h>
1424 #include <linux/syscalls.h>
1425@@ -239,7 +239,7 @@
1426 else
1427 ret = do_sync_read(file, buf, count, pos);
1428 if (ret > 0) {
1429- dnotify_parent(file->f_dentry, DN_ACCESS);
1430+ fsnotify_access(file->f_dentry);
1431 current->rchar += ret;
1432 }
1433 current->syscr++;
1434@@ -287,7 +287,7 @@
1435 else
1436 ret = do_sync_write(file, buf, count, pos);
1437 if (ret > 0) {
1438- dnotify_parent(file->f_dentry, DN_MODIFY);
1439+ fsnotify_modify(file->f_dentry);
1440 current->wchar += ret;
1441 }
1442 current->syscw++;
1443@@ -523,9 +523,12 @@
1444 out:
1445 if (iov != iovstack)
1446 kfree(iov);
1447- if ((ret + (type == READ)) > 0)
1448- dnotify_parent(file->f_dentry,
1449- (type == READ) ? DN_ACCESS : DN_MODIFY);
1450+ if ((ret + (type == READ)) > 0) {
1451+ if (type == READ)
1452+ fsnotify_access(file->f_dentry);
1453+ else
1454+ fsnotify_modify(file->f_dentry);
1455+ }
1456 return ret;
1457 Efault:
1458 ret = -EFAULT;
1459diff -urN linux-2.6.12-rc2-mm1/include/linux/fs.h linux/include/linux/fs.h
1460--- linux-2.6.12-rc2-mm1/include/linux/fs.h 2005-04-05 12:40:03.000000000 -0400
1461+++ linux/include/linux/fs.h 2005-04-05 12:41:51.000000000 -0400
1462@@ -472,6 +472,11 @@
1463 struct dnotify_struct *i_dnotify; /* for directory notifications */
1464 #endif
1465
1466+#ifdef CONFIG_INOTIFY
1467+ struct list_head inotify_watches; /* watches on this inode */
1468+ struct semaphore inotify_sem; /* protects the watches list */
1469+#endif
1470+
1471 unsigned long i_state;
1472 unsigned long dirtied_when; /* jiffies of first dirtying */
1473
1474@@ -1387,7 +1392,6 @@
1475 extern int do_remount_sb(struct super_block *sb, int flags,
1476 void *data, int force);
1477 extern sector_t bmap(struct inode *, sector_t);
1478-extern int setattr_mask(unsigned int);
1479 extern int notify_change(struct dentry *, struct iattr *);
1480 extern int permission(struct inode *, int, struct nameidata *);
1481 extern int generic_permission(struct inode *, int,
1482diff -urN linux-2.6.12-rc2-mm1/include/linux/fsnotify.h linux/include/linux/fsnotify.h
1483--- linux-2.6.12-rc2-mm1/include/linux/fsnotify.h 1969-12-31 19:00:00.000000000 -0500
1484+++ linux/include/linux/fsnotify.h 2005-04-05 12:41:51.000000000 -0400
1485@@ -0,0 +1,228 @@
1486+#ifndef _LINUX_FS_NOTIFY_H
1487+#define _LINUX_FS_NOTIFY_H
1488+
1489+/*
1490+ * include/linux/fs_notify.h - generic hooks for filesystem notification, to
1491+ * reduce in-source duplication from both dnotify and inotify.
1492+ *
1493+ * We don't compile any of this away in some complicated menagerie of ifdefs.
1494+ * Instead, we rely on the code inside to optimize away as needed.
1495+ *
1496+ * (C) Copyright 2005 Robert Love
1497+ */
1498+
1499+#ifdef __KERNEL__
1500+
1501+#include <linux/dnotify.h>
1502+#include <linux/inotify.h>
1503+
1504+/*
1505+ * fsnotify_move - file old_name at old_dir was moved to new_name at new_dir
1506+ */
1507+static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
1508+ const char *old_name, const char *new_name)
1509+{
1510+ u32 cookie;
1511+
1512+ if (old_dir == new_dir)
1513+ inode_dir_notify(old_dir, DN_RENAME);
1514+ else {
1515+ inode_dir_notify(old_dir, DN_DELETE);
1516+ inode_dir_notify(new_dir, DN_CREATE);
1517+ }
1518+
1519+ cookie = inotify_get_cookie();
1520+
1521+ inotify_inode_queue_event(old_dir, IN_MOVED_FROM, cookie, old_name);
1522+ inotify_inode_queue_event(new_dir, IN_MOVED_TO, cookie, new_name);
1523+}
1524+
1525+/*
1526+ * fsnotify_unlink - file was unlinked
1527+ */
1528+static inline void fsnotify_unlink(struct dentry *dentry, struct inode *dir)
1529+{
1530+ struct inode *inode = dentry->d_inode;
1531+
1532+ inode_dir_notify(dir, DN_DELETE);
1533+ inotify_inode_queue_event(dir, IN_DELETE_FILE, 0, dentry->d_name.name);
1534+ inotify_inode_queue_event(inode, IN_DELETE_SELF, 0, NULL);
1535+
1536+ inotify_inode_is_dead(inode);
1537+}
1538+
1539+/*
1540+ * fsnotify_rmdir - directory was removed
1541+ */
1542+static inline void fsnotify_rmdir(struct dentry *dentry, struct inode *inode,
1543+ struct inode *dir)
1544+{
1545+ inode_dir_notify(dir, DN_DELETE);
1546+ inotify_inode_queue_event(dir, IN_DELETE_SUBDIR,0,dentry->d_name.name);
1547+ inotify_inode_queue_event(inode, IN_DELETE_SELF, 0, NULL);
1548+
1549+ inotify_inode_is_dead(inode);
1550+}
1551+
1552+/*
1553+ * fsnotify_create - filename was linked in
1554+ */
1555+static inline void fsnotify_create(struct inode *inode, const char *filename)
1556+{
1557+ inode_dir_notify(inode, DN_CREATE);
1558+ inotify_inode_queue_event(inode, IN_CREATE_FILE, 0, filename);
1559+}
1560+
1561+/*
1562+ * fsnotify_mkdir - directory 'name' was created
1563+ */
1564+static inline void fsnotify_mkdir(struct inode *inode, const char *name)
1565+{
1566+ inode_dir_notify(inode, DN_CREATE);
1567+ inotify_inode_queue_event(inode, IN_CREATE_SUBDIR, 0, name);
1568+}
1569+
1570+/*
1571+ * fsnotify_access - file was read
1572+ */
1573+static inline void fsnotify_access(struct dentry *dentry)
1574+{
1575+ dnotify_parent(dentry, DN_ACCESS);
1576+ inotify_dentry_parent_queue_event(dentry, IN_ACCESS, 0,
1577+ dentry->d_name.name);
1578+ inotify_inode_queue_event(dentry->d_inode, IN_ACCESS, 0, NULL);
1579+}
1580+
1581+/*
1582+ * fsnotify_modify - file was modified
1583+ */
1584+static inline void fsnotify_modify(struct dentry *dentry)
1585+{
1586+ dnotify_parent(dentry, DN_MODIFY);
1587+ inotify_dentry_parent_queue_event(dentry, IN_MODIFY, 0,
1588+ dentry->d_name.name);
1589+ inotify_inode_queue_event(dentry->d_inode, IN_MODIFY, 0, NULL);
1590+}
1591+
1592+/*
1593+ * fsnotify_open - file was opened
1594+ */
1595+static inline void fsnotify_open(struct dentry *dentry)
1596+{
1597+ inotify_inode_queue_event(dentry->d_inode, IN_OPEN, 0, NULL);
1598+ inotify_dentry_parent_queue_event(dentry, IN_OPEN, 0,
1599+ dentry->d_name.name);
1600+}
1601+
1602+/*
1603+ * fsnotify_close - file was closed
1604+ */
1605+static inline void fsnotify_close(struct file *file)
1606+{
1607+ struct dentry *dentry = file->f_dentry;
1608+ struct inode *inode = dentry->d_inode;
1609+ const char *filename = dentry->d_name.name;
1610+ mode_t mode = file->f_mode;
1611+ u32 mask;
1612+
1613+ mask = (mode & FMODE_WRITE) ? IN_CLOSE_WRITE : IN_CLOSE_NOWRITE;
1614+ inotify_dentry_parent_queue_event(dentry, mask, 0, filename);
1615+ inotify_inode_queue_event(inode, mask, 0, NULL);
1616+}
1617+
1618+/*
1619+ * fsnotify_change - notify_change event. file was modified and/or metadata
1620+ * was changed.
1621+ */
1622+static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid)
1623+{
1624+ int dn_mask = 0;
1625+ u32 in_mask = 0;
1626+
1627+ if (ia_valid & ATTR_UID) {
1628+ in_mask |= IN_ATTRIB;
1629+ dn_mask |= DN_ATTRIB;
1630+ }
1631+ if (ia_valid & ATTR_GID) {
1632+ in_mask |= IN_ATTRIB;
1633+ dn_mask |= DN_ATTRIB;
1634+ }
1635+ if (ia_valid & ATTR_SIZE) {
1636+ in_mask |= IN_MODIFY;
1637+ dn_mask |= DN_MODIFY;
1638+ }
1639+ /* both times implies a utime(s) call */
1640+ if ((ia_valid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME))
1641+ {
1642+ in_mask |= IN_ATTRIB;
1643+ dn_mask |= DN_ATTRIB;
1644+ } else if (ia_valid & ATTR_ATIME) {
1645+ in_mask |= IN_ACCESS;
1646+ dn_mask |= DN_ACCESS;
1647+ } else if (ia_valid & ATTR_MTIME) {
1648+ in_mask |= IN_MODIFY;
1649+ dn_mask |= DN_MODIFY;
1650+ }
1651+ if (ia_valid & ATTR_MODE) {
1652+ in_mask |= IN_ATTRIB;
1653+ dn_mask |= DN_ATTRIB;
1654+ }
1655+
1656+ if (dn_mask)
1657+ dnotify_parent(dentry, dn_mask);
1658+ if (in_mask) {
1659+ inotify_inode_queue_event(dentry->d_inode, in_mask, 0, NULL);
1660+ inotify_dentry_parent_queue_event(dentry, in_mask, 0,
1661+ dentry->d_name.name);
1662+ }
1663+}
1664+
1665+/*
1666+ * fsnotify_flush - flush time!
1667+ */
1668+static inline void fsnotify_flush(struct file *filp, fl_owner_t id)
1669+{
1670+ dnotify_flush(filp, id);
1671+}
1672+
1673+#ifdef CONFIG_INOTIFY /* inotify helpers */
1674+
1675+/*
1676+ * fsnotify_oldname_init - save off the old filename before we change it
1677+ *
1678+ * this could be kstrdup if only we could add that to lib/string.c
1679+ */
1680+static inline char *fsnotify_oldname_init(struct dentry *old_dentry)
1681+{
1682+ char *old_name;
1683+
1684+ old_name = kmalloc(strlen(old_dentry->d_name.name) + 1, GFP_KERNEL);
1685+ if (old_name)
1686+ strcpy(old_name, old_dentry->d_name.name);
1687+ return old_name;
1688+}
1689+
1690+/*
1691+ * fsnotify_oldname_free - free the name we got from fsnotify_oldname_init
1692+ */
1693+static inline void fsnotify_oldname_free(const char *old_name)
1694+{
1695+ kfree(old_name);
1696+}
1697+
1698+#else /* CONFIG_INOTIFY */
1699+
1700+static inline char *fsnotify_oldname_init(struct dentry *old_dentry)
1701+{
1702+ return NULL;
1703+}
1704+
1705+static inline void fsnotify_oldname_free(const char *old_name)
1706+{
1707+}
1708+
1709+#endif /* ! CONFIG_INOTIFY */
1710+
1711+#endif /* __KERNEL__ */
1712+
1713+#endif /* _LINUX_FS_NOTIFY_H */
1714diff -urN linux-2.6.12-rc2-mm1/include/linux/inotify.h linux/include/linux/inotify.h
1715--- linux-2.6.12-rc2-mm1/include/linux/inotify.h 1969-12-31 19:00:00.000000000 -0500
1716+++ linux/include/linux/inotify.h 2005-04-05 12:41:51.000000000 -0400
1717@@ -0,0 +1,111 @@
1718+/*
1719+ * Inode based directory notification for Linux
1720+ *
1721+ * Copyright (C) 2005 John McCutchan
1722+ */
1723+
1724+#ifndef _LINUX_INOTIFY_H
1725+#define _LINUX_INOTIFY_H
1726+
1727+#include <linux/types.h>
1728+
1729+/*
1730+ * struct inotify_event - structure read from the inotify device for each event
1731+ *
1732+ * When you are watching a directory, you will receive the filename for events
1733+ * such as IN_CREATE, IN_DELETE, IN_OPEN, IN_CLOSE, ..., relative to the wd.
1734+ */
1735+struct inotify_event {
1736+ __s32 wd; /* watch descriptor */
1737+ __u32 mask; /* watch mask */
1738+ __u32 cookie; /* cookie to synchronize two events */
1739+ __u32 len; /* length (including nulls) of name */
1740+ char name[0]; /* stub for possible name */
1741+};
1742+
1743+/*
1744+ * struct inotify_watch_request - represents a watch request
1745+ *
1746+ * Pass to the inotify device via the INOTIFY_WATCH ioctl
1747+ */
1748+struct inotify_watch_request {
1749+ int fd; /* fd of filename to watch */
1750+ __u32 mask; /* event mask */
1751+};
1752+
1753+/* the following are legal, implemented events */
1754+#define IN_ACCESS 0x00000001 /* File was accessed */
1755+#define IN_MODIFY 0x00000002 /* File was modified */
1756+#define IN_ATTRIB 0x00000004 /* File changed attributes */
1757+#define IN_CLOSE_WRITE 0x00000008 /* Writtable file was closed */
1758+#define IN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed */
1759+#define IN_OPEN 0x00000020 /* File was opened */
1760+#define IN_MOVED_FROM 0x00000040 /* File was moved from X */
1761+#define IN_MOVED_TO 0x00000080 /* File was moved to Y */
1762+#define IN_DELETE_SUBDIR 0x00000100 /* Subdir was deleted */
1763+#define IN_DELETE_FILE 0x00000200 /* Subfile was deleted */
1764+#define IN_CREATE_SUBDIR 0x00000400 /* Subdir was created */
1765+#define IN_CREATE_FILE 0x00000800 /* Subfile was created */
1766+#define IN_DELETE_SELF 0x00001000 /* Self was deleted */
1767+#define IN_UNMOUNT 0x00002000 /* Backing fs was unmounted */
1768+#define IN_Q_OVERFLOW 0x00004000 /* Event queued overflowed */
1769+#define IN_IGNORED 0x00008000 /* File was ignored */
1770+
1771+/* special flags */
1772+#define IN_ALL_EVENTS 0xffffffff /* All the events */
1773+#define IN_CLOSE (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)
1774+
1775+#define INOTIFY_IOCTL_MAGIC 'Q'
1776+#define INOTIFY_IOCTL_MAXNR 2
1777+
1778+#define INOTIFY_WATCH _IOR(INOTIFY_IOCTL_MAGIC, 1, struct inotify_watch_request)
1779+#define INOTIFY_IGNORE _IOR(INOTIFY_IOCTL_MAGIC, 2, int)
1780+
1781+#ifdef __KERNEL__
1782+
1783+#include <linux/dcache.h>
1784+#include <linux/fs.h>
1785+#include <linux/config.h>
1786+
1787+#ifdef CONFIG_INOTIFY
1788+
1789+extern void inotify_inode_queue_event(struct inode *, __u32, __u32,
1790+ const char *);
1791+extern void inotify_dentry_parent_queue_event(struct dentry *, __u32, __u32,
1792+ const char *);
1793+extern void inotify_unmount_inodes(struct list_head *);
1794+extern void inotify_inode_is_dead(struct inode *);
1795+extern u32 inotify_get_cookie(void);
1796+
1797+#else
1798+
1799+static inline void inotify_inode_queue_event(struct inode *inode,
1800+ __u32 mask, __u32 cookie,
1801+ const char *filename)
1802+{
1803+}
1804+
1805+static inline void inotify_dentry_parent_queue_event(struct dentry *dentry,
1806+ __u32 mask, __u32 cookie,
1807+ const char *filename)
1808+{
1809+}
1810+
1811+static inline void inotify_unmount_inodes(struct list_head *list)
1812+{
1813+}
1814+
1815+static inline void inotify_inode_is_dead(struct inode *inode)
1816+{
1817+}
1818+
1819+static inline u32 inotify_get_cookie(void)
1820+{
1821+ return 0;
1822+}
1823+
1824+#endif /* CONFIG_INOTIFY */
1825+
1826+#endif /* __KERNEL __ */
1827+
1828+#endif /* _LINUX_INOTIFY_H */
1829diff -urN linux-2.6.12-rc2-mm1/include/linux/sched.h linux/include/linux/sched.h
1830--- linux-2.6.12-rc2-mm1/include/linux/sched.h 2005-04-05 12:40:03.000000000 -0400
1831+++ linux/include/linux/sched.h 2005-04-05 12:41:51.000000000 -0400
1832@@ -426,6 +426,10 @@
1833 atomic_t processes; /* How many processes does this user have? */
1834 atomic_t files; /* How many open files does this user have? */
1835 atomic_t sigpending; /* How many pending signals does this user have? */
1836+#ifdef CONFIG_INOTIFY
1837+ atomic_t inotify_watches; /* How many inotify watches does this user have? */
1838+ atomic_t inotify_devs; /* How many inotify devs does this user have opened? */
1839+#endif
1840 /* protected by mq_lock */
1841 unsigned long mq_bytes; /* How many bytes can be allocated to mqueue? */
1842 unsigned long locked_shm; /* How many pages of mlocked shm ? */
1843diff -urN linux-2.6.12-rc2-mm1/kernel/user.c linux/kernel/user.c
1844--- linux-2.6.12-rc2-mm1/kernel/user.c 2005-04-05 12:40:03.000000000 -0400
1845+++ linux/kernel/user.c 2005-04-05 12:41:51.000000000 -0400
1846@@ -120,6 +120,10 @@
1847 atomic_set(&new->processes, 0);
1848 atomic_set(&new->files, 0);
1849 atomic_set(&new->sigpending, 0);
1850+#ifdef CONFIG_INOTIFY
1851+ atomic_set(&new->inotify_watches, 0);
1852+ atomic_set(&new->inotify_devs, 0);
1853+#endif
1854
1855 new->mq_bytes = 0;
1856 new->locked_shm = 0;
This page took 0.224853 seconds and 4 git commands to generate.