]> rtime.felk.cvut.cz Git - zynq/linux.git/blobdiff - fs/dcache.c
Apply preempt_rt patch-4.9-rt1.patch.xz
[zynq/linux.git] / fs / dcache.c
index 5c7cc953ac8191d80bc899f5bb510e9d71d7d69d..a9bb31f1c1af47c1d0ad5808d269f322903e28d0 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/fsnotify.h>
+#include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/hash.h>
@@ -750,6 +751,8 @@ static inline bool fast_dput(struct dentry *dentry)
  */
 void dput(struct dentry *dentry)
 {
+       struct dentry *parent;
+
        if (unlikely(!dentry))
                return;
 
@@ -788,9 +791,18 @@ repeat:
        return;
 
 kill_it:
-       dentry = dentry_kill(dentry);
-       if (dentry) {
-               cond_resched();
+       parent = dentry_kill(dentry);
+       if (parent) {
+               int r;
+
+               if (parent == dentry) {
+                       /* the task with the highest priority won't schedule */
+                       r = cond_resched();
+                       if (!r)
+                               cpu_chill();
+               } else {
+                       dentry = parent;
+               }
                goto repeat;
        }
 }
@@ -2321,7 +2333,7 @@ again:
        if (dentry->d_lockref.count == 1) {
                if (!spin_trylock(&inode->i_lock)) {
                        spin_unlock(&dentry->d_lock);
-                       cpu_relax();
+                       cpu_chill();
                        goto again;
                }
                dentry->d_flags &= ~DCACHE_CANT_MOUNT;
@@ -2381,21 +2393,24 @@ static inline void end_dir_add(struct inode *dir, unsigned n)
 
 static void d_wait_lookup(struct dentry *dentry)
 {
-       if (d_in_lookup(dentry)) {
-               DECLARE_WAITQUEUE(wait, current);
-               add_wait_queue(dentry->d_wait, &wait);
-               do {
-                       set_current_state(TASK_UNINTERRUPTIBLE);
-                       spin_unlock(&dentry->d_lock);
-                       schedule();
-                       spin_lock(&dentry->d_lock);
-               } while (d_in_lookup(dentry));
-       }
+       struct swait_queue __wait;
+
+       if (!d_in_lookup(dentry))
+               return;
+
+       INIT_LIST_HEAD(&__wait.task_list);
+       do {
+               prepare_to_swait(dentry->d_wait, &__wait, TASK_UNINTERRUPTIBLE);
+               spin_unlock(&dentry->d_lock);
+               schedule();
+               spin_lock(&dentry->d_lock);
+       } while (d_in_lookup(dentry));
+       finish_swait(dentry->d_wait, &__wait);
 }
 
 struct dentry *d_alloc_parallel(struct dentry *parent,
                                const struct qstr *name,
-                               wait_queue_head_t *wq)
+                               struct swait_queue_head *wq)
 {
        unsigned int hash = name->hash;
        struct hlist_bl_head *b = in_lookup_hash(parent, hash);
@@ -2504,7 +2519,7 @@ void __d_lookup_done(struct dentry *dentry)
        hlist_bl_lock(b);
        dentry->d_flags &= ~DCACHE_PAR_LOOKUP;
        __hlist_bl_del(&dentry->d_u.d_in_lookup_hash);
-       wake_up_all(dentry->d_wait);
+       swake_up_all(dentry->d_wait);
        dentry->d_wait = NULL;
        hlist_bl_unlock(b);
        INIT_HLIST_NODE(&dentry->d_u.d_alias);
@@ -3601,6 +3616,11 @@ EXPORT_SYMBOL(d_genocide);
 
 void __init vfs_caches_init_early(void)
 {
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(in_lookup_hashtable); i++)
+               INIT_HLIST_BL_HEAD(&in_lookup_hashtable[i]);
+
        dcache_init_early();
        inode_init_early();
 }