drm/nouveau: off by one in init_i2c_device_find()
[safe/jmp/linux-2.6] / fs / dcache.c
index 4365998..d96047b 100644 (file)
@@ -536,7 +536,7 @@ restart:
  */
 static void prune_dcache(int count)
 {
-       struct super_block *sb;
+       struct super_block *sb, *n;
        int w_count;
        int unused = dentry_stat.nr_unused;
        int prune_ratio;
@@ -545,13 +545,14 @@ static void prune_dcache(int count)
        if (unused == 0 || count == 0)
                return;
        spin_lock(&dcache_lock);
-restart:
        if (count >= unused)
                prune_ratio = 1;
        else
                prune_ratio = unused / count;
        spin_lock(&sb_lock);
-       list_for_each_entry(sb, &super_blocks, s_list) {
+       list_for_each_entry_safe(sb, n, &super_blocks, s_list) {
+               if (list_empty(&sb->s_instances))
+                       continue;
                if (sb->s_nr_dentry_unused == 0)
                        continue;
                sb->s_count++;
@@ -590,14 +591,10 @@ restart:
                }
                spin_lock(&sb_lock);
                count -= pruned;
-               /*
-                * restart only when sb is no longer on the list and
-                * we have more work to do.
-                */
-               if (__put_super_and_need_restart(sb) && count > 0) {
-                       spin_unlock(&sb_lock);
-                       goto restart;
-               }
+               __put_super(sb);
+               /* more work left to do? */
+               if (count <= 0)
+                       break;
        }
        spin_unlock(&sb_lock);
        spin_unlock(&dcache_lock);
@@ -1222,7 +1219,6 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
                        BUG_ON(!(new->d_flags & DCACHE_DISCONNECTED));
                        spin_unlock(&dcache_lock);
                        security_d_instantiate(new, inode);
-                       d_rehash(dentry);
                        d_move(new, dentry);
                        iput(inode);
                } else {
@@ -1530,6 +1526,7 @@ void d_delete(struct dentry * dentry)
        spin_lock(&dentry->d_lock);
        isdir = S_ISDIR(dentry->d_inode->i_mode);
        if (atomic_read(&dentry->d_count) == 1) {
+               dentry->d_flags &= ~DCACHE_CANT_MOUNT;
                dentry_iput(dentry);
                fsnotify_nameremove(dentry, isdir);
                return;
@@ -2191,6 +2188,30 @@ int is_subdir(struct dentry *new_dentry, struct dentry *old_dentry)
        return result;
 }
 
+int path_is_under(struct path *path1, struct path *path2)
+{
+       struct vfsmount *mnt = path1->mnt;
+       struct dentry *dentry = path1->dentry;
+       int res;
+       spin_lock(&vfsmount_lock);
+       if (mnt != path2->mnt) {
+               for (;;) {
+                       if (mnt->mnt_parent == mnt) {
+                               spin_unlock(&vfsmount_lock);
+                               return 0;
+                       }
+                       if (mnt->mnt_parent == path2->mnt)
+                               break;
+                       mnt = mnt->mnt_parent;
+               }
+               dentry = mnt->mnt_mountpoint;
+       }
+       res = is_subdir(dentry, path2->dentry);
+       spin_unlock(&vfsmount_lock);
+       return res;
+}
+EXPORT_SYMBOL(path_is_under);
+
 void d_genocide(struct dentry *root)
 {
        struct dentry *this_parent = root;