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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show annotations) (download)
Sat Jun 18 16:07:34 2005 UTC (13 years ago) by dsd
File size: 59059 byte(s)
inotify 0.23-12
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 @@ -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-17 11:07:19.000000000 -0400
330 @@ -0,0 +1,983 @@
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 inotify 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 +
751 + return watch;
752 +}
753 +
754 +/*
755 + * inotify_find_dev - find the watch associated with the given inode and dev
756 + *
757 + * Callers must hold inode->inotify_sem.
758 + */
759 +static struct inotify_watch *inode_find_dev(struct inode *inode,
760 + struct inotify_device *dev)
761 +{
762 + struct inotify_watch *watch;
763 +
764 + list_for_each_entry(watch, &inode->inotify_watches, i_list) {
765 + if (watch->dev == dev)
766 + return watch;
767 + }
768 +
769 + return NULL;
770 +}
771 +
772 +/*
773 + * remove_watch_no_event - remove_watch() without the IN_IGNORED event.
774 + */
775 +static void remove_watch_no_event(struct inotify_watch *watch,
776 + struct inotify_device *dev)
777 +{
778 + list_del(&watch->i_list);
779 + list_del(&watch->d_list);
780 +
781 + atomic_dec(&dev->user->inotify_watches);
782 + idr_remove(&dev->idr, watch->wd);
783 + put_inotify_watch(watch);
784 +}
785 +
786 +/*
787 + * remove_watch - Remove a watch from both the device and the inode. Sends
788 + * the IN_IGNORED event to the given device signifying that the inode is no
789 + * longer watched.
790 + *
791 + * Callers must hold both inode->inotify_sem and dev->sem. We drop a
792 + * reference to the inode before returning.
793 + *
794 + * The inode is not iput() so as to remain atomic. If the inode needs to be
795 + * iput(), the call returns one. Otherwise, it returns zero.
796 + */
797 +static void remove_watch(struct inotify_watch *watch,struct inotify_device *dev)
798 +{
799 + inotify_dev_queue_event(dev, watch, IN_IGNORED, 0, NULL);
800 + remove_watch_no_event(watch, dev);
801 +}
802 +
803 +/*
804 + * inotify_inode_watched - returns nonzero if there are watches on this inode
805 + * and zero otherwise. We call this lockless, we do not care if we race.
806 + */
807 +static inline int inotify_inode_watched(struct inode *inode)
808 +{
809 + return !list_empty(&inode->inotify_watches);
810 +}
811 +
812 +/* Kernel API */
813 +
814 +/**
815 + * inotify_inode_queue_event - queue an event to all watches on this inode
816 + * @inode: inode event is originating from
817 + * @mask: event mask describing this event
818 + * @cookie: cookie for synchronization, or zero
819 + * @name: filename, if any
820 + */
821 +void inotify_inode_queue_event(struct inode *inode, u32 mask, u32 cookie,
822 + const char *name)
823 +{
824 + struct inotify_watch *watch, *next;
825 +
826 + if (!inotify_inode_watched(inode))
827 + return;
828 +
829 + down(&inode->inotify_sem);
830 + list_for_each_entry_safe(watch, next, &inode->inotify_watches, i_list) {
831 + u32 watch_mask = watch->mask;
832 + if (watch_mask & mask) {
833 + struct inotify_device *dev = watch->dev;
834 + get_inotify_watch(watch);
835 + down(&dev->sem);
836 + inotify_dev_queue_event(dev, watch, mask, cookie, name);
837 + if (watch_mask & IN_ONESHOT)
838 + remove_watch_no_event(watch, dev);
839 + up(&dev->sem);
840 + put_inotify_watch(watch);
841 + }
842 + }
843 + up(&inode->inotify_sem);
844 +}
845 +EXPORT_SYMBOL_GPL(inotify_inode_queue_event);
846 +
847 +/**
848 + * inotify_dentry_parent_queue_event - queue an event to a dentry's parent
849 + * @dentry: the dentry in question, we queue against this dentry's parent
850 + * @mask: event mask describing this event
851 + * @cookie: cookie for synchronization, or zero
852 + * @name: filename, if any
853 + */
854 +void inotify_dentry_parent_queue_event(struct dentry *dentry, u32 mask,
855 + u32 cookie, const char *name)
856 +{
857 + struct dentry *parent;
858 + struct inode *inode;
859 +
860 + spin_lock(&dentry->d_lock);
861 + parent = dentry->d_parent;
862 + inode = parent->d_inode;
863 +
864 + if (inotify_inode_watched(inode)) {
865 + dget(parent);
866 + spin_unlock(&dentry->d_lock);
867 + inotify_inode_queue_event(inode, mask, cookie, name);
868 + dput(parent);
869 + } else
870 + spin_unlock(&dentry->d_lock);
871 +}
872 +EXPORT_SYMBOL_GPL(inotify_dentry_parent_queue_event);
873 +
874 +/**
875 + * inotify_get_cookie - return a unique cookie for use in synchronizing events.
876 + */
877 +u32 inotify_get_cookie(void)
878 +{
879 + return atomic_inc_return(&inotify_cookie);
880 +}
881 +EXPORT_SYMBOL_GPL(inotify_get_cookie);
882 +
883 +/**
884 + * inotify_unmount_inodes - an sb is unmounting. handle any watched inodes.
885 + * @list: list of inodes being unmounted (sb->s_inodes)
886 + *
887 + * Called with inode_lock held, protecting the unmounting super block's list
888 + * of inodes, and with iprune_sem held, keeping shrink_icache_memory() at bay.
889 + * We temporarily drop inode_lock, however, and CAN block.
890 + */
891 +void inotify_unmount_inodes(struct list_head *list)
892 +{
893 + struct inode *inode, *next_i;
894 +
895 + list_for_each_entry_safe(inode, next_i, list, i_sb_list) {
896 + struct inotify_watch *watch, *next_w;
897 + struct list_head *watches;
898 +
899 + /*
900 + * We cannot __iget() an inode in state I_CLEAR, which is fine
901 + * as by that point the inode cannot have any watches.
902 + */
903 + if (inode->i_state & I_CLEAR)
904 + continue;
905 +
906 + /* In case the remove_watch() drops a reference */
907 + __iget(inode);
908 +
909 + /*
910 + * We can safely drop inode_lock here because the per-sb list
911 + * of inodes must not change during unmount and iprune_sem
912 + * keeps shrink_icache_memory() away.
913 + */
914 + spin_unlock(&inode_lock);
915 +
916 + /* for each watch, send IN_UNMOUNT and then remove it */
917 + down(&inode->inotify_sem);
918 + watches = &inode->inotify_watches;
919 + list_for_each_entry_safe(watch, next_w, watches, i_list) {
920 + struct inotify_device *dev = watch->dev;
921 + down(&dev->sem);
922 + inotify_dev_queue_event(dev, watch, IN_UNMOUNT,0,NULL);
923 + remove_watch(watch, dev);
924 + up(&dev->sem);
925 + }
926 + up(&inode->inotify_sem);
927 + iput(inode);
928 +
929 + spin_lock(&inode_lock);
930 + }
931 +}
932 +EXPORT_SYMBOL_GPL(inotify_unmount_inodes);
933 +
934 +/**
935 + * inotify_inode_is_dead - an inode has been deleted, cleanup any watches
936 + * @inode: inode that is about to be removed
937 + */
938 +void inotify_inode_is_dead(struct inode *inode)
939 +{
940 + struct inotify_watch *watch, *next;
941 +
942 + down(&inode->inotify_sem);
943 + list_for_each_entry_safe(watch, next, &inode->inotify_watches, i_list) {
944 + struct inotify_device *dev = watch->dev;
945 + down(&dev->sem);
946 + remove_watch(watch, dev);
947 + up(&dev->sem);
948 + }
949 + up(&inode->inotify_sem);
950 +}
951 +EXPORT_SYMBOL_GPL(inotify_inode_is_dead);
952 +
953 +/* Device Interface */
954 +
955 +static unsigned int inotify_poll(struct file *file, poll_table *wait)
956 +{
957 + struct inotify_device *dev = file->private_data;
958 + int ret = 0;
959 +
960 + poll_wait(file, &dev->wq, wait);
961 + down(&dev->sem);
962 + if (!list_empty(&dev->events))
963 + ret = POLLIN | POLLRDNORM;
964 + up(&dev->sem);
965 +
966 + return ret;
967 +}
968 +
969 +static ssize_t inotify_read(struct file *file, char __user *buf,
970 + size_t count, loff_t *pos)
971 +{
972 + size_t event_size = sizeof (struct inotify_event);
973 + struct inotify_device *dev;
974 + char __user *start;
975 + int ret;
976 + DEFINE_WAIT(wait);
977 +
978 + start = buf;
979 + dev = file->private_data;
980 +
981 + while (1) {
982 + int events;
983 +
984 + prepare_to_wait(&dev->wq, &wait, TASK_INTERRUPTIBLE);
985 +
986 + down(&dev->sem);
987 + events = !list_empty(&dev->events);
988 + up(&dev->sem);
989 + if (events) {
990 + ret = 0;
991 + break;
992 + }
993 +
994 + if (file->f_flags & O_NONBLOCK) {
995 + ret = -EAGAIN;
996 + break;
997 + }
998 +
999 + if (signal_pending(current)) {
1000 + ret = -EINTR;
1001 + break;
1002 + }
1003 +
1004 + schedule();
1005 + }
1006 +
1007 + finish_wait(&dev->wq, &wait);
1008 + if (ret)
1009 + return ret;
1010 +
1011 + down(&dev->sem);
1012 + while (1) {
1013 + struct inotify_kernel_event *kevent;
1014 +
1015 + ret = buf - start;
1016 + if (list_empty(&dev->events))
1017 + break;
1018 +
1019 + kevent = inotify_dev_get_event(dev);
1020 + if (event_size + kevent->event.len > count)
1021 + break;
1022 +
1023 + if (copy_to_user(buf, &kevent->event, event_size)) {
1024 + ret = -EFAULT;
1025 + break;
1026 + }
1027 + buf += event_size;
1028 + count -= event_size;
1029 +
1030 + if (kevent->name) {
1031 + if (copy_to_user(buf, kevent->name, kevent->event.len)){
1032 + ret = -EFAULT;
1033 + break;
1034 + }
1035 + buf += kevent->event.len;
1036 + count -= kevent->event.len;
1037 + }
1038 +
1039 + remove_kevent(dev, kevent);
1040 + }
1041 + up(&dev->sem);
1042 +
1043 + return ret;
1044 +}
1045 +
1046 +static int inotify_open(struct inode *inode, struct file *file)
1047 +{
1048 + struct inotify_device *dev;
1049 + struct user_struct *user;
1050 + int ret;
1051 +
1052 + user = get_uid(current->user);
1053 +
1054 + if (unlikely(atomic_read(&user->inotify_devs) >= max_user_devices)) {
1055 + ret = -EMFILE;
1056 + goto out_err;
1057 + }
1058 +
1059 + dev = kmalloc(sizeof(struct inotify_device), GFP_KERNEL);
1060 + if (unlikely(!dev)) {
1061 + ret = -ENOMEM;
1062 + goto out_err;
1063 + }
1064 +
1065 + idr_init(&dev->idr);
1066 + INIT_LIST_HEAD(&dev->events);
1067 + INIT_LIST_HEAD(&dev->watches);
1068 + init_waitqueue_head(&dev->wq);
1069 + sema_init(&dev->sem, 1);
1070 + dev->event_count = 0;
1071 + dev->queue_size = 0;
1072 + dev->max_events = max_queued_events;
1073 + dev->user = user;
1074 + atomic_set(&dev->count, 0);
1075 +
1076 + get_inotify_dev(dev);
1077 + atomic_inc(&user->inotify_devs);
1078 +
1079 + file->private_data = dev;
1080 +
1081 + ret = nonseekable_open(inode, file);
1082 + if (ret)
1083 + goto out_err;
1084 +
1085 + return 0;
1086 +out_err:
1087 + free_uid(user);
1088 + return ret;
1089 +}
1090 +
1091 +static int inotify_release(struct inode *ignored, struct file *file)
1092 +{
1093 + struct inotify_device *dev = file->private_data;
1094 +
1095 + /*
1096 + * Destroy all of the watches on this device. Unfortunately, not very
1097 + * pretty. We cannot do a simple iteration over the list, because we
1098 + * do not know the inode until we iterate to the watch. But we need to
1099 + * hold inode->inotify_sem before dev->sem. The following works.
1100 + */
1101 + while (1) {
1102 + struct inotify_watch *watch;
1103 + struct list_head *watches;
1104 + struct inode *inode;
1105 +
1106 + down(&dev->sem);
1107 + watches = &dev->watches;
1108 + if (list_empty(watches)) {
1109 + up(&dev->sem);
1110 + break;
1111 + }
1112 + watch = list_entry(watches->next, struct inotify_watch, d_list);
1113 + get_inotify_watch(watch);
1114 + up(&dev->sem);
1115 +
1116 + inode = watch->inode;
1117 + down(&inode->inotify_sem);
1118 + down(&dev->sem);
1119 + remove_watch_no_event(watch, dev);
1120 + up(&dev->sem);
1121 + up(&inode->inotify_sem);
1122 + put_inotify_watch(watch);
1123 + }
1124 +
1125 + /* destroy all of the events on this device */
1126 + down(&dev->sem);
1127 + while (!list_empty(&dev->events))
1128 + inotify_dev_event_dequeue(dev);
1129 + up(&dev->sem);
1130 +
1131 + /* free this device: the put matching the get in inotify_open() */
1132 + put_inotify_dev(dev);
1133 +
1134 + return 0;
1135 +}
1136 +
1137 +static int inotify_add_watch(struct inotify_device *dev, int fd, u32 mask)
1138 +{
1139 + struct inotify_watch *watch, *old;
1140 + struct inode *inode;
1141 + struct file *filp;
1142 + int ret;
1143 +
1144 + filp = fget(fd);
1145 + if (!filp)
1146 + return -EBADF;
1147 + inode = filp->f_dentry->d_inode;
1148 +
1149 + down(&inode->inotify_sem);
1150 + down(&dev->sem);
1151 +
1152 + /* don't let user-space set invalid bits: we don't want flags set */
1153 + mask &= IN_ALL_EVENTS;
1154 + if (!mask) {
1155 + ret = -EINVAL;
1156 + goto out;
1157 + }
1158 +
1159 + /*
1160 + * Handle the case of re-adding a watch on an (inode,dev) pair that we
1161 + * are already watching. We just update the mask and return its wd.
1162 + */
1163 + old = inode_find_dev(inode, dev);
1164 + if (unlikely(old)) {
1165 + old->mask = mask;
1166 + ret = old->wd;
1167 + goto out;
1168 + }
1169 +
1170 + watch = create_watch(dev, mask, inode);
1171 + if (unlikely(IS_ERR(watch))) {
1172 + ret = PTR_ERR(watch);
1173 + goto out;
1174 + }
1175 +
1176 + /* Add the watch to the device's and the inode's list */
1177 + list_add(&watch->d_list, &dev->watches);
1178 + list_add(&watch->i_list, &inode->inotify_watches);
1179 + ret = watch->wd;
1180 +
1181 +out:
1182 + up(&dev->sem);
1183 + up(&inode->inotify_sem);
1184 + fput(filp);
1185 +
1186 + return ret;
1187 +}
1188 +
1189 +/*
1190 + * inotify_ignore - handle the INOTIFY_IGNORE ioctl, asking that a given wd be
1191 + * removed from the device.
1192 + *
1193 + * Can sleep.
1194 + */
1195 +static int inotify_ignore(struct inotify_device *dev, s32 wd)
1196 +{
1197 + struct inotify_watch *watch;
1198 + struct inode *inode;
1199 +
1200 + down(&dev->sem);
1201 + watch = idr_find(&dev->idr, wd);
1202 + if (unlikely(!watch)) {
1203 + up(&dev->sem);
1204 + return -EINVAL;
1205 + }
1206 + get_inotify_watch(watch);
1207 + inode = watch->inode;
1208 + up(&dev->sem);
1209 +
1210 + down(&inode->inotify_sem);
1211 + down(&dev->sem);
1212 +
1213 + /* make sure that we did not race */
1214 + watch = idr_find(&dev->idr, wd);
1215 + if (likely(watch))
1216 + remove_watch(watch, dev);
1217 +
1218 + up(&dev->sem);
1219 + up(&inode->inotify_sem);
1220 + put_inotify_watch(watch);
1221 +
1222 + return 0;
1223 +}
1224 +
1225 +static long inotify_ioctl(struct file *file, unsigned int cmd,
1226 + unsigned long arg)
1227 +{
1228 + struct inotify_device *dev;
1229 + struct inotify_watch_request request;
1230 + void __user *p;
1231 + int ret = -ENOTTY;
1232 + s32 wd;
1233 +
1234 + dev = file->private_data;
1235 + p = (void __user *) arg;
1236 +
1237 + switch (cmd) {
1238 + case INOTIFY_WATCH:
1239 + if (unlikely(copy_from_user(&request, p, sizeof (request)))) {
1240 + ret = -EFAULT;
1241 + break;
1242 + }
1243 + ret = inotify_add_watch(dev, request.fd, request.mask);
1244 + break;
1245 + case INOTIFY_IGNORE:
1246 + if (unlikely(get_user(wd, (int __user *) p))) {
1247 + ret = -EFAULT;
1248 + break;
1249 + }
1250 + ret = inotify_ignore(dev, wd);
1251 + break;
1252 + case FIONREAD:
1253 + ret = put_user(dev->queue_size, (int __user *) p);
1254 + break;
1255 + }
1256 +
1257 + return ret;
1258 +}
1259 +
1260 +static struct file_operations inotify_fops = {
1261 + .owner = THIS_MODULE,
1262 + .poll = inotify_poll,
1263 + .read = inotify_read,
1264 + .open = inotify_open,
1265 + .release = inotify_release,
1266 + .unlocked_ioctl = inotify_ioctl,
1267 + .compat_ioctl = inotify_ioctl,
1268 +};
1269 +
1270 +static struct miscdevice inotify_device = {
1271 + .minor = MISC_DYNAMIC_MINOR,
1272 + .name = "inotify",
1273 + .fops = &inotify_fops,
1274 +};
1275 +
1276 +/*
1277 + * inotify_init - Our initialization function. Note that we cannnot return
1278 + * error because we have compiled-in VFS hooks. So an (unlikely) failure here
1279 + * must result in panic().
1280 + */
1281 +static int __init inotify_init(void)
1282 +{
1283 + struct class_device *class;
1284 + int ret;
1285 +
1286 + ret = misc_register(&inotify_device);
1287 + if (unlikely(ret))
1288 + panic("inotify: misc_register returned %d\n", ret);
1289 +
1290 + max_queued_events = 8192;
1291 + max_user_devices = 128;
1292 + max_user_watches = 8192;
1293 +
1294 + class = inotify_device.class;
1295 + class_device_create_file(class, &class_device_attr_max_queued_events);
1296 + class_device_create_file(class, &class_device_attr_max_user_devices);
1297 + class_device_create_file(class, &class_device_attr_max_user_watches);
1298 +
1299 + atomic_set(&inotify_cookie, 0);
1300 +
1301 + watch_cachep = kmem_cache_create("inotify_watch_cache",
1302 + sizeof(struct inotify_watch),
1303 + 0, SLAB_PANIC, NULL, NULL);
1304 + event_cachep = kmem_cache_create("inotify_event_cache",
1305 + sizeof(struct inotify_kernel_event),
1306 + 0, SLAB_PANIC, NULL, NULL);
1307 +
1308 + printk(KERN_INFO "inotify device minor=%d\n", inotify_device.minor);
1309 +
1310 + return 0;
1311 +}
1312 +
1313 +module_init(inotify_init);
1314 diff -urN linux-2.6.12-rc6/fs/Kconfig linux/fs/Kconfig
1315 --- linux-2.6.12-rc6/fs/Kconfig 2005-06-07 15:47:52.000000000 -0400
1316 +++ linux/fs/Kconfig 2005-06-13 11:28:04.000000000 -0400
1317 @@ -339,6 +339,19 @@
1318 If you don't know whether you need it, then you don't need it:
1319 answer N.
1320
1321 +config INOTIFY
1322 + bool "Inotify file change notification support"
1323 + default y
1324 + ---help---
1325 + Say Y here to enable inotify support and the /dev/inotify character
1326 + device. Inotify is a file change notification system and a
1327 + replacement for dnotify. Inotify fixes numerous shortcomings in
1328 + dnotify and introduces several new features. It allows monitoring
1329 + of both files and directories via a single open fd. Multiple file
1330 + events are supported.
1331 +
1332 + If unsure, say Y.
1333 +
1334 config QUOTA
1335 bool "Quota support"
1336 help
1337 diff -urN linux-2.6.12-rc6/fs/Makefile linux/fs/Makefile
1338 --- linux-2.6.12-rc6/fs/Makefile 2005-03-02 02:38:10.000000000 -0500
1339 +++ linux/fs/Makefile 2005-06-13 11:28:04.000000000 -0400
1340 @@ -11,6 +11,7 @@
1341 attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \
1342 seq_file.o xattr.o libfs.o fs-writeback.o mpage.o direct-io.o \
1343
1344 +obj-$(CONFIG_INOTIFY) += inotify.o
1345 obj-$(CONFIG_EPOLL) += eventpoll.o
1346 obj-$(CONFIG_COMPAT) += compat.o
1347
1348 diff -urN linux-2.6.12-rc6/fs/namei.c linux/fs/namei.c
1349 --- linux-2.6.12-rc6/fs/namei.c 2005-06-07 15:47:52.000000000 -0400
1350 +++ linux/fs/namei.c 2005-06-13 11:28:04.000000000 -0400
1351 @@ -21,7 +21,7 @@
1352 #include <linux/namei.h>
1353 #include <linux/quotaops.h>
1354 #include <linux/pagemap.h>
1355 -#include <linux/dnotify.h>
1356 +#include <linux/fsnotify.h>
1357 #include <linux/smp_lock.h>
1358 #include <linux/personality.h>
1359 #include <linux/security.h>
1360 @@ -1296,7 +1296,7 @@
1361 DQUOT_INIT(dir);
1362 error = dir->i_op->create(dir, dentry, mode, nd);
1363 if (!error) {
1364 - inode_dir_notify(dir, DN_CREATE);
1365 + fsnotify_create(dir, dentry->d_name.name);
1366 security_inode_post_create(dir, dentry, mode);
1367 }
1368 return error;
1369 @@ -1602,7 +1602,7 @@
1370 DQUOT_INIT(dir);
1371 error = dir->i_op->mknod(dir, dentry, mode, dev);
1372 if (!error) {
1373 - inode_dir_notify(dir, DN_CREATE);
1374 + fsnotify_create(dir, dentry->d_name.name);
1375 security_inode_post_mknod(dir, dentry, mode, dev);
1376 }
1377 return error;
1378 @@ -1675,7 +1675,7 @@
1379 DQUOT_INIT(dir);
1380 error = dir->i_op->mkdir(dir, dentry, mode);
1381 if (!error) {
1382 - inode_dir_notify(dir, DN_CREATE);
1383 + fsnotify_mkdir(dir, dentry->d_name.name);
1384 security_inode_post_mkdir(dir,dentry, mode);
1385 }
1386 return error;
1387 @@ -1766,7 +1766,7 @@
1388 }
1389 up(&dentry->d_inode->i_sem);
1390 if (!error) {
1391 - inode_dir_notify(dir, DN_DELETE);
1392 + fsnotify_rmdir(dentry, dentry->d_inode, dir);
1393 d_delete(dentry);
1394 }
1395 dput(dentry);
1396 @@ -1839,9 +1839,10 @@
1397
1398 /* We don't d_delete() NFS sillyrenamed files--they still exist. */
1399 if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) {
1400 + fsnotify_unlink(dentry, dir);
1401 d_delete(dentry);
1402 - inode_dir_notify(dir, DN_DELETE);
1403 }
1404 +
1405 return error;
1406 }
1407
1408 @@ -1915,7 +1916,7 @@
1409 DQUOT_INIT(dir);
1410 error = dir->i_op->symlink(dir, dentry, oldname);
1411 if (!error) {
1412 - inode_dir_notify(dir, DN_CREATE);
1413 + fsnotify_create(dir, dentry->d_name.name);
1414 security_inode_post_symlink(dir, dentry, oldname);
1415 }
1416 return error;
1417 @@ -1988,7 +1989,7 @@
1418 error = dir->i_op->link(old_dentry, dir, new_dentry);
1419 up(&old_dentry->d_inode->i_sem);
1420 if (!error) {
1421 - inode_dir_notify(dir, DN_CREATE);
1422 + fsnotify_create(dir, new_dentry->d_name.name);
1423 security_inode_post_link(old_dentry, dir, new_dentry);
1424 }
1425 return error;
1426 @@ -2152,6 +2153,7 @@
1427 {
1428 int error;
1429 int is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
1430 + const char *old_name;
1431
1432 if (old_dentry->d_inode == new_dentry->d_inode)
1433 return 0;
1434 @@ -2173,18 +2175,18 @@
1435 DQUOT_INIT(old_dir);
1436 DQUOT_INIT(new_dir);
1437
1438 + old_name = fsnotify_oldname_init(old_dentry->d_name.name);
1439 +
1440 if (is_dir)
1441 error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
1442 else
1443 error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
1444 if (!error) {
1445 - if (old_dir == new_dir)
1446 - inode_dir_notify(old_dir, DN_RENAME);
1447 - else {
1448 - inode_dir_notify(old_dir, DN_DELETE);
1449 - inode_dir_notify(new_dir, DN_CREATE);
1450 - }
1451 + const char *new_name = old_dentry->d_name.name;
1452 + fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir);
1453 }
1454 + fsnotify_oldname_free(old_name);
1455 +
1456 return error;
1457 }
1458
1459 diff -urN linux-2.6.12-rc6/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c
1460 --- linux-2.6.12-rc6/fs/nfsd/vfs.c 2005-06-07 15:47:52.000000000 -0400
1461 +++ linux/fs/nfsd/vfs.c 2005-06-13 11:28:04.000000000 -0400
1462 @@ -45,7 +45,7 @@
1463 #endif /* CONFIG_NFSD_V3 */
1464 #include <linux/nfsd/nfsfh.h>
1465 #include <linux/quotaops.h>
1466 -#include <linux/dnotify.h>
1467 +#include <linux/fsnotify.h>
1468 #ifdef CONFIG_NFSD_V4
1469 #include <linux/posix_acl.h>
1470 #include <linux/posix_acl_xattr.h>
1471 @@ -861,7 +861,7 @@
1472 nfsdstats.io_read += err;
1473 *count = err;
1474 err = 0;
1475 - dnotify_parent(file->f_dentry, DN_ACCESS);
1476 + fsnotify_access(file->f_dentry);
1477 } else
1478 err = nfserrno(err);
1479 out:
1480 @@ -917,7 +917,7 @@
1481 set_fs(oldfs);
1482 if (err >= 0) {
1483 nfsdstats.io_write += cnt;
1484 - dnotify_parent(file->f_dentry, DN_MODIFY);
1485 + fsnotify_modify(file->f_dentry);
1486 }
1487
1488 /* clear setuid/setgid flag after write */
1489 diff -urN linux-2.6.12-rc6/fs/open.c linux/fs/open.c
1490 --- linux-2.6.12-rc6/fs/open.c 2005-03-02 02:37:47.000000000 -0500
1491 +++ linux/fs/open.c 2005-06-13 11:28:04.000000000 -0400
1492 @@ -10,7 +10,7 @@
1493 #include <linux/file.h>
1494 #include <linux/smp_lock.h>
1495 #include <linux/quotaops.h>
1496 -#include <linux/dnotify.h>
1497 +#include <linux/fsnotify.h>
1498 #include <linux/module.h>
1499 #include <linux/slab.h>
1500 #include <linux/tty.h>
1501 @@ -944,9 +944,11 @@
1502 fd = get_unused_fd();
1503 if (fd >= 0) {
1504 struct file *f = filp_open(tmp, flags, mode);
1505 +
1506 error = PTR_ERR(f);
1507 if (IS_ERR(f))
1508 goto out_error;
1509 + fsnotify_open(f->f_dentry);
1510 fd_install(fd, f);
1511 }
1512 out:
1513 diff -urN linux-2.6.12-rc6/fs/read_write.c linux/fs/read_write.c
1514 --- linux-2.6.12-rc6/fs/read_write.c 2005-06-07 15:47:52.000000000 -0400
1515 +++ linux/fs/read_write.c 2005-06-13 11:28:04.000000000 -0400
1516 @@ -10,7 +10,7 @@
1517 #include <linux/file.h>
1518 #include <linux/uio.h>
1519 #include <linux/smp_lock.h>
1520 -#include <linux/dnotify.h>
1521 +#include <linux/fsnotify.h>
1522 #include <linux/security.h>
1523 #include <linux/module.h>
1524 #include <linux/syscalls.h>
1525 @@ -239,7 +239,7 @@
1526 else
1527 ret = do_sync_read(file, buf, count, pos);
1528 if (ret > 0) {
1529 - dnotify_parent(file->f_dentry, DN_ACCESS);
1530 + fsnotify_access(file->f_dentry);
1531 current->rchar += ret;
1532 }
1533 current->syscr++;
1534 @@ -287,7 +287,7 @@
1535 else
1536 ret = do_sync_write(file, buf, count, pos);
1537 if (ret > 0) {
1538 - dnotify_parent(file->f_dentry, DN_MODIFY);
1539 + fsnotify_modify(file->f_dentry);
1540 current->wchar += ret;
1541 }
1542 current->syscw++;
1543 @@ -523,9 +523,12 @@
1544 out:
1545 if (iov != iovstack)
1546 kfree(iov);
1547 - if ((ret + (type == READ)) > 0)
1548 - dnotify_parent(file->f_dentry,
1549 - (type == READ) ? DN_ACCESS : DN_MODIFY);
1550 + if ((ret + (type == READ)) > 0) {
1551 + if (type == READ)
1552 + fsnotify_access(file->f_dentry);
1553 + else
1554 + fsnotify_modify(file->f_dentry);
1555 + }
1556 return ret;
1557 Efault:
1558 ret = -EFAULT;
1559 diff -urN linux-2.6.12-rc6/fs/sysfs/file.c linux/fs/sysfs/file.c
1560 --- linux-2.6.12-rc6/fs/sysfs/file.c 2005-06-07 15:47:52.000000000 -0400
1561 +++ linux/fs/sysfs/file.c 2005-06-13 11:28:04.000000000 -0400
1562 @@ -3,7 +3,7 @@
1563 */
1564
1565 #include <linux/module.h>
1566 -#include <linux/dnotify.h>
1567 +#include <linux/fsnotify.h>
1568 #include <linux/kobject.h>
1569 #include <asm/uaccess.h>
1570 #include <asm/semaphore.h>
1571 @@ -389,9 +389,6 @@
1572 * sysfs_update_file - update the modified timestamp on an object attribute.
1573 * @kobj: object we're acting for.
1574 * @attr: attribute descriptor.
1575 - *
1576 - * Also call dnotify for the dentry, which lots of userspace programs
1577 - * use.
1578 */
1579 int sysfs_update_file(struct kobject * kobj, const struct attribute * attr)
1580 {
1581 @@ -406,7 +403,7 @@
1582 if (victim->d_inode &&
1583 (victim->d_parent->d_inode == dir->d_inode)) {
1584 victim->d_inode->i_mtime = CURRENT_TIME;
1585 - dnotify_parent(victim, DN_MODIFY);
1586 + fsnotify_modify(victim);
1587
1588 /**
1589 * Drop reference from initial sysfs_get_dentry().
1590 diff -urN linux-2.6.12-rc6/fs/xattr.c linux/fs/xattr.c
1591 --- linux-2.6.12-rc6/fs/xattr.c 2005-03-02 02:38:07.000000000 -0500
1592 +++ linux/fs/xattr.c 2005-06-13 11:28:04.000000000 -0400
1593 @@ -16,6 +16,7 @@
1594 #include <linux/security.h>
1595 #include <linux/syscalls.h>
1596 #include <linux/module.h>
1597 +#include <linux/fsnotify.h>
1598 #include <asm/uaccess.h>
1599
1600 /*
1601 @@ -57,8 +58,10 @@
1602 if (error)
1603 goto out;
1604 error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags);
1605 - if (!error)
1606 + if (!error) {
1607 + fsnotify_xattr(d);
1608 security_inode_post_setxattr(d, kname, kvalue, size, flags);
1609 + }
1610 out:
1611 up(&d->d_inode->i_sem);
1612 }
1613 diff -urN linux-2.6.12-rc6/include/linux/fs.h linux/include/linux/fs.h
1614 --- linux-2.6.12-rc6/include/linux/fs.h 2005-06-07 15:47:53.000000000 -0400
1615 +++ linux/include/linux/fs.h 2005-06-17 11:01:37.000000000 -0400
1616 @@ -471,6 +471,11 @@
1617 struct dnotify_struct *i_dnotify; /* for directory notifications */
1618 #endif
1619
1620 +#ifdef CONFIG_INOTIFY
1621 + struct list_head inotify_watches; /* watches on this inode */
1622 + struct semaphore inotify_sem; /* protects the watches list */
1623 +#endif
1624 +
1625 unsigned long i_state;
1626 unsigned long dirtied_when; /* jiffies of first dirtying */
1627
1628 @@ -1369,7 +1374,6 @@
1629 extern int do_remount_sb(struct super_block *sb, int flags,
1630 void *data, int force);
1631 extern sector_t bmap(struct inode *, sector_t);
1632 -extern int setattr_mask(unsigned int);
1633 extern int notify_change(struct dentry *, struct iattr *);
1634 extern int permission(struct inode *, int, struct nameidata *);
1635 extern int generic_permission(struct inode *, int,
1636 diff -urN linux-2.6.12-rc6/include/linux/fsnotify.h linux/include/linux/fsnotify.h
1637 --- linux-2.6.12-rc6/include/linux/fsnotify.h 1969-12-31 19:00:00.000000000 -0500
1638 +++ linux/include/linux/fsnotify.h 2005-06-13 11:28:04.000000000 -0400
1639 @@ -0,0 +1,257 @@
1640 +#ifndef _LINUX_FS_NOTIFY_H
1641 +#define _LINUX_FS_NOTIFY_H
1642 +
1643 +/*
1644 + * include/linux/fsnotify.h - generic hooks for filesystem notification, to
1645 + * reduce in-source duplication from both dnotify and inotify.
1646 + *
1647 + * We don't compile any of this away in some complicated menagerie of ifdefs.
1648 + * Instead, we rely on the code inside to optimize away as needed.
1649 + *
1650 + * (C) Copyright 2005 Robert Love
1651 + */
1652 +
1653 +#ifdef __KERNEL__
1654 +
1655 +#include <linux/dnotify.h>
1656 +#include <linux/inotify.h>
1657 +
1658 +/*
1659 + * fsnotify_move - file old_name at old_dir was moved to new_name at new_dir
1660 + */
1661 +static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
1662 + const char *old_name, const char *new_name,
1663 + int isdir)
1664 +{
1665 + u32 cookie = inotify_get_cookie();
1666 +
1667 + if (old_dir == new_dir)
1668 + inode_dir_notify(old_dir, DN_RENAME);
1669 + else {
1670 + inode_dir_notify(old_dir, DN_DELETE);
1671 + inode_dir_notify(new_dir, DN_CREATE);
1672 + }
1673 +
1674 + if (isdir)
1675 + isdir = IN_ISDIR;
1676 + inotify_inode_queue_event(old_dir, IN_MOVED_FROM|isdir,cookie,old_name);
1677 + inotify_inode_queue_event(new_dir, IN_MOVED_TO|isdir, cookie, new_name);
1678 +}
1679 +
1680 +/*
1681 + * fsnotify_unlink - file was unlinked
1682 + */
1683 +static inline void fsnotify_unlink(struct dentry *dentry, struct inode *dir)
1684 +{
1685 + struct inode *inode = dentry->d_inode;
1686 +
1687 + inode_dir_notify(dir, DN_DELETE);
1688 + inotify_inode_queue_event(dir, IN_DELETE, 0, dentry->d_name.name);
1689 + inotify_inode_queue_event(inode, IN_DELETE_SELF, 0, NULL);
1690 +
1691 + inotify_inode_is_dead(inode);
1692 +}
1693 +
1694 +/*
1695 + * fsnotify_rmdir - directory was removed
1696 + */
1697 +static inline void fsnotify_rmdir(struct dentry *dentry, struct inode *inode,
1698 + struct inode *dir)
1699 +{
1700 + inode_dir_notify(dir, DN_DELETE);
1701 + inotify_inode_queue_event(dir,IN_DELETE|IN_ISDIR,0,dentry->d_name.name);
1702 + inotify_inode_queue_event(inode, IN_DELETE_SELF | IN_ISDIR, 0, NULL);
1703 + inotify_inode_is_dead(inode);
1704 +}
1705 +
1706 +/*
1707 + * fsnotify_create - 'name' was linked in
1708 + */
1709 +static inline void fsnotify_create(struct inode *inode, const char *name)
1710 +{
1711 + inode_dir_notify(inode, DN_CREATE);
1712 + inotify_inode_queue_event(inode, IN_CREATE, 0, name);
1713 +}
1714 +
1715 +/*
1716 + * fsnotify_mkdir - directory 'name' was created
1717 + */
1718 +static inline void fsnotify_mkdir(struct inode *inode, const char *name)
1719 +{
1720 + inode_dir_notify(inode, DN_CREATE);
1721 + inotify_inode_queue_event(inode, IN_CREATE | IN_ISDIR, 0, name);
1722 +}
1723 +
1724 +/*
1725 + * fsnotify_access - file was read
1726 + */
1727 +static inline void fsnotify_access(struct dentry *dentry)
1728 +{
1729 + struct inode *inode = dentry->d_inode;
1730 + u32 mask = IN_ACCESS;
1731 +
1732 + if (S_ISDIR(inode->i_mode))
1733 + mask |= IN_ISDIR;
1734 +
1735 + dnotify_parent(dentry, DN_ACCESS);
1736 + inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
1737 + inotify_inode_queue_event(inode, mask, 0, NULL);
1738 +}
1739 +
1740 +/*
1741 + * fsnotify_modify - file was modified
1742 + */
1743 +static inline void fsnotify_modify(struct dentry *dentry)
1744 +{
1745 + struct inode *inode = dentry->d_inode;
1746 + u32 mask = IN_MODIFY;
1747 +
1748 + if (S_ISDIR(inode->i_mode))
1749 + mask |= IN_ISDIR;
1750 +
1751 + dnotify_parent(dentry, DN_MODIFY);
1752 + inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
1753 + inotify_inode_queue_event(inode, mask, 0, NULL);
1754 +}
1755 +
1756 +/*
1757 + * fsnotify_open - file was opened
1758 + */
1759 +static inline void fsnotify_open(struct dentry *dentry)
1760 +{
1761 + struct inode *inode = dentry->d_inode;
1762 + u32 mask = IN_OPEN;
1763 +
1764 + if (S_ISDIR(inode->i_mode))
1765 + mask |= IN_ISDIR;
1766 +
1767 + inotify_inode_queue_event(inode, mask, 0, NULL);
1768 + inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
1769 +}
1770 +
1771 +/*
1772 + * fsnotify_close - file was closed
1773 + */
1774 +static inline void fsnotify_close(struct file *file)
1775 +{
1776 + struct dentry *dentry = file->f_dentry;
1777 + struct inode *inode = dentry->d_inode;
1778 + const char *name = dentry->d_name.name;
1779 + mode_t mode = file->f_mode;
1780 + u32 mask = (mode & FMODE_WRITE) ? IN_CLOSE_WRITE : IN_CLOSE_NOWRITE;
1781 +
1782 + if (S_ISDIR(inode->i_mode))
1783 + mask |= IN_ISDIR;
1784 +
1785 + inotify_dentry_parent_queue_event(dentry, mask, 0, name);
1786 + inotify_inode_queue_event(inode, mask, 0, NULL);
1787 +}
1788 +
1789 +/*
1790 + * fsnotify_xattr - extended attributes were changed
1791 + */
1792 +static inline void fsnotify_xattr(struct dentry *dentry)
1793 +{
1794 + struct inode *inode = dentry->d_inode;
1795 + u32 mask = IN_ATTRIB;
1796 +
1797 + if (S_ISDIR(inode->i_mode))
1798 + mask |= IN_ISDIR;
1799 +
1800 + inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
1801 + inotify_inode_queue_event(inode, mask, 0, NULL);
1802 +}
1803 +
1804 +/*
1805 + * fsnotify_change - notify_change event. file was modified and/or metadata
1806 + * was changed.
1807 + */
1808 +static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid)
1809 +{
1810 + struct inode *inode = dentry->d_inode;
1811 + int dn_mask = 0;
1812 + u32 in_mask = 0;
1813 +
1814 + if (ia_valid & ATTR_UID) {
1815 + in_mask |= IN_ATTRIB;
1816 + dn_mask |= DN_ATTRIB;
1817 + }
1818 + if (ia_valid & ATTR_GID) {
1819 + in_mask |= IN_ATTRIB;
1820 + dn_mask |= DN_ATTRIB;
1821 + }
1822 + if (ia_valid & ATTR_SIZE) {
1823 + in_mask |= IN_MODIFY;
1824 + dn_mask |= DN_MODIFY;
1825 + }
1826 + /* both times implies a utime(s) call */
1827 + if ((ia_valid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME))
1828 + {
1829 + in_mask |= IN_ATTRIB;
1830 + dn_mask |= DN_ATTRIB;
1831 + } else if (ia_valid & ATTR_ATIME) {
1832 + in_mask |= IN_ACCESS;
1833 + dn_mask |= DN_ACCESS;
1834 + } else if (ia_valid & ATTR_MTIME) {
1835 + in_mask |= IN_MODIFY;
1836 + dn_mask |= DN_MODIFY;
1837 + }
1838 + if (ia_valid & ATTR_MODE) {
1839 + in_mask |= IN_ATTRIB;
1840 + dn_mask |= DN_ATTRIB;
1841 + }
1842 +
1843 + if (dn_mask)
1844 + dnotify_parent(dentry, dn_mask);
1845 + if (in_mask) {
1846 + if (S_ISDIR(inode->i_mode))
1847 + in_mask |= IN_ISDIR;
1848 + inotify_inode_queue_event(inode, in_mask, 0, NULL);
1849 + inotify_dentry_parent_queue_event(dentry, in_mask, 0,
1850 + dentry->d_name.name);
1851 + }
1852 +}
1853 +
1854 +#ifdef CONFIG_INOTIFY /* inotify helpers */
1855 +
1856 +/*
1857 + * fsnotify_oldname_init - save off the old filename before we change it
1858 + *
1859 + * XXX: This could be kstrdup if only we could add that to lib/string.c
1860 + */
1861 +static inline const char *fsnotify_oldname_init(const char *name)
1862 +{
1863 + size_t len;
1864 + char *buf;
1865 +
1866 + len = strlen(name) + 1;
1867 + buf = kmalloc(len, GFP_KERNEL);
1868 + if (likely(buf))
1869 + memcpy(buf, name, len);
1870 + return buf;
1871 +}
1872 +
1873 +/*
1874 + * fsnotify_oldname_free - free the name we got from fsnotify_oldname_init
1875 + */
1876 +static inline void fsnotify_oldname_free(const char *old_name)
1877 +{
1878 + kfree(old_name);
1879 +}
1880 +
1881 +#else /* CONFIG_INOTIFY */
1882 +
1883 +static inline const char *fsnotify_oldname_init(const char *name)
1884 +{
1885 + return NULL;
1886 +}
1887 +
1888 +static inline void fsnotify_oldname_free(const char *old_name)
1889 +{
1890 +}
1891 +
1892 +#endif /* ! CONFIG_INOTIFY */
1893 +
1894 +#endif /* __KERNEL__ */
1895 +
1896 +#endif /* _LINUX_FS_NOTIFY_H */
1897 diff -urN linux-2.6.12-rc6/include/linux/inotify.h linux/include/linux/inotify.h
1898 --- linux-2.6.12-rc6/include/linux/inotify.h 1969-12-31 19:00:00.000000000 -0500
1899 +++ linux/include/linux/inotify.h 2005-06-13 11:28:04.000000000 -0400
1900 @@ -0,0 +1,124 @@
1901 +/*
1902 + * Inode based directory notification for Linux
1903 + *
1904 + * Copyright (C) 2005 John McCutchan
1905 + */
1906 +
1907 +#ifndef _LINUX_INOTIFY_H
1908 +#define _LINUX_INOTIFY_H
1909 +
1910 +#include <linux/types.h>
1911 +
1912 +/*
1913 + * struct inotify_event - structure read from the inotify device for each event
1914 + *
1915 + * When you are watching a directory, you will receive the filename for events
1916 + * such as IN_CREATE, IN_DELETE, IN_OPEN, IN_CLOSE, ..., relative to the wd.
1917 + */
1918 +struct inotify_event {
1919 + __s32 wd; /* watch descriptor */
1920 + __u32 mask; /* watch mask */
1921 + __u32 cookie; /* cookie to synchronize two events */
1922 + __u32 len; /* length (including nulls) of name */
1923 + char name[0]; /* stub for possible name */
1924 +};
1925 +
1926 +/*
1927 + * struct inotify_watch_request - represents a watch request
1928 + *
1929 + * Pass to the inotify device via the INOTIFY_WATCH ioctl
1930 + */
1931 +struct inotify_watch_request {
1932 + int fd; /* fd of filename to watch */
1933 + __u32 mask; /* event mask */
1934 +};
1935 +
1936 +/* the following are legal, implemented events that user-space can watch for */
1937 +#define IN_ACCESS 0x00000001 /* File was accessed */
1938 +#define IN_MODIFY 0x00000002 /* File was modified */
1939 +#define IN_ATTRIB 0x00000004 /* Metadata changed */
1940 +#define IN_CLOSE_WRITE 0x00000008 /* Writtable file was closed */
1941 +#define IN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed */
1942 +#define IN_OPEN 0x00000020 /* File was opened */
1943 +#define IN_MOVED_FROM 0x00000040 /* File was moved from X */
1944 +#define IN_MOVED_TO 0x00000080 /* File was moved to Y */
1945 +#define IN_CREATE 0x00000100 /* Subfile was created */
1946 +#define IN_DELETE 0x00000200 /* Subfile was deleted */
1947 +#define IN_DELETE_SELF 0x00000400 /* Self was deleted */
1948 +
1949 +/* the following are legal events. they are sent as needed to any watch */
1950 +#define IN_UNMOUNT 0x00002000 /* Backing fs was unmounted */
1951 +#define IN_Q_OVERFLOW 0x00004000 /* Event queued overflowed */
1952 +#define IN_IGNORED 0x00008000 /* File was ignored */
1953 +
1954 +/* helper events */
1955 +#define IN_CLOSE (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) /* close */
1956 +#define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) /* moves */
1957 +
1958 +/* special flags */
1959 +#define IN_ISDIR 0x40000000 /* event occurred against dir */
1960 +#define IN_ONESHOT 0x80000000 /* only send event once */
1961 +
1962 +/*
1963 + * All of the events - we build the list by hand so that we can add flags in
1964 + * the future and not break backward compatibility. Apps will get only the
1965 + * events that they originally wanted. Be sure to add new events here!
1966 + */
1967 +#define IN_ALL_EVENTS (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE | \
1968 + IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | \
1969 + IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF)
1970 +
1971 +#define INOTIFY_IOCTL_MAGIC 'Q'
1972 +#define INOTIFY_IOCTL_MAXNR 2
1973 +
1974 +#define INOTIFY_WATCH _IOR(INOTIFY_IOCTL_MAGIC, 1, struct inotify_watch_request)
1975 +#define INOTIFY_IGNORE _IOR(INOTIFY_IOCTL_MAGIC, 2, int)
1976 +
1977 +#ifdef __KERNEL__
1978 +
1979 +#include <linux/dcache.h>
1980 +#include <linux/fs.h>
1981 +#include <linux/config.h>
1982 +
1983 +#ifdef CONFIG_INOTIFY
1984 +
1985 +extern void inotify_inode_queue_event(struct inode *, __u32, __u32,
1986 + const char *);
1987 +extern void inotify_dentry_parent_queue_event(struct dentry *, __u32, __u32,
1988 + const char *);
1989 +extern void inotify_unmount_inodes(struct list_head *);
1990 +extern void inotify_inode_is_dead(struct inode *);
1991 +extern u32 inotify_get_cookie(void);
1992 +
1993 +#else
1994 +
1995 +static inline void inotify_inode_queue_event(struct inode *inode,
1996 + __u32 mask, __u32 cookie,
1997 + const char *filename)
1998 +{
1999 +}
2000 +
2001 +static inline void inotify_dentry_parent_queue_event(struct dentry *dentry,
2002 + __u32 mask, __u32 cookie,
2003 + const char *filename)
2004 +{
2005 +}
2006 +
2007 +static inline void inotify_unmount_inodes(struct list_head *list)
2008 +{
2009 +}
2010 +
2011 +static inline void inotify_inode_is_dead(struct inode *inode)
2012 +{
2013 +}
2014 +
2015 +static inline u32 inotify_get_cookie(void)
2016 +{
2017 + return 0;
2018 +}
2019 +
2020 +#endif /* CONFIG_INOTIFY */
2021 +
2022 +#endif /* __KERNEL __ */
2023 +
2024 +#endif /* _LINUX_INOTIFY_H */
2025 diff -urN linux-2.6.12-rc6/include/linux/sched.h linux/include/linux/sched.h
2026 --- linux-2.6.12-rc6/include/linux/sched.h 2005-06-07 15:47:53.000000000 -0400
2027 +++ linux/include/linux/sched.h 2005-06-13 11:28:04.000000000 -0400
2028 @@ -404,6 +404,10 @@
2029 atomic_t processes; /* How many processes does this user have? */
2030 atomic_t files; /* How many open files does this user have? */
2031 atomic_t sigpending; /* How many pending signals does this user have? */
2032 +#ifdef CONFIG_INOTIFY
2033 + atomic_t inotify_watches; /* How many inotify watches does this user have? */
2034 + atomic_t inotify_devs; /* How many inotify devs does this user have opened? */
2035 +#endif
2036 /* protected by mq_lock */
2037 unsigned long mq_bytes; /* How many bytes can be allocated to mqueue? */
2038 unsigned long locked_shm; /* How many pages of mlocked shm ? */
2039 diff -urN linux-2.6.12-rc6/kernel/user.c linux/kernel/user.c
2040 --- linux-2.6.12-rc6/kernel/user.c 2005-06-07 15:47:53.000000000 -0400
2041 +++ linux/kernel/user.c 2005-06-13 11:28:04.000000000 -0400
2042 @@ -120,6 +120,10 @@
2043 atomic_set(&new->processes, 0);
2044 atomic_set(&new->files, 0);
2045 atomic_set(&new->sigpending, 0);
2046 +#ifdef CONFIG_INOTIFY
2047 + atomic_set(&new->inotify_watches, 0);
2048 + atomic_set(&new->inotify_devs, 0);
2049 +#endif
2050
2051 new->mq_bytes = 0;
2052 new->locked_shm = 0;

  ViewVC Help
Powered by ViewVC 1.1.20