OSDN Git Service

Merge 4.4.173 into android-4.4-p
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / fs / super.c
index 652c9e6..eb27955 100644 (file)
@@ -118,13 +118,23 @@ static unsigned long super_cache_count(struct shrinker *shrink,
        sb = container_of(shrink, struct super_block, s_shrink);
 
        /*
-        * Don't call trylock_super as it is a potential
-        * scalability bottleneck. The counts could get updated
-        * between super_cache_count and super_cache_scan anyway.
-        * Call to super_cache_count with shrinker_rwsem held
-        * ensures the safety of call to list_lru_shrink_count() and
-        * s_op->nr_cached_objects().
+        * We don't call trylock_super() here as it is a scalability bottleneck,
+        * so we're exposed to partial setup state. The shrinker rwsem does not
+        * protect filesystem operations backing list_lru_shrink_count() or
+        * s_op->nr_cached_objects(). Counts can change between
+        * super_cache_count and super_cache_scan, so we really don't need locks
+        * here.
+        *
+        * However, if we are currently mounting the superblock, the underlying
+        * filesystem might be in a state of partial construction and hence it
+        * is dangerous to access it.  trylock_super() uses a MS_BORN check to
+        * avoid this situation, so do the same here. The memory barrier is
+        * matched with the one in mount_fs() as we don't hold locks here.
         */
+       if (!(sb->s_flags & MS_BORN))
+               return 0;
+       smp_rmb();
+
        if (sb->s_op && sb->s_op->nr_cached_objects)
                total_objects = sb->s_op->nr_cached_objects(sb, sc);
 
@@ -1151,6 +1161,14 @@ mount_fs(struct file_system_type *type, int flags, const char *name, struct vfsm
        sb = root->d_sb;
        BUG_ON(!sb);
        WARN_ON(!sb->s_bdi);
+
+       /*
+        * Write barrier is for super_cache_count(). We place it before setting
+        * MS_BORN as the data dependency between the two functions is the
+        * superblock structure contents that we just set up, not the MS_BORN
+        * flag.
+        */
+       smp_wmb();
        sb->s_flags |= MS_BORN;
 
        error = security_sb_kern_mount(sb, flags, secdata);