]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
fs: assign sb->s_bdi to default_backing_dev_info if the bdi is going away
authorJens Axboe <jaxboe@fusionio.com>
Thu, 17 Mar 2011 10:13:12 +0000 (11:13 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Sun, 27 Mar 2011 18:36:26 +0000 (11:36 -0700)
commit 95f28604a65b1c40b6c6cd95e58439cd7ded3add upstream.

We don't have proper reference counting for this yet, so we run into
cases where the device is pulled and we OOPS on flushing the fs data.
This happens even though the dirty inodes have already been
migrated to the default_backing_dev_info.

Reported-by: Torsten Hilbrich <torsten.hilbrich@secunet.com>
Tested-by: Torsten Hilbrich <torsten.hilbrich@secunet.com>
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
fs/super.c
fs/sync.c
mm/backing-dev.c

index 7e9dd4cc2c01170d0d7a38035a430e554c90cc57..0d89e93f654e1310572dfd714912e48f918c724e 100644 (file)
@@ -71,6 +71,7 @@ static struct super_block *alloc_super(struct file_system_type *type)
 #else
                INIT_LIST_HEAD(&s->s_files);
 #endif
+               s->s_bdi = &default_backing_dev_info;
                INIT_LIST_HEAD(&s->s_instances);
                INIT_HLIST_BL_HEAD(&s->s_anon);
                INIT_LIST_HEAD(&s->s_inodes);
@@ -1003,6 +1004,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
        }
        BUG_ON(!mnt->mnt_sb);
        WARN_ON(!mnt->mnt_sb->s_bdi);
+       WARN_ON(mnt->mnt_sb->s_bdi == &default_backing_dev_info);
        mnt->mnt_sb->s_flags |= MS_BORN;
 
        error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata);
index ba76b9623e7e809f6b3c5e6223020836069dc4ab..412dc89163d31bbd58a8314dff28c38b867519e8 100644 (file)
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -33,7 +33,7 @@ static int __sync_filesystem(struct super_block *sb, int wait)
         * This should be safe, as we require bdi backing to actually
         * write out data in the first place
         */
-       if (!sb->s_bdi || sb->s_bdi == &noop_backing_dev_info)
+       if (sb->s_bdi == &noop_backing_dev_info)
                return 0;
 
        if (sb->s_qcop && sb->s_qcop->quota_sync)
@@ -79,7 +79,7 @@ EXPORT_SYMBOL_GPL(sync_filesystem);
 
 static void sync_one_sb(struct super_block *sb, void *arg)
 {
-       if (!(sb->s_flags & MS_RDONLY) && sb->s_bdi)
+       if (!(sb->s_flags & MS_RDONLY))
                __sync_filesystem(sb, *(int *)arg);
 }
 /*
index 027100d30227fead0a4010d1feb0e2791a98fcaa..8e4ed884f198bb324ccbfde368c4944b2296d6a0 100644 (file)
@@ -604,7 +604,7 @@ static void bdi_prune_sb(struct backing_dev_info *bdi)
        spin_lock(&sb_lock);
        list_for_each_entry(sb, &super_blocks, s_list) {
                if (sb->s_bdi == bdi)
-                       sb->s_bdi = NULL;
+                       sb->s_bdi = &default_backing_dev_info;
        }
        spin_unlock(&sb_lock);
 }