/[linux-patches]/genpatches-2.6/trunk/2.6.12-pre/4800_inotify-0.23-9.patch
Gentoo

Contents of /genpatches-2.6/trunk/2.6.12-pre/4800_inotify-0.23-9.patch

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20