source: scripts/untested/blfs-patches/inotify-0.17-rml-2.6.10-2.patch @ 617118d

clfs-1.2clfs-2.1clfs-3.0.0-systemdclfs-3.0.0-sysvinitsystemdsysvinit
Last change on this file since 617118d was 617118d, checked in by Jim Gifford <clfs@…>, 18 years ago

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

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

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