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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.20