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

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

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

  • Property mode set to 100644
File size: 46.3 KB
  • drivers/char/inotify.c

    inotify, bitches.
    
    Signed-off-by: Robert Love <rml@novell.com>
    
     drivers/char/Kconfig       |   13 
     drivers/char/Makefile      |    2 
     drivers/char/inotify.c     | 1067 +++++++++++++++++++++++++++++++++++++++++++++
     drivers/char/misc.c        |   14 
     fs/attr.c                  |   73 ++-
     fs/file_table.c            |    7 
     fs/inode.c                 |    3 
     fs/namei.c                 |   36 +
     fs/open.c                  |    5 
     fs/read_write.c            |   33 +
     fs/super.c                 |    2 
     include/linux/fs.h         |    7 
     include/linux/inotify.h    |  160 ++++++
     include/linux/miscdevice.h |    5 
     include/linux/sched.h      |    2 
     kernel/user.c              |    2 
     16 files changed, 1392 insertions(+), 39 deletions(-)
    
    diff -urN linux-2.6.10/drivers/char/inotify.c linux/drivers/char/inotify.c
    old new  
     1/*
     2 * Inode based directory notifications for Linux.
     3 *
     4 * Copyright (C) 2004 John McCutchan
     5 *
     6 * This program is free software; you can redistribute it and/or modify it
     7 * under the terms of the GNU General Public License as published by the
     8 * Free Software Foundation; either version 2, or (at your option) any
     9 * later version.
     10 *
     11 * This program is distributed in the hope that it will be useful, but
     12 * WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14 * General Public License for more details.
     15 */
     16
     17#include <linux/module.h>
     18#include <linux/kernel.h>
     19#include <linux/sched.h>
     20#include <linux/spinlock.h>
     21#include <linux/idr.h>
     22#include <linux/slab.h>
     23#include <linux/fs.h>
     24#include <linux/namei.h>
     25#include <linux/poll.h>
     26#include <linux/device.h>
     27#include <linux/miscdevice.h>
     28#include <linux/init.h>
     29#include <linux/list.h>
     30#include <linux/writeback.h>
     31#include <linux/inotify.h>
     32
     33#include <asm/ioctls.h>
     34
     35static atomic_t inotify_cookie;
     36static kmem_cache_t *watch_cachep;
     37static kmem_cache_t *event_cachep;
     38static kmem_cache_t *inode_data_cachep;
     39
     40static int sysfs_attrib_max_user_devices;
     41static int sysfs_attrib_max_user_watches;
     42static unsigned int sysfs_attrib_max_queued_events;
     43
     44/*
     45 * struct inotify_device - represents an open instance of an inotify device
     46 *
     47 * For each inotify device, we need to keep track of the events queued on it,
     48 * a list of the inodes that we are watching, and so on.
     49 *
     50 * This structure is protected by 'lock'.  Lock ordering:
     51 *
     52 * dev->lock (protects dev)
     53 *      inode_lock (used to safely walk inode_in_use list)
     54 *              inode->i_lock (only needed for getting ref on inode_data)
     55 */
     56struct inotify_device {
     57        wait_queue_head_t       wait;
     58        struct idr              idr;
     59        struct list_head        events;
     60        struct list_head        watches;
     61        spinlock_t              lock;
     62        unsigned int            queue_size;
     63        unsigned int            event_count;
     64        unsigned int            max_events;
     65        struct user_struct      *user;
     66};
     67
     68struct inotify_watch {
     69        s32                     wd;     /* watch descriptor */
     70        u32                     mask;
     71        struct inode            *inode;
     72        struct inotify_device   *dev;
     73        struct list_head        d_list; /* device list */
     74        struct list_head        i_list; /* inode list */
     75};
     76
     77static ssize_t show_max_queued_events(struct class_device *class, char *buf)
     78{
     79        return sprintf(buf, "%d\n", sysfs_attrib_max_queued_events);
     80}
     81
     82static ssize_t store_max_queued_events(struct class_device *class,
     83                                       const char *buf, size_t count)
     84{
     85        unsigned int max;
     86
     87        if (sscanf(buf, "%u", &max) > 0 && max > 0) {
     88                sysfs_attrib_max_queued_events = max;
     89                return strlen(buf);
     90        }
     91        return -EINVAL;
     92}
     93
     94static ssize_t show_max_user_devices(struct class_device *class, char *buf)
     95{
     96        return sprintf(buf, "%d\n", sysfs_attrib_max_user_devices);
     97}
     98
     99static ssize_t store_max_user_devices(struct class_device *class,
     100                                      const char *buf, size_t count)
     101{
     102        int max;
     103
     104        if (sscanf(buf, "%d", &max) > 0 && max > 0) {
     105                sysfs_attrib_max_user_devices = max;
     106                return strlen(buf);
     107        }
     108        return -EINVAL;
     109}
     110
     111static ssize_t show_max_user_watches(struct class_device *class, char *buf)
     112{
     113        return sprintf(buf, "%d\n", sysfs_attrib_max_user_watches);
     114}
     115
     116static ssize_t store_max_user_watches(struct class_device *class,
     117                                      const char *buf, size_t count)
     118{
     119        int max;
     120
     121        if (sscanf(buf, "%d", &max) > 0 && max > 0) {
     122                sysfs_attrib_max_user_watches = max;
     123                return strlen(buf);
     124        }
     125        return -EINVAL;
     126}
     127
     128static CLASS_DEVICE_ATTR(max_queued_events, S_IRUGO | S_IWUSR,
     129        show_max_queued_events, store_max_queued_events);
     130static CLASS_DEVICE_ATTR(max_user_devices, S_IRUGO | S_IWUSR,
     131        show_max_user_devices, store_max_user_devices);
     132static CLASS_DEVICE_ATTR(max_user_watches, S_IRUGO | S_IWUSR,
     133        show_max_user_watches, store_max_user_watches);
     134
     135/*
     136 * A list of these is attached to each instance of the driver
     137 * when the drivers read() gets called, this list is walked and
     138 * all events that can fit in the buffer get delivered
     139 */
     140struct inotify_kernel_event {
     141        struct list_head        list;
     142        struct inotify_event    event;
     143};
     144
     145static inline void __get_inode_data(struct inotify_inode_data *data)
     146{
     147        atomic_inc(&data->count);
     148}
     149
     150/*
     151 * get_inode_data - pin an inotify_inode_data structure.  Returns the structure
     152 * if successful and NULL on failure, which can only occur if inotify_data is
     153 * not yet allocated.  The inode must be pinned prior to invocation.
     154 */
     155static inline struct inotify_inode_data * get_inode_data(struct inode *inode)
     156{
     157        struct inotify_inode_data *data;
     158
     159        spin_lock(&inode->i_lock);
     160        data = inode->inotify_data;
     161        if (data)
     162                __get_inode_data(data);
     163        spin_unlock(&inode->i_lock);
     164
     165        return data;
     166}
     167
     168/*
     169 * put_inode_data - drop our reference on an inotify_inode_data and the
     170 * inode structure in which it lives.  If the reference count on inotify_data
     171 * reaches zero, free it.
     172 */
     173static inline void put_inode_data(struct inode *inode)
     174{
     175        //spin_lock(&inode->i_lock);
     176        if (atomic_dec_and_test(&inode->inotify_data->count)) {
     177                kmem_cache_free(inode_data_cachep, inode->inotify_data);
     178                inode->inotify_data = NULL;
     179        }
     180        //spin_unlock(&inode->i_lock);
     181}
     182
     183/*
     184 * find_inode - resolve a user-given path to a specific inode and iget() it
     185 */
     186static struct inode * find_inode(const char __user *dirname)
     187{
     188        struct inode *inode;
     189        struct nameidata nd;
     190        int error;
     191
     192        error = __user_walk(dirname, LOOKUP_FOLLOW, &nd);
     193        if (error)
     194                return ERR_PTR(error);
     195
     196        inode = nd.dentry->d_inode;
     197
     198        /* you can only watch an inode if you have read permissions on it */
     199        error = permission(inode, MAY_READ, NULL);
     200        if (error) {
     201                inode = ERR_PTR(error);
     202                goto release_and_out;
     203        }
     204
     205        spin_lock(&inode_lock);
     206        __iget(inode);
     207        spin_unlock(&inode_lock);
     208release_and_out:
     209        path_release(&nd);
     210        return inode;
     211}
     212
     213struct inotify_kernel_event * kernel_event(s32 wd, u32 mask, u32 cookie,
     214                                           const char *filename)
     215{
     216        struct inotify_kernel_event *kevent;
     217
     218        kevent = kmem_cache_alloc(event_cachep, GFP_ATOMIC);
     219        if (!kevent)
     220                return NULL;
     221
     222        /* we hand this out to user-space, so zero it out just in case */
     223        memset(kevent, 0, sizeof(struct inotify_kernel_event));
     224
     225        kevent->event.wd = wd;
     226        kevent->event.mask = mask;
     227        kevent->event.cookie = cookie;
     228        INIT_LIST_HEAD(&kevent->list);
     229
     230        if (filename) {
     231                size_t len;
     232
     233                len = strlen(filename);
     234                kevent->event.filename = kmalloc(len+1, GFP_ATOMIC);
     235                if (!kevent->event.filename) {
     236                        kmem_cache_free (event_cachep, kevent);
     237                        return NULL;
     238                }
     239                memset(kevent->event.filename, 0, len+1);
     240                strncpy(kevent->event.filename, filename, len);
     241                kevent->event.len = len;
     242        } else
     243                kevent->event.filename = NULL;
     244
     245        return kevent;
     246}
     247
     248void delete_kernel_event(struct inotify_kernel_event *kevent)
     249{
     250        if (!kevent)
     251                return;
     252
     253        if (kevent->event.filename)
     254                kfree (kevent->event.filename);
     255        kmem_cache_free(event_cachep, kevent);
     256}
     257
     258#define list_to_inotify_kernel_event(pos)       \
     259                list_entry((pos), struct inotify_kernel_event, list)
     260
     261#define inotify_dev_get_event(dev)              \
     262                (list_to_inotify_kernel_event(dev->events.next))
     263
     264/* Does this events mask get sent to the watch ? */
     265#define event_and(event_mask,watches_mask)      ((event_mask == IN_UNMOUNT) || \
     266                                                (event_mask == IN_IGNORED) || \
     267                                                (event_mask & watches_mask))
     268
     269/*
     270 * inotify_dev_queue_event - add a new event to the given device
     271 *
     272 * Caller must hold dev->lock.
     273 */
     274static void inotify_dev_queue_event(struct inotify_device *dev,
     275                                    struct inotify_watch *watch, u32 mask,
     276                                    u32 cookie, const char *filename)
     277{
     278        struct inotify_kernel_event *kevent, *last;
     279
     280        /* Check if the new event is a duplicate of the last event queued. */
     281        last = inotify_dev_get_event(dev);
     282        if (dev->event_count && last->event.mask == mask &&
     283                        last->event.wd == watch->wd) {
     284                /* Check if the filenames match */
     285                if (!filename && last->event.filename[0] == '\0')
     286                        return;
     287                if (filename && !strcmp(last->event.filename, filename))
     288                        return;
     289        }
     290
     291        /*
     292         * the queue has already overflowed and we have already sent the
     293         * Q_OVERFLOW event
     294         */
     295        if (dev->event_count > dev->max_events)
     296                return;
     297
     298        /* the queue has just overflowed and we need to notify user space */
     299        if (dev->event_count == dev->max_events) {
     300                kevent = kernel_event(-1, IN_Q_OVERFLOW, cookie, NULL);
     301                goto add_event_to_queue;
     302        }
     303
     304        if (!event_and(mask, watch->inode->inotify_data->watch_mask) ||
     305                        !event_and(mask, watch->mask))
     306                return;
     307
     308        kevent = kernel_event(watch->wd, mask, cookie, filename);
     309
     310add_event_to_queue:
     311        if (!kevent)
     312                return;
     313
     314        /* queue the event and wake up anyone waiting */
     315        dev->event_count++;
     316        dev->queue_size += sizeof(struct inotify_event) + kevent->event.len -
     317                        sizeof(char *) + 1;
     318        list_add_tail(&kevent->list, &dev->events);
     319        wake_up_interruptible(&dev->wait);
     320}
     321
     322static inline int inotify_dev_has_events(struct inotify_device *dev)
     323{
     324        return !list_empty(&dev->events);
     325}
     326
     327/*
     328 * inotify_dev_event_dequeue - destroy an event on the given device
     329 *
     330 * Caller must hold dev->lock.
     331 */
     332static void inotify_dev_event_dequeue(struct inotify_device *dev)
     333{
     334        struct inotify_kernel_event *kevent;
     335
     336        if (!inotify_dev_has_events(dev))
     337                return;
     338
     339        kevent = inotify_dev_get_event(dev);
     340        list_del_init(&kevent->list);
     341        dev->event_count--;
     342        dev->queue_size -= sizeof(struct inotify_event) + kevent->event.len -
     343                        sizeof(char *) + 1;
     344        delete_kernel_event(kevent);
     345}
     346
     347/*
     348 * inotify_dev_get_wd - returns the next WD for use by the given dev
     349 *
     350 * This function can sleep.
     351 */
     352static int inotify_dev_get_wd(struct inotify_device *dev,
     353                             struct inotify_watch *watch)
     354{
     355        int ret;
     356
     357        if (atomic_read(&dev->user->inotify_watches) >=
     358                        sysfs_attrib_max_user_watches)
     359                return -ENOSPC;
     360
     361repeat:
     362        if (!idr_pre_get(&dev->idr, GFP_KERNEL))
     363                return -ENOSPC;
     364        spin_lock(&dev->lock);
     365        ret = idr_get_new(&dev->idr, watch, &watch->wd);
     366        spin_unlock(&dev->lock);
     367        if (ret == -EAGAIN) /* more memory is required, try again */
     368                goto repeat;
     369        else if (ret)       /* the idr is full! */
     370                return -ENOSPC;
     371
     372        atomic_inc(&dev->user->inotify_watches);
     373
     374        return 0;
     375}
     376
     377/*
     378 * inotify_dev_put_wd - release the given WD on the given device
     379 *
     380 * Caller must hold dev->lock.
     381 */
     382static int inotify_dev_put_wd(struct inotify_device *dev, s32 wd)
     383{
     384        if (!dev || wd < 0)
     385                return -1;
     386
     387        atomic_dec(&dev->user->inotify_watches);
     388        idr_remove(&dev->idr, wd);
     389
     390        return 0;
     391}
     392
     393/*
     394 * create_watch - creates a watch on the given device.
     395 *
     396 * Grabs dev->lock, so the caller must not hold it.
     397 */
     398static struct inotify_watch *create_watch(struct inotify_device *dev,
     399                                          u32 mask, struct inode *inode)
     400{
     401        struct inotify_watch *watch;
     402
     403        watch = kmem_cache_alloc(watch_cachep, GFP_KERNEL);
     404        if (!watch)
     405                return NULL;
     406
     407        watch->mask = mask;
     408        watch->inode = inode;
     409        watch->dev = dev;
     410        INIT_LIST_HEAD(&watch->d_list);
     411        INIT_LIST_HEAD(&watch->i_list);
     412
     413        if (inotify_dev_get_wd(dev, watch)) {
     414                kmem_cache_free(watch_cachep, watch);
     415                return NULL;
     416        }
     417
     418        return watch;
     419}
     420
     421/*
     422 * delete_watch - removes the given 'watch' from the given 'dev'
     423 *
     424 * Caller must hold dev->lock.
     425 */
     426static void delete_watch(struct inotify_device *dev,
     427                         struct inotify_watch *watch)
     428{
     429        inotify_dev_put_wd(dev, watch->wd);
     430        kmem_cache_free(watch_cachep, watch);
     431}
     432
     433/*
     434 * inotify_find_dev - find the watch associated with the given inode and dev
     435 *
     436 * Caller must hold dev->lock.
     437 * FIXME: Needs inotify_data->lock too.  Don't need dev->lock, just pin it.
     438 */
     439static struct inotify_watch *inode_find_dev(struct inode *inode,
     440                                            struct inotify_device *dev)
     441{
     442        struct inotify_watch *watch;
     443
     444        if (!inode->inotify_data)
     445                return NULL;
     446
     447        list_for_each_entry(watch, &inode->inotify_data->watches, i_list) {
     448                if (watch->dev == dev)
     449                        return watch;
     450        }
     451
     452        return NULL;
     453}
     454
     455/*
     456 * dev_find_wd - given a (dev,wd) pair, returns the matching inotify_watcher
     457 *
     458 * Returns the results of looking up (dev,wd) in the idr layer.  NULL is
     459 * returned on error.
     460 *
     461 * The caller must hold dev->lock.
     462 */
     463static inline struct inotify_watch *dev_find_wd(struct inotify_device *dev,
     464                                                u32 wd)
     465{
     466        return idr_find(&dev->idr, wd);
     467}
     468
     469static int inotify_dev_is_watching_inode(struct inotify_device *dev,
     470                                         struct inode *inode)
     471{
     472        struct inotify_watch *watch;
     473
     474        list_for_each_entry(watch, &dev->watches, d_list) {
     475                if (watch->inode == inode)
     476                        return 1;
     477        }
     478
     479        return 0;
     480}
     481
     482/*
     483 * inotify_dev_add_watcher - add the given watcher to the given device instance
     484 *
     485 * Caller must hold dev->lock.
     486 */
     487static int inotify_dev_add_watch(struct inotify_device *dev,
     488                                 struct inotify_watch *watch)
     489{
     490        if (!dev || !watch)
     491                return -EINVAL;
     492
     493        list_add(&watch->d_list, &dev->watches);
     494        return 0;
     495}
     496
     497/*
     498 * inotify_dev_rm_watch - remove the given watch from the given device
     499 *
     500 * Caller must hold dev->lock because we call inotify_dev_queue_event().
     501 */
     502static int inotify_dev_rm_watch(struct inotify_device *dev,
     503                                struct inotify_watch *watch)
     504{
     505        if (!watch)
     506                return -EINVAL;
     507
     508        inotify_dev_queue_event(dev, watch, IN_IGNORED, 0, NULL);
     509        list_del_init(&watch->d_list);
     510
     511        return 0;
     512}
     513
     514/*
     515 * inode_update_watch_mask - update inode->inotify_data->watch_mask
     516 *
     517 * Grabs inode->inotify_data->lock.
     518 */
     519static void inode_update_watch_mask(struct inode *inode)
     520{
     521        struct inotify_inode_data *data;
     522        struct inotify_watch *watch;
     523        u32 new_mask;
     524
     525        data = get_inode_data(inode);
     526        if (!data)      /* FIXME: this should never happen */
     527                return;
     528        spin_lock(&data->lock);
     529
     530        new_mask = 0;
     531        list_for_each_entry(watch, &data->watches, i_list)
     532                new_mask |= watch->mask;
     533
     534        data->watch_mask = new_mask;
     535
     536        spin_unlock(&data->lock);
     537        put_inode_data(inode);
     538}
     539
     540/*
     541 * inode_add_watch - add a watch to the given inode
     542 *
     543 * Callers must hold dev->lock, because we call inode_find_dev().
     544 */
     545static int inode_add_watch(struct inode *inode, struct inotify_watch *watch)
     546{
     547        int ret;
     548
     549        if (!inode || !watch)
     550                return -EINVAL;
     551
     552        spin_lock(&inode->i_lock);
     553        if (!inode->inotify_data) {
     554                /* inotify_data is not attached to the inode, so add it */
     555                inode->inotify_data = kmem_cache_alloc(inode_data_cachep,
     556                                                       GFP_ATOMIC);
     557                if (!inode->inotify_data) {
     558                        ret = -ENOMEM;
     559                        goto out_lock;
     560                }
     561
     562                atomic_set(&inode->inotify_data->count, 0);
     563                INIT_LIST_HEAD(&inode->inotify_data->watches);
     564                inode->inotify_data->watch_mask = 0;
     565                spin_lock_init(&inode->inotify_data->lock);
     566        } else if (inode_find_dev(inode, watch->dev)) {
     567                /* a watch is already associated with this (inode,dev) pair */
     568                ret = -EINVAL;
     569                goto out_lock;
     570        }
     571        __get_inode_data(inode->inotify_data);
     572        spin_unlock(&inode->i_lock);
     573
     574        list_add(&watch->i_list, &inode->inotify_data->watches);
     575        inode_update_watch_mask(inode);
     576
     577        return 0;
     578out_lock:
     579        spin_unlock(&inode->i_lock);
     580        return ret;
     581}
     582
     583static int inode_rm_watch(struct inode *inode,
     584                          struct inotify_watch *watch)
     585{
     586        if (!inode || !watch || !inode->inotify_data)
     587                return -EINVAL;
     588
     589        list_del_init(&watch->i_list);
     590        inode_update_watch_mask(inode);
     591
     592        /* clean up inode->inotify_data */
     593        put_inode_data(inode); 
     594
     595        return 0;
     596}
     597
     598/* Kernel API */
     599
     600/*
     601 * inotify_inode_queue_event - queue an event with the given mask, cookie, and
     602 * filename to any watches associated with the given inode.
     603 *
     604 * inode must be pinned prior to calling.
     605 */
     606void inotify_inode_queue_event(struct inode *inode, u32 mask, u32 cookie,
     607                               const char *filename)
     608{
     609        struct inotify_watch *watch;
     610
     611        if (!inode->inotify_data)
     612                return;
     613
     614        list_for_each_entry(watch, &inode->inotify_data->watches, i_list) {
     615                spin_lock(&watch->dev->lock);
     616                inotify_dev_queue_event(watch->dev, watch, mask, cookie,
     617                                        filename);
     618                spin_unlock(&watch->dev->lock);
     619        }
     620}
     621EXPORT_SYMBOL_GPL(inotify_inode_queue_event);
     622
     623void inotify_dentry_parent_queue_event(struct dentry *dentry, u32 mask,
     624                                       u32 cookie, const char *filename)
     625{
     626        struct dentry *parent;
     627
     628        parent = dget_parent(dentry);
     629        inotify_inode_queue_event(parent->d_inode, mask, cookie, filename);
     630        dput(parent);
     631}
     632EXPORT_SYMBOL_GPL(inotify_dentry_parent_queue_event);
     633
     634u32 inotify_get_cookie(void)
     635{
     636        atomic_inc(&inotify_cookie);
     637        return atomic_read(&inotify_cookie);
     638}
     639EXPORT_SYMBOL_GPL(inotify_get_cookie);
     640
     641/*
     642 * watch->inode must be pinned.  We drop a reference before returning.
     643 */
     644static void ignore_helper(struct inotify_watch *watch, int event)
     645{
     646        struct inotify_device *dev;
     647        struct inode *inode;
     648
     649        inode = watch->inode;
     650        dev = watch->dev;
     651
     652        spin_lock(&dev->lock);
     653
     654        if (event)
     655                inotify_dev_queue_event(dev, watch, event, 0, NULL);
     656
     657        inode_rm_watch(inode, watch);
     658        inotify_dev_rm_watch(watch->dev, watch);
     659
     660        delete_watch(dev, watch);
     661        spin_unlock(&dev->lock);
     662
     663        iput(inode);
     664}
     665
     666void inotify_super_block_umount(struct super_block *sb)
     667{
     668        struct inode *inode;
     669
     670        spin_lock(&inode_lock);
     671
     672        /*
     673         * We hold the inode_lock, so the inodes are not going anywhere, and
     674         * we grab a reference on inotify_data before walking its list of
     675         * watches.
     676         */
     677        list_for_each_entry(inode, &inode_in_use, i_list) {
     678                struct inotify_inode_data *inode_data;
     679                struct inotify_watch *watch;
     680
     681                if (inode->i_sb != sb)
     682                        continue;
     683
     684                inode_data = get_inode_data(inode);
     685                if (!inode_data)
     686                        continue;
     687
     688                list_for_each_entry(watch, &inode_data->watches, i_list)
     689                        ignore_helper(watch, IN_UNMOUNT);
     690                put_inode_data(inode);
     691        }
     692
     693        spin_unlock(&inode_lock);
     694}
     695EXPORT_SYMBOL_GPL(inotify_super_block_umount);
     696
     697/*
     698 * inotify_inode_is_dead - an inode has been deleted, cleanup any watches
     699 */
     700void inotify_inode_is_dead(struct inode *inode)
     701{
     702        struct inotify_watch *watch, *next;
     703        struct inotify_inode_data *data;
     704
     705        data = get_inode_data(inode);
     706        if (!data)
     707                return;
     708        list_for_each_entry_safe(watch, next, &data->watches, i_list)
     709                ignore_helper(watch, 0);
     710        put_inode_data(inode);
     711}
     712EXPORT_SYMBOL_GPL(inotify_inode_is_dead);
     713
     714/* The driver interface is implemented below */
     715
     716static unsigned int inotify_poll(struct file *file, poll_table *wait)
     717{
     718        struct inotify_device *dev;
     719
     720        dev = file->private_data;
     721
     722        poll_wait(file, &dev->wait, wait);
     723
     724        if (inotify_dev_has_events(dev))
     725                return POLLIN | POLLRDNORM;
     726
     727        return 0;
     728}
     729
     730static ssize_t inotify_read(struct file *file, char __user *buf,
     731                            size_t count, loff_t *pos)
     732{
     733        size_t event_size;
     734        struct inotify_device *dev;
     735        char __user *start;
     736        DECLARE_WAITQUEUE(wait, current);
     737
     738        start = buf;
     739        dev = file->private_data;
     740
     741        /* We only hand out full inotify events */
     742        event_size = sizeof(struct inotify_event) - sizeof(char *);
     743
     744        if (count < event_size)
     745                return -EINVAL;
     746
     747        while (1) {
     748                int has_events;
     749
     750                spin_lock(&dev->lock);
     751                has_events = inotify_dev_has_events(dev);
     752                spin_unlock(&dev->lock);
     753                if (has_events)
     754                        break;
     755
     756                if (file->f_flags & O_NONBLOCK)
     757                        return -EAGAIN;
     758
     759                if (signal_pending(current))
     760                        return -ERESTARTSYS;
     761
     762                add_wait_queue(&dev->wait, &wait);
     763                set_current_state(TASK_INTERRUPTIBLE);
     764
     765                schedule();
     766
     767                set_current_state(TASK_RUNNING);               
     768                remove_wait_queue(&dev->wait, &wait);
     769        }
     770
     771        while (count >= event_size) {
     772                struct inotify_kernel_event *kevent;
     773
     774                spin_lock(&dev->lock);
     775                if (!inotify_dev_has_events(dev)) {
     776                        spin_unlock(&dev->lock);
     777                        break;
     778                }
     779                kevent = inotify_dev_get_event(dev);
     780
     781                /* We can't send this event, not enough space in the buffer */
     782                if ((event_size + kevent->event.len + 1) > count) {
     783                        spin_unlock(&dev->lock);
     784                        break;
     785                }
     786                spin_unlock(&dev->lock);
     787
     788                /* Copy the entire event except the string to user space */
     789                if (copy_to_user(buf, &kevent->event, event_size))
     790                        return -EFAULT;
     791
     792                buf += event_size;
     793                count -= event_size;
     794
     795                /* Copy the filename to user space */
     796                if (kevent->event.filename) {
     797                        if (copy_to_user(buf, kevent->event.filename,
     798                                        kevent->event.len+1))
     799                                return -EFAULT;
     800                        buf += kevent->event.len + 1;
     801                        count -= kevent->event.len + 1;
     802                } else {
     803                        int z = 0;
     804                        /* Copy the NULL */
     805                        if (copy_to_user(buf, &z, 1))
     806                                return -EFAULT;
     807
     808                        buf += 1;
     809                        count -= 1;
     810                }
     811
     812                spin_lock(&dev->lock);
     813                inotify_dev_event_dequeue(dev);
     814                spin_unlock(&dev->lock);
     815        }
     816
     817        return buf - start;
     818}
     819
     820static int inotify_open(struct inode *inode, struct file *file)
     821{
     822        struct inotify_device *dev;
     823        struct user_struct *user;
     824        int ret;
     825
     826        user = get_uid(current->user);
     827
     828        if (atomic_read(&user->inotify_devs) >= sysfs_attrib_max_user_devices) {
     829                ret = -ENOSPC;
     830                goto out_err;
     831        }
     832
     833        atomic_inc(&current->user->inotify_devs);
     834
     835        dev = kmalloc(sizeof(struct inotify_device), GFP_KERNEL);
     836        if (!dev) {
     837                ret = -ENOMEM;
     838                goto out_err;
     839        }
     840
     841        idr_init(&dev->idr);
     842
     843        INIT_LIST_HEAD(&dev->events);
     844        INIT_LIST_HEAD(&dev->watches);
     845        init_waitqueue_head(&dev->wait);
     846
     847        dev->event_count = 0;
     848        dev->queue_size = 0;
     849        dev->max_events = sysfs_attrib_max_queued_events;
     850        dev->user = user;
     851        spin_lock_init(&dev->lock);
     852
     853        file->private_data = dev;
     854
     855        return 0;
     856out_err:
     857        free_uid(current->user);
     858        return ret;
     859}
     860
     861/*
     862 * inotify_release_all_watches - destroy all watches on a given device
     863 *
     864 * FIXME: Do we want a lock here?
     865 */
     866static void inotify_release_all_watches(struct inotify_device *dev)
     867{
     868        struct inotify_watch *watch, *next;
     869
     870        list_for_each_entry_safe(watch, next, &dev->watches, d_list)
     871                ignore_helper(watch, 0);
     872}
     873
     874/*
     875 * inotify_release_all_events - destroy all of the events on a given device
     876 */
     877static void inotify_release_all_events(struct inotify_device *dev)
     878{
     879        spin_lock(&dev->lock);
     880        while (inotify_dev_has_events(dev))
     881                inotify_dev_event_dequeue(dev);
     882        spin_unlock(&dev->lock);
     883}
     884
     885static int inotify_release(struct inode *inode, struct file *file)
     886{
     887        struct inotify_device *dev;
     888
     889        dev = file->private_data;
     890
     891        inotify_release_all_watches(dev);
     892        inotify_release_all_events(dev);
     893
     894        atomic_dec(&dev->user->inotify_devs);
     895        free_uid(dev->user);
     896
     897        kfree(dev);
     898
     899        return 0;
     900}
     901
     902static int inotify_add_watch(struct inotify_device *dev,
     903                             struct inotify_watch_request *request)
     904{
     905        struct inode *inode;
     906        struct inotify_watch *watch;
     907        int ret;
     908
     909        inode = find_inode((const char __user*) request->dirname);
     910        if (IS_ERR(inode))
     911                return PTR_ERR(inode);
     912
     913        spin_lock(&dev->lock);
     914
     915        /*
     916         * This handles the case of re-adding a directory we are already
     917         * watching, we just update the mask and return 0
     918         */
     919        if (inotify_dev_is_watching_inode(dev, inode)) {
     920                struct inotify_watch *owatch;   /* the old watch */
     921
     922                owatch = inode_find_dev(inode, dev);
     923                owatch->mask = request->mask;
     924                inode_update_watch_mask(inode);
     925                spin_unlock(&dev->lock);
     926                iput(inode);
     927
     928                return owatch->wd;
     929        }
     930
     931        spin_unlock(&dev->lock);
     932
     933        watch = create_watch(dev, request->mask, inode);
     934        if (!watch) {
     935                iput(inode);
     936                return -ENOSPC;
     937        }
     938
     939        spin_lock(&dev->lock);
     940
     941        /* We can't add anymore watches to this device */
     942        if (inotify_dev_add_watch(dev, watch)) {
     943                delete_watch(dev, watch);
     944                spin_unlock(&dev->lock);
     945                iput(inode);
     946                return -EINVAL;
     947        }
     948
     949        ret = inode_add_watch(inode, watch);
     950        if (ret < 0) {
     951                list_del_init(&watch->d_list);
     952                delete_watch(dev, watch);
     953                spin_unlock(&dev->lock);
     954                iput(inode);
     955                return ret;
     956        }
     957
     958        spin_unlock(&dev->lock);
     959
     960        return watch->wd;
     961}
     962
     963static int inotify_ignore(struct inotify_device *dev, s32 wd)
     964{
     965        struct inotify_watch *watch;
     966
     967        /*
     968         * FIXME: Silly to grab dev->lock here and then drop it, when
     969         * ignore_helper() grabs it anyway a few lines down.
     970         */
     971        spin_lock(&dev->lock);
     972        watch = dev_find_wd(dev, wd);
     973        spin_unlock(&dev->lock);
     974        if (!watch)
     975                return -EINVAL;
     976        ignore_helper(watch, 0);
     977
     978        return 0;
     979}
     980
     981/*
     982 * inotify_ioctl() - our device file's ioctl method
     983 *
     984 * The VFS serializes all of our calls via the BKL and we rely on that.  We
     985 * could, alternatively, grab dev->lock.  Right now lower levels grab that
     986 * where needed.
     987 */
     988static int inotify_ioctl(struct inode *ip, struct file *fp,
     989                         unsigned int cmd, unsigned long arg)
     990{
     991        struct inotify_device *dev;
     992        struct inotify_watch_request request;
     993        void __user *p;
     994        s32 wd;
     995
     996        dev = fp->private_data;
     997        p = (void __user *) arg;
     998
     999        switch (cmd) {
     1000        case INOTIFY_WATCH:
     1001                if (copy_from_user(&request, p, sizeof (request)))
     1002                        return -EFAULT;
     1003                return inotify_add_watch(dev, &request);
     1004        case INOTIFY_IGNORE:
     1005                if (copy_from_user(&wd, p, sizeof (wd)))
     1006                        return -EFAULT;
     1007                return inotify_ignore(dev, wd);
     1008        case FIONREAD:
     1009                return put_user(dev->queue_size, (int __user *) p);
     1010        default:
     1011                return -ENOTTY;
     1012        }
     1013}
     1014
     1015static struct file_operations inotify_fops = {
     1016        .owner          = THIS_MODULE,
     1017        .poll           = inotify_poll,
     1018        .read           = inotify_read,
     1019        .open           = inotify_open,
     1020        .release        = inotify_release,
     1021        .ioctl          = inotify_ioctl,
     1022};
     1023
     1024struct miscdevice inotify_device = {
     1025        .minor  = MISC_DYNAMIC_MINOR,
     1026        .name   = "inotify",
     1027        .fops   = &inotify_fops,
     1028};
     1029
     1030static int __init inotify_init(void)
     1031{
     1032        struct class_device *class;
     1033        int ret;
     1034
     1035        ret = misc_register(&inotify_device);
     1036        if (ret)
     1037                return ret;
     1038
     1039        sysfs_attrib_max_queued_events = 512;
     1040        sysfs_attrib_max_user_devices = 64;
     1041        sysfs_attrib_max_user_watches = 16384;
     1042
     1043        class = inotify_device.class;
     1044        class_device_create_file(class, &class_device_attr_max_queued_events);
     1045        class_device_create_file(class, &class_device_attr_max_user_devices);
     1046        class_device_create_file(class, &class_device_attr_max_user_watches);
     1047
     1048        atomic_set(&inotify_cookie, 0);
     1049
     1050        watch_cachep = kmem_cache_create("inotify_watch_cache",
     1051                        sizeof(struct inotify_watch), 0, SLAB_PANIC,
     1052                        NULL, NULL);
     1053
     1054        event_cachep = kmem_cache_create("inotify_event_cache",
     1055                        sizeof(struct inotify_kernel_event), 0,
     1056                        SLAB_PANIC, NULL, NULL);
     1057
     1058        inode_data_cachep = kmem_cache_create("inotify_inode_data_cache",
     1059                        sizeof(struct inotify_inode_data), 0, SLAB_PANIC,
     1060                        NULL, NULL);
     1061
     1062        printk(KERN_INFO "inotify device minor=%d\n", inotify_device.minor);
     1063
     1064        return 0;
     1065}
     1066
     1067module_init(inotify_init);
  • drivers/char/Kconfig

    diff -urN linux-2.6.10/drivers/char/Kconfig linux/drivers/char/Kconfig
    old new  
    6262        depends on VT && !S390 && !USERMODE
    6363        default y
    6464
     65config INOTIFY
     66        bool "Inotify file change notification support"
     67        default y
     68        ---help---
     69          Say Y here to enable inotify support and the /dev/inotify character
     70          device.  Inotify is a file change notification system and a
     71          replacement for dnotify.  Inotify fixes numerous shortcomings in
     72          dnotify and introduces several new features.  It allows monitoring
     73          of both files and directories via a single open fd.  Multiple file
     74          events are supported.
     75         
     76          If unsure, say Y.
     77
    6578config SERIAL_NONSTANDARD
    6679        bool "Non-standard serial port support"
    6780        ---help---
  • drivers/char/Makefile

    diff -urN linux-2.6.10/drivers/char/Makefile linux/drivers/char/Makefile
    old new  
    99
    1010obj-y    += mem.o random.o tty_io.o n_tty.o tty_ioctl.o
    1111
     12
     13obj-$(CONFIG_INOTIFY)           += inotify.o
    1214obj-$(CONFIG_LEGACY_PTYS)       += pty.o
    1315obj-$(CONFIG_UNIX98_PTYS)       += pty.o
    1416obj-y                           += misc.o
  • drivers/char/misc.c

    diff -urN linux-2.6.10/drivers/char/misc.c linux/drivers/char/misc.c
    old new  
    207207int misc_register(struct miscdevice * misc)
    208208{
    209209        struct miscdevice *c;
    210         struct class_device *class;
    211210        dev_t dev;
    212211        int err;
    213        
     212
    214213        down(&misc_sem);
    215214        list_for_each_entry(c, &misc_list, list) {
    216215                if (c->minor == misc->minor) {
     
    224223                while (--i >= 0)
    225224                        if ( (misc_minors[i>>3] & (1 << (i&7))) == 0)
    226225                                break;
    227                 if (i<0)
    228                 {
     226                if (i<0) {
    229227                        up(&misc_sem);
    230228                        return -EBUSY;
    231229                }
     
    240238        }
    241239        dev = MKDEV(MISC_MAJOR, misc->minor);
    242240
    243         class = class_simple_device_add(misc_class, dev,
    244                                         misc->dev, misc->name);
    245         if (IS_ERR(class)) {
    246                 err = PTR_ERR(class);
     241        misc->class = class_simple_device_add(misc_class, dev,
     242                                              misc->dev, misc->name);
     243        if (IS_ERR(misc->class)) {
     244                err = PTR_ERR(misc->class);
    247245                goto out;
    248246        }
    249247
  • fs/attr.c

    diff -urN linux-2.6.10/fs/attr.c linux/fs/attr.c
    old new  
    1111#include <linux/string.h>
    1212#include <linux/smp_lock.h>
    1313#include <linux/dnotify.h>
     14#include <linux/inotify.h>
    1415#include <linux/fcntl.h>
    1516#include <linux/quotaops.h>
    1617#include <linux/security.h>
     
    103104out:
    104105        return error;
    105106}
    106 
    107107EXPORT_SYMBOL(inode_setattr);
    108108
    109 int setattr_mask(unsigned int ia_valid)
     109void setattr_mask (unsigned int ia_valid, int *dn_mask, u32 *in_mask)
    110110{
    111         unsigned long dn_mask = 0;
     111        int dnmask;
     112        u32 inmask;
    112113
    113         if (ia_valid & ATTR_UID)
    114                 dn_mask |= DN_ATTRIB;
    115         if (ia_valid & ATTR_GID)
    116                 dn_mask |= DN_ATTRIB;
    117         if (ia_valid & ATTR_SIZE)
    118                 dn_mask |= DN_MODIFY;
    119         /* both times implies a utime(s) call */
    120         if ((ia_valid & (ATTR_ATIME|ATTR_MTIME)) == (ATTR_ATIME|ATTR_MTIME))
    121                 dn_mask |= DN_ATTRIB;
    122         else if (ia_valid & ATTR_ATIME)
    123                 dn_mask |= DN_ACCESS;
    124         else if (ia_valid & ATTR_MTIME)
    125                 dn_mask |= DN_MODIFY;
    126         if (ia_valid & ATTR_MODE)
    127                 dn_mask |= DN_ATTRIB;
    128         return dn_mask;
     114        inmask = 0;
     115        dnmask = 0;
     116
     117        if (!dn_mask || !in_mask) {
     118                return;
     119        }
     120        if (ia_valid & ATTR_UID) {
     121                inmask |= IN_ATTRIB;
     122                dnmask |= DN_ATTRIB;
     123        }
     124        if (ia_valid & ATTR_GID) {
     125                inmask |= IN_ATTRIB;
     126                dnmask |= DN_ATTRIB;
     127        }
     128        if (ia_valid & ATTR_SIZE) {
     129                inmask |= IN_MODIFY;
     130                dnmask |= DN_MODIFY;
     131        }
     132        /* both times implies a utime(s) call */
     133        if ((ia_valid & (ATTR_ATIME|ATTR_MTIME)) == (ATTR_ATIME|ATTR_MTIME)) {
     134                inmask |= IN_ATTRIB;
     135                dnmask |= DN_ATTRIB;
     136        }
     137        else if (ia_valid & ATTR_ATIME) {
     138                inmask |= IN_ACCESS;
     139                dnmask |= DN_ACCESS;
     140        }
     141        else if (ia_valid & ATTR_MTIME) {
     142                inmask |= IN_MODIFY;
     143                dnmask |= DN_MODIFY;
     144        }
     145        if (ia_valid & ATTR_MODE) {
     146                inmask |= IN_ATTRIB;
     147                dnmask |= DN_ATTRIB;
     148        }
     149
     150        *in_mask = inmask;
     151        *dn_mask = dnmask;
    129152}
    130153
    131154int notify_change(struct dentry * dentry, struct iattr * attr)
     
    184207                }
    185208        }
    186209        if (!error) {
    187                 unsigned long dn_mask = setattr_mask(ia_valid);
     210                int dn_mask;
     211                u32 in_mask;
     212
     213                setattr_mask (ia_valid, &dn_mask, &in_mask);
     214
    188215                if (dn_mask)
    189216                        dnotify_parent(dentry, dn_mask);
     217                if (in_mask) {
     218                        inotify_inode_queue_event(dentry->d_inode, in_mask, 0,
     219                                                  NULL);
     220                        inotify_dentry_parent_queue_event(dentry, in_mask, 0,
     221                                                          dentry->d_name.name);
     222                }
    190223        }
    191224        return error;
    192225}
  • fs/file_table.c

    diff -urN linux-2.6.10/fs/file_table.c linux/fs/file_table.c
    old new  
    1616#include <linux/eventpoll.h>
    1717#include <linux/mount.h>
    1818#include <linux/cdev.h>
     19#include <linux/inotify.h>
    1920
    2021/* sysctl tunables... */
    2122struct files_stat_struct files_stat = {
     
    120121        struct dentry *dentry = file->f_dentry;
    121122        struct vfsmount *mnt = file->f_vfsmnt;
    122123        struct inode *inode = dentry->d_inode;
     124        u32 mask;
     125
     126
     127        mask = (file->f_mode & FMODE_WRITE) ? IN_CLOSE_WRITE : IN_CLOSE_NOWRITE;
     128        inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
     129        inotify_inode_queue_event(inode, mask, 0, NULL);
    123130
    124131        might_sleep();
    125132        /*
  • fs/inode.c

    diff -urN linux-2.6.10/fs/inode.c linux/fs/inode.c
    old new  
    130130#ifdef CONFIG_QUOTA
    131131                memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
    132132#endif
     133#ifdef CONFIG_INOTIFY
     134                inode->inotify_data = NULL;
     135#endif
    133136                inode->i_pipe = NULL;
    134137                inode->i_bdev = NULL;
    135138                inode->i_cdev = NULL;
  • fs/namei.c

    diff -urN linux-2.6.10/fs/namei.c linux/fs/namei.c
    old new  
    2222#include <linux/quotaops.h>
    2323#include <linux/pagemap.h>
    2424#include <linux/dnotify.h>
     25#include <linux/inotify.h>
    2526#include <linux/smp_lock.h>
    2627#include <linux/personality.h>
    2728#include <linux/security.h>
     
    12421243        error = dir->i_op->create(dir, dentry, mode, nd);
    12431244        if (!error) {
    12441245                inode_dir_notify(dir, DN_CREATE);
     1246                inotify_inode_queue_event(dir, IN_CREATE_FILE,
     1247                                0, dentry->d_name.name);
    12451248                security_inode_post_create(dir, dentry, mode);
    12461249        }
    12471250        return error;
     
    15561559        error = dir->i_op->mknod(dir, dentry, mode, dev);
    15571560        if (!error) {
    15581561                inode_dir_notify(dir, DN_CREATE);
     1562                inotify_inode_queue_event(dir, IN_CREATE_FILE, 0,
     1563                                dentry->d_name.name);
    15591564                security_inode_post_mknod(dir, dentry, mode, dev);
    15601565        }
    15611566        return error;
     
    16291634        error = dir->i_op->mkdir(dir, dentry, mode);
    16301635        if (!error) {
    16311636                inode_dir_notify(dir, DN_CREATE);
     1637                inotify_inode_queue_event(dir, IN_CREATE_SUBDIR, 0,
     1638                                dentry->d_name.name);
    16321639                security_inode_post_mkdir(dir,dentry, mode);
    16331640        }
    16341641        return error;
     
    17241731        up(&dentry->d_inode->i_sem);
    17251732        if (!error) {
    17261733                inode_dir_notify(dir, DN_DELETE);
     1734                inotify_inode_queue_event(dir, IN_DELETE_SUBDIR, 0,
     1735                                dentry->d_name.name);
     1736                inotify_inode_queue_event(dentry->d_inode, IN_DELETE_SELF, 0,
     1737                                NULL);
     1738                inotify_inode_is_dead (dentry->d_inode);
    17271739                d_delete(dentry);
    17281740        }
    17291741        dput(dentry);
     
    17961808
    17971809        /* We don't d_delete() NFS sillyrenamed files--they still exist. */
    17981810        if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) {
    1799                 d_delete(dentry);
    18001811                inode_dir_notify(dir, DN_DELETE);
     1812                inotify_inode_queue_event(dir, IN_DELETE_FILE, 0,
     1813                                dentry->d_name.name);
     1814                inotify_inode_queue_event(dentry->d_inode, IN_DELETE_SELF, 0,
     1815                                NULL);
     1816                inotify_inode_is_dead (dentry->d_inode);
     1817                d_delete(dentry);
    18011818        }
    18021819        return error;
    18031820}
     
    18731890        error = dir->i_op->symlink(dir, dentry, oldname);
    18741891        if (!error) {
    18751892                inode_dir_notify(dir, DN_CREATE);
     1893                inotify_inode_queue_event(dir, IN_CREATE_FILE, 0,
     1894                                dentry->d_name.name);
    18761895                security_inode_post_symlink(dir, dentry, oldname);
    18771896        }
    18781897        return error;
     
    19461965        up(&old_dentry->d_inode->i_sem);
    19471966        if (!error) {
    19481967                inode_dir_notify(dir, DN_CREATE);
     1968                inotify_inode_queue_event(dir, IN_CREATE_FILE, 0,
     1969                                        new_dentry->d_name.name);
    19491970                security_inode_post_link(old_dentry, dir, new_dentry);
    19501971        }
    19511972        return error;
     
    21092130{
    21102131        int error;
    21112132        int is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
     2133        char *old_name;
     2134        u32 cookie;
    21122135
    21132136        if (old_dentry->d_inode == new_dentry->d_inode)
    21142137                return 0;
     
    21302153        DQUOT_INIT(old_dir);
    21312154        DQUOT_INIT(new_dir);
    21322155
     2156        old_name = inotify_oldname_init(old_dentry);
     2157
    21332158        if (is_dir)
    21342159                error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
    21352160        else
     
    21412166                        inode_dir_notify(old_dir, DN_DELETE);
    21422167                        inode_dir_notify(new_dir, DN_CREATE);
    21432168                }
     2169
     2170                cookie = inotify_get_cookie();
     2171
     2172                inotify_inode_queue_event(old_dir, IN_MOVED_FROM, cookie,
     2173                                          old_name);
     2174                inotify_inode_queue_event(new_dir, IN_MOVED_TO, cookie,
     2175                                          old_dentry->d_name.name);
    21442176        }
     2177        inotify_oldname_free(old_name);
     2178
    21452179        return error;
    21462180}
    21472181
  • fs/open.c

    diff -urN linux-2.6.10/fs/open.c linux/fs/open.c
    old new  
    1111#include <linux/smp_lock.h>
    1212#include <linux/quotaops.h>
    1313#include <linux/dnotify.h>
     14#include <linux/inotify.h>
    1415#include <linux/module.h>
    1516#include <linux/slab.h>
    1617#include <linux/tty.h>
     
    956957                        error = PTR_ERR(f);
    957958                        if (IS_ERR(f))
    958959                                goto out_error;
     960                        inotify_inode_queue_event(f->f_dentry->d_inode,
     961                                        IN_OPEN, 0, NULL);
     962                        inotify_dentry_parent_queue_event(f->f_dentry, IN_OPEN,
     963                                        0, f->f_dentry->d_name.name);
    959964                        fd_install(fd, f);
    960965                }
    961966out:
  • fs/read_write.c

    diff -urN linux-2.6.10/fs/read_write.c linux/fs/read_write.c
    old new  
    1111#include <linux/uio.h>
    1212#include <linux/smp_lock.h>
    1313#include <linux/dnotify.h>
     14#include <linux/inotify.h>
    1415#include <linux/security.h>
    1516#include <linux/module.h>
    1617#include <linux/syscalls.h>
     
    216217                                ret = file->f_op->read(file, buf, count, pos);
    217218                        else
    218219                                ret = do_sync_read(file, buf, count, pos);
    219                         if (ret > 0)
    220                                 dnotify_parent(file->f_dentry, DN_ACCESS);
     220                        if (ret > 0) {
     221                                struct dentry *dentry = file->f_dentry;
     222                                dnotify_parent(dentry, DN_ACCESS);
     223                                inotify_dentry_parent_queue_event(dentry,
     224                                                IN_ACCESS, 0, dentry->d_name.name);
     225                                inotify_inode_queue_event(inode, IN_ACCESS, 0,
     226                                                NULL);
     227                        }
    221228                }
    222229        }
    223230
     
    260267                                ret = file->f_op->write(file, buf, count, pos);
    261268                        else
    262269                                ret = do_sync_write(file, buf, count, pos);
    263                         if (ret > 0)
    264                                 dnotify_parent(file->f_dentry, DN_MODIFY);
     270                        if (ret > 0) {
     271                                struct dentry *dentry = file->f_dentry;
     272                                dnotify_parent(dentry, DN_MODIFY);
     273                                inotify_dentry_parent_queue_event(dentry,
     274                                                IN_MODIFY, 0, dentry->d_name.name);
     275                                inotify_inode_queue_event(inode, IN_MODIFY, 0,
     276                                                NULL);
     277                        }
    265278                }
    266279        }
    267280
     
    493506out:
    494507        if (iov != iovstack)
    495508                kfree(iov);
    496         if ((ret + (type == READ)) > 0)
    497                 dnotify_parent(file->f_dentry,
    498                                 (type == READ) ? DN_ACCESS : DN_MODIFY);
     509        if ((ret + (type == READ)) > 0) {
     510                struct dentry *dentry = file->f_dentry;
     511                dnotify_parent(dentry, (type == READ) ? DN_ACCESS : DN_MODIFY);
     512                inotify_dentry_parent_queue_event(dentry,
     513                                (type == READ) ? IN_ACCESS : IN_MODIFY, 0,
     514                                dentry->d_name.name);
     515                inotify_inode_queue_event (dentry->d_inode,
     516                                (type == READ) ? IN_ACCESS : IN_MODIFY, 0, NULL);
     517        }
    499518        return ret;
    500519}
    501520
  • fs/super.c

    diff -urN linux-2.6.10/fs/super.c linux/fs/super.c
    old new  
    3838#include <linux/idr.h>
    3939#include <linux/kobject.h>
    4040#include <asm/uaccess.h>
     41#include <linux/inotify.h>
    4142
    4243
    4344void get_filesystem(struct file_system_type *fs);
     
    227228
    228229        if (root) {
    229230                sb->s_root = NULL;
     231                inotify_super_block_umount(sb);
    230232                shrink_dcache_parent(root);
    231233                shrink_dcache_anon(&sb->s_anon);
    232234                dput(root);
  • include/linux/fs.h

    diff -urN linux-2.6.10/include/linux/fs.h linux/include/linux/fs.h
    old new  
    2727struct kstatfs;
    2828struct vm_area_struct;
    2929struct vfsmount;
     30struct inotify_inode_data;
    3031
    3132/*
    3233 * It's silly to have NR_OPEN bigger than NR_FILE, but you can change
     
    473474        struct dnotify_struct   *i_dnotify; /* for directory notifications */
    474475#endif
    475476
     477#ifdef CONFIG_INOTIFY
     478        struct inotify_inode_data *inotify_data;
     479#endif
     480
    476481        unsigned long           i_state;
    477482        unsigned long           dirtied_when;   /* jiffies of first dirtying */
    478483
     
    13531358extern int do_remount_sb(struct super_block *sb, int flags,
    13541359                         void *data, int force);
    13551360extern sector_t bmap(struct inode *, sector_t);
    1356 extern int setattr_mask(unsigned int);
     1361extern void setattr_mask(unsigned int, int *, u32 *);
    13571362extern int notify_change(struct dentry *, struct iattr *);
    13581363extern int permission(struct inode *, int, struct nameidata *);
    13591364extern int generic_permission(struct inode *, int,
  • include/linux/inotify.h

    diff -urN linux-2.6.10/include/linux/inotify.h linux/include/linux/inotify.h
    old new  
     1/*
     2 * Inode based directory notification for Linux
     3 *
     4 * Copyright (C) 2004 John McCutchan
     5 */
     6
     7#ifndef _LINUX_INOTIFY_H
     8#define _LINUX_INOTIFY_H
     9
     10#include <linux/types.h>
     11#include <linux/limits.h>
     12
     13/* this size could limit things, since technically we could need PATH_MAX */
     14#define INOTIFY_FILENAME_MAX    256
     15
     16/*
     17 * struct inotify_event - structure read from the inotify device for each event
     18 *
     19 * When you are watching a directory, you will receive the filename for events
     20 * such as IN_CREATE, IN_DELETE, IN_OPEN, IN_CLOSE, ...
     21 *
     22 * Note: When reading from the device you must provide a buffer that is a
     23 * multiple of sizeof(struct inotify_event)
     24 */
     25struct inotify_event {
     26        __s32 wd;
     27        __u32 mask;
     28        __u32 cookie;
     29        size_t len;
     30#ifdef __KERNEL__
     31        char *filename;
     32#else
     33        char filename[0];
     34#endif
     35};
     36
     37/*
     38 * struct inotify_watch_request - represents a watch request
     39 *
     40 * Pass to the inotify device via the INOTIFY_WATCH ioctl
     41 */
     42struct inotify_watch_request {
     43        char *dirname;          /* directory name */
     44        __u32 mask;             /* event mask */
     45};
     46
     47/* the following are legal, implemented events */
     48#define IN_ACCESS               0x00000001      /* File was accessed */
     49#define IN_MODIFY               0x00000002      /* File was modified */
     50#define IN_ATTRIB               0x00000004      /* File changed attributes */
     51#define IN_CLOSE_WRITE          0x00000008      /* Writtable file was closed */
     52#define IN_CLOSE_NOWRITE        0x00000010      /* Unwrittable file closed */
     53#define IN_OPEN                 0x00000020      /* File was opened */
     54#define IN_MOVED_FROM           0x00000040      /* File was moved from X */
     55#define IN_MOVED_TO             0x00000080      /* File was moved to Y */
     56#define IN_DELETE_SUBDIR        0x00000100      /* Subdir was deleted */
     57#define IN_DELETE_FILE          0x00000200      /* Subfile was deleted */
     58#define IN_CREATE_SUBDIR        0x00000400      /* Subdir was created */
     59#define IN_CREATE_FILE          0x00000800      /* Subfile was created */
     60#define IN_DELETE_SELF          0x00001000      /* Self was deleted */
     61#define IN_UNMOUNT              0x00002000      /* Backing fs was unmounted */
     62#define IN_Q_OVERFLOW           0x00004000      /* Event queued overflowed */
     63#define IN_IGNORED              0x00008000      /* File was ignored */
     64
     65/* special flags */
     66#define IN_ALL_EVENTS           0xffffffff      /* All the events */
     67#define IN_CLOSE                (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)
     68
     69#define INOTIFY_IOCTL_MAGIC     'Q'
     70#define INOTIFY_IOCTL_MAXNR     2
     71
     72#define INOTIFY_WATCH           _IOR(INOTIFY_IOCTL_MAGIC, 1, struct inotify_watch_request)
     73#define INOTIFY_IGNORE          _IOR(INOTIFY_IOCTL_MAGIC, 2, int)
     74
     75#ifdef __KERNEL__
     76
     77#include <linux/dcache.h>
     78#include <linux/fs.h>
     79#include <linux/config.h>
     80
     81struct inotify_inode_data {
     82        struct list_head watches;
     83        __u32 watch_mask;
     84        spinlock_t lock;
     85        atomic_t count;
     86};
     87
     88#ifdef CONFIG_INOTIFY
     89
     90extern void inotify_inode_queue_event(struct inode *, __u32, __u32,
     91                                      const char *);
     92extern void inotify_dentry_parent_queue_event(struct dentry *, __u32, __u32,
     93                                              const char *);
     94extern void inotify_super_block_umount(struct super_block *);
     95extern void inotify_inode_is_dead(struct inode *);
     96extern __u32 inotify_get_cookie(void);
     97extern __u32 setattr_mask_inotify(unsigned int);
     98
     99/* this could be kstrdup if only we could add that to lib/string.c */
     100static inline char * inotify_oldname_init(struct dentry *old_dentry)
     101{
     102        char *old_name;
     103
     104        old_name = kmalloc(strlen(old_dentry->d_name.name) + 1, GFP_KERNEL);
     105        if (old_name)
     106                strcpy(old_name, old_dentry->d_name.name);
     107        return old_name;
     108}
     109
     110static inline void inotify_oldname_free(const char *old_name)
     111{
     112        kfree(old_name);
     113}
     114
     115#else
     116
     117static inline void inotify_inode_queue_event(struct inode *inode,
     118                                             __u32 mask, __u32 cookie,
     119                                             const char *filename)
     120{
     121}
     122
     123static inline void inotify_dentry_parent_queue_event(struct dentry *dentry,
     124                                                     __u32 mask, __u32 cookie,
     125                                                     const char *filename)
     126{
     127}
     128
     129static inline void inotify_super_block_umount(struct super_block *sb)
     130{
     131}
     132
     133static inline void inotify_inode_is_dead(struct inode *inode)
     134{
     135}
     136
     137static inline char * inotify_oldname_init(struct dentry *old_dentry)
     138{
     139        return NULL;
     140}
     141
     142static inline __u32 inotify_get_cookie(void)
     143{
     144        return 0;
     145}
     146
     147static inline void inotify_oldname_free(const char *old_name)
     148{
     149}
     150
     151static inline int setattr_mask_inotify(unsigned int ia_mask)
     152{
     153        return 0;
     154}
     155
     156#endif  /* CONFIG_INOTIFY */
     157
     158#endif  /* __KERNEL __ */
     159
     160#endif  /* _LINUX_INOTIFY_H */
  • include/linux/miscdevice.h

    diff -urN linux-2.6.10/include/linux/miscdevice.h linux/include/linux/miscdevice.h
    old new  
    22#define _LINUX_MISCDEVICE_H
    33#include <linux/module.h>
    44#include <linux/major.h>
     5#include <linux/device.h>
    56
    67#define PSMOUSE_MINOR  1
    78#define MS_BUSMOUSE_MINOR 2
     
    3233
    3334struct device;
    3435
    35 struct miscdevice
    36 {
     36struct miscdevice  {
    3737        int minor;
    3838        const char *name;
    3939        struct file_operations *fops;
    4040        struct list_head list;
    4141        struct device *dev;
     42        struct class_device *class;
    4243        char devfs_name[64];
    4344};
    4445
  • include/linux/sched.h

    diff -urN linux-2.6.10/include/linux/sched.h linux/include/linux/sched.h
    old new  
    353353        atomic_t processes;     /* How many processes does this user have? */
    354354        atomic_t files;         /* How many open files does this user have? */
    355355        atomic_t sigpending;    /* How many pending signals does this user have? */
     356        atomic_t inotify_watches;       /* How many inotify watches does this user have? */
     357        atomic_t inotify_devs;  /* How many inotify devs does this user have opened? */
    356358        /* protected by mq_lock */
    357359        unsigned long mq_bytes; /* How many bytes can be allocated to mqueue? */
    358360        unsigned long locked_shm; /* How many pages of mlocked shm ? */
  • kernel/user.c

    diff -urN linux-2.6.10/kernel/user.c linux/kernel/user.c
    old new  
    119119                atomic_set(&new->processes, 0);
    120120                atomic_set(&new->files, 0);
    121121                atomic_set(&new->sigpending, 0);
     122                atomic_set(&new->inotify_watches, 0);
     123                atomic_set(&new->inotify_devs, 0);
    122124
    123125                new->mq_bytes = 0;
    124126                new->locked_shm = 0;
Note: See TracBrowser for help on using the repository browser.