]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - fs/super.c
cpuimx27: fix i2c bus selection
[net-next-2.6.git] / fs / super.c
index 938119ab8dcbc28f3f9853bc0808d6d70cd51d55..9674ab2c8718c3f1061f3556e6ec3e9b479cb8a9 100644 (file)
@@ -305,8 +305,13 @@ retry:
                        if (s) {
                                up_write(&s->s_umount);
                                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;
                }
        }
@@ -358,10 +363,10 @@ EXPORT_SYMBOL(drop_super);
  */
 void sync_supers(void)
 {
-       struct super_block *sb, *n;
+       struct super_block *sb, *p = NULL;
 
        spin_lock(&sb_lock);
-       list_for_each_entry_safe(sb, n, &super_blocks, s_list) {
+       list_for_each_entry(sb, &super_blocks, s_list) {
                if (list_empty(&sb->s_instances))
                        continue;
                if (sb->s_op->write_super && sb->s_dirt) {
@@ -374,11 +379,13 @@ void sync_supers(void)
                        up_read(&sb->s_umount);
 
                        spin_lock(&sb_lock);
-                       /* lock was dropped, must reset next */
-                       list_safe_reset_next(sb, n, s_list);
-                       __put_super(sb);
+                       if (p)
+                               __put_super(p);
+                       p = sb;
                }
        }
+       if (p)
+               __put_super(p);
        spin_unlock(&sb_lock);
 }
 
@@ -392,10 +399,10 @@ void sync_supers(void)
  */
 void iterate_supers(void (*f)(struct super_block *, void *), void *arg)
 {
-       struct super_block *sb, *n;
+       struct super_block *sb, *p = NULL;
 
        spin_lock(&sb_lock);
-       list_for_each_entry_safe(sb, n, &super_blocks, s_list) {
+       list_for_each_entry(sb, &super_blocks, s_list) {
                if (list_empty(&sb->s_instances))
                        continue;
                sb->s_count++;
@@ -407,10 +414,12 @@ void iterate_supers(void (*f)(struct super_block *, void *), void *arg)
                up_read(&sb->s_umount);
 
                spin_lock(&sb_lock);
-               /* lock was dropped, must reset next */
-               list_safe_reset_next(sb, n, s_list);
-               __put_super(sb);
+               if (p)
+                       __put_super(p);
+               p = sb;
        }
+       if (p)
+               __put_super(p);
        spin_unlock(&sb_lock);
 }
 
@@ -572,10 +581,10 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force)
 
 static void do_emergency_remount(struct work_struct *work)
 {
-       struct super_block *sb, *n;
+       struct super_block *sb, *p = NULL;
 
        spin_lock(&sb_lock);
-       list_for_each_entry_safe(sb, n, &super_blocks, s_list) {
+       list_for_each_entry(sb, &super_blocks, s_list) {
                if (list_empty(&sb->s_instances))
                        continue;
                sb->s_count++;
@@ -589,10 +598,12 @@ static void do_emergency_remount(struct work_struct *work)
                }
                up_write(&sb->s_umount);
                spin_lock(&sb_lock);
-               /* lock was dropped, must reset next */
-               list_safe_reset_next(sb, n, s_list);
-               __put_super(sb);
+               if (p)
+                       __put_super(p);
+               p = sb;
        }
+       if (p)
+               __put_super(p);
        spin_unlock(&sb_lock);
        kfree(work);
        printk("Emergency Remount complete\n");
@@ -773,7 +784,16 @@ int get_sb_bdev(struct file_system_type *fs_type,
                        goto error_bdev;
                }
 
+               /*
+                * s_umount nests inside bd_mutex during
+                * __invalidate_device().  close_bdev_exclusive()
+                * acquires bd_mutex and can't be called under
+                * s_umount.  Drop s_umount temporarily.  This is safe
+                * as we're holding an active reference.
+                */
+               up_write(&s->s_umount);
                close_bdev_exclusive(bdev, mode);
+               down_write(&s->s_umount);
        } else {
                char b[BDEVNAME_SIZE];
 
@@ -909,6 +929,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
                goto out_free_secdata;
        BUG_ON(!mnt->mnt_sb);
        WARN_ON(!mnt->mnt_sb->s_bdi);
+       mnt->mnt_sb->s_flags |= MS_BORN;
 
        error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata);
        if (error)