aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJens Axboe <jaxboe@fusionio.com>2011-03-17 06:13:12 -0400
committerJens Axboe <jaxboe@fusionio.com>2011-03-17 06:13:12 -0400
commit95f28604a65b1c40b6c6cd95e58439cd7ded3add (patch)
tree25b3be2d5505f06b2262bade8d1ecf5323c47ff8
parenta91a2785b200864aef2270ed6a3babac7a253a20 (diff)
fs: assign sb->s_bdi to default_backing_dev_info if the bdi is going away
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> Cc: stable@kernel.org Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
-rw-r--r--fs/super.c2
-rw-r--r--fs/sync.c4
-rw-r--r--mm/backing-dev.c2
3 files changed, 5 insertions, 3 deletions
diff --git a/fs/super.c b/fs/super.c
index 7e9dd4cc2c01..0d89e93f654e 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -71,6 +71,7 @@ static struct super_block *alloc_super(struct file_system_type *type)
71#else 71#else
72 INIT_LIST_HEAD(&s->s_files); 72 INIT_LIST_HEAD(&s->s_files);
73#endif 73#endif
74 s->s_bdi = &default_backing_dev_info;
74 INIT_LIST_HEAD(&s->s_instances); 75 INIT_LIST_HEAD(&s->s_instances);
75 INIT_HLIST_BL_HEAD(&s->s_anon); 76 INIT_HLIST_BL_HEAD(&s->s_anon);
76 INIT_LIST_HEAD(&s->s_inodes); 77 INIT_LIST_HEAD(&s->s_inodes);
@@ -1003,6 +1004,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
1003 } 1004 }
1004 BUG_ON(!mnt->mnt_sb); 1005 BUG_ON(!mnt->mnt_sb);
1005 WARN_ON(!mnt->mnt_sb->s_bdi); 1006 WARN_ON(!mnt->mnt_sb->s_bdi);
1007 WARN_ON(mnt->mnt_sb->s_bdi == &default_backing_dev_info);
1006 mnt->mnt_sb->s_flags |= MS_BORN; 1008 mnt->mnt_sb->s_flags |= MS_BORN;
1007 1009
1008 error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata); 1010 error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata);
diff --git a/fs/sync.c b/fs/sync.c
index ba76b9623e7e..412dc89163d3 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -33,7 +33,7 @@ static int __sync_filesystem(struct super_block *sb, int wait)
33 * This should be safe, as we require bdi backing to actually 33 * This should be safe, as we require bdi backing to actually
34 * write out data in the first place 34 * write out data in the first place
35 */ 35 */
36 if (!sb->s_bdi || sb->s_bdi == &noop_backing_dev_info) 36 if (sb->s_bdi == &noop_backing_dev_info)
37 return 0; 37 return 0;
38 38
39 if (sb->s_qcop && sb->s_qcop->quota_sync) 39 if (sb->s_qcop && sb->s_qcop->quota_sync)
@@ -79,7 +79,7 @@ EXPORT_SYMBOL_GPL(sync_filesystem);
79 79
80static void sync_one_sb(struct super_block *sb, void *arg) 80static void sync_one_sb(struct super_block *sb, void *arg)
81{ 81{
82 if (!(sb->s_flags & MS_RDONLY) && sb->s_bdi) 82 if (!(sb->s_flags & MS_RDONLY))
83 __sync_filesystem(sb, *(int *)arg); 83 __sync_filesystem(sb, *(int *)arg);
84} 84}
85/* 85/*
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index c91e139a652e..8fe9d3407921 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -598,7 +598,7 @@ static void bdi_prune_sb(struct backing_dev_info *bdi)
598 spin_lock(&sb_lock); 598 spin_lock(&sb_lock);
599 list_for_each_entry(sb, &super_blocks, s_list) { 599 list_for_each_entry(sb, &super_blocks, s_list) {
600 if (sb->s_bdi == bdi) 600 if (sb->s_bdi == bdi)
601 sb->s_bdi = NULL; 601 sb->s_bdi = &default_backing_dev_info;
602 } 602 }
603 spin_unlock(&sb_lock); 603 spin_unlock(&sb_lock);
604} 604}