video: tegra: dc: Add quick for Vizio P series
[linux-3.10.git] / fs / super.c
index 12f1237..eb03b48 100644 (file)
@@ -76,6 +76,8 @@ static int prune_super(struct shrinker *shrink, struct shrink_control *sc)
 
        total_objects = sb->s_nr_dentry_unused +
                        sb->s_nr_inodes_unused + fs_objects + 1;
+       if (!total_objects)
+               total_objects = 1;
 
        if (sc->nr_to_scan) {
                int     dentries;
@@ -152,28 +154,9 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags)
        static const struct super_operations default_op;
 
        if (s) {
-               if (security_sb_alloc(s)) {
-                       /*
-                        * We cannot call security_sb_free() without
-                        * security_sb_alloc() succeeding. So bail out manually
-                        */
-                       kfree(s);
-                       s = NULL;
-                       goto out;
-               }
-#ifdef CONFIG_SMP
-               s->s_files = alloc_percpu(struct list_head);
-               if (!s->s_files)
-                       goto err_out;
-               else {
-                       int i;
+               if (security_sb_alloc(s))
+                       goto out_free_sb;
 
-                       for_each_possible_cpu(i)
-                               INIT_LIST_HEAD(per_cpu_ptr(s->s_files, i));
-               }
-#else
-               INIT_LIST_HEAD(&s->s_files);
-#endif
                if (init_sb_writers(s, type))
                        goto err_out;
                s->s_flags = flags;
@@ -223,11 +206,8 @@ out:
        return s;
 err_out:
        security_sb_free(s);
-#ifdef CONFIG_SMP
-       if (s->s_files)
-               free_percpu(s->s_files);
-#endif
        destroy_sb_writers(s);
+out_free_sb:
        kfree(s);
        s = NULL;
        goto out;
@@ -241,9 +221,6 @@ err_out:
  */
 static inline void destroy_super(struct super_block *s)
 {
-#ifdef CONFIG_SMP
-       free_percpu(s->s_files);
-#endif
        destroy_sb_writers(s);
        security_sb_free(s);
        WARN_ON(!list_empty(&s->s_mounts));
@@ -336,19 +313,19 @@ EXPORT_SYMBOL(deactivate_super);
  *     and want to turn it into a full-blown active reference.  grab_super()
  *     is called with sb_lock held and drops it.  Returns 1 in case of
  *     success, 0 if we had failed (superblock contents was already dead or
- *     dying when grab_super() had been called).
+ *     dying when grab_super() had been called).  Note that this is only
+ *     called for superblocks not in rundown mode (== ones still on ->fs_supers
+ *     of their type), so increment of ->s_count is OK here.
  */
 static int grab_super(struct super_block *s) __releases(sb_lock)
 {
-       if (atomic_inc_not_zero(&s->s_active)) {
-               spin_unlock(&sb_lock);
-               return 1;
-       }
-       /* it's going away */
        s->s_count++;
        spin_unlock(&sb_lock);
-       /* wait for it to die */
        down_write(&s->s_umount);
+       if ((s->s_flags & MS_BORN) && atomic_inc_not_zero(&s->s_active)) {
+               put_super(s);
+               return 1;
+       }
        up_write(&s->s_umount);
        put_super(s);
        return 0;
@@ -414,6 +391,11 @@ void generic_shutdown_super(struct super_block *sb)
 
                evict_inodes(sb);
 
+               if (sb->s_dio_done_wq) {
+                       destroy_workqueue(sb->s_dio_done_wq);
+                       sb->s_dio_done_wq = NULL;
+               }
+
                if (sop->put_super)
                        sop->put_super(sb);
 
@@ -447,14 +429,13 @@ struct super_block *sget(struct file_system_type *type,
                        void *data)
 {
        struct super_block *s = NULL;
-       struct hlist_node *node;
        struct super_block *old;
        int err;
 
 retry:
        spin_lock(&sb_lock);
        if (test) {
-               hlist_for_each_entry(old, node, &type->fs_supers, s_instances) {
+               hlist_for_each_entry(old, &type->fs_supers, s_instances) {
                        if (!test(old, data))
                                continue;
                        if (!grab_super(old))
@@ -464,11 +445,6 @@ retry:
                                destroy_super(s);
                                s = NULL;
                        }
-                       down_write(&old->s_umount);
-                       if (unlikely(!(old->s_flags & MS_BORN))) {
-                               deactivate_locked_super(old);
-                               goto retry;
-                       }
                        return old;
                }
        }
@@ -554,10 +530,9 @@ void iterate_supers_type(struct file_system_type *type,
        void (*f)(struct super_block *, void *), void *arg)
 {
        struct super_block *sb, *p = NULL;
-       struct hlist_node *node;
 
        spin_lock(&sb_lock);
-       hlist_for_each_entry(sb, node, &type->fs_supers, s_instances) {
+       hlist_for_each_entry(sb, &type->fs_supers, s_instances) {
                sb->s_count++;
                spin_unlock(&sb_lock);
 
@@ -662,10 +637,10 @@ restart:
                if (hlist_unhashed(&sb->s_instances))
                        continue;
                if (sb->s_bdev == bdev) {
-                       if (grab_super(sb)) /* drops sb_lock */
-                               return sb;
-                       else
+                       if (!grab_super(sb))
                                goto restart;
+                       up_write(&sb->s_umount);
+                       return sb;
                }
        }
        spin_unlock(&sb_lock);
@@ -732,7 +707,8 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
           make sure there are no rw files opened */
        if (remount_ro) {
                if (force) {
-                       mark_files_ro(sb);
+                       sb->s_readonly_remount = 1;
+                       smp_wmb();
                } else {
                        retval = sb_prepare_remount_readonly(sb);
                        if (retval)
@@ -842,7 +818,7 @@ int get_anon_bdev(dev_t *p)
        else if (error)
                return -EAGAIN;
 
-       if ((dev & MAX_IDR_MASK) == (1 << MINORBITS)) {
+       if (dev == (1 << MINORBITS)) {
                spin_lock(&unnamed_dev_lock);
                ida_remove(&unnamed_dev_ida, dev);
                if (unnamed_dev_start > dev)