fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / fs / dnotify.c
index daee2ed..936409f 100644 (file)
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 
-int dir_notify_enable = 1;
+int dir_notify_enable __read_mostly = 1;
 
-static rwlock_t dn_lock = RW_LOCK_UNLOCKED;
-static kmem_cache_t *dn_cache;
+static struct kmem_cache *dn_cache __read_mostly;
 
 static void redo_inode_mask(struct inode *inode)
 {
@@ -43,10 +42,10 @@ void dnotify_flush(struct file *filp, fl_owner_t id)
        struct dnotify_struct **prev;
        struct inode *inode;
 
-       inode = filp->f_dentry->d_inode;
+       inode = filp->f_path.dentry->d_inode;
        if (!S_ISDIR(inode->i_mode))
                return;
-       write_lock(&dn_lock);
+       spin_lock(&inode->i_lock);
        prev = &inode->i_dnotify;
        while ((dn = *prev) != NULL) {
                if ((dn->dn_owner == id) && (dn->dn_filp == filp)) {
@@ -57,7 +56,7 @@ void dnotify_flush(struct file *filp, fl_owner_t id)
                }
                prev = &dn->dn_next;
        }
-       write_unlock(&dn_lock);
+       spin_unlock(&inode->i_lock);
 }
 
 int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
@@ -75,13 +74,13 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
        }
        if (!dir_notify_enable)
                return -EINVAL;
-       inode = filp->f_dentry->d_inode;
+       inode = filp->f_path.dentry->d_inode;
        if (!S_ISDIR(inode->i_mode))
                return -ENOTDIR;
-       dn = kmem_cache_alloc(dn_cache, SLAB_KERNEL);
+       dn = kmem_cache_alloc(dn_cache, GFP_KERNEL);
        if (dn == NULL)
                return -ENOMEM;
-       write_lock(&dn_lock);
+       spin_lock(&inode->i_lock);
        prev = &inode->i_dnotify;
        while ((odn = *prev) != NULL) {
                if ((odn->dn_owner == id) && (odn->dn_filp == filp)) {
@@ -93,7 +92,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
                prev = &odn->dn_next;
        }
 
-       error = f_setown(filp, current->pid, 0);
+       error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0);
        if (error)
                goto out_free;
 
@@ -104,12 +103,16 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
        inode->i_dnotify_mask |= arg & ~DN_MULTISHOT;
        dn->dn_next = inode->i_dnotify;
        inode->i_dnotify = dn;
-out:
-       write_unlock(&dn_lock);
-       return error;
+       spin_unlock(&inode->i_lock);
+
+       if (filp->f_op && filp->f_op->dir_notify)
+               return filp->f_op->dir_notify(filp, arg);
+       return 0;
+
 out_free:
+       spin_unlock(&inode->i_lock);
        kmem_cache_free(dn_cache, dn);
-       goto out;
+       return error;
 }
 
 void __inode_dir_notify(struct inode *inode, unsigned long event)
@@ -119,7 +122,7 @@ void __inode_dir_notify(struct inode *inode, unsigned long event)
        struct fown_struct *    fown;
        int                     changed = 0;
 
-       write_lock(&dn_lock);
+       spin_lock(&inode->i_lock);
        prev = &inode->i_dnotify;
        while ((dn = *prev) != NULL) {
                if ((dn->dn_mask & event) == 0) {
@@ -138,7 +141,7 @@ void __inode_dir_notify(struct inode *inode, unsigned long event)
        }
        if (changed)
                redo_inode_mask(inode);
-       write_unlock(&dn_lock);
+       spin_unlock(&inode->i_lock);
 }
 
 EXPORT_SYMBOL(__inode_dir_notify);