]> git.karo-electronics.de Git - karo-tx-linux.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)
committerPaul Gortmaker <paul.gortmaker@windriver.com>
Fri, 17 Aug 2012 19:34:58 +0000 (15:34 -0400)
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: Paul Gortmaker <paul.gortmaker@windriver.com>
fs/super.c
fs/sync.c
mm/backing-dev.c

index 53040a673bf24b1577806e6150fce9add448f58a..7123fa728af7ab840c655cfb8f50d20f9e7486a8 100644 (file)
@@ -64,6 +64,7 @@ static struct super_block *alloc_super(struct file_system_type *type)
                        goto out;
                }
                INIT_LIST_HEAD(&s->s_files);
+               s->s_bdi = &default_backing_dev_info;
                INIT_LIST_HEAD(&s->s_instances);
                INIT_HLIST_HEAD(&s->s_anon);
                INIT_LIST_HEAD(&s->s_inodes);
@@ -962,6 +963,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);
+       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 92b228176f7cb05f4be58aabcae02e6ffb0b832d..5281fb372d59b74fbf589c5c4a57e40c0bf26478 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)
@@ -110,7 +110,7 @@ restart:
                spin_unlock(&sb_lock);
 
                down_read(&sb->s_umount);
-               if (!(sb->s_flags & MS_RDONLY) && sb->s_root && sb->s_bdi)
+               if (!(sb->s_flags & MS_RDONLY) && sb->s_root)
                        __sync_filesystem(sb, wait);
                up_read(&sb->s_umount);
 
index 707d0dc6da0f59a5730f613e2980fefc154c807a..7bd17d294b83b0124d39e8a40697f6faf849cee3 100644 (file)
@@ -634,7 +634,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);
 }