Merge tag 'v3.10.70' into update
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / fs / super.c
index 7465d4364208a2e751d2d3a7c8a8c1cc10d2d7c3..dbd72931bc00768a19da0dfff2bcac9f300d8a71 100644 (file)
@@ -38,6 +38,8 @@
 
 
 LIST_HEAD(super_blocks);
+EXPORT_SYMBOL_GPL(super_blocks);
+
 DEFINE_SPINLOCK(sb_lock);
 
 static char *sb_writers_name[SB_FREEZE_LEVELS] = {
@@ -76,6 +78,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;
@@ -336,19 +340,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;
@@ -463,11 +467,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;
                }
        }
@@ -660,10 +659,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);
@@ -1156,7 +1155,9 @@ void __sb_end_write(struct super_block *sb, int level)
        smp_mb();
        if (waitqueue_active(&sb->s_writers.wait))
                wake_up(&sb->s_writers.wait);
+       lockdep_off();
        rwsem_release(&sb->s_writers.lock_map[level-1], 1, _RET_IP_);
+       lockdep_on();
 }
 EXPORT_SYMBOL(__sb_end_write);
 
@@ -1182,7 +1183,9 @@ static void acquire_freeze_lock(struct super_block *sb, int level, bool trylock,
                                break;
                        }
        }
+       lockdep_off();
        rwsem_acquire_read(&sb->s_writers.lock_map[level-1], 0, trylock, ip);
+       lockdep_on();
 }
 #endif